示例#1
0
  describe('redirects', () => {

    var tcb: TestComponentBuilder;
    var rootTC: ComponentFixture<any>;
    var rtr: any /** TODO #9100 */;

    beforeEachProviders(() => TEST_ROUTER_PROVIDERS);

    beforeEach(inject(
        [TestComponentBuilder, Router],
        (tcBuilder: any /** TODO #9100 */, router: any /** TODO #9100 */) => {
          tcb = tcBuilder;
          rtr = router;
          childCmpInstanceCount = 0;
          cmpInstanceCount = 0;
        }));


    it('should apply when navigating by URL',
       inject(
           [AsyncTestCompleter, Location],
           (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
             compile(tcb)
                 .then((rtc) => { rootTC = rtc; })
                 .then((_) => rtr.config([
                   new Redirect({path: '/original', redirectTo: ['Hello']}),
                   new Route({path: '/redirected', component: HelloCmp, name: 'Hello'})
                 ]))
                 .then((_) => rtr.navigateByUrl('/original'))
                 .then((_) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement).toHaveText('hello');
                   expect(location.urlChanges).toEqual(['/redirected']);
                   async.done();
                 });
           }));


    it('should recognize and apply absolute redirects',
       inject(
           [AsyncTestCompleter, Location],
           (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
             compile(tcb)
                 .then((rtc) => { rootTC = rtc; })
                 .then((_) => rtr.config([
                   new Redirect({path: '/original', redirectTo: ['/Hello']}),
                   new Route({path: '/redirected', component: HelloCmp, name: 'Hello'})
                 ]))
                 .then((_) => rtr.navigateByUrl('/original'))
                 .then((_) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement).toHaveText('hello');
                   expect(location.urlChanges).toEqual(['/redirected']);
                   async.done();
                 });
           }));


    it('should recognize and apply relative child redirects',
       inject(
           [AsyncTestCompleter, Location],
           (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
             compile(tcb)
                 .then((rtc) => { rootTC = rtc; })
                 .then((_) => rtr.config([
                   new Redirect({path: '/original', redirectTo: ['./Hello']}),
                   new Route({path: '/redirected', component: HelloCmp, name: 'Hello'})
                 ]))
                 .then((_) => rtr.navigateByUrl('/original'))
                 .then((_) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement).toHaveText('hello');
                   expect(location.urlChanges).toEqual(['/redirected']);
                   async.done();
                 });
           }));


    it('should recognize and apply relative parent redirects',
       inject(
           [AsyncTestCompleter, Location],
           (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
             compile(tcb)
                 .then((rtc) => { rootTC = rtc; })
                 .then((_) => rtr.config([
                   new Route({path: '/original/...', component: RedirectToParentCmp}),
                   new Route({path: '/redirected', component: HelloCmp, name: 'HelloSib'})
                 ]))
                 .then((_) => rtr.navigateByUrl('/original/child-redirect'))
                 .then((_) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement).toHaveText('hello');
                   expect(location.urlChanges).toEqual(['/redirected']);
                   async.done();
                 });
           }));


    it('should not redirect when redirect is less specific than other matching routes',
       inject(
           [AsyncTestCompleter, Location],
           (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
             compile(tcb)
                 .then((rtc) => { rootTC = rtc; })
                 .then((_) => rtr.config([
                   new Route({path: '/foo', component: HelloCmp, name: 'Hello'}),
                   new Route({path: '/:param', component: GoodbyeCmp, name: 'Goodbye'}),
                   new Redirect({path: '/*rest', redirectTo: ['/Hello']})
                 ]))
                 .then((_) => rtr.navigateByUrl('/bye'))
                 .then((_) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement).toHaveText('goodbye');
                   expect(location.urlChanges).toEqual(['/bye']);
                   async.done();
                 });
           }));
  });
