feat($sniffer): Add support for supportsAnimations flag for detecting CSS Animations browser support

This commit is contained in:
Matias Niemelä 2013-05-07 10:29:29 -04:00 committed by Misko Hevery
parent 0cb04e2e91
commit 88c3480aff
11 changed files with 101 additions and 40 deletions

View file

@ -241,7 +241,7 @@ var $AnimatorProvider = function() {
if (!parent) {
parent = after ? after.parent() : element.parent();
}
if ((!$sniffer.supportsTransitions && !polyfillSetup && !polyfillStart) ||
if ((!$sniffer.transitions && !polyfillSetup && !polyfillStart) ||
(parent.inheritedData(NG_ANIMATE_CONTROLLER) || noop).running) {
beforeFn(element, parent, after);
afterFn(element, parent, after);

View file

@ -9,7 +9,8 @@
*
* @property {boolean} history Does the browser support html5 history api ?
* @property {boolean} hashchange Does the browser support hashchange event ?
* @property {boolean} supportsTransitions Does the browser support CSS transition events ?
* @property {boolean} transitions Does the browser support CSS transition events ?
* @property {boolean} animations Does the browser support CSS animation events ?
*
* @description
* This is very simple implementation of testing browser's features.
@ -23,6 +24,7 @@ function $SnifferProvider() {
vendorRegex = /^(Moz|webkit|O|ms)(?=[A-Z])/,
bodyStyle = document.body && document.body.style,
transitions = false,
animations = false,
match;
if (bodyStyle) {
@ -34,6 +36,7 @@ function $SnifferProvider() {
}
}
transitions = !!(('transition' in bodyStyle) || (vendorPrefix + 'Transition' in bodyStyle));
animations = !!(('animation' in bodyStyle) || (vendorPrefix + 'Animation' in bodyStyle));
}
@ -61,7 +64,8 @@ function $SnifferProvider() {
},
csp: document.securityPolicy ? document.securityPolicy.isActive : false,
vendorPrefix: vendorPrefix,
supportsTransitions : transitions
transitions : transitions,
animations : animations
};
}];
}

View file

