perf($animate): use rAF instead of timeouts to issue animation callbacks

This commit is contained in:
Matias Niemelä
2014-02-24 19:43:57 -05:00
parent 62761428ef
commit 4c4537e65e
7 changed files with 143 additions and 126 deletions

View File

@@ -81,7 +81,11 @@ var $AnimateProvider = ['$provide', function($provide) {
return this.$$classNameFilter;
};
this.$get = ['$timeout', function($timeout) {
this.$get = ['$timeout', '$$asyncCallback', function($timeout, $$asyncCallback) {
function async(fn) {
fn && $$asyncCallback(fn);
}
/**
*
@@ -126,7 +130,7 @@ var $AnimateProvider = ['$provide', function($provide) {
}
parent.append(element);
}
done && $timeout(done, 0, false);
async(done);
},
/**
@@ -142,7 +146,7 @@ var $AnimateProvider = ['$provide', function($provide) {
*/
leave : function(element, done) {
element.remove();
done && $timeout(done, 0, false);
async(done);
},
/**
@@ -189,7 +193,7 @@ var $AnimateProvider = ['$provide', function($provide) {
forEach(element, function (element) {
jqLiteAddClass(element, className);
});
done && $timeout(done, 0, false);
async(done);
},
/**
@@ -212,7 +216,7 @@ var $AnimateProvider = ['$provide', function($provide) {
forEach(element, function (element) {
jqLiteRemoveClass(element, className);
});
done && $timeout(done, 0, false);
async(done);
},
/**
@@ -234,7 +238,7 @@ var $AnimateProvider = ['$provide', function($provide) {
jqLiteAddClass(element, add);
jqLiteRemoveClass(element, remove);
});
done && $timeout(done, 0, false);
async(done);
},
enabled : noop

View File

@@ -247,42 +247,24 @@ angular.module('ngAnimate', ['ng'])
* Please visit the {@link ngAnimate `ngAnimate`} module overview page learn more about how to use animations in your application.
*
*/
.factory('$$animateReflow', ['$window', '$timeout', '$document',
function($window, $timeout, $document) {
var bod = $document[0].body;
var requestAnimationFrame = $window.requestAnimationFrame ||
$window.webkitRequestAnimationFrame ||
function(fn) {
return $timeout(fn, 10, false);
};
var cancelAnimationFrame = $window.cancelAnimationFrame ||
$window.webkitCancelAnimationFrame ||
function(timer) {
return $timeout.cancel(timer);
};
//this private service is only used within CSS-enabled animations
//IE8 + IE9 do not support rAF natively, but that is fine since they
//also don't support transitions and keyframes which means that the code
//below will never be used by the two browsers.
.factory('$$animateReflow', ['$$rAF', '$document', function($$rAF, $document) {
var bod = $document[0].body;
return function(fn) {
var id = requestAnimationFrame(function() {
//the returned function acts as the cancellation function
return $$rAF(function() {
//the line below will force the browser to perform a repaint
//so that all the animated elements within the animation frame
//will be properly updated and drawn on screen. This is
//required to perform multi-class CSS based animations with
//Firefox. DO NOT REMOVE THIS LINE.
var a = bod.offsetWidth + 1;
fn();
});
return function() {
cancelAnimationFrame(id);
};
};
}])
.factory('$$asyncQueueBuffer', ['$timeout', function($timeout) {
var timer, queue = [];
return function(fn) {
$timeout.cancel(timer);
queue.push(fn);
timer = $timeout(function() {
for(var i = 0; i < queue.length; i++) {
queue[i]();
}
queue = [];
}, 0, false);
};
}])
@@ -313,8 +295,8 @@ angular.module('ngAnimate', ['ng'])
return extractElementNode(elm1) == extractElementNode(elm2);
}
$provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncQueueBuffer', '$rootScope', '$document',
function($delegate, $injector, $sniffer, $rootElement, $$asyncQueueBuffer, $rootScope, $document) {
$provide.decorator('$animate', ['$delegate', '$injector', '$sniffer', '$rootElement', '$$asyncCallback', '$rootScope', '$document',
function($delegate, $injector, $sniffer, $rootElement, $$asyncCallback, $rootScope, $document) {
var globalAnimationCounter = 0;
$rootElement.data(NG_ANIMATE_STATE, rootAnimateState);
@@ -876,7 +858,7 @@ angular.module('ngAnimate', ['ng'])
function fireDOMCallback(animationPhase) {
var eventName = '$animate:' + animationPhase;
if(elementEvents && elementEvents[eventName] && elementEvents[eventName].length > 0) {
$$asyncQueueBuffer(function() {
$$asyncCallback(function() {
element.triggerHandler(eventName, {
event : animationEvent,
className : className
@@ -896,7 +878,7 @@ angular.module('ngAnimate', ['ng'])
function fireDoneCallbackAsync() {
fireDOMCallback('close');
if(doneCallback) {
$$asyncQueueBuffer(function() {
$$asyncCallback(function() {
doneCallback();
});
}
@@ -923,7 +905,7 @@ angular.module('ngAnimate', ['ng'])
if(isClassBased) {
cleanup(element, className);
} else {
$$asyncQueueBuffer(function() {
$$asyncCallback(function() {
var data = element.data(NG_ANIMATE_STATE) || {};
if(localAnimationCount == data.index) {
cleanup(element, className, animationEvent);

View File

@@ -757,21 +757,24 @@ angular.mock.TzDate.prototype = Date.prototype;
angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
.config(['$provide', function($provide) {
var reflowQueue = [];
var reflowQueue = [];
$provide.value('$$animateReflow', function(fn) {
var index = reflowQueue.length;
reflowQueue.push(fn);
return angular.noop;
return function cancel() {
reflowQueue.splice(index, 1);
};
});
$provide.decorator('$animate', function($delegate) {
$provide.decorator('$animate', function($delegate, $$asyncCallback) {
var animate = {
queue : [],
enabled : $delegate.enabled,
triggerCallbacks : function() {
$$asyncCallback.flush();
},
triggerReflow : function() {
if(reflowQueue.length === 0) {
throw new Error('No animation reflows present');
}
angular.forEach(reflowQueue, function(fn) {
fn();
});

View File

@@ -345,6 +345,7 @@ describe('ngClass animations', function() {
//mocks are not used since the enter delegation method is called before addClass and
//it makes it impossible to test to see that addClass is called first
module('ngAnimate');
module('ngAnimateMock');
var digestQueue = [];
module(function($animateProvider) {
@@ -367,7 +368,7 @@ describe('ngClass animations', function() {
};
};
});
inject(function($compile, $rootScope, $rootElement, $animate, $timeout, $document) {
inject(function($compile, $rootScope, $browser, $rootElement, $animate, $timeout, $document) {
// Enable animations by triggering the first item in the postDigest queue
digestQueue.shift()();
@@ -407,7 +408,7 @@ describe('ngClass animations', function() {
//is spaced-out then it is required so that the original digestion
//is kicked into gear
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(element.data('state')).toBe('crazy-enter');
expect(enterComplete).toBe(true);

View File

@@ -368,7 +368,7 @@ describe('ngInclude', function() {
expect(autoScrollSpy).not.toHaveBeenCalled();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).toHaveBeenCalledOnce();
}));
@@ -385,7 +385,7 @@ describe('ngInclude', function() {
});
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
$rootScope.$apply(function () {
$rootScope.tpl = 'another.html';
@@ -394,7 +394,7 @@ describe('ngInclude', function() {
expect($animate.queue.shift().event).toBe('leave');
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
$rootScope.$apply(function() {
$rootScope.tpl = 'template.html';
@@ -403,7 +403,7 @@ describe('ngInclude', function() {
expect($animate.queue.shift().event).toBe('leave');
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).toHaveBeenCalled();
expect(autoScrollSpy.callCount).toBe(3);
@@ -419,7 +419,7 @@ describe('ngInclude', function() {
});
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).not.toHaveBeenCalled();
}));
@@ -435,7 +435,7 @@ describe('ngInclude', function() {
});
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
$rootScope.$apply(function () {
$rootScope.tpl = 'template.html';
@@ -457,7 +457,7 @@ describe('ngInclude', function() {
$rootScope.$apply("tpl = 'template.html'");
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).toHaveBeenCalledOnce();
}));

View File

@@ -380,7 +380,7 @@ describe("ngAnimate", function() {
expect(child.attr('class')).toContain('ng-enter');
expect(child.attr('class')).toContain('ng-enter-active');
browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
$timeout.flush();
$animate.triggerCallbacks();
//move
element.append(after);
@@ -391,7 +391,7 @@ describe("ngAnimate", function() {
expect(child.attr('class')).toContain('ng-move');
expect(child.attr('class')).toContain('ng-move-active');
browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
$timeout.flush();
$animate.triggerCallbacks();
//hide
$animate.addClass(child, 'ng-hide');
@@ -537,7 +537,7 @@ describe("ngAnimate", function() {
$animate.triggerReflow();
browserTrigger(child,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
}
$timeout.flush();
$animate.triggerCallbacks();
expect(completed).toBe(true);
}));
@@ -782,7 +782,7 @@ describe("ngAnimate", function() {
$animate.enabled(true);
ss.addRule('.real-animation.ng-enter, .real-animation.ng-leave, .real-animation-fake.ng-enter, .real-animation-fake.ng-leave',
ss.addRule('.real-animation.ng-enter, .real-animation.ng-leave',
'-webkit-animation:1s my_animation;' +
'animation:1s my_animation;');
@@ -817,6 +817,9 @@ describe("ngAnimate", function() {
expect(elements[3].attr('style')).toMatch(/animation-delay: 0\.3\d*s/);
expect(elements[4].attr('style')).toMatch(/animation-delay: 0\.4\d*s/);
//final closing timeout
$timeout.flush();
for(var i = 0; i < 5; i++) {
dealoc(elements[i]);
var newScope = $rootScope.$new();
@@ -826,13 +829,9 @@ describe("ngAnimate", function() {
};
$rootScope.$digest();
var expectFailure = true;
try {
$animate.triggerReflow();
expectFailure = false;
} catch(e) {}
expect(expectFailure).toBe(true);
//this means no animations were triggered
$timeout.verifyNoPendingTasks();
expect(elements[0].attr('style')).toBeFalsy();
expect(elements[1].attr('style')).not.toMatch(/animation-delay: 0\.1\d*s/);
@@ -1117,14 +1116,7 @@ describe("ngAnimate", function() {
};
$rootScope.$digest();
var expectFailure = true;
try {
$animate.triggerReflow();
expectFailure = false;
} catch(e) {}
expect(expectFailure).toBe(true);
$animate.triggerReflow();
expect(elements[0].attr('style')).toBeFalsy();
expect(elements[1].attr('style')).not.toMatch(/transition-delay: 0\.1\d*s/);
@@ -1337,7 +1329,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('ng-enter')).toBe(true);
expect(element.hasClass('ng-enter-active')).toBe(true);
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 22000, elapsedTime: 22 });
$timeout.flush();
$animate.triggerCallbacks();
}
expect(element.hasClass('abc')).toBe(true);
@@ -1351,7 +1343,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('ng-enter')).toBe(true);
expect(element.hasClass('ng-enter-active')).toBe(true);
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 11000, elapsedTime: 11 });
$timeout.flush();
$animate.triggerCallbacks();
}
expect(element.hasClass('xyz')).toBe(true);
}));
@@ -1426,7 +1418,7 @@ describe("ngAnimate", function() {
});
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
}));
@@ -1446,7 +1438,7 @@ describe("ngAnimate", function() {
});
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
}));
@@ -1467,7 +1459,7 @@ describe("ngAnimate", function() {
});
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
expect(element.parent().id).toBe(parent2.id);
@@ -1493,7 +1485,7 @@ describe("ngAnimate", function() {
signature += 'B';
});
$timeout.flush();
$animate.triggerCallbacks();
expect(signature).toBe('AB');
}));
@@ -1529,17 +1521,19 @@ describe("ngAnimate", function() {
steps.push(['done', 'klass', 'addClass']);
});
$timeout.flush(1);
$animate.triggerCallbacks();
expect(steps.pop()).toEqual(['before', 'klass', 'addClass']);
$animate.triggerReflow();
$timeout.flush(1);
$animate.triggerCallbacks();
expect(steps.pop()).toEqual(['after', 'klass', 'addClass']);
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
$timeout.flush(1);
$animate.triggerCallbacks();
expect(steps.shift()).toEqual(['close', 'klass', 'addClass']);
@@ -1568,7 +1562,7 @@ describe("ngAnimate", function() {
$animate.enter(element, parent);
$rootScope.$digest();
$timeout.flush(1);
$animate.triggerCallbacks();
expect(steps.shift()).toEqual(['before', 'ng-enter', 'enter']);
expect(steps.shift()).toEqual(['after', 'ng-enter', 'enter']);
@@ -1602,7 +1596,7 @@ describe("ngAnimate", function() {
flag = true;
});
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
}));
@@ -1629,7 +1623,7 @@ describe("ngAnimate", function() {
$animate.triggerReflow();
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
}
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
}));
@@ -1648,7 +1642,7 @@ describe("ngAnimate", function() {
flag = true;
});
$timeout.flush();
$animate.triggerCallbacks();
expect(flag).toBe(true);
}));
@@ -1677,8 +1671,9 @@ describe("ngAnimate", function() {
$animate.addClass(element, 'ng-hide'); //earlier animation cancelled
if($sniffer.transitions) {
$animate.triggerReflow();
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 9 });
}
$timeout.flush();
$animate.triggerCallbacks();
expect(signature).toBe('AB');
}));
});
@@ -1707,7 +1702,7 @@ describe("ngAnimate", function() {
it("should not perform an animation, and the followup DOM operation, if the class is " +
"already present during addClass or not present during removeClass on the element",
inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout) {
inject(function($animate, $rootScope, $sniffer, $rootElement, $timeout, $browser) {
var element = jqLite('<div class="klassy"></div>');
$rootElement.append(element);
@@ -1781,7 +1776,7 @@ describe("ngAnimate", function() {
signature += 'B';
});
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('klass')).toBe(false);
expect(signature).toBe('AB');
}));
@@ -1813,7 +1808,8 @@ describe("ngAnimate", function() {
expect(element.hasClass('klass-add-active')).toBe(true);
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 3000, elapsedTime: 3 });
}
$timeout.flush();
$animate.triggerCallbacks();
//this cancels out the older animation
$animate.removeClass(element,'klass', function() {
@@ -1830,7 +1826,8 @@ describe("ngAnimate", function() {
browserTrigger(element,'transitionend', { timeStamp: Date.now() + 3000, elapsedTime: 3 });
}
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('klass')).toBe(false);
expect(signature).toBe('12');
@@ -1863,6 +1860,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('klassy')).toBe(false);
$animate.triggerCallbacks();
expect(signature).toBe('XY');
}));
@@ -1895,7 +1893,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('klass-add-active')).toBe(false);
}
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('klass')).toBe(true);
$animate.removeClass(element,'klass', function() {
@@ -1911,7 +1909,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('klass-remove-active')).toBe(false);
}
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('klass')).toBe(false);
expect(signature).toBe('db');
@@ -1951,7 +1949,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('two-add-active')).toBe(false);
}
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('one')).toBe(true);
expect(element.hasClass('two')).toBe(true);
@@ -1997,7 +1995,7 @@ describe("ngAnimate", function() {
expect(element.hasClass('two-remove-active')).toBe(false);
}
$timeout.flush();
$animate.triggerCallbacks();
expect(element.hasClass('one')).toBe(false);
expect(element.hasClass('two')).toBe(false);
@@ -2159,7 +2157,7 @@ describe("ngAnimate", function() {
child.addClass('usurper');
$animate.leave(child);
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(child.hasClass('ng-enter')).toBe(false);
expect(child.hasClass('ng-enter-active')).toBe(false);
@@ -2213,10 +2211,10 @@ describe("ngAnimate", function() {
// if($sniffer.transitions) {
// expect(element.hasClass('on')).toBe(false);
// expect(element.hasClass('on-add')).toBe(true);
// $timeout.flush();
// $animate.triggerCallbacks();
// }
//
// $timeout.flush();
// $animate.triggerCallbacks();
//
// expect(element.hasClass('on')).toBe(true);
// expect(element.hasClass('on-add')).toBe(false);
@@ -2229,7 +2227,7 @@ describe("ngAnimate", function() {
// $timeout.flush(10000);
// }
//
// $timeout.flush();
// $animate.triggerCallbacks();
// expect(element.hasClass('on')).toBe(false);
// expect(element.hasClass('on-remove')).toBe(false);
// expect(element.hasClass('on-remove-active')).toBe(false);
@@ -2272,11 +2270,11 @@ describe("ngAnimate", function() {
//
// if($sniffer.transitions) {
// expect(element).toBeShown(); //still showing
// $timeout.flush();
// $animate.triggerCallbacks();
// expect(element).toBeShown();
// $timeout.flush(5555);
// }
// $timeout.flush();
// $animate.triggerCallbacks();
// expect(element).toBeHidden();
//
// expect(element.hasClass('showing')).toBe(false);
@@ -2285,11 +2283,11 @@ describe("ngAnimate", function() {
//
// if($sniffer.transitions) {
// expect(element).toBeHidden();
// $timeout.flush();
// $animate.triggerCallbacks();
// expect(element).toBeHidden();
// $timeout.flush(5580);
// }
// $timeout.flush();
// $animate.triggerCallbacks();
// expect(element).toBeShown();
//
// expect(element.hasClass('showing')).toBe(true);
@@ -2484,7 +2482,7 @@ describe("ngAnimate", function() {
expect(animationState).toBe('enter-cancel');
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
$animate.addClass(child, 'something');
if($sniffer.transitions) {
@@ -2646,16 +2644,16 @@ describe("ngAnimate", function() {
expect(intercepted).toBe('move');
//flush the enter reflow
$timeout.flush();
//flush the POST enter callback
$animate.triggerCallbacks();
$animate.addClass(child2, 'testing');
expect(intercepted).toBe('move');
continueAnimation();
//flush the move reflow
$timeout.flush();
//flush the POST move callback
$animate.triggerCallbacks();
$animate.leave(child2);
$rootScope.$digest();
@@ -3100,7 +3098,7 @@ describe("ngAnimate", function() {
forEach(element.children(), function(kid) {
browserTrigger(kid, 'transitionend', { timeStamp: Date.now() + 1000, elapsedTime: 1 });
});
$timeout.flush();
$animate.triggerCallbacks();
$rootScope.items = [];
$rootScope.$digest();
@@ -3141,7 +3139,7 @@ describe("ngAnimate", function() {
});
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(captures['enter']).toBeUndefined();
expect(enterDone).toBe(true);
@@ -3152,8 +3150,9 @@ describe("ngAnimate", function() {
$animate.leave(element, function() {
leaveDone = true;
});
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
expect(captures['leave']).toBe(true);
expect(leaveDone).toBe(true);
@@ -3184,11 +3183,11 @@ describe("ngAnimate", function() {
$animate.triggerReflow();
browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 1 });
$timeout.flush(1);
expect(ready).toBe(false);
browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 5 });
$timeout.flush(1);
$animate.triggerReflow();
$animate.triggerCallbacks();
expect(ready).toBe(true);
ready = false;
@@ -3198,7 +3197,7 @@ describe("ngAnimate", function() {
$animate.triggerReflow();
browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 1 });
$timeout.flush(1);
$animate.triggerCallbacks();
expect(ready).toBe(true);
}));
@@ -3221,7 +3220,7 @@ describe("ngAnimate", function() {
ready = true;
});
$timeout.flush(1);
$animate.triggerCallbacks();
expect(ready).toBe(true);
}));
@@ -3248,14 +3247,42 @@ describe("ngAnimate", function() {
});
$animate.triggerReflow();
$timeout.flush(1);
$animate.triggerCallbacks();
expect(signature).toBe('A');
browserTrigger(element, 'transitionend', { timeStamp: Date.now(), elapsedTime: 2000 });
$timeout.flush(1);
$animate.triggerCallbacks();
expect(signature).toBe('AB');
}));
it('should cancel the previous reflow when new animations are added', function() {
var cancelReflowCallback = jasmine.createSpy('callback');
module(function($provide) {
$provide.value('$$animateReflow', function(fn) {
return cancelReflowCallback;
});
});
inject(function($animate, $sniffer, $rootScope, $compile) {
if (!$sniffer.transitions) return;
ss.addRule('.fly', '-webkit-transition:2s linear all;' +
'transition:2s linear all;');
$animate.enabled(true);
var element = $compile('<div class="fly"></div>')($rootScope);
$rootElement.append(element);
jqLite($document[0].body).append($rootElement);
expect(cancelReflowCallback).not.toHaveBeenCalled();
$animate.addClass(element, 'fast');
$animate.addClass(element, 'smooth');
$animate.triggerReflow();
expect(cancelReflowCallback).toHaveBeenCalled();
});
});
});
});

View File

@@ -707,7 +707,7 @@ describe('ngView animations', function() {
$location.path('/foo');
$rootScope.$digest();
$timeout.flush();
$animate.triggerCallbacks();
$location.path('/');
$rootScope.$digest();
@@ -872,7 +872,7 @@ describe('ngView animations', function() {
$location.path('/foo');
$rootScope.$digest();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).toHaveBeenCalledOnce();
}));
@@ -886,7 +886,7 @@ describe('ngView animations', function() {
$location.path('/foo');
$rootScope.$digest();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).toHaveBeenCalledOnce();
}));
@@ -899,7 +899,7 @@ describe('ngView animations', function() {
$location.path('/foo');
$rootScope.$digest();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).not.toHaveBeenCalled();
}));
@@ -913,7 +913,7 @@ describe('ngView animations', function() {
$location.path('/foo');
$rootScope.$digest();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect(autoScrollSpy).not.toHaveBeenCalled();
}));
@@ -930,7 +930,7 @@ describe('ngView animations', function() {
expect(autoScrollSpy).not.toHaveBeenCalled();
expect($animate.queue.shift().event).toBe('enter');
$timeout.flush();
$animate.triggerCallbacks();
expect($animate.enter).toHaveBeenCalledOnce();
expect(autoScrollSpy).toHaveBeenCalledOnce();