示例#2
0
  describe('CompileMetadataResolver', () => {
    beforeEachProviders(() => TEST_PROVIDERS);

    describe('getMetadata', () => {
      it('should read metadata',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           var meta = resolver.getDirectiveMetadata(ComponentWithEverything);
           expect(meta.selector).toEqual('someSelector');
           expect(meta.exportAs).toEqual('someExportAs');
           expect(meta.isComponent).toBe(true);
           expect(meta.type.runtime).toBe(ComponentWithEverything);
           expect(meta.type.name).toEqual(stringify(ComponentWithEverything));
           expect(meta.lifecycleHooks).toEqual(LIFECYCLE_HOOKS_VALUES);
           expect(meta.changeDetection).toBe(ChangeDetectionStrategy.CheckAlways);
           expect(meta.inputs).toEqual({'someProp': 'someProp'});
           expect(meta.outputs).toEqual({'someEvent': 'someEvent'});
           expect(meta.hostListeners).toEqual({'someHostListener': 'someHostListenerExpr'});
           expect(meta.hostProperties).toEqual({'someHostProp': 'someHostPropExpr'});
           expect(meta.hostAttributes).toEqual({'someHostAttr': 'someHostAttrValue'});
           expect(meta.template.encapsulation).toBe(ViewEncapsulation.Emulated);
           expect(meta.template.styles).toEqual(['someStyle']);
           expect(meta.template.styleUrls).toEqual(['someStyleUrl']);
           expect(meta.template.template).toEqual('someTemplate');
           expect(meta.template.templateUrl).toEqual('someTemplateUrl');
           expect(meta.template.interpolation).toEqual(['{{', '}}']);
         }));

      it('should use the moduleUrl from the reflector if none is given',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           var value: string =
               resolver.getDirectiveMetadata(ComponentWithoutModuleId).type.moduleUrl;
           var expectedEndValue =
               IS_DART ? 'test/compiler/metadata_resolver_spec.dart' : './ComponentWithoutModuleId';
           expect(value.endsWith(expectedEndValue)).toBe(true);
         }));

      it('should throw when metadata is incorrectly typed',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(MalformedStylesComponent))
               .toThrowError(`Expected 'styles' to be an array of strings.`);
         }));

      it('should throw with descriptive error message when provider token can not be resolved',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(MyBrokenComp1))
               .toThrowError(`Can't resolve all parameters for MyBrokenComp1: (?).`);
         }));

      it('should throw with descriptive error message when a param token of a dependency is undefined',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(MyBrokenComp2))
               .toThrowError(`Can't resolve all parameters for NonAnnotatedService: (?).`);
         }));

      it('should throw with descriptive error message when one of providers is not present',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(MyBrokenComp3))
               .toThrowError(
                   `One or more of providers for "MyBrokenComp3" were not defined: [?, SimpleService, ?].`);
         }));

      it('should throw with descriptive error message when one of viewProviders is not present',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(MyBrokenComp4))
               .toThrowError(
                   `One or more of viewProviders for "MyBrokenComp4" were not defined: [?, SimpleService, ?].`);
         }));

      it('should throw an error when the interpolation config has invalid symbols',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(() => resolver.getDirectiveMetadata(ComponentWithInvalidInterpolation1))
               .toThrowError(`[' ', ' '] contains unusable interpolation symbol.`);
           expect(() => resolver.getDirectiveMetadata(ComponentWithInvalidInterpolation2))
               .toThrowError(`['{', '}'] contains unusable interpolation symbol.`);
           expect(() => resolver.getDirectiveMetadata(ComponentWithInvalidInterpolation3))
               .toThrowError(`['<%', '%>'] contains unusable interpolation symbol.`);
           expect(() => resolver.getDirectiveMetadata(ComponentWithInvalidInterpolation4))
               .toThrowError(`['&#', '}}'] contains unusable interpolation symbol.`);
           expect(() => resolver.getDirectiveMetadata(ComponentWithInvalidInterpolation5))
               .toThrowError(`['&lbrace;', '}}'] contains unusable interpolation symbol.`);
         }));
    });

    describe('getViewDirectivesMetadata', () => {

      it('should return the directive metadatas',
         inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
           expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
               .toContain(resolver.getDirectiveMetadata(SomeDirective));
         }));

      describe('platform directives', () => {
        beforeEachProviders(() => [{
                              provide: CompilerConfig,
                              useValue: new CompilerConfig(
                                  {genDebugInfo: true, platformDirectives: [ADirective]})
                            }]);

        it('should include platform directives when available',
           inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
             expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
                 .toContain(resolver.getDirectiveMetadata(ADirective));
             expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
                 .toContain(resolver.getDirectiveMetadata(SomeDirective));
           }));
      });
    });

  });
 describe('jit', () => {
   beforeEachProviders(
       () => [provide(CompilerConfig, {useValue: new CompilerConfig(true, false, true)})]);
   declareTests(true);
 });