@ -75,7 +75,7 @@ angular.scenario.Application.prototype.navigateTo = function(url, loadFn, errorF
// we don't need that for our tests, but it should be done
$window.angular.resumeBootstrap([['$provide', function($provide) {
$provide.decorator('$sniffer', function($delegate) {
$delegate.supportsTransitions = false;
$delegate.transitions = false;
return $delegate;
});
}]]);

View file

@ -216,7 +216,7 @@ describe("$animator", function() {
it("should assign the ngAnimate string to all events if a string is given",
inject(function($animator, $sniffer, $rootScope) {
$animator.enabled(true);
if (!$sniffer.supportsTransitions) return;
if (!$sniffer.transitions) return;
animator = $animator($rootScope, {
ngAnimate : '"custom"'
});
@ -328,7 +328,7 @@ describe("$animator", function() {
expect(element.css('display')).toBe('none');
animator.show(element);
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(1000).process();
}

View file

@ -120,7 +120,7 @@ describe('ngIf ngAnimate', function () {
expect(element.children().length).toBe(1);
var first = element.children()[0];
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.className).toContain('custom-enter-setup');
window.setTimeout.expect(1).process();
expect(first.className).toContain('custom-enter-start');
@ -147,7 +147,7 @@ describe('ngIf ngAnimate', function () {
expect(element.children().length).toBe(1);
var first = element.children()[0];
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(1000).process();
} else {
@ -155,9 +155,9 @@ describe('ngIf ngAnimate', function () {
}
$scope.$apply('value = false');
expect(element.children().length).toBe($sniffer.supportsTransitions ? 1 : 0);
expect(element.children().length).toBe($sniffer.transitions ? 1 : 0);
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.className).toContain('custom-leave-setup');
window.setTimeout.expect(1).process();
expect(first.className).toContain('custom-leave-start');
@ -180,7 +180,7 @@ describe('ngIf ngAnimate', function () {
))($scope);
$scope.$apply('value = true');
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(500).process();
} else {

View file

@ -351,7 +351,7 @@ describe('ngInclude ngAnimate', function() {
var child = jqLite(element.children()[0]);
applyCSS(child, 'transition', '1s linear all');
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(child.attr('class')).toContain('custom-enter-setup');
window.setTimeout.expect(1).process();
@ -384,7 +384,7 @@ describe('ngInclude ngAnimate', function() {
$rootScope.tpl = '';
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(child.attr('class')).toContain('custom-leave-setup');
window.setTimeout.expect(1).process();
@ -417,7 +417,7 @@ describe('ngInclude ngAnimate', function() {
$rootScope.tpl = 'enter';
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(500).process();
} else {

View file

@ -608,7 +608,7 @@ describe('ngRepeat ngAnimate', function() {
applyCSS(kids[i], 'transition', '1s linear all');
}
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
angular.forEach(kids, function(kid) {
expect(kid.attr('class')).toContain('custom-enter-setup');
window.setTimeout.expect(1).process();
@ -654,7 +654,7 @@ describe('ngRepeat ngAnimate', function() {
//the last element gets pushed down when it animates
var kid = jqLite(element.children()[1]);
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(kid.attr('class')).toContain('custom-leave-setup');
window.setTimeout.expect(1).process();
expect(kid.attr('class')).toContain('custom-leave-start');
@ -696,7 +696,7 @@ describe('ngRepeat ngAnimate', function() {
var left = jqLite(kids[1]);
var right = jqLite(kids[2]);
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.attr('class')).toContain('custom-move-setup');
window.setTimeout.expect(1).process();
expect(left.attr('class')).toContain('custom-move-setup');
@ -743,7 +743,7 @@ describe('ngRepeat ngAnimate', function() {
applyCSS(first, cssProp, cssValue);
applyCSS(second, cssProp, cssValue);
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(1).process();
window.setTimeout.expect(500).process();

View file

@ -87,7 +87,7 @@ describe('ngShow / ngHide - ngAnimate', function() {
))($scope);
$scope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(element.attr('class')).toContain('custom-show-setup');
window.setTimeout.expect(1).process();
@ -102,7 +102,7 @@ describe('ngShow / ngHide - ngAnimate', function() {
$scope.on = false;
$scope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(element.attr('class')).toContain('custom-hide-setup');
window.setTimeout.expect(1).process();
expect(element.attr('class')).toContain('custom-hide-start');
@ -133,7 +133,7 @@ describe('ngShow / ngHide - ngAnimate', function() {
$rootElement.controller('ngAnimate').running = false;
$rootScope.val = false;
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(0).process();
} else {
@ -157,7 +157,7 @@ describe('ngShow / ngHide - ngAnimate', function() {
))($scope);
$scope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(element.attr('class')).toContain('custom-hide-setup');
window.setTimeout.expect(1).process();
@ -173,7 +173,7 @@ describe('ngShow / ngHide - ngAnimate', function() {
$scope.off = false;
$scope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(element.attr('class')).toContain('custom-show-setup');
window.setTimeout.expect(1).process();
expect(element.attr('class')).toContain('custom-show-start');

View file

@ -261,7 +261,7 @@ describe('ngSwitch ngAnimate', function() {
expect(element.children().length).toBe(1);
var first = element.children()[0];
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.className).toContain('cool-enter-setup');
window.setTimeout.expect(1).process();
@ -292,7 +292,7 @@ describe('ngSwitch ngAnimate', function() {
$scope.val = 'two';
$scope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(1000).process();
} else {
@ -302,11 +302,11 @@ describe('ngSwitch ngAnimate', function() {
$scope.val = 'three';
$scope.$digest();
expect(element.children().length).toBe($sniffer.supportsTransitions ? 2 : 1);
expect(element.children().length).toBe($sniffer.transitions ? 2 : 1);
var first = element.children()[0];
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.className).toContain('cool-leave-setup');
window.setTimeout.expect(1).process();
window.setTimeout.expect(1).process();
@ -315,7 +315,7 @@ describe('ngSwitch ngAnimate', function() {
}
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(first.className).toContain('cool-leave-start');
window.setTimeout.expect(1000).process();
window.setTimeout.expect(1000).process();
@ -339,7 +339,7 @@ describe('ngSwitch ngAnimate', function() {
$rootScope.val = 'one';
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect(500).process();
} else {

View file

@ -554,7 +554,7 @@ describe('ngView', function() {
var child = jqLite(element.children()[0]);
applyCSS(child, 'transition', '1s linear all');
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(child.attr('class')).toContain('custom-enter-setup');
window.setTimeout.expect(1).process();
@ -583,7 +583,7 @@ describe('ngView', function() {
$location.path('/');
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
expect(child.attr('class')).toContain('custom-leave-setup');
window.setTimeout.expect(1).process();
@ -614,9 +614,9 @@ describe('ngView', function() {
var child = jqLite(element.children()[0]);
applyCSS(child, 'transition', '0.5s linear all');
if($sniffer.supportsTransitions) {
if($sniffer.transitions) {
window.setTimeout.expect(1).process();
window.setTimeout.expect($sniffer.supportsTransitions ? 500 : 0).process();
window.setTimeout.expect($sniffer.transitions ? 500 : 0).process();
} else {
expect(window.setTimeout.queue).toEqual([]);
}
@ -641,7 +641,7 @@ describe('ngView', function() {
$location.path('/foo');
$rootScope.$digest();
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
$window.setTimeout.expect(1).process();
$window.setTimeout.expect(0).process();
}
@ -650,7 +650,7 @@ describe('ngView', function() {
$location.path('/bar');
$rootScope.$digest();
expect(n(element.text())).toEqual('1234');
if ($sniffer.supportsTransitions) {
if ($sniffer.transitions) {
$window.setTimeout.expect(1).process();
$window.setTimeout.expect(1).process();
} else {

View file

@ -124,11 +124,68 @@ describe('$sniffer', function() {
});
describe('supportsTransitions', function() {
describe('animations', function() {
it('should be either true or false', function() {
inject(function($sniffer) {
expect($sniffer.animations).not.toBe(undefined);
});
});
it('should be false when there is no animation style', function() {
module(function($provide) {
var doc = {
body : {
style : {}
}
};
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.animations).toBe(false);
});
});
it('should be true with vendor-specific animations', function() {
module(function($provide) {
var animationStyle = 'some_animation 2s linear';
var doc = {
body : {
style : {
WebkitAnimation : animationStyle,
MozAnimation : animationStyle,
OAnimation : animationStyle
}
}
};
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.animations).toBe(true);
});
});
it('should be true with w3c-style animations', function() {
module(function($provide) {
var doc = {
body : {
style : {
animation : 'some_animation 2s linear'
}
}
};
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.animations).toBe(true);
});
});
});
describe('transitions', function() {
it('should be either true or false', function() {
inject(function($sniffer) {
expect($sniffer.supportsTransitions).not.toBe(undefined);
expect($sniffer.transitions).not.toBe(undefined);
});
});
@ -142,7 +199,7 @@ describe('$sniffer', function() {
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.supportsTransitions).toBe(false);
expect($sniffer.transitions).toBe(false);
});
});
@ -161,7 +218,7 @@ describe('$sniffer', function() {
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.supportsTransitions).toBe(true);
expect($sniffer.transitions).toBe(true);
});
});
@ -177,7 +234,7 @@ describe('$sniffer', function() {
$provide.value('$document', jqLite(doc));
});
inject(function($sniffer) {
expect($sniffer.supportsTransitions).toBe(true);
expect($sniffer.transitions).toBe(true);
});
});