Permalink
Browse files
fix($timeout): make $flush handle new $timeouts added in $timeout cal…
…lbacks
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
Loading branch information
Showing
2 changed files
with
40 additions
and
4 deletions .
+13
−3
src/ngMock/angular-mocks.js
+27
−1
test/ngMock/angular-mocksSpec.js
@@ -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 = '/' ;
@@ -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 ) ;
} ) ) ;
} ) ;
Toggle all file notes