AnimateRunner adds to the $timeout queue when the document is hidden but does not flush the queue #16048
Description
openedon Jun 12, 2017
I'm submitting a ...
- bug report
- feature request
- other (Please do not submit support requests here (see above))
Current behavior:
AnimateRunner in https://github.com/angular/angular.js/blob/07849779ba365f371a8caa3b58e23f677cfdc5ad/src/ng/animateRunner.js runs timeoutTick
(line 89) or rafTick
(line 91), depending on whether or not the document is hidden. If the document is not hidden, rafTick will be executed and its queue will be flushed. However, in the case where the document is hidden, $timeout will be used and a pending task will be added to the $timeout queue. This pending task is never flushed which can lead to bugs when using $timeout.verifyNoPendingTasks in tests.
Expected / new behavior:
When the document is hidden (such as when using jsdom
) the $timeout queue needs to be flushed.
Minimal reproduction of the problem with instructions:
https://plnkr.co/edit/617KlYg237TkWKDOtECG
We are using jest (and jsdom) for testing. Jsdom sets document.hidden to true for the duration of all tests (see 8.3.0 of https://github.com/tmpvar/jsdom/blob/master/Changelog.md). This plunker is a simple directive that will show or hide (using ng-if) based on a mouse event. I copied $$AnimateRunnerFactoryProvider from the source and used $provide.provider to overwrite the existing functionality. Since I can't import jsdom in plunker, I forced timeoutTick
to be called instead of rafTick
:
function AnimateRunner(host) {
this.setHost(host);
var rafTick = $$animateAsyncRun();
var timeoutTick = function(fn) {
$timeout(fn, 0, false);
};
this._doneCallbacks = [];
this._tick = function(fn) {
timeoutTick(fn);
// if ($$isDocumentHidden()) {
// timeoutTick(fn);
// } else {
// rafTick(fn);
// }
};
this._state = 0;
}
The test in the plunker shows that there is a pending entry in $timeout. We should not have to clear this pending entry in our tests.
Angular version: 1.x.y
The plunker is using angular@1.6.4.
Browser: [all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView ]
This will occur if document.hidden is true. It is not browser specific.
Anything else:
The pending entry in the timeout needs to be cleared. We should be able to update $$AnimateRunnerFactory to do this similar to how the raf queue is being cleaned up.