示例#4
0
  describe('router bootstrap', () => {
    beforeEachProviders(() => [
      ROUTER_PROVIDERS,
      provide(LocationStrategy, {useClass: MockLocationStrategy}),
      provide(ApplicationRef, {useClass: MockApplicationRef})
    ]);

    // do not refactor out the `bootstrap` functionality. We still want to
    // keep this test around so we can ensure that bootstrap a router works
    it('should bootstrap a simple app', inject([AsyncTestCompleter], (async) => {
         var fakeDoc = getDOM().createHtmlDocument();
         var el = getDOM().createElement('app-cmp', fakeDoc);
         getDOM().appendChild(fakeDoc.body, el);

         bootstrap(AppCmp,
                   [
                     ROUTER_PROVIDERS,
                     provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppCmp}),
                     provide(LocationStrategy, {useClass: MockLocationStrategy}),
                     provide(DOCUMENT, {useValue: fakeDoc}),
                     provide(Console, {useClass: DummyConsole})
                   ])
             .then((applicationRef) => {
               var router = applicationRef.instance.router;
               router.subscribe((_) => {
                 expect(el).toHaveText('outer { hello }');
                 expect(applicationRef.instance.location.path()).toEqual('');
                 async.done();
               });
             });
       }));

    describe('broken app', () => {
      beforeEachProviders(() => [provide(ROUTER_PRIMARY_COMPONENT, {useValue: BrokenAppCmp})]);

      it('should rethrow exceptions from component constructors',
         inject([AsyncTestCompleter, TestComponentBuilder], (async, tcb: TestComponentBuilder) => {
           tcb.createAsync(AppCmp).then((fixture) => {
             var router = fixture.debugElement.componentInstance.router;
             PromiseWrapper.catchError(router.navigateByUrl('/cause-error'), (error) => {
               expect(error).toContainError('oops!');
               async.done();
             });
           });
         }));
    });

    describe('back button app', () => {
      beforeEachProviders(() => [provide(ROUTER_PRIMARY_COMPONENT, {useValue: HierarchyAppCmp})]);

      it('should change the url without pushing a new history state for back navigations',
         inject([AsyncTestCompleter, TestComponentBuilder], (async, tcb: TestComponentBuilder) => {

           tcb.createAsync(HierarchyAppCmp)
               .then((fixture) => {
                 var router = fixture.debugElement.componentInstance.router;
                 var position = 0;
                 var flipped = false;
                 var history = [
                   ['/parent/child', 'root { parent { hello } }', '/super-parent/child'],
                   ['/super-parent/child', 'root { super-parent { hello2 } }', '/parent/child'],
                   ['/parent/child', 'root { parent { hello } }', false]
                 ];

                 router.subscribe((_) => {
                   var location = fixture.debugElement.componentInstance.location;
                   var element = fixture.debugElement.nativeElement;
                   var path = location.path();

                   var entry = history[position];

                   expect(path).toEqual(entry[0]);
                   expect(element).toHaveText(entry[1]);

                   var nextUrl = entry[2];
                   if (nextUrl == false) {
                     flipped = true;
                   }

                   if (flipped && position == 0) {
                     async.done();
                     return;
                   }

                   position = position + (flipped ? -1 : 1);
                   if (flipped) {
                     location.back();
                   } else {
                     router.navigateByUrl(nextUrl);
                   }
                 });

                 router.navigateByUrl(history[0][0]);
               });
         }), 1000);
    });

    describe('hierarchical app', () => {
      beforeEachProviders(
          () => { return [provide(ROUTER_PRIMARY_COMPONENT, {useValue: HierarchyAppCmp})]; });

      it('should bootstrap an app with a hierarchy',
         inject([AsyncTestCompleter, TestComponentBuilder], (async, tcb: TestComponentBuilder) => {

           tcb.createAsync(HierarchyAppCmp)
               .then((fixture) => {
                 var router = fixture.debugElement.componentInstance.router;
                 router.subscribe((_) => {
                   expect(fixture.debugElement.nativeElement)
                       .toHaveText('root { parent { hello } }');
                   expect(fixture.debugElement.componentInstance.location.path())
                       .toEqual('/parent/child');
                   async.done();
                 });
                 router.navigateByUrl('/parent/child');
               });
         }));

      // TODO(btford): mock out level lower than LocationStrategy once that level exists
      xdescribe('custom app base ref', () => {
        beforeEachProviders(() => { return [provide(APP_BASE_HREF, {useValue: '/my/app'})]; });
        it('should bootstrap',
           inject([AsyncTestCompleter, TestComponentBuilder],
                  (async, tcb: TestComponentBuilder) => {

                    tcb.createAsync(HierarchyAppCmp)
                        .then((fixture) => {
                          var router = fixture.debugElement.componentInstance.router;
                          router.subscribe((_) => {
                            expect(fixture.debugElement.nativeElement)
                                .toHaveText('root { parent { hello } }');
                            expect(fixture.debugElement.componentInstance.location.path())
                                .toEqual('/my/app/parent/child');
                            async.done();
                          });
                          router.navigateByUrl('/parent/child');
                        });
                  }));
      });
    });


    describe('querystring params app', () => {
      beforeEachProviders(
          () => { return [provide(ROUTER_PRIMARY_COMPONENT, {useValue: QueryStringAppCmp})]; });

      it('should recognize and return querystring params with the injected RouteParams',
         inject([AsyncTestCompleter, TestComponentBuilder], (async, tcb: TestComponentBuilder) => {
           tcb.createAsync(QueryStringAppCmp)
               .then((fixture) => {
                 var router = fixture.debugElement.componentInstance.router;
                 router.subscribe((_) => {
                   fixture.detectChanges();

                   expect(fixture.debugElement.nativeElement)
                       .toHaveText('qParam = search-for-something');
                   /*
                   expect(applicationRef.hostComponent.location.path())
                       .toEqual('/qs?q=search-for-something');*/
                   async.done();
                 });
                 router.navigateByUrl('/qs?q=search-for-something');
                 fixture.detectChanges();
               });
         }));
    });

    describe('activate event on outlet', () => {
      let tcb: TestComponentBuilder = null;

      beforeEachProviders(() => [provide(ROUTER_PRIMARY_COMPONENT, {useValue: AppCmp})]);

      beforeEach(inject([TestComponentBuilder],
                        (testComponentBuilder) => { tcb = testComponentBuilder; }));

      it('should get a reference and pass data to components loaded inside of outlets',
         inject([AsyncTestCompleter], (async) => {
           tcb.createAsync(AppWithOutletListeners)
               .then(fixture => {
                 let appInstance = fixture.debugElement.componentInstance;
                 let router = appInstance.router;

                 router.subscribe((_) => {
                   fixture.detectChanges();

                   expect(appInstance.helloCmp).toBeAnInstanceOf(HelloCmp);
                   expect(appInstance.helloCmp.message).toBe('Ahoy');

                   async.done();
                 });

                 // TODO(juliemr): This isn't necessary for the test to pass - figure
                 // out what's going on.
                 // router.navigateByUrl('/rainbow(pony)');
               });
         }));
    });
  });
