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 | |
| 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')
| -rw-r--r-- | test/ng/directive/ngViewSpec.js | 22 | ||||
| -rw-r--r-- | test/ng/routeSpec.js | 254 | 
2 files changed, 243 insertions, 33 deletions
diff --git a/test/ng/directive/ngViewSpec.js b/test/ng/directive/ngViewSpec.js index 00fc6827..7524884f 100644 --- a/test/ng/directive/ngViewSpec.js +++ b/test/ng/directive/ngViewSpec.js @@ -229,24 +229,6 @@ describe('ngView', function() {    }); -  it('should clear the content when error during xhr request', function() { -    module(function($routeProvider) { -      $routeProvider.when('/foo', {controller: noop, template: 'myUrl1'}); -    }); - -    inject(function($route, $location, $rootScope, $httpBackend) { -      $location.path('/foo'); -      $httpBackend.expect('GET', 'myUrl1').respond(404, ''); -      element.text('content'); - -      $rootScope.$digest(); -      $httpBackend.flush(); - -      expect(element.text()).toBe(''); -    }); -  }); - -    it('should be async even if served from cache', function() {      module(function($routeProvider) {        $routeProvider.when('/foo', {controller: noop, template: 'myUrl1'}); @@ -293,8 +275,8 @@ describe('ngView', function() {        $rootScope.$digest();        expect(element.text()).toBe('bound-value'); -      expect(log).toEqual(['$beforeRouteChange', '$afterRouteChange', 'init-ctrl', -                           '$viewContentLoaded']); +      expect(log).toEqual([ +        '$beforeRouteChange', 'init-ctrl', '$viewContentLoaded', '$afterRouteChange' ]);      });    }); 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'});  | 
