diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index c63b33d921f0..5ce3188f8a84 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -103,8 +103,11 @@ angular.mock.$Browser = function() { * Flushes all pending requests and executes the defer callbacks. * * @param {number=} number of milliseconds to flush. See {@link #defer.now} + * @param {boolean=} [atomic=false] If set to `true` — will handle only tasks + * available at the moment of execution, otherwise will process tasks that was + * added during execution as well. */ - self.defer.flush = function(delay) { + self.defer.flush = function(delay, atomic) { if (angular.isDefined(delay)) { self.defer.now += delay; } else { @@ -115,8 +118,25 @@ angular.mock.$Browser = function() { } } - while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { - self.deferredFns.shift().fn(); + function shiftExecutableFns(handler) { + while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { + handler(self.deferredFns.shift()); + } + } + + if (atomic) { + var fnsToRun = []; + shiftExecutableFns(function(task) { + fnsToRun.push(task); + }); + + angular.forEach(fnsToRun, function(item) { + item.fn(); + }); + } else { + shiftExecutableFns(function(task) { + task.fn(); + }); } }; @@ -1948,9 +1968,11 @@ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $ * Flushes the queue of pending tasks. * * @param {number=} delay maximum timeout amount to flush up until + * @param {boolean=} [atomic=false] If set to `true` — will not run the tasks + * added during execution of flash even if they added with `0` timeout. */ - $delegate.flush = function(delay) { - $browser.defer.flush(delay); + $delegate.flush = function(delay, atomic) { + $browser.defer.flush(delay, atomic); }; /** diff --git a/test/ngMock/angular-mocksSpec.js b/test/ngMock/angular-mocksSpec.js index 806b37036dcf..f042b64d2ceb 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -690,8 +690,41 @@ describe('ngMock', function() { $timeout.flush(123); expect(count).toBe(2); })); - }); + it('should process dynamically added tasks one per each flush,' + + ' if called in atomic mode', inject(function($timeout) { + + var task1 = jasmine.createSpy('first handler'); + var task2 = jasmine.createSpy('second handler'); + + $timeout(function() { + task1(); + $timeout(function() { + task2(); + }); + }); + + $timeout.flush(0, true); + expect(task1).toHaveBeenCalled(); + expect(task2).not.toHaveBeenCalled(); + + $timeout.flush(0); + expect(task2).toHaveBeenCalled(); + + })); + + it('should process dynamically added tasks by default', inject(function($timeout) { + var nestedTask = jasmine.createSpy('handler behind the nested timeouts'); + $timeout(function() { + $timeout(function() { + nestedTask(); + }); + }); + + $timeout.flush(0); + expect(nestedTask).toHaveBeenCalled(); + })); + }); describe('angular.mock.dump', function() { var d = angular.mock.dump;