function asyncRoutesWithAsyncChildrenWithoutParamsWithDefaultRoutes() {
  var rootTC: any /** TODO #9100 */;
  var tcb: any /** TODO #9100 */;
  var rtr: any /** TODO #9100 */;

  beforeEachProviders(() => TEST_ROUTER_PROVIDERS);

  beforeEach(inject(
      [TestComponentBuilder, Router],
      (tcBuilder: any /** TODO #9100 */, router: any /** TODO #9100 */) => {
        tcb = tcBuilder;
        rtr = router;
      }));

  it('should navigate by URL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(tcb, `outer { <router-outlet></router-outlet> }`)
           .then((rtc) => {rootTC = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/a/...', loader: asyncDefaultParentCmpLoader, name: 'Parent'})]))
           .then((_) => rtr.navigateByUrl('/a'))
           .then((_) => {
             rootTC.detectChanges();
             expect(rootTC.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
             async.done();
           });
     }));

  it('should navigate by link DSL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(tcb, `outer { <router-outlet></router-outlet> }`)
           .then((rtc) => {rootTC = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/a/...', loader: asyncDefaultParentCmpLoader, name: 'Parent'})]))
           .then((_) => rtr.navigate(['/Parent']))
           .then((_) => {
             rootTC.detectChanges();
             expect(rootTC.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
             async.done();
           });
     }));

  it('should generate a link URL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(
           tcb,
           `<a [routerLink]="['Parent']">nav to child</a> | outer { <router-outlet></router-outlet> }`)
           .then((rtc) => {rootTC = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/a/...', loader: asyncDefaultParentCmpLoader, name: 'Parent'})]))
           .then((_) => {
             rootTC.detectChanges();
             expect(getHref(getLinkElement(rootTC))).toEqual('/a');
             async.done();
           });
     }));

  it('should navigate from a link click',
     inject(
         [AsyncTestCompleter, Location],
         (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
           compile(
               tcb,
               `<a [routerLink]="['Parent']">nav to child</a> | outer { <router-outlet></router-outlet> }`)
               .then((rtc) => {rootTC = rtc})
               .then((_) => rtr.config([new AsyncRoute(
                         {path: '/a/...', loader: asyncDefaultParentCmpLoader, name: 'Parent'})]))
               .then((_) => {
                 rootTC.detectChanges();
                 expect(rootTC.debugElement.nativeElement).toHaveText('nav to child | outer {  }');

                 rtr.subscribe((_: any /** TODO #9100 */) => {
                   rootTC.detectChanges();
                   expect(rootTC.debugElement.nativeElement)
                       .toHaveText('nav to child | outer { inner { hello } }');
                   expect(location.urlChanges).toEqual(['/a/b']);
                   async.done();
                 });

                 clickOnElement(getLinkElement(rootTC));
               });
         }));
}
function asyncRoutesWithoutChildrenWithoutParams() {
  var fixture: any /** TODO #9100 */;
  var tcb: any /** TODO #9100 */;
  var rtr: any /** TODO #9100 */;

  beforeEachProviders(() => TEST_ROUTER_PROVIDERS);

  beforeEach(inject(
      [TestComponentBuilder, Router],
      (tcBuilder: any /** TODO #9100 */, router: any /** TODO #9100 */) => {
        tcb = tcBuilder;
        rtr = router;
      }));

  it('should navigate by URL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(tcb)
           .then((rtc) => {fixture = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/test', loader: helloCmpLoader, name: 'Hello'})]))
           .then((_) => rtr.navigateByUrl('/test'))
           .then((_) => {
             fixture.detectChanges();
             expect(fixture.debugElement.nativeElement).toHaveText('hello');
             async.done();
           });
     }));

  it('should navigate by link DSL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(tcb)
           .then((rtc) => {fixture = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/test', loader: helloCmpLoader, name: 'Hello'})]))
           .then((_) => rtr.navigate(['/Hello']))
           .then((_) => {
             fixture.detectChanges();
             expect(fixture.debugElement.nativeElement).toHaveText('hello');
             async.done();
           });
     }));

  it('should generate a link URL', inject([AsyncTestCompleter], (async: AsyncTestCompleter) => {
       compile(tcb, `<a [routerLink]="['Hello']">go to hello</a> | <router-outlet></router-outlet>`)
           .then((rtc) => {fixture = rtc})
           .then((_) => rtr.config([new AsyncRoute(
                     {path: '/test', loader: helloCmpLoader, name: 'Hello'})]))
           .then((_) => {
             fixture.detectChanges();
             expect(getHref(getLinkElement(fixture))).toEqual('/test');
             async.done();
           });
     }));

  it('should navigate from a link click',
     inject(
         [AsyncTestCompleter, Location],
         (async: AsyncTestCompleter, location: any /** TODO #9100 */) => {
           compile(
               tcb, `<a [routerLink]="['Hello']">go to hello</a> | <router-outlet></router-outlet>`)
               .then((rtc) => {fixture = rtc})
               .then((_) => rtr.config([new AsyncRoute(
                         {path: '/test', loader: helloCmpLoader, name: 'Hello'})]))
               .then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('go to hello | ');

                 rtr.subscribe((_: any /** TODO #9100 */) => {
                   fixture.detectChanges();
                   expect(fixture.debugElement.nativeElement).toHaveText('go to hello | hello');
                   expect(location.urlChanges).toEqual(['/test']);
                   async.done();
                 });

                 clickOnElement(getLinkElement(fixture));
               });
         }));
}
  describe('HashLocationStrategy', () => {
    var platformLocation: SpyPlatformLocation;
    var locationStrategy: HashLocationStrategy;

    beforeEachProviders(
        () => [HashLocationStrategy, provide(PlatformLocation, {useClass: SpyPlatformLocation})]);

    describe('without APP_BASE_HREF', () => {
      beforeEach(inject([PlatformLocation, HashLocationStrategy], (pl, ls) => {
        platformLocation = pl;
        locationStrategy = ls;
        platformLocation.spy('pushState');
        platformLocation.pathname = '';
      }));

      it('should prepend urls with a hash for non-empty URLs', () => {
        expect(locationStrategy.prepareExternalUrl('foo')).toEqual('#foo');

        locationStrategy.pushState(null, 'Title', 'foo', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#foo');
      });

      it('should prepend urls with a hash for URLs with query params', () => {
        expect(locationStrategy.prepareExternalUrl('foo?bar')).toEqual('#foo?bar');

        locationStrategy.pushState(null, 'Title', 'foo', 'bar=baz');
        expect(platformLocation.spy('pushState'))
            .toHaveBeenCalledWith(null, 'Title', '#foo?bar=baz');
      });

      it('should prepend urls with a hash for URLs with just query params', () => {
        expect(locationStrategy.prepareExternalUrl('?bar')).toEqual('#?bar');

        locationStrategy.pushState(null, 'Title', '', 'bar=baz');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#?bar=baz');
      });

      it('should not prepend a hash to external urls for an empty internal URL', () => {
        expect(locationStrategy.prepareExternalUrl('')).toEqual('');

        locationStrategy.pushState(null, 'Title', '', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '');
      });
    });

    describe('with APP_BASE_HREF with neither leading nor trailing slash', () => {
      beforeEachProviders(() => [provide(APP_BASE_HREF, {useValue: 'app'})]);

      beforeEach(inject([PlatformLocation, HashLocationStrategy], (pl, ls) => {
        platformLocation = pl;
        locationStrategy = ls;
        platformLocation.spy('pushState');
        platformLocation.pathname = '';
      }));

      it('should prepend urls with a hash for non-empty URLs', () => {
        expect(locationStrategy.prepareExternalUrl('foo')).toEqual('#app/foo');

        locationStrategy.pushState(null, 'Title', 'foo', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#app/foo');
      });

      it('should prepend urls with a hash for URLs with query params', () => {
        expect(locationStrategy.prepareExternalUrl('foo?bar')).toEqual('#app/foo?bar');

        locationStrategy.pushState(null, 'Title', 'foo', 'bar=baz');
        expect(platformLocation.spy('pushState'))
            .toHaveBeenCalledWith(null, 'Title', '#app/foo?bar=baz');
      });

      it('should not prepend a hash to external urls for an empty internal URL', () => {
        expect(locationStrategy.prepareExternalUrl('')).toEqual('#app');

        locationStrategy.pushState(null, 'Title', '', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#app');
      });
    });

    describe('with APP_BASE_HREF with leading slash', () => {
      beforeEachProviders(() => [provide(APP_BASE_HREF, {useValue: '/app'})]);

      beforeEach(inject([PlatformLocation, HashLocationStrategy], (pl, ls) => {
        platformLocation = pl;
        locationStrategy = ls;
        platformLocation.spy('pushState');
        platformLocation.pathname = '';
      }));

      it('should prepend urls with a hash for non-empty URLs', () => {
        expect(locationStrategy.prepareExternalUrl('foo')).toEqual('#/app/foo');

        locationStrategy.pushState(null, 'Title', 'foo', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#/app/foo');
      });

      it('should prepend urls with a hash for URLs with query params', () => {
        expect(locationStrategy.prepareExternalUrl('foo?bar')).toEqual('#/app/foo?bar');

        locationStrategy.pushState(null, 'Title', 'foo', 'bar=baz');
        expect(platformLocation.spy('pushState'))
            .toHaveBeenCalledWith(null, 'Title', '#/app/foo?bar=baz');
      });

      it('should not prepend a hash to external urls for an empty internal URL', () => {
        expect(locationStrategy.prepareExternalUrl('')).toEqual('#/app');

        locationStrategy.pushState(null, 'Title', '', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#/app');
      });
    });

    describe('with APP_BASE_HREF with both leading and trailing slash', () => {
      beforeEachProviders(() => [provide(APP_BASE_HREF, {useValue: '/app/'})]);

      beforeEach(inject([PlatformLocation, HashLocationStrategy], (pl, ls) => {
        platformLocation = pl;
        locationStrategy = ls;
        platformLocation.spy('pushState');
        platformLocation.pathname = '';
      }));

      it('should prepend urls with a hash for non-empty URLs', () => {
        expect(locationStrategy.prepareExternalUrl('foo')).toEqual('#/app/foo');

        locationStrategy.pushState(null, 'Title', 'foo', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#/app/foo');
      });

      it('should prepend urls with a hash for URLs with query params', () => {
        expect(locationStrategy.prepareExternalUrl('foo?bar')).toEqual('#/app/foo?bar');

        locationStrategy.pushState(null, 'Title', 'foo', 'bar=baz');
        expect(platformLocation.spy('pushState'))
            .toHaveBeenCalledWith(null, 'Title', '#/app/foo?bar=baz');
      });

      it('should not prepend a hash to external urls for an empty internal URL', () => {
        expect(locationStrategy.prepareExternalUrl('')).toEqual('#/app/');

        locationStrategy.pushState(null, 'Title', '', '');
        expect(platformLocation.spy('pushState')).toHaveBeenCalledWith(null, 'Title', '#/app/');
      });
    });

    describe('hashLocationStrategy bugs', () => {
      beforeEach(inject([PlatformLocation, HashLocationStrategy], (pl, ls) => {
        platformLocation = pl;
        locationStrategy = ls;
        platformLocation.spy('pushState');
        platformLocation.pathname = '';
      }));

      it('should not include platform search', () => {
        platformLocation.search = '?donotinclude';
        expect(locationStrategy.path()).toEqual('');
      });

      it('should not include platform search even with hash', () => {
        platformLocation.hash = '#hashPath';
        platformLocation.search = '?donotinclude';
        expect(locationStrategy.path()).toEqual('hashPath');
      });
    });
  });
示例#8
0
  describe('navigation', () => {

    var tcb: TestComponentBuilder;
    var fixture: ComponentFixture<any>;
    var rtr;

    beforeEachProviders(() => TEST_ROUTER_PROVIDERS);

    beforeEach(inject([TestComponentBuilder, Router], (tcBuilder, router) => {
      tcb = tcBuilder;
      rtr = router;
      childCmpInstanceCount = 0;
      cmpInstanceCount = 0;
    }));

    it('should work in a simple case', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
             .then((_) => rtr.navigateByUrl('/test'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('hello');
               async.done();
             });
       }));


    it('should navigate between components with different parameters',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/user/:name', component: UserCmp})]))
             .then((_) => rtr.navigateByUrl('/user/brian'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('hello brian');
             })
             .then((_) => rtr.navigateByUrl('/user/igor'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('hello igor');
               async.done();
             });
       }));

    it('should navigate to child routes', inject([AsyncTestCompleter], (async) => {
         compile(tcb, 'outer { <router-outlet></router-outlet> }')
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/a/...', component: ParentCmp})]))
             .then((_) => rtr.navigateByUrl('/a/b'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
               async.done();
             });
       }));

    it('should navigate to child routes that capture an empty path',
       inject([AsyncTestCompleter], (async) => {

         compile(tcb, 'outer { <router-outlet></router-outlet> }')
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/a/...', component: ParentCmp})]))
             .then((_) => rtr.navigateByUrl('/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
               async.done();
             });
       }));

    it('should navigate to child routes when the root component has an empty path',
       inject([AsyncTestCompleter, Location], (async, location) => {
         compile(tcb, 'outer { <router-outlet></router-outlet> }')
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: ParentCmp})]))
             .then((_) => rtr.navigateByUrl('/b'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
               expect(location.urlChanges).toEqual(['/b']);
               async.done();
             });
       }));

    it('should navigate to child routes of async routes', inject([AsyncTestCompleter], (async) => {
         compile(tcb, 'outer { <router-outlet></router-outlet> }')
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new AsyncRoute({path: '/a/...', loader: parentLoader})]))
             .then((_) => rtr.navigateByUrl('/a/b'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('outer { inner { hello } }');
               async.done();
             });
       }));

    it('should reuse common parent components', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/team/:id/...', component: TeamCmp})]))
             .then((_) => rtr.navigateByUrl('/team/angular/user/rado'))
             .then((_) => {
               fixture.detectChanges();
               expect(cmpInstanceCount).toBe(1);
               expect(fixture.debugElement.nativeElement).toHaveText('team angular { hello rado }');
             })
             .then((_) => rtr.navigateByUrl('/team/angular/user/victor'))
             .then((_) => {
               fixture.detectChanges();
               expect(cmpInstanceCount).toBe(1);
               expect(fixture.debugElement.nativeElement)
                   .toHaveText('team angular { hello victor }');
               async.done();
             });
       }));

    it('should not reuse children when parent components change',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/team/:id/...', component: TeamCmp})]))
             .then((_) => rtr.navigateByUrl('/team/angular/user/rado'))
             .then((_) => {
               fixture.detectChanges();
               expect(cmpInstanceCount).toBe(1);
               expect(childCmpInstanceCount).toBe(1);
               expect(fixture.debugElement.nativeElement).toHaveText('team angular { hello rado }');
             })
             .then((_) => rtr.navigateByUrl('/team/dart/user/rado'))
             .then((_) => {
               fixture.detectChanges();
               expect(cmpInstanceCount).toBe(2);
               expect(childCmpInstanceCount).toBe(2);
               expect(fixture.debugElement.nativeElement).toHaveText('team dart { hello rado }');
               async.done();
             });
       }));

    it('should inject route data into component', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([
               new Route({path: '/route-data', component: RouteDataCmp, data: {isAdmin: true}})
             ]))
             .then((_) => rtr.navigateByUrl('/route-data'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('true');
               async.done();
             });
       }));

    it('should inject route data into component with AsyncRoute',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([
               new AsyncRoute(
                   {path: '/route-data', loader: asyncRouteDataCmp, data: {isAdmin: true}})
             ]))
             .then((_) => rtr.navigateByUrl('/route-data'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('true');
               async.done();
             });
       }));

    it('should inject empty object if the route has no data property',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config(
                       [new Route({path: '/route-data-default', component: RouteDataCmp})]))
             .then((_) => rtr.navigateByUrl('/route-data-default'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('');
               async.done();
             });
       }));

    it('should fire an event for each activated component',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb, '<router-outlet (activate)="activatedCmp = $event"></router-outlet>')
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/test', component: HelloCmp})]))
             .then((_) => rtr.navigateByUrl('/test'))
             .then((_) => {
               // Note: need a timeout so that all promises are flushed
               var completer = PromiseWrapper.completer();
               TimerWrapper.setTimeout(() => { completer.resolve(null); }, 0);
               return completer.promise;
             })
             .then((_) => {
               expect(fixture.componentInstance.activatedCmp).toBeAnInstanceOf(HelloCmp);
               async.done();
             });
       }));
  });
