diff options
| author | Igor Minar | 2013-08-22 02:08:41 -0700 | 
|---|---|---|
| committer | Igor Minar | 2013-08-26 09:06:25 -0700 | 
| commit | 6b91aa0a18098100e5f50ea911ee135b50680d67 (patch) | |
| tree | 636d84df13da7afa31b6ac9d3db45dc00e78c2d4 /test/ng/rootScopeSpec.js | |
| parent | 42af8eada2803a54a98b4f792e60feb480d68a0c (diff) | |
| download | angular.js-6b91aa0a18098100e5f50ea911ee135b50680d67.tar.bz2 | |
feat(Scope): async auto-flush $evalAsync queue when outside of $digest
This change causes a new $digest to be scheduled in the next tick if
a task was was sent to the $evalAsync queue from outside of a $digest
or an $apply.
While this mode of operation is not common for most of the user code,
this change means that $q promises that utilze $evalAsync queue to
guarantee asynchronicity of promise apis will now also resolve outside
of a $digest, which turned out to be a big pain point for some developers.
The implementation ensures that we don't do more work than needed and
that we coalese as much work as possible into a single $digest.
The use of $browser instead of setTimeout ensures that we can mock out
and control the scheduling of "auto-flush", which should in theory
allow all of the existing code and tests to work without negative
side-effects.
Closes #3539
Closes #2438
Diffstat (limited to 'test/ng/rootScopeSpec.js')
| -rw-r--r-- | test/ng/rootScopeSpec.js | 51 | 
1 files changed, 51 insertions, 0 deletions
| diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index ddd83088..0a85d9a8 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -705,6 +705,57 @@ describe('Scope', function() {        expect(isolateScope.$$asyncQueue).toBe($rootScope.$$asyncQueue);        expect($rootScope.$$asyncQueue).toEqual(['rootExpression', 'childExpression', 'isolateExpression']);      })); + + +    describe('auto-flushing when queueing outside of an $apply', function() { +      var log, $rootScope, $browser; + +      beforeEach(inject(function(_log_, _$rootScope_, _$browser_) { +        log = _log_; +        $rootScope = _$rootScope_; +        $browser = _$browser_; +      })); + + +      it('should auto-flush the queue asynchronously and trigger digest', function() { +        $rootScope.$evalAsync(log.fn('eval-ed!')); +        $rootScope.$watch(log.fn('digesting')); +        expect(log).toEqual([]); + +        $browser.defer.flush(0); + +        expect(log).toEqual(['eval-ed!', 'digesting', 'digesting']); +      }); + + +      it('should not trigger digest asynchronously if the queue is empty in the next tick', function() { +        $rootScope.$evalAsync(log.fn('eval-ed!')); +        $rootScope.$watch(log.fn('digesting')); +        expect(log).toEqual([]); + +        $rootScope.$digest(); + +        expect(log).toEqual(['eval-ed!', 'digesting', 'digesting']); +        log.reset(); + +        $browser.defer.flush(0); + +        expect(log).toEqual([]); +      }); + + +      it('should not schedule more than one auto-flush task', function() { +        $rootScope.$evalAsync(log.fn('eval-ed 1!')); +        $rootScope.$evalAsync(log.fn('eval-ed 2!')); + +        $browser.defer.flush(0); +        expect(log).toEqual(['eval-ed 1!', 'eval-ed 2!']); + +        expect(function() { +          $browser.defer.flush(0); +        }).toThrow('No deferred tasks with delay up to 0ms to be flushed!'); +      }); +    });    }); | 
