Skip to content
Permalink
Browse files

fix(ngAnimate): ensure that animate promises resolve when the documen…

…t is hidden

Prior to this fix any promise/callback chained on a call to the $animate
methods would only flush if and when the browser page is visible. This
fix ensures that a timeout will be used instead when the document
is hidden.
  • Loading branch information...
matsko authored and Narretz committed Jan 15, 2016
1 parent a3a7afd commit 52ea4110d33b7de2845a698913682a03365aa074
Showing with 52 additions and 4 deletions.
  1. +15 −4 src/ng/animateRunner.js
  2. +37 −0 test/ng/animateRunnerSpec.js
@@ -28,8 +28,8 @@ var $$AnimateAsyncRunFactoryProvider = function() {
};

var $$AnimateRunnerFactoryProvider = function() {
this.$get = ['$q', '$sniffer', '$$animateAsyncRun',
function($q, $sniffer, $$animateAsyncRun) {
this.$get = ['$q', '$sniffer', '$$animateAsyncRun', '$document', '$timeout',
function($q, $sniffer, $$animateAsyncRun, $document, $timeout) {

var INITIAL_STATE = 0;
var DONE_PENDING_STATE = 1;
@@ -74,8 +74,19 @@ var $$AnimateRunnerFactoryProvider = function() {
function AnimateRunner(host) {
this.setHost(host);

var rafTick = $$animateAsyncRun();
var timeoutTick = function(fn) {
$timeout(fn, 0, false);
};

this._doneCallbacks = [];
this._runInAnimationFrame = $$animateAsyncRun();
this._tick = function(fn) {
if ($document[0].hidden) {
timeoutTick(fn);
} else {
rafTick(fn);
}
};
this._state = 0;
}

@@ -148,7 +159,7 @@ var $$AnimateRunnerFactoryProvider = function() {
var self = this;
if (self._state === INITIAL_STATE) {
self._state = DONE_PENDING_STATE;
self._runInAnimationFrame(function() {
self._tick(function() {
self._resolve(response);
});
}
@@ -162,6 +162,43 @@ describe("$$AnimateRunner", function() {
expect(animationFailed).toBe(true);
}));

it("should use timeouts to trigger async operations when the document is hidden", function() {
var doc;

module(function($provide) {
doc = jqLite({
body: document.body,
hidden: true
});
$provide.value('$document', doc);
});

inject(function($$AnimateRunner, $rootScope, $$rAF, $timeout) {
var spy = jasmine.createSpy();
var runner = new $$AnimateRunner();
runner.done(spy);
runner.complete(true);
expect(spy).not.toHaveBeenCalled();
$$rAF.flush();
expect(spy).not.toHaveBeenCalled();
$timeout.flush();
expect(spy).toHaveBeenCalled();

doc[0].hidden = false;

spy = jasmine.createSpy();
runner = new $$AnimateRunner();
runner.done(spy);
runner.complete(true);
expect(spy).not.toHaveBeenCalled();
$$rAF.flush();
expect(spy).toHaveBeenCalled();
expect(function() {
$timeout.flush();
}).toThrow();
});
});

they("should expose the `finally` promise function to handle the final state when $prop",
{ 'rejected': 'cancel', 'resolved': 'end' }, function(method) {
inject(function($$AnimateRunner, $rootScope) {

0 comments on commit 52ea411

Please sign in to comment.
You can’t perform that action at this time.