示例#9
0
  describe('navigation', () => {
    beforeEachProviders(
        () =>
            [{provide: RouterUrlSerializer, useClass: DefaultRouterUrlSerializer}, RouterOutletMap,
             {provide: Location, useClass: SpyLocation}, {
               provide: RouteSegment,
               useFactory: (r: any /** TODO #9100 */) => r.routeTree.root,
               deps: [Router]
             },
             {
               provide: Router,
               useFactory:
                   (resolver: any /** TODO #9100 */, urlParser: any /** TODO #9100 */,
                    outletMap: any /** TODO #9100 */, location: any /** TODO #9100 */) =>
                       new Router(
                           'RootComponent', RootCmp, resolver, urlParser, outletMap, location),
               deps: [ComponentResolver, RouterUrlSerializer, RouterOutletMap, Location]
             }]);

    it('should update location when navigating',
       fakeAsync(inject(
           [Router, TestComponentBuilder, Location],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */,
            location: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);
             expect(location.path()).toEqual('/team/22/user/victor');

             router.navigateByUrl('/team/33/simple');
             advance(fixture);

             expect(location.path()).toEqual('/team/33/simple');
           })));

    it('should navigate back and forward',
       fakeAsync(inject(
           [Router, TestComponentBuilder, Location],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */,
            location: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/33/simple');
             advance(fixture);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);

             location.back();
             advance(fixture);
             expect(location.path()).toEqual('/team/33/simple');

             location.forward();
             advance(fixture);
             expect(location.path()).toEqual('/team/22/user/victor');
           })));

    it('should navigate when locations changes',
       fakeAsync(inject(
           [Router, TestComponentBuilder, Location],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */,
            location: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);

             location.simulateHashChange('/team/22/user/fedor');
             advance(fixture);

             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { hello fedor, aux:  }');
           })));

    it('should support nested routes',
       fakeAsync(inject(
           [Router, TestComponentBuilder],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);

             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { hello victor, aux:  }');
           })));

    it('should support aux routes',
       fakeAsync(inject(
           [Router, TestComponentBuilder],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor(/simple)');
             advance(fixture);

             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { hello victor, aux: simple }');
           })));

    it('should deactivate outlets',
       fakeAsync(inject(
           [Router, TestComponentBuilder],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor(/simple)');
             advance(fixture);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);

             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { hello victor, aux:  }');
           })));

    it('should deactivate nested outlets',
       fakeAsync(inject(
           [Router, TestComponentBuilder],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor(/simple)');
             advance(fixture);

             router.navigateByUrl('/');
             advance(fixture);

             expect(fixture.debugElement.nativeElement).toHaveText('');
           })));

    it('should update nested routes when url changes',
       fakeAsync(inject(
           [Router, TestComponentBuilder],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/user/victor');
             advance(fixture);
             let team1 = fixture.debugElement.children[1].componentInstance;

             router.navigateByUrl('/team/22/user/fedor');
             advance(fixture);
             let team2 = fixture.debugElement.children[1].componentInstance;

             expect(team1).toBe(team2);
             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { hello fedor, aux:  }');
           })));

    it('should not deactivate the route if can deactivate returns false',
       fakeAsync(inject(
           [Router, TestComponentBuilder, Location],
           (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */,
            location: any /** TODO #9100 */) => {
             let fixture = tcb.createFakeAsync(RootCmp);

             router.navigateByUrl('/team/22/cannotDeactivate');
             advance(fixture);

             router.navigateByUrl('/team/22/user/fedor');
             advance(fixture);

             expect(fixture.debugElement.nativeElement)
                 .toHaveText('team 22 { cannotDeactivate, aux:  }');

             expect(location.path()).toEqual('/team/22/cannotDeactivate');
           })));

    if (getDOM().supportsDOMEvents()) {
      it('should support absolute router links',
         fakeAsync(inject(
             [Router, TestComponentBuilder],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(RootCmp);
               advance(fixture);

               router.navigateByUrl('/team/22/link');
               advance(fixture);
               expect(fixture.debugElement.nativeElement).toHaveText('team 22 { link, aux:  }');

               let native = getDOM().querySelector(fixture.debugElement.nativeElement, 'a');
               expect(getDOM().getAttribute(native, 'href')).toEqual('/team/33/simple');
               getDOM().dispatchEvent(native, getDOM().createMouseEvent('click'));
               advance(fixture);

               expect(fixture.debugElement.nativeElement).toHaveText('team 33 { simple, aux:  }');
             })));

      it('should support relative router links',
         fakeAsync(inject(
             [Router, TestComponentBuilder],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(RootCmp);
               advance(fixture);

               router.navigateByUrl('/team/22/relativelink');
               advance(fixture);
               expect(fixture.debugElement.nativeElement)
                   .toHaveText('team 22 { relativelink {  }, aux:  }');

               let native = getDOM().querySelector(fixture.debugElement.nativeElement, 'a');
               expect(getDOM().getAttribute(native, 'href'))
                   .toEqual('/team/22/relativelink/simple');
               getDOM().dispatchEvent(native, getDOM().createMouseEvent('click'));
               advance(fixture);

               expect(fixture.debugElement.nativeElement)
                   .toHaveText('team 22 { relativelink { simple }, aux:  }');
             })));

      it('should set the router-link-active class',
         fakeAsync(inject(
             [Router, TestComponentBuilder],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(RootCmp);
               advance(fixture);

               router.navigateByUrl('/team/22/relativelink');
               advance(fixture);
               expect(fixture.debugElement.nativeElement)
                   .toHaveText('team 22 { relativelink {  }, aux:  }');
               let link = getDOM().querySelector(fixture.debugElement.nativeElement, 'a');
               expect(getDOM().hasClass(link, 'router-link-active')).toEqual(false);

               getDOM().dispatchEvent(link, getDOM().createMouseEvent('click'));
               advance(fixture);

               expect(getDOM().hasClass(link, 'router-link-active')).toEqual(true);
             })));

      it('should update router links when router changes',
         fakeAsync(inject(
             [Router, TestComponentBuilder],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(RootCmp);
               advance(fixture);

               router.navigateByUrl('/team/22/link(simple)');
               advance(fixture);
               expect(fixture.debugElement.nativeElement)
                   .toHaveText('team 22 { link, aux: simple }');

               let native = getDOM().querySelector(fixture.debugElement.nativeElement, 'a');
               expect(getDOM().getAttribute(native, 'href')).toEqual('/team/33/simple(aux:simple)');

               router.navigateByUrl('/team/22/link(simple2)');
               advance(fixture);

               expect(getDOM().getAttribute(native, 'href'))
                   .toEqual('/team/33/simple(aux:simple2)');
             })));

      it('should support top-level link',
         fakeAsync(inject(
             [Router, TestComponentBuilder],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(LinkCmp);
               advance(fixture);
               expect(fixture.debugElement.nativeElement).toHaveText('link');
             })));

      it('should replace state when path is equal to current path',
         fakeAsync(inject(
             [Router, TestComponentBuilder, Location],
             (router: any /** TODO #9100 */, tcb: any /** TODO #9100 */,
              location: any /** TODO #9100 */) => {
               let fixture = tcb.createFakeAsync(RootCmp);

               router.navigateByUrl('/team/33/simple');
               advance(fixture);

               router.navigateByUrl('/team/22/user/victor');
               advance(fixture);

               router.navigateByUrl('/team/22/user/victor');
               advance(fixture);

               location.back();
               advance(fixture);
               expect(location.path()).toEqual('/team/33/simple');
             })));
    }
  });
 describe('no jit', () => {
   beforeEachProviders(
       () => [{provide: CompilerConfig, useValue: new CompilerConfig(true, false, false)}]);
   declareTests(false);
 });