From 8e690fcbb8215864bb0055e35df748c27cf10d67 Mon Sep 17 00:00:00 2001 From: elkeis Date: Tue, 27 Oct 2015 23:21:31 +0300 Subject: [PATCH 1/2] feat(ngMock) add atomic flushing strategy for $timeout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add flag to `$timeout.flush()` function. If set to `true` — will handle only the tasks available at the moment of execution, otherwise will process the tasks that were added during execution as well (`false` by default). --- src/ngMock/angular-mocks.js | 32 +++++++++++++++++++++++++----- test/ngMock/angular-mocksSpec.js | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 5 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index c63b33d921f..5ce3188f8a8 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 806b37036dc..58fd494fab1 100644 --- a/test/ngMock/angular-mocksSpec.js +++ b/test/ngMock/angular-mocksSpec.js @@ -690,6 +690,40 @@ 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(); + })); }); From 3ae06eea3d565d6f5471b3e8152e479ff873683f Mon Sep 17 00:00:00 2001 From: elkeis Date: Thu, 12 Nov 2015 17:32:23 +0300 Subject: [PATCH 2/2] docs(ngMock) fix spelling and typo --- src/ngMock/angular-mocks.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ngMock/angular-mocks.js b/src/ngMock/angular-mocks.js index 5ce3188f8a8..d6be3ee1aa1 100644 --- a/src/ngMock/angular-mocks.js +++ b/src/ngMock/angular-mocks.js @@ -104,7 +104,7 @@ angular.mock.$Browser = function() { * * @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 + * available at the moment of execution, otherwise will process tasks that were * added during execution as well. */ self.defer.flush = function(delay, atomic) { @@ -1969,7 +1969,7 @@ angular.mock.$TimeoutDecorator = ['$delegate', '$browser', function($delegate, $ * * @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. + * added during execution of flush even if they were added with `0` timeout. */ $delegate.flush = function(delay, atomic) { $browser.defer.flush(delay, atomic);