diff --git a/docs/component-spec/annotationsSpec.js b/docs/component-spec/annotationsSpec.js index d84bd5bdf57d..f1acd64ee6b1 100644 --- a/docs/component-spec/annotationsSpec.js +++ b/docs/component-spec/annotationsSpec.js @@ -118,14 +118,12 @@ describe('Docs Annotations', function() { expect(foldout.html()).toContain('loading'); })); - it('should download a foldout HTML page and animate the contents', inject(function($httpBackend, $timeout) { + it('should download a foldout HTML page and animate the contents', inject(function($httpBackend, $timeout, $sniffer) { $httpBackend.expect('GET', url).respond('hello'); element.triggerHandler('click'); $httpBackend.flush(); - $timeout.flushNext(0); - $timeout.flushNext(1); $timeout.flushNext(0); $timeout.flushNext(1000); @@ -134,27 +132,22 @@ describe('Docs Annotations', function() { expect(foldout.text()).toContain('hello'); })); - it('should hide then show when clicked again', inject(function($httpBackend, $timeout) { + it('should hide then show when clicked again', inject(function($httpBackend, $timeout, $sniffer) { $httpBackend.expect('GET', url).respond('hello'); //enter element.triggerHandler('click'); $httpBackend.flush(); $timeout.flushNext(0); - $timeout.flushNext(1); - $timeout.flushNext(0); $timeout.flushNext(1000); //hide element.triggerHandler('click'); - $timeout.flushNext(1); $timeout.flushNext(0); $timeout.flushNext(200); - $timeout.flushNext(0); //show element.triggerHandler('click'); - $timeout.flushNext(1); $timeout.flushNext(0); $timeout.flushNext(500); $timeout.flushNext(0); diff --git a/src/ngAnimate/animate.js b/src/ngAnimate/animate.js index 4207470b3792..1c1a0cba05cc 100644 --- a/src/ngAnimate/animate.js +++ b/src/ngAnimate/animate.js @@ -282,7 +282,9 @@ angular.module('ngAnimate', ['ng']) */ enter : function(element, parent, after, done) { $delegate.enter(element, parent, after); - performAnimation('enter', 'ng-enter', element, parent, after, done); + performAnimation('enter', 'ng-enter', element, parent, after, function() { + $timeout(done || noop, 0, false); + }); }, /** @@ -350,7 +352,9 @@ angular.module('ngAnimate', ['ng']) */ move : function(element, parent, after, done) { $delegate.move(element, parent, after); - performAnimation('move', 'ng-move', element, null, null, done); + performAnimation('move', 'ng-move', element, null, null, function() { + $timeout(done || noop, 0, false); + }); }, /** @@ -361,7 +365,8 @@ angular.module('ngAnimate', ['ng']) * @description * Triggers a custom animation event based off the className variable and then attaches the className value to the element as a CSS class. * Unlike the other animation methods, the animate service will suffix the className value with {@type -add} in order to provide - * the animate service the setup and active CSS classes in order to trigger the animation. + * the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if no CSS transitions + * or keyframes are defined on the -add CSS class). * * Below is a breakdown of each step that occurs during addClass animation: * @@ -395,7 +400,8 @@ angular.module('ngAnimate', ['ng']) * @description * Triggers a custom animation event based off the className variable and then removes the CSS class provided by the className value * from the element. Unlike the other animation methods, the animate service will suffix the className value with {@type -remove} in - * order to provide the animate service the setup and active CSS classes in order to trigger the animation. + * order to provide the animate service the setup and active CSS classes in order to trigger the animation (this will be skipped if + * no CSS transitions or keyframes are defined on the -remove CSS class). * * Below is a breakdown of each step that occurs during removeClass animation: * @@ -546,90 +552,89 @@ angular.module('ngAnimate', ['ng']) function animate(element, className, done) { if (!($sniffer.transitions || $sniffer.animations)) { done(); - } else { - var activeClassName = ''; - $timeout(startAnimation, 1, false); - - //this acts as the cancellation function in case - //a new animation is triggered while another animation - //is still going on (otherwise the active className - //would still hang around until the timer is complete). - return onEnd; - } - - function parseMaxTime(str) { - var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : []; - forEach(values, function(value) { - total = Math.max(parseFloat(value) || 0, total); - }); - return total; + return; } - function startAnimation() { - var duration = 0; - forEach(className.split(' '), function(klass, i) { - activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; - }); + //one day all browsers will have these properties + var w3cAnimationProp = 'animation'; + var w3cTransitionProp = 'transition'; - element.addClass(activeClassName); + //but some still use vendor-prefixed styles + var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation'; + var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition'; - //one day all browsers will have these properties - var w3cAnimationProp = 'animation'; - var w3cTransitionProp = 'transition'; + var durationKey = 'Duration', + delayKey = 'Delay', + animationIterationCountKey = 'IterationCount'; - //but some still use vendor-prefixed styles - var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation'; - var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition'; + //we want all the styles defined before and after + var duration = 0, ELEMENT_NODE = 1; + forEach(element, function(element) { + if (element.nodeType == ELEMENT_NODE) { + var elementStyles = $window.getComputedStyle(element) || {}; - var durationKey = 'Duration', - delayKey = 'Delay', - animationIterationCountKey = 'IterationCount'; + var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]), + parseMaxTime(elementStyles[vendorTransitionProp + delayKey])); - //we want all the styles defined before and after - var ELEMENT_NODE = 1; - forEach(element, function(element) { - if (element.nodeType == ELEMENT_NODE) { - var elementStyles = $window.getComputedStyle(element) || {}; + var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]), + parseMaxTime(elementStyles[vendorAnimationProp + delayKey])); - var transitionDelay = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + delayKey]), - parseMaxTime(elementStyles[vendorTransitionProp + delayKey])); + var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]), + parseMaxTime(elementStyles[vendorTransitionProp + durationKey])); - var animationDelay = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + delayKey]), - parseMaxTime(elementStyles[vendorAnimationProp + delayKey])); + var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]), + parseMaxTime(elementStyles[vendorAnimationProp + durationKey])); - var transitionDuration = Math.max(parseMaxTime(elementStyles[w3cTransitionProp + durationKey]), - parseMaxTime(elementStyles[vendorTransitionProp + durationKey])); - - var animationDuration = Math.max(parseMaxTime(elementStyles[w3cAnimationProp + durationKey]), - parseMaxTime(elementStyles[vendorAnimationProp + durationKey])); + if(animationDuration > 0) { + animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0, + parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0, + 1); + } - if(animationDuration > 0) { - animationDuration *= Math.max(parseInt(elementStyles[w3cAnimationProp + animationIterationCountKey]) || 0, - parseInt(elementStyles[vendorAnimationProp + animationIterationCountKey]) || 0, - 1); - } + duration = Math.max(animationDelay + animationDuration, + transitionDelay + transitionDuration, + duration); + } + }); - duration = Math.max(animationDelay + animationDuration, - transitionDelay + transitionDuration, - duration); - } + /* there is no point in performing a reflow if the animation + timeout is empty (this would cause a flicker bug normally + in the page */ + if(duration > 0) { + var activeClassName = ''; + forEach(className.split(' '), function(klass, i) { + activeClassName += (i > 0 ? ' ' : '') + klass + '-active'; }); - $timeout(done, duration * 1000, false); + $timeout(function() { + element.addClass(activeClassName); + $timeout(done, duration * 1000, false); + },0,false); + + //this will automatically be called by $animate so + //there is no need to attach this internally to the + //timeout done method + return function onEnd(cancelled) { + element.removeClass(activeClassName); + + //only when the animation is cancelled is the done() + //function not called for this animation therefore + //this must be also called + if(cancelled) { + done(); + } + } + } + else { + done(); } - //this will automatically be called by $animate so - //there is no need to attach this internally to the - //timeout done method - function onEnd(cancelled) { - element.removeClass(activeClassName); - - //only when the animation is cancelled is the done() - //function not called for this animation therefore - //this must be also called - if(cancelled) { - done(); - } + function parseMaxTime(str) { + var total = 0, values = angular.isString(str) ? str.split(/\s*,\s*/) : []; + forEach(values, function(value) { + total = Math.max(parseFloat(value) || 0, total); + }); + return total; } } diff --git a/test/ngAnimate/animateSpec.js b/test/ngAnimate/animateSpec.js index 3702664037c8..2d9d25afc688 100644 --- a/test/ngAnimate/animateSpec.js +++ b/test/ngAnimate/animateSpec.js @@ -4,9 +4,28 @@ describe("ngAnimate", function() { beforeEach(module('ngAnimate')); + var ss, body; + beforeEach(module(function() { + body = jqLite(document.body); + return function($window, $document, $animate, $timeout) { + ss = createMockStyleSheet($document, $window); + try { + $timeout.flush(); + } catch(e) {}; + $animate.enabled(true); + }; + })); + + afterEach(function(){ + if(ss) { + ss.destroy(); + } + dealoc(body); + }); + describe("$animate", function() { - var body, element, $rootElement; + var element, $rootElement; function html(html) { body.append($rootElement); @@ -15,21 +34,6 @@ describe("ngAnimate", function() { return element; } - beforeEach(module(function() { - // we need to run animation on attached elements; - body = jqLite(document.body); - return function($animate, $timeout) { - try { - $timeout.flush(); - } catch(e) {}; - $animate.enabled(true); - }; - })); - - afterEach(function(){ - dealoc(body); - }); - describe("enable / disable", function() { it("should disable and enable the animations", function() { @@ -104,9 +108,19 @@ describe("ngAnimate", function() { } } }); - return function($animate, $compile, $rootScope, $rootElement) { + return function($animate, $compile, $rootScope, $rootElement, $sniffer) { element = $compile('
')($rootScope); child = $compile('
')($rootScope); + + angular.forEach(['.ng-hide-add', '.ng-hide-remove', '.ng-enter', '.ng-leave', '.ng-move'], function(selector) { + ss.addRule(selector, 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); + }); + + child = $compile('
...
')($rootScope); + jqLite($document[0].body).append($rootElement); + element.append(child); + after = $compile('
')($rootScope); $rootElement.append(element); }; @@ -115,10 +129,19 @@ describe("ngAnimate", function() { it("should animate the enter animation event", inject(function($animate, $rootScope, $sniffer, $timeout) { + element[0].removeChild(child[0]); expect(element.contents().length).toBe(0); $animate.enter(child, element); - $timeout.flush($sniffer.transitions ? 1 : 0); + $timeout.flushNext(0); + + if($sniffer.transitions) { + expect(child.hasClass('ng-enter')).toBe(true); + $timeout.flushNext(0); + expect(child.hasClass('ng-enter-active')).toBe(true); + $timeout.flushNext(1000); + } + $timeout.flush(); expect(element.contents().length).toBe(1); })); @@ -126,10 +149,15 @@ describe("ngAnimate", function() { it("should animate the leave animation event", inject(function($animate, $rootScope, $sniffer, $timeout) { - element.append(child); expect(element.contents().length).toBe(1); $animate.leave(child); - $timeout.flush($sniffer.transitions ? 1 : 0); + if($sniffer.transitions) { + expect(child.hasClass('ng-leave')).toBe(true); + $timeout.flushNext(0); + expect(child.hasClass('ng-leave-active')).toBe(true); + $timeout.flushNext(1000); + } + $timeout.flush(); expect(element.contents().length).toBe(0); })); @@ -138,6 +166,8 @@ describe("ngAnimate", function() { inject(function($animate, $compile, $rootScope, $sniffer, $timeout) { $rootScope.$digest(); + element.html(''); + var child1 = $compile('
1
')($rootScope); var child2 = $compile('
2
')($rootScope); element.append(child1); @@ -145,59 +175,57 @@ describe("ngAnimate", function() { expect(element.text()).toBe('12'); $animate.move(child1, element, child2); expect(element.text()).toBe('21'); - if($sniffer.transitions) { - $timeout.flushNext(0); - $timeout.flushNext(1); - } })); it("should animate the show animation event", inject(function($animate, $rootScope, $sniffer, $timeout) { $rootScope.$digest(); - element.addClass('ng-hide'); - expect(element).toBeHidden(); - $animate.removeClass(element, 'ng-hide'); + child.addClass('ng-hide'); + expect(child).toBeHidden(); + $animate.removeClass(child, 'ng-hide'); if($sniffer.transitions) { - expect(element.hasClass('ng-hide-remove')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('ng-hide-remove-active')).toBe(true); + expect(child.hasClass('ng-hide-remove')).toBe(true); $timeout.flushNext(0); + expect(child.hasClass('ng-hide-remove-active')).toBe(true); + $timeout.flushNext(1000); } - expect(element.hasClass('ng-hide-remove')).toBe(false); - expect(element.hasClass('ng-hide-remove-active')).toBe(false); - expect(element).toBeShown(); + expect(child.hasClass('ng-hide-remove')).toBe(false); + expect(child.hasClass('ng-hide-remove-active')).toBe(false); + expect(child).toBeShown(); })); it("should animate the hide animation event", inject(function($animate, $rootScope, $sniffer, $timeout) { $rootScope.$digest(); - expect(element).toBeShown(); - $animate.addClass(element, 'ng-hide'); + expect(child).toBeShown(); + $animate.addClass(child, 'ng-hide'); if($sniffer.transitions) { - expect(element.hasClass('ng-hide-add')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('ng-hide-add-active')).toBe(true); + expect(child.hasClass('ng-hide-add')).toBe(true); $timeout.flushNext(0); + expect(child.hasClass('ng-hide-add-active')).toBe(true); + $timeout.flushNext(1000); } $timeout.flush(); - expect(element).toBeHidden(); + expect(child).toBeHidden(); })); - it("should assign the ngAnimate string to all events if a string is given", - inject(function($animate, $sniffer, $rootScope, $timeout, $browser) { + it("should assign the ng-event className to all animation events when transitions/keyframes are used", + inject(function($animate, $sniffer, $rootScope, $timeout, $browser, $compile, $rootElement, $document) { if (!$sniffer.transitions) return; $rootScope.$digest(); + element[0].removeChild(child[0]); //enter $animate.enter(child, element); $timeout.flushNext(0); expect(child.attr('class')).toContain('ng-enter'); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(child.attr('class')).toContain('ng-enter-active'); + $timeout.flushNext(1000); $timeout.flushNext(0); //move @@ -205,32 +233,33 @@ describe("ngAnimate", function() { $animate.move(child, element, after); $timeout.flushNext(0); expect(child.attr('class')).toContain('ng-move'); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(child.attr('class')).toContain('ng-move-active'); + $timeout.flushNext(1000); $timeout.flushNext(0); //hide $animate.addClass(child, 'ng-hide'); expect(child.attr('class')).toContain('ng-hide-add'); - $timeout.flushNext(1); - expect(child.attr('class')).toContain('ng-hide-add-active'); $timeout.flushNext(0); + expect(child.attr('class')).toContain('ng-hide-add-active'); + $timeout.flushNext(1000); $timeout.flushNext(0); //show $animate.removeClass(child, 'ng-hide'); expect(child.attr('class')).toContain('ng-hide-remove'); - $timeout.flushNext(1); - expect(child.attr('class')).toContain('ng-hide-remove-active'); $timeout.flushNext(0); + expect(child.attr('class')).toContain('ng-hide-remove-active'); + $timeout.flushNext(1000); $timeout.flushNext(0); //leave $animate.leave(child); expect(child.attr('class')).toContain('ng-leave'); - $timeout.flushNext(1); - expect(child.attr('class')).toContain('ng-leave-active'); $timeout.flushNext(0); + expect(child.attr('class')).toContain('ng-leave-active'); + $timeout.flushNext(1000); $timeout.flushNext(0); })); @@ -252,10 +281,6 @@ describe("ngAnimate", function() { $animate.enabled(true); $animate.removeClass(element, 'ng-hide'); - if($sniffer.transitions) { - $timeout.flushNext(0); - $timeout.flushNext(1); - } $timeout.flushNext(0); expect(element.text()).toBe('memento'); })); @@ -268,9 +293,6 @@ describe("ngAnimate", function() { expect(element).toBeShown(); $animate.addClass(child, 'ng-hide'); - if($sniffer.transitions) { - $timeout.flushNext(1); - } expect(child).toBeShown(); $animate.leave(child); @@ -280,15 +302,14 @@ describe("ngAnimate", function() { child.css('display','block'); child.removeClass('ng-hide'); - if($sniffer.transitions) { - $timeout.flushNext(0); - } $timeout.flushNext(0); if($sniffer.transitions) { - $timeout.flushNext(1); $timeout.flushNext(0); + $timeout.flushNext(0); + expect(element.children().length).toBe(1); //still animating + $timeout.flushNext(1000); + $timeout.flushNext(1000); } - expect(element.children().length).toBe(1); //still animating $timeout.flushNext(2000); $timeout.flushNext(2000); $timeout.flushNext(0); @@ -305,8 +326,8 @@ describe("ngAnimate", function() { child.addClass('custom-delay ng-hide'); $animate.removeClass(child, 'ng-hide'); if($sniffer.transitions) { - $timeout.flushNext(1); $timeout.flushNext(0); + $timeout.flushNext(1000); } $timeout.flushNext(2000); @@ -322,11 +343,6 @@ describe("ngAnimate", function() { element.append(child); $animate.addClass(child, 'custom-delay'); - - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } $animate.addClass(child, 'custom-long-delay'); expect(child.hasClass('animation-cancelled')).toBe(true); @@ -344,13 +360,7 @@ describe("ngAnimate", function() { element.data('foo', 'bar'); $animate.removeClass(element, 'ng-hide'); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } - $animate.addClass(element, 'ng-hide'); - expect(element.data('foo')).toEqual('bar'); })); @@ -359,41 +369,30 @@ describe("ngAnimate", function() { inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { $animate.addClass(element, 'custom-delay custom-long-delay'); - if($sniffer.transitions) { - expect(element[0].className).toContain('custom-delay-add custom-long-delay-add'); - $timeout.flushNext(1); - expect(element[0].className).toContain('custom-delay-add-active custom-long-delay-add-active'); - $timeout.flushNext(0); - } $timeout.flushNext(2000); $timeout.flushNext(20000); $timeout.flushNext(0); - expect(element.hasClass('custom-delay')).toBe(true); - expect(element.hasClass('custom-delay-add')).toBe(false); - expect(element.hasClass('custom-delay-add-active')).toBe(false); - expect(element.hasClass('custom-long-delay')).toBe(true); - expect(element.hasClass('custom-long-delay-add')).toBe(false); - expect(element.hasClass('custom-long-delay-add-active')).toBe(false); })); it("should allow both multiple JS and CSS animations which run in parallel", inject(function($animate, $rootScope, $compile, $sniffer, $timeout, _$rootElement_) { $rootElement = _$rootElement_; - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 1s linear all;' + - vendorPrefix + 'transition: 1s linear all;' + ss.addRule('.ng-hide-add', 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); + ss.addRule('.ng-hide-remove', 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); - element = $compile(html('
1
'))($rootScope); + element = $compile(html('
1
'))($rootScope); element.addClass('custom-delay custom-long-delay'); $rootScope.$digest(); $animate.removeClass(element, 'ng-hide'); if($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(1000); } $timeout.flushNext(2000); @@ -426,16 +425,19 @@ describe("ngAnimate", function() { it("should properly detect and make use of CSS Animations", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - var style = 'animation: some_animation 4s linear 0s 1 alternate;' + - vendorPrefix + 'animation: some_animation 4s linear 0s 1 alternate;'; - element = $compile(html('
1
'))($rootScope); + ss.addRule('.ng-hide-add', 'animation: some_animation 4s linear 0s 1 alternate;' + + vendorPrefix + 'animation: some_animation 4s linear 0s 1 alternate'); + ss.addRule('.ng-hide-remove', 'animation: some_animation 4s linear 0s 1 alternate;' + + vendorPrefix + 'animation: some_animation 4s linear 0s 1 alternate'); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); if ($sniffer.animations) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(4000); } expect(element).toBeShown(); @@ -448,14 +450,18 @@ describe("ngAnimate", function() { 'animation-iteration-count: 3;' + vendorPrefix + 'animation-duration: 2s;' + vendorPrefix + 'animation-iteration-count: 3;'; - element = $compile(html('
1
'))($rootScope); + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); if ($sniffer.animations) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(6000); } expect(element).toBeShown(); @@ -468,14 +474,18 @@ describe("ngAnimate", function() { 'animation-iteration-count: infinite;' + vendorPrefix + 'animation-duration: 2s;' + vendorPrefix + 'animation-iteration-count: infinite;'; - element = $compile(html('
1
'))($rootScope); + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); if ($sniffer.animations) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(2000); } expect(element).toBeShown(); @@ -490,14 +500,18 @@ describe("ngAnimate", function() { vendorPrefix + 'animation-duration: 2s;' + vendorPrefix + 'animation-delay: 10s;' + vendorPrefix + 'animation-iteration-count: 5;'; - element = $compile(html('
1
'))($rootScope); + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); if ($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(20000); } expect(element).toBeShown(); @@ -509,7 +523,10 @@ describe("ngAnimate", function() { var style = 'animation: some_animation 2s linear 0s 1 alternate;' + vendorPrefix + 'animation: some_animation 2s linear 0s 1 alternate;' - element = $compile(html('
1
'))($rootScope); + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); @@ -522,13 +539,16 @@ describe("ngAnimate", function() { var style = 'animation: some_animation 2s linear 0s 1 alternate;' + vendorPrefix + 'animation: some_animation 2s linear 0s 1 alternate;' - element = $compile(html('
1
'))($rootScope); + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('custom'); $animate.removeClass(element, 'ng-hide'); if($sniffer.animations) { expect(element.hasClass('ng-hide-remove')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('ng-hide-remove-active')).toBe(true); } @@ -539,7 +559,7 @@ describe("ngAnimate", function() { if($sniffer.animations) { //cleanup some pending animations expect(element.hasClass('ng-hide-add')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('ng-hide-add-active')).toBe(true); $timeout.flushNext(2000); } @@ -552,8 +572,14 @@ describe("ngAnimate", function() { it("should skip transitions if disabled and run when enabled", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { + var style = 'transition: 1s linear all;' + + vendorPrefix + 'transition: 1s linear all'; + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + $animate.enabled(false); - element = $compile(html('
1
'))($rootScope); + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); @@ -569,7 +595,7 @@ describe("ngAnimate", function() { $animate.removeClass(element, 'ng-hide'); if ($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(1000); } $timeout.flushNext(0); @@ -578,12 +604,21 @@ describe("ngAnimate", function() { it("should skip animations if disabled and run when enabled picking the longest specified duration", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - element = $compile(html('
foo
'))($rootScope); + + var style = 'transition-duration: 1s, 2000ms, 1s;' + + 'transition-property: height, left, opacity;' + + vendorPrefix + 'transition-duration: 1s, 2000ms, 1s;' + + vendorPrefix + 'transition-property: height, left, opacity'; + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
foo
'))($rootScope); element.addClass('ng-hide'); $animate.removeClass(element, 'ng-hide'); if ($sniffer.transitions) { expect(element).toBeHidden(); - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(2000); } $timeout.flush(); @@ -593,10 +628,17 @@ describe("ngAnimate", function() { it("should skip animations if disabled and run when enabled picking the longest specified duration/delay combination", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { $animate.enabled(false); - element = $compile(html('
foo
'))($rootScope); + var style = 'transition-duration: 1s, 0s, 1s; ' + + 'transition-delay: 2s, 1000ms, 2s; ' + + 'transition-property: height, left, opacity;' + + vendorPrefix + 'transition-duration: 1s, 0s, 1s; ' + + vendorPrefix + 'transition-delay: 2s, 1000ms, 2s; ' + + vendorPrefix + 'transition-property: height, left, opacity'; + + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
foo
'))($rootScope); element.addClass('ng-hide'); $animate.removeClass(element, 'ng-hide'); @@ -611,7 +653,7 @@ describe("ngAnimate", function() { $animate.removeClass(element, 'ng-hide'); if ($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(3000); } $timeout.flush(); @@ -620,19 +662,22 @@ describe("ngAnimate", function() { it("should select the highest duration and delay", inject(function($animate, $rootScope, $compile, $sniffer, $timeout) { - var styles = 'transition:1s linear all 2s;' + + var style = 'transition:1s linear all 2s;' + vendorPrefix + 'transition:1s linear all 2s;' + 'animation:my_ani 10s 1s;' + vendorPrefix + 'animation:my_ani 10s 1s;'; - element = $compile(html('
foo
'))($rootScope); + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
foo
'))($rootScope); element.addClass('ng-hide'); expect(element).toBeHidden(); $animate.removeClass(element, 'ng-hide'); if ($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(11000); } expect(element).toBeShown(); @@ -643,13 +688,16 @@ describe("ngAnimate", function() { var style = 'transition: 1s linear all;' + vendorPrefix + 'transition: 1s linear all;' - element = $compile(html('
1
'))($rootScope); + ss.addRule('.ng-hide-add', style); + ss.addRule('.ng-hide-remove', style); + + element = $compile(html('
1
'))($rootScope); element.addClass('ng-hide'); $animate.removeClass(element, 'ng-hide'); if($sniffer.transitions) { expect(element.hasClass('ng-hide-remove')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('ng-hide-remove-active')).toBe(true); $timeout.flushNext(1000); } @@ -661,7 +709,7 @@ describe("ngAnimate", function() { $animate.addClass(element, 'ng-hide'); if($sniffer.transitions) { expect(element.hasClass('ng-hide-add')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('ng-hide-add-active')).toBe(true); } })); @@ -672,6 +720,11 @@ describe("ngAnimate", function() { it('should re-evaluate the CSS classes for an animation each time', inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { + ss.addRule('.ng-enter', 'transition:22s linear all;' + + vendorPrefix + 'transition:22s linear all'); + ss.addRule('.ng-enter', 'transition:22s linear all;' + + vendorPrefix + 'transition:22s linear all'); + var parent = jqLite('
'); var element = parent.find('span'); $rootElement.append(parent); @@ -683,10 +736,11 @@ describe("ngAnimate", function() { if ($sniffer.transitions) { expect(element.hasClass('abc ng-enter')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('abc ng-enter ng-enter-active')).toBe(true); $timeout.flushNext(0); + expect(element.hasClass('abc ng-enter ng-enter-active')).toBe(true); + $timeout.flushNext(22000); } + $timeout.flushNext(0); expect(element.hasClass('abc')).toBe(true); element[0].className = 'xyz'; @@ -695,16 +749,22 @@ describe("ngAnimate", function() { if ($sniffer.transitions) { expect(element.hasClass('xyz')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('xyz ng-enter ng-enter-active')).toBe(true); $timeout.flushNext(0); + expect(element.hasClass('xyz ng-enter ng-enter-active')).toBe(true); + $timeout.flushNext(22000); } + $timeout.flushNext(0); expect(element.hasClass('xyz')).toBe(true); })); it('should only append active to the newly append CSS className values', inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { + ss.addRule('.ng-enter', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + ss.addRule('.ng-enter', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + var parent = jqLite('
'); var element = parent.find('span'); $rootElement.append(parent); @@ -716,11 +776,11 @@ describe("ngAnimate", function() { $timeout.flushNext(0); if($sniffer.transitions) { expect(element.hasClass('one two ng-enter')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('one two ng-enter ng-enter-active')).toBe(true); expect(element.hasClass('one-active')).toBe(false); expect(element.hasClass('two-active')).toBe(false); - $timeout.flushNext(0); + $timeout.flushNext(9000); } expect(element.hasClass('one two')).toBe(true); @@ -765,11 +825,9 @@ describe("ngAnimate", function() { flag = true; }); - $timeout.flushNext(0); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } + $timeout.flushNext(0); //move operation callback + $timeout.flushNext(0); //ngAnimate callback + expect(flag).toBe(true); })); @@ -786,10 +844,6 @@ describe("ngAnimate", function() { flag = true; }); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(0); expect(flag).toBe(true); })); @@ -808,11 +862,8 @@ describe("ngAnimate", function() { flag = true; }); - $timeout.flushNext(0); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } + $timeout.flushNext(0); //move operation callback + $timeout.flushNext(0); //ngAnimate callback expect(flag).toBe(true); expect(element.parent().id).toBe(parent2.id); @@ -830,23 +881,13 @@ describe("ngAnimate", function() { $animate.addClass(element, 'on', function() { signature += 'A'; }); - - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(0); $animate.removeClass(element, 'on', function() { signature += 'B'; }); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(0); - expect(signature).toBe('AB'); })); @@ -871,9 +912,12 @@ describe("ngAnimate", function() { it("should fire a done callback when provided with a css animation/transition", inject(function($animate, $rootScope, $compile, $sniffer, $rootElement, $timeout) { - var transition = 'transition:1s linear all;'; - var style = transition + ' ' + vendorPrefix + transition; - var parent = jqLite('
'); + ss.addRule('.ng-hide-add', 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); + ss.addRule('.ng-hide-remove', 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); + + var parent = jqLite('
'); $rootElement.append(parent); body.append($rootElement); var element = parent.find('span'); @@ -884,7 +928,7 @@ describe("ngAnimate", function() { }); if($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); $timeout.flushNext(1000); } $timeout.flushNext(0); @@ -905,10 +949,6 @@ describe("ngAnimate", function() { flag = true; }); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(2000); $timeout.flushNext(0); expect(flag).toBe(true); @@ -917,6 +957,11 @@ describe("ngAnimate", function() { it("should fire the callback right away if another animation is called right after", inject(function($animate, $rootScope, $compile, $sniffer, $rootElement, $timeout) { + ss.addRule('.ng-hide-add', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + ss.addRule('.ng-hide-remove', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + var parent = jqLite('
'); $rootElement.append(parent); body.append($rootElement); @@ -932,14 +977,16 @@ describe("ngAnimate", function() { if($sniffer.transitions) { $timeout.flushNext(0); //callback for removeClass - $timeout.flushNext(1); $timeout.flushNext(0); - $timeout.flushNext(1); + $timeout.flushNext(0); + $timeout.flushNext(9000); + $timeout.flushNext(9000); + $timeout.flushNext(0); } $animate.addClass(element, 'ng-hide'); //earlier animation cancelled if($sniffer.transitions) { $timeout.flushNext(0); - $timeout.flushNext(0); + $timeout.flushNext(9000); } $timeout.flush(); expect(signature).toBe('AB'); @@ -976,28 +1023,11 @@ describe("ngAnimate", function() { var element = jqLite(parent.find('span')); $animate.addClass(element,'klass'); - - if($sniffer.transitions) { - expect(element.hasClass('klass-add')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('klass-add-active')).toBe(true); - $timeout.flushNext(0); - expect(element.hasClass('klass-add')).toBe(false); - expect(element.hasClass('klass-add-active')).toBe(false); - } $timeout.flushNext(0); expect(element.hasClass('klass')).toBe(true); $animate.removeClass(element,'klass'); - - if($sniffer.transitions) { - expect(element.hasClass('klass')).toBe(true); - expect(element.hasClass('klass-remove')).toBe(true); - $timeout.flushNext(1); - expect(element.hasClass('klass-remove-active')).toBe(true); - $timeout.flushNext(0); - } $timeout.flushNext(0); expect(element.hasClass('klass')).toBe(false); @@ -1019,11 +1049,6 @@ describe("ngAnimate", function() { signature += 'A'; }); - if($sniffer.transitions) { - expect(element.hasClass('klass')).toBe(false); - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(0); expect(element.hasClass('klass')).toBe(true); @@ -1031,11 +1056,6 @@ describe("ngAnimate", function() { signature += 'B'; }); - if($sniffer.transitions) { - expect(element.hasClass('klass')).toBe(true); - $timeout.flushNext(1); - $timeout.flushNext(0); - } $timeout.flushNext(0); expect(element.hasClass('klass')).toBe(false); @@ -1045,6 +1065,11 @@ describe("ngAnimate", function() { it("should end the current addClass animation, add the CSS class and then run the removeClass animation", inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { + ss.addRule('.klass-add', 'transition:3s linear all;' + + vendorPrefix + 'transition:3s linear all'); + ss.addRule('.klass-remove', 'transition:3s linear all;' + + vendorPrefix + 'transition:3s linear all'); + var parent = jqLite('
'); $rootElement.append(parent); body.append($rootElement); @@ -1058,9 +1083,11 @@ describe("ngAnimate", function() { if($sniffer.transitions) { expect(element.hasClass('klass')).toBe(false); expect(element.hasClass('klass-add')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('klass-add-active')).toBe(true); + $timeout.flushNext(3000); } + $timeout.flushNext(0); //this cancels out the older animation $animate.removeClass(element,'klass', function() { @@ -1072,6 +1099,7 @@ describe("ngAnimate", function() { expect(element.hasClass('klass-add')).toBe(false); expect(element.hasClass('klass-add-active')).toBe(false); + $timeout.flushNext(0); expect(element.hasClass('klass-remove')).toBe(true); } $timeout.flush(); @@ -1093,10 +1121,7 @@ describe("ngAnimate", function() { $animate.addClass(element,'klassy', function() { signature += 'X'; }); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } + $timeout.flushNext(500); $timeout.flushNext(0); @@ -1105,10 +1130,7 @@ describe("ngAnimate", function() { $animate.removeClass(element,'klassy', function() { signature += 'Y'; }); - if($sniffer.transitions) { - $timeout.flushNext(1); - $timeout.flushNext(0); - } + $timeout.flushNext(3000); $timeout.flushNext(0); @@ -1118,13 +1140,12 @@ describe("ngAnimate", function() { })); it("should properly execute CSS animations/transitions and use callbacks when using addClass / removeClass", - inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout, $window, $document) { + inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { - var ss = createMockStyleSheet($document, $window); - ss.addRule('.klass-add', 'transition:11s linear all'); - ss.addRule('.klass-add', vendorPrefix + 'transition:11s linear all'); - ss.addRule('.klass-remove', 'transition:11s linear all'); - ss.addRule('.klass-remove', vendorPrefix + 'transition:11s linear all'); + ss.addRule('.klass-add', 'transition:11s linear all;' + + vendorPrefix + 'transition:11s linear all'); + ss.addRule('.klass-remove', 'transition:11s linear all;' + + vendorPrefix + 'transition:11s linear all'); var parent = jqLite('
'); $rootElement.append(parent); @@ -1138,7 +1159,7 @@ describe("ngAnimate", function() { }); if($sniffer.transitions) { expect(element.hasClass('klass-add')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('klass-add-active')).toBe(true); $timeout.flushNext(11000); expect(element.hasClass('klass-add')).toBe(false); @@ -1153,7 +1174,7 @@ describe("ngAnimate", function() { }); if($sniffer.transitions) { expect(element.hasClass('klass-remove')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('klass-remove-active')).toBe(true); $timeout.flushNext(11000); expect(element.hasClass('klass-remove')).toBe(false); @@ -1169,9 +1190,12 @@ describe("ngAnimate", function() { it("should allow for multiple css classes to be animated plus a callback when added", inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { - var transition = 'transition:7s linear all;'; - var style = transition + ' ' + vendorPrefix + transition; - var parent = jqLite('
'); + ss.addRule('.one-add', 'transition:7s linear all;' + + vendorPrefix + 'transition:7s linear all'); + ss.addRule('.two-add', 'transition:7s linear all;' + + vendorPrefix + 'transition:7s linear all'); + + var parent = jqLite('
'); $rootElement.append(parent); body.append($rootElement); var element = jqLite(parent.find('span')); @@ -1184,7 +1208,7 @@ describe("ngAnimate", function() { if($sniffer.transitions) { expect(element.hasClass('one-add')).toBe(true); expect(element.hasClass('two-add')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('one-add-active')).toBe(true); expect(element.hasClass('two-add-active')).toBe(true); @@ -1206,9 +1230,12 @@ describe("ngAnimate", function() { it("should allow for multiple css classes to be animated plus a callback when removed", inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) { - var transition = 'transition:9s linear all;'; - var style = transition + ' ' + vendorPrefix + transition; - var parent = jqLite('
'); + ss.addRule('.one-remove', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + ss.addRule('.two-remove', 'transition:9s linear all;' + + vendorPrefix + 'transition:9s linear all'); + + var parent = jqLite('
'); $rootElement.append(parent); body.append($rootElement); var element = jqLite(parent.find('span')); @@ -1225,7 +1252,7 @@ describe("ngAnimate", function() { if($sniffer.transitions) { expect(element.hasClass('one-remove')).toBe(true); expect(element.hasClass('two-remove')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(element.hasClass('one-remove-active')).toBe(true); expect(element.hasClass('two-remove-active')).toBe(true); @@ -1246,9 +1273,10 @@ describe("ngAnimate", function() { }); }); - var $rootElement, $document; + var $rootElement, $document, vendorPrefix; beforeEach(module(function($provide) { - return function(_$rootElement_, _$document_, $animate) { + return function(_$rootElement_, _$document_, $animate, $sniffer) { + vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; $rootElement = _$rootElement_; $document = _$document_; $animate.enabled(true); @@ -1265,18 +1293,18 @@ describe("ngAnimate", function() { it("should properly animate and parse CSS3 transitions", inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 1s linear all;' + - vendorPrefix + 'transition: 1s linear all;'; + ss.addRule('.ng-enter', 'transition:1s linear all;' + + vendorPrefix + 'transition:1s linear all'); + var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); + var child = $compile('
...
')($rootScope); $animate.enter(child, element); $timeout.flushNext(0); if($sniffer.transitions) { expect(child.hasClass('ng-enter')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(child.hasClass('ng-enter-active')).toBe(true); $timeout.flushNext(1000); } @@ -1288,18 +1316,18 @@ describe("ngAnimate", function() { it("should properly animate and parse CSS3 animations", inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'animation: some_animation 4s linear 1s 2 alternate;' + - vendorPrefix + 'animation: some_animation 4s linear 1s 2 alternate;'; + ss.addRule('.ng-enter', 'some_animation 4s linear 1s 2 alternate;' + + vendorPrefix + 'animation: some_animation 4s linear 1s 2 alternate'); + var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); + var child = $compile('
...
')($rootScope); $animate.enter(child, element); $timeout.flushNext(0); if($sniffer.transitions) { expect(child.hasClass('ng-enter')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(child.hasClass('ng-enter-active')).toBe(true); $timeout.flushNext(9000); } @@ -1313,11 +1341,11 @@ describe("ngAnimate", function() { $sniffer.animations = false; $sniffer.transitions = false; - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'animation: some_animation 4s linear 1s 2 alternate;' + - vendorPrefix + 'animation: some_animation 4s linear 1s 2 alternate;'; + ss.addRule('.ng-enter', 'some_animation 4s linear 1s 2 alternate;' + + vendorPrefix + 'animation: some_animation 4s linear 1s 2 alternate'); + var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); + var child = $compile('
...
')($rootScope); expect(child.hasClass('ng-enter')).toBe(false); $animate.enter(child, element); @@ -1336,11 +1364,12 @@ describe("ngAnimate", function() { }); }) inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 1s linear all;' + - vendorPrefix + 'transition: 1s linear all;'; + + ss.addRule('.ng-enter', 'transition: 1s linear all;' + + vendorPrefix + 'transition: 1s linear all'); + var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); + var child = $compile('
...
')($rootScope); expect(child.hasClass('i-was-animated')).toBe(false); @@ -1350,7 +1379,7 @@ describe("ngAnimate", function() { if($sniffer.transitions) { expect(child.hasClass('ng-enter')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); expect(child.hasClass('ng-enter-active')).toBe(true); } @@ -1378,27 +1407,28 @@ describe("ngAnimate", function() { } }); }); - inject(function($compile, $rootScope, $animate, $sniffer) { - }) inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 2s linear all;' + - vendorPrefix + 'transition: 2s linear all;'; + ss.addRule('.ng-enter', 'transition: 2s linear all;' + + vendorPrefix + 'transition: 2s linear all'); + ss.addRule('.ng-leave', 'transition: 2s linear all;' + + vendorPrefix + 'transition: 2s linear all'); + var element = html($compile('
...
')($rootScope)); - var child = $compile('
...
')($rootScope); + var child = $compile('
...
')($rootScope); $animate.enter(child, element); - $timeout.flushNext(0); //initial callback + $timeout.flushNext(0); //this is added/removed right away otherwise if($sniffer.transitions) { expect(child.hasClass('ng-enter')).toBe(true); - $timeout.flushNext(1); + $timeout.flushNext(0); } expect(child.hasClass('this-is-mine-now')).toBe(false); child.addClass('usurper'); $animate.leave(child); + $timeout.flushNext(0); expect(child.hasClass('ng-enter')).toBe(false); expect(child.hasClass('ng-enter-active')).toBe(false); @@ -1406,7 +1436,7 @@ describe("ngAnimate", function() { expect(child.hasClass('usurper')).toBe(true); expect(child.hasClass('this-is-mine-now')).toBe(true); if($sniffer.transitions) { - $timeout.flushNext(1); + $timeout.flushNext(0); } $timeout.flushNext(55); @@ -1425,10 +1455,12 @@ describe("ngAnimate", function() { it("should add and remove CSS classes and perform CSS animations during the process", inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 10s linear all;' + - vendorPrefix + 'transition: 10s linear all;'; - var element = html($compile('
')($rootScope)); + ss.addRule('.on-add', 'transition: 10s linear all; ' + + vendorPrefix + 'transition: 10s linear all'); + ss.addRule('.on-remove', 'transition: 10s linear all; ' + + vendorPrefix + 'transition: 10s linear all'); + + var element = html($compile('
')($rootScope)); expect(element.hasClass('on')).toBe(false); @@ -1477,10 +1509,13 @@ describe("ngAnimate", function() { }); }) inject(function($compile, $rootScope, $animate, $sniffer, $timeout) { - var vendorPrefix = '-' + $sniffer.vendorPrefix.toLowerCase() + '-'; - var style = 'transition: 5s linear all;' + - vendorPrefix + 'transition: 5s linear all;'; - var element = html($compile('
')($rootScope)); + + ss.addRule('.ng-hide-add', 'transition: 5s linear all;' + + vendorPrefix + 'transition: 5s linear all'); + ss.addRule('.ng-hide-remove', 'transition: 5s linear all;' + + vendorPrefix + 'transition: 5s linear all'); + + var element = html($compile('
')($rootScope)); element.addClass('displayer');