fix($timeout): make $flush handle new $timeouts added in $timeout callbacks

If a $timeout handler calls $timeout itself, this new $timeout should be
added to the mock deferred queue with a "now" time based on when the original
handler was triggered.

Previously it was being added with a now time of when the `$timeout.flush`
method was originally called.

Closes #5420
Closes #14686
This commit is contained in:
Lucas Galfasó
2013-12-15 21:00:57 -03:00
committed by Peter Bacon Darwin
parent de544807c2
commit d23c1453cd
2 changed files with 40 additions and 4 deletions
+13 -3
View File
@@ -106,19 +106,29 @@ angular.mock.$Browser = function() {
* @param {number=} number of milliseconds to flush. See {@link #defer.now}
*/
self.defer.flush = function(delay) {
var nextTime;
if (angular.isDefined(delay)) {
self.defer.now += delay;
// A delay was passed so compute the next time
nextTime = self.defer.now + delay;
} else {
if (self.deferredFns.length) {
self.defer.now = self.deferredFns[self.deferredFns.length - 1].time;
// No delay was passed so set the next time so that it clears the deferred queue
nextTime = self.deferredFns[self.deferredFns.length - 1].time;
} else {
// No delay passed, but there are no deferred tasks so flush - indicates an error!
throw new Error('No deferred tasks to be flushed');
}
}
while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) {
while (self.deferredFns.length && self.deferredFns[0].time <= nextTime) {
// Increment the time and call the next deferred function
self.defer.now = self.deferredFns[0].time;
self.deferredFns.shift().fn();
}
// Ensure that the current time is correct
self.defer.now = nextTime;
};
self.$$baseHref = '/';
+27 -1
View File
@@ -296,8 +296,10 @@ describe('ngMock', function() {
expect(counter).toBe(1);
$interval.flush(1000);
expect(counter).toBe(2);
$interval.flush(2000);
expect(counter).toBe(4);
}));
@@ -692,6 +694,30 @@ describe('ngMock', function() {
$timeout.flush(123);
expect(count).toBe(2);
}));
it('should resolve timeout functions following the timeline', inject(function($timeout) {
var count1 = 0, count2 = 0;
var iterate1 = function() {
count1++;
$timeout(iterate1, 100);
};
var iterate2 = function() {
count2++;
$timeout(iterate2, 150);
};
$timeout(iterate1, 100);
$timeout(iterate2, 150);
$timeout.flush(150);
expect(count1).toBe(1);
expect(count2).toBe(1);
$timeout.flush(50);
expect(count1).toBe(2);
expect(count2).toBe(1);
$timeout.flush(400);
expect(count1).toBe(6);
expect(count2).toBe(4);
}));
});