diff options
| author | Misko Hevery | 2012-05-22 21:12:19 -0700 |
|---|---|---|
| committer | Misko Hevery | 2012-06-01 16:56:31 -0700 |
| commit | 885fb0dd0743859a8985c23e4d0c1855a2be711e (patch) | |
| tree | 96b03b26395d500c21e4044f7afb048c2a7cebe9 /test/ng/routeSpec.js | |
| parent | 4361efb03b79e71bf0cea92b94ff377ed718bad4 (diff) | |
| download | angular.js-885fb0dd0743859a8985c23e4d0c1855a2be711e.tar.bz2 | |
feat($route): resolve local route promises
Resolve all promises on route before we fire $afterRouteChange which then renders the ngView.
Diffstat (limited to 'test/ng/routeSpec.js')
| -rw-r--r-- | test/ng/routeSpec.js | 254 |
1 files changed, 241 insertions, 13 deletions
diff --git a/test/ng/routeSpec.js b/test/ng/routeSpec.js index b66cbb8e..3097d72d 100644 --- a/test/ng/routeSpec.js +++ b/test/ng/routeSpec.js @@ -1,6 +1,19 @@ 'use strict'; describe('$route', function() { + var $httpBackend; + + beforeEach(module(function() { + return function(_$httpBackend_) { + $httpBackend = _$httpBackend_; + $httpBackend.when('GET', 'Chapter.html').respond('chapter'); + $httpBackend.when('GET', 'test.html').respond('test'); + $httpBackend.when('GET', 'foo.html').respond('foo'); + $httpBackend.when('GET', 'baz.html').respond('baz'); + $httpBackend.when('GET', 'bar.html').respond('bar'); + $httpBackend.when('GET', '404.html').respond('not found'); + }; + })); it('should route and fire change event', function() { var log = '', @@ -28,6 +41,7 @@ describe('$route', function() { $location.path('/Book/Moby/Chapter/Intro').search('p=123'); $rootScope.$digest(); + $httpBackend.flush(); expect(log).toEqual('before();after();'); expect($route.current.params).toEqual({book:'Moby', chapter:'Intro', p:'123'}); @@ -165,27 +179,241 @@ describe('$route', function() { }); - it('should not fire $after/beforeRouteChange during bootstrap (if no route)', function() { - var routeChangeSpy = jasmine.createSpy('route change'); + describe('events', function() { + it('should not fire $after/beforeRouteChange during bootstrap (if no route)', function() { + var routeChangeSpy = jasmine.createSpy('route change'); - module(function($routeProvider) { - $routeProvider.when('/one', {}); // no otherwise defined + module(function($routeProvider) { + $routeProvider.when('/one', {}); // no otherwise defined + }); + + inject(function($rootScope, $route, $location) { + $rootScope.$on('$beforeRouteChange', routeChangeSpy); + $rootScope.$on('$afterRouteChange', routeChangeSpy); + + $rootScope.$digest(); + expect(routeChangeSpy).not.toHaveBeenCalled(); + + $location.path('/no-route-here'); + $rootScope.$digest(); + expect(routeChangeSpy).not.toHaveBeenCalled(); + }); }); - inject(function($rootScope, $route, $location) { - $rootScope.$on('$beforeRouteChange', routeChangeSpy); - $rootScope.$on('$afterRouteChange', routeChangeSpy); + it('should fire $beforeRouteChange and resolve promises', function() { + var deferA, + deferB; - $rootScope.$digest(); - expect(routeChangeSpy).not.toHaveBeenCalled(); + module(function($provide, $routeProvider) { + $provide.factory('b', function($q) { + deferB = $q.defer(); + return deferB.promise; + }); + $routeProvider.when('/path', { template: 'foo.html', resolve: { + a: function($q) { + deferA = $q.defer(); + return deferA.promise; + }, + b: 'b' + } }); + }); - $location.path('/no-route-here'); - $rootScope.$digest(); - expect(routeChangeSpy).not.toHaveBeenCalled(); + inject(function($location, $route, $rootScope, $httpBackend) { + var log = ''; + + $httpBackend.expectGET('foo.html').respond('FOO'); + + $location.path('/path'); + $rootScope.$digest(); + expect(log).toEqual(''); + $httpBackend.flush(); + expect(log).toEqual(''); + deferA.resolve(); + $rootScope.$digest(); + expect(log).toEqual(''); + deferB.resolve(); + $rootScope.$digest(); + expect($route.current.locals.$template).toEqual('FOO'); + }); }); - }); + it('should fire $routeChangeError event on resolution error', function() { + var deferA; + + module(function($provide, $routeProvider) { + $routeProvider.when('/path', { template: 'foo', resolve: { + a: function($q) { + deferA = $q.defer(); + return deferA.promise; + } + } }); + }); + + inject(function($location, $route, $rootScope) { + var log = ''; + + $rootScope.$on('$beforeRouteChange', function() { log += 'before();'; }); + $rootScope.$on('$routeChangeError', function(e, n, l, reason) { log += 'failed(' + reason + ');'; }); + + $location.path('/path'); + $rootScope.$digest(); + expect(log).toEqual('before();'); + + deferA.reject('MyError'); + $rootScope.$digest(); + expect(log).toEqual('before();failed(MyError);'); + }); + }); + + + it('should fetch templates', function() { + module(function($routeProvider) { + $routeProvider. + when('/r1', { template: 'r1.html' }). + when('/r2', { template: 'r2.html' }); + }); + + inject(function($route, $httpBackend, $location, $rootScope) { + var log = ''; + $rootScope.$on('$beforeRouteChange', function(e, next) { log += '$before(' + next.template + ');'}); + $rootScope.$on('$afterRouteChange', function(e, next) { log += '$after(' + next.template + ');'}); + + $httpBackend.expectGET('r1.html').respond('R1'); + $httpBackend.expectGET('r2.html').respond('R2'); + + $location.path('/r1'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);'); + + $location.path('/r2'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);$before(r2.html);'); + + $httpBackend.flush(); + expect(log).toBe('$before(r1.html);$before(r2.html);$after(r2.html);'); + expect(log).not.toContain('$after(r1.html);'); + }); + }); + + + it('should not update $routeParams until $afterRouteChange', function() { + module(function($routeProvider) { + $routeProvider. + when('/r1/:id', { template: 'r1.html' }). + when('/r2/:id', { template: 'r2.html' }); + }); + + inject(function($route, $httpBackend, $location, $rootScope, $routeParams) { + var log = ''; + $rootScope.$on('$beforeRouteChange', function(e, next) { log += '$before' + toJson($routeParams) + ';'}); + $rootScope.$on('$afterRouteChange', function(e, next) { log += '$after' + toJson($routeParams) + ';'}); + + $httpBackend.whenGET('r1.html').respond('R1'); + $httpBackend.whenGET('r2.html').respond('R2'); + + $location.path('/r1/1'); + $rootScope.$digest(); + expect(log).toBe('$before{};'); + $httpBackend.flush(); + expect(log).toBe('$before{};$after{"id":"1"};'); + + log = ''; + + $location.path('/r2/2'); + $rootScope.$digest(); + expect(log).toBe('$before{"id":"1"};'); + $httpBackend.flush(); + expect(log).toBe('$before{"id":"1"};$after{"id":"2"};'); + }); + }); + + + it('should drop in progress route change when new route change occurs', function() { + module(function($routeProvider) { + $routeProvider. + when('/r1', { template: 'r1.html' }). + when('/r2', { template: 'r2.html' }); + }); + + inject(function($route, $httpBackend, $location, $rootScope) { + var log = ''; + $rootScope.$on('$beforeRouteChange', function(e, next) { log += '$before(' + next.template + ');'}); + $rootScope.$on('$afterRouteChange', function(e, next) { log += '$after(' + next.template + ');'}); + + $httpBackend.expectGET('r1.html').respond('R1'); + $httpBackend.expectGET('r2.html').respond('R2'); + + $location.path('/r1'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);'); + + $location.path('/r2'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);$before(r2.html);'); + + $httpBackend.flush(); + expect(log).toBe('$before(r1.html);$before(r2.html);$after(r2.html);'); + expect(log).not.toContain('$after(r1.html);'); + }); + }); + + + it('should drop in progress route change when new route change occurs and old fails', function() { + module(function($routeProvider) { + $routeProvider. + when('/r1', { templateUrl: 'r1.html' }). + when('/r2', { templateUrl: 'r2.html' }); + }); + + inject(function($route, $httpBackend, $location, $rootScope) { + var log = ''; + $rootScope.$on('$routeChangeError', function(e, next, last, error) { + log += '$failed(' + next.templateUrl + ', ' + error.status + ');'; + }); + $rootScope.$on('$beforeRouteChange', function(e, next) { log += '$before(' + next.templateUrl + ');'}); + $rootScope.$on('$afterRouteChange', function(e, next) { log += '$after(' + next.templateUrl + ');'}); + + $httpBackend.expectGET('r1.html').respond(404, 'R1'); + $httpBackend.expectGET('r2.html').respond('R2'); + + $location.path('/r1'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);'); + + $location.path('/r2'); + $rootScope.$digest(); + expect(log).toBe('$before(r1.html);$before(r2.html);'); + + $httpBackend.flush(); + expect(log).toBe('$before(r1.html);$before(r2.html);$after(r2.html);'); + expect(log).not.toContain('$after(r1.html);'); + }); + }); + + + it('should catch local factory errors', function() { + var myError = new Error('MyError'); + module(function($routeProvider, $exceptionHandlerProvider) { + $exceptionHandlerProvider.mode('log'); + $routeProvider.when('/locals', { + resolve: { + a: function($q) { + throw myError; + } + } + }); + }); + + inject(function($location, $route, $rootScope, $exceptionHandler) { + $location.path('/locals'); + $rootScope.$digest(); + expect($exceptionHandler.errors).toEqual([myError]); + }); + }); + }); + + it('should match route with and without trailing slash', function() { module(function($routeProvider){ $routeProvider.when('/foo', {template: 'foo.html'}); |
