export function main() {
  describe('WebWorkerPlatformLocation', () => {
    var uiBus: MessageBus = null;
    var workerBus: MessageBus = null;
    var broker: any = null;
    var TEST_LOCATION = new LocationType(
        'http://www.example.com', 'http', 'example.com', 'example.com', '80', '/', '', '',
        'http://www.example.com');


    function createWebWorkerPlatformLocation(loc: LocationType): WebWorkerPlatformLocation {
      broker.spy('runOnService').andCallFake((args: UiArguments, returnType: Type) => {
        if (args.method === 'getLocation') {
          return PromiseWrapper.resolve(loc);
        }
      });
      var factory = new MockMessageBrokerFactory(broker);
      return new WebWorkerPlatformLocation(factory, workerBus, null);
    }

    function testPushOrReplaceState(pushState: boolean) {
      let platformLocation = createWebWorkerPlatformLocation(null);
      const TITLE = 'foo';
      const URL = 'http://www.example.com/foo';
      expectBrokerCall(broker, pushState ? 'pushState' : 'replaceState', [null, TITLE, URL]);
      if (pushState) {
        platformLocation.pushState(null, TITLE, URL);
      } else {
        platformLocation.replaceState(null, TITLE, URL);
      }
    }

    beforeEach(() => {
      var buses = createPairedMessageBuses();
      uiBus = buses.ui;
      workerBus = buses.worker;
      workerBus.initChannel('ng-Router');
      uiBus.initChannel('ng-Router');
      broker = new SpyMessageBroker();
    });

    it('should throw if getBaseHrefFromDOM is called', () => {
      let platformLocation = createWebWorkerPlatformLocation(null);
      expect(() => platformLocation.getBaseHrefFromDOM()).toThrowError();
    });

    it('should get location on init', () => {
      let platformLocation = createWebWorkerPlatformLocation(null);
      expectBrokerCall(broker, 'getLocation');
      platformLocation.init();
    });

    it('should throw if set pathname is called before init finishes', () => {
      let platformLocation = createWebWorkerPlatformLocation(null);
      platformLocation.init();
      expect(() => platformLocation.pathname = 'TEST').toThrowError();
    });

    it('should send pathname to render thread', inject([AsyncTestCompleter], (async) => {
         let platformLocation = createWebWorkerPlatformLocation(TEST_LOCATION);
         platformLocation.init().then((_) => {
           let PATHNAME = '/test';
           expectBrokerCall(broker, 'setPathname', [PATHNAME]);
           platformLocation.pathname = PATHNAME;
           async.done();
         });
       }));

    it('should send pushState to render thread', () => { testPushOrReplaceState(true); });

    it('should send replaceState to render thread', () => { testPushOrReplaceState(false); });
  });
}
示例#2
0
export function main() {
  describe('navigation', () => {

    var tcb: TestComponentBuilder;
    var fixture: ComponentFixture;
    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();
             });
       }));
  });
}
示例#3
0
  describe('ChangeDetectorCompiler', () => {
    beforeEachBindings(() => TEST_PROVIDERS);

    var parser: TemplateParser;
    var compiler: ChangeDetectionCompiler;

    beforeEach(inject([TemplateParser, ChangeDetectionCompiler], (_parser, _compiler) => {
      parser = _parser;
      compiler = _compiler;
    }));

    describe('compileComponentRuntime', () => {
      function detectChanges(compiler: ChangeDetectionCompiler, template: string,
                             directives: CompileDirectiveMetadata[] = CONST_EXPR([])): string[] {
        var type =
            new CompileTypeMetadata({name: stringify(SomeComponent), moduleUrl: THIS_MODULE_URL});
        var parsedTemplate = parser.parse(template, directives, 'TestComp');
        var factories =
            compiler.compileComponentRuntime(type, ChangeDetectionStrategy.Default, parsedTemplate);
        return testChangeDetector(factories[0]);
      }

      describe('no jit', () => {
        beforeEachBindings(() => [
          provide(ChangeDetectorGenConfig,
                  {useValue: new ChangeDetectorGenConfig(true, true, false, false)})
        ]);
        it('should watch element properties', () => {
          expect(detectChanges(compiler, '<div [el-prop]="someProp">'))
              .toEqual(['elementProperty(elProp)=someValue']);
        });
      });

      describe('jit', () => {
        beforeEachBindings(() => [
          provide(ChangeDetectorGenConfig,
                  {useValue: new ChangeDetectorGenConfig(true, true, false, true)})
        ]);
        it('should watch element properties', () => {
          expect(detectChanges(compiler, '<div [el-prop]="someProp">'))
              .toEqual(['elementProperty(elProp)=someValue']);
        });

      });


    });

    describe('compileComponentCodeGen', () => {
      function detectChanges(compiler: ChangeDetectionCompiler, template: string,
                             directives: CompileDirectiveMetadata[] = CONST_EXPR([])):
          Promise<string[]> {
        var type =
            new CompileTypeMetadata({name: stringify(SomeComponent), moduleUrl: THIS_MODULE_URL});
        var parsedTemplate = parser.parse(template, directives, 'TestComp');
        var sourceExpressions =
            compiler.compileComponentCodeGen(type, ChangeDetectionStrategy.Default, parsedTemplate);
        var testableModule = createTestableModule(sourceExpressions, 0).getSourceWithImports();
        return evalModule(testableModule.source, testableModule.imports, null);
      }

      it('should watch element properties', inject([AsyncTestCompleter], (async) => {
           detectChanges(compiler, '<div [el-prop]="someProp">')
               .then((value) => {
                 expect(value).toEqual(['elementProperty(elProp)=someValue']);
                 async.done();
               });

         }));
    });

  });
  describe("NgZone", () => {

    function createZone(enableLongStackTrace) {
      var zone = new NgZone({enableLongStackTrace: enableLongStackTrace});
      zone.overrideOnTurnStart(_log.fn('onTurnStart'));
      zone.overrideOnTurnDone(_log.fn('onTurnDone'));
      return zone;
    }

    beforeEach(() => {
      _log = new Log();
      _errors = [];
      _traces = [];
    });

    describe('long stack trace', () => {
      beforeEach(() => { _zone = createZone(true); });

      commonTests();

      it('should produce long stack traces', inject([AsyncTestCompleter], (async) => {
           macroTask(() => {
             _zone.overrideOnErrorHandler(logError);
             var c: PromiseCompleter<any> = PromiseWrapper.completer();

             _zone.run(() => {
               TimerWrapper.setTimeout(() => {
                 TimerWrapper.setTimeout(() => {
                   c.resolve(null);
                   throw new BaseException('ccc');
                 }, 0);
               }, 0);
             });

             c.promise.then((_) => {
               expect(_traces.length).toBe(1);
               expect(_traces[0].length).toBeGreaterThan(1);
               async.done();
             });
           });
         }), testTimeout);

      it('should produce long stack traces (when using microtasks)',
         inject([AsyncTestCompleter], (async) => {
           macroTask(() => {
             _zone.overrideOnErrorHandler(logError);
             var c: PromiseCompleter<any> = PromiseWrapper.completer();

             _zone.run(() => {
               microTask(() => {
                 microTask(() => {
                   c.resolve(null);
                   throw new BaseException("ddd");
                 });
               });
             });

             c.promise.then((_) => {
               expect(_traces.length).toBe(1);
               expect(_traces[0].length).toBeGreaterThan(1);
               async.done();
             });
           });
         }), testTimeout);
    });

    describe('short stack trace', () => {
      beforeEach(() => { _zone = createZone(false); });

      commonTests();

      it('should disable long stack traces', inject([AsyncTestCompleter], (async) => {
           macroTask(() => {
             _zone.overrideOnErrorHandler(logError);
             var c: PromiseCompleter<any> = PromiseWrapper.completer();

             _zone.run(() => {
               TimerWrapper.setTimeout(() => {
                 TimerWrapper.setTimeout(() => {
                   c.resolve(null);
                   throw new BaseException('ccc');
                 }, 0);
               }, 0);
             });

             c.promise.then((_) => {
               expect(_traces.length).toBe(1);
               expect(_traces[0].length).toEqual(1);
               async.done();
             });
           });
         }), testTimeout);
    });
  });
export function main() {

  describe('ContactComponent', () => {

    let contactService: ContactService;

    beforeEach(() => {

      contactService = new ContactService(null);

      spyOn(contactService, 'find').and.callFake(() => Observable.of(contacts));

      spyOn(contactService, 'findOneById').and.callFake((id: string) =>
        Observable.of(contacts.find(it => it._id === id))
      );

      spyOn(contactService, 'removeOneById').and.callFake((id: string) => {
        let pos: number;
        for (let i = 0; i < contacts.length; ++i) {
          if (contacts[i]._id === id) {
            pos = i;
            break;
          }
        }
        return Observable.of(contacts.splice(pos, 1));
      });
    });


    it('should work',
      inject([TestComponentBuilder, AsyncTestCompleter], (tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
        tcb.overrideProviders(ContactComponent, [provide(ContactService, { useValue: contactService })])
          .createAsync(ContactComponent).then((fixture) => {

            fixture.detectChanges();

            const cmp: ContactComponent = fixture.componentInstance;

            const compiled = fixture.debugElement.nativeElement;
            expect(compiled.querySelector('h2').textContent).toEqual('Contacts!');

            const itemsSelector = 'tbody tr';

            function obtainContactsLenght() {
              return compiled.querySelectorAll(itemsSelector).length;
            }

            const originalLength = obtainContactsLenght();
            let newLength = originalLength;
            
            expect(originalLength).toBeGreaterThan(0);            
            expect(originalLength).toBe(contacts.length);

            const existingContact = ObjectUtil.clone(contacts[0]);

            cmp.select(existingContact._id);

            fixture.detectChanges();

            const selectedContact = cmp.selectedContact;

            expect(selectedContact._id).toBe(existingContact._id);
            expect(selectedContact.name).toBe(existingContact.name);

            cmp.remove(new Event('mock'), existingContact);

            fixture.detectChanges();

            newLength--;

            expect(obtainContactsLenght()).toBe(newLength);

            async.done();
          });
      }));

  });
}
示例#6
0
  describe('String', () => {
    var s;

    describe('slice', () => {
      beforeEach(() => { s = 'abcdefghij'; });

      it('should return the whole string if neither start nor end are specified',
         () => { expect(StringWrapper.slice(s)).toEqual('abcdefghij'); });

      it('should return up to the end if end is not specified',
         () => { expect(StringWrapper.slice(s, 1)).toEqual('bcdefghij'); });

      it('should support negative start',
         () => { expect(StringWrapper.slice(s, -1)).toEqual('j'); });

      it('should support negative end',
         () => { expect(StringWrapper.slice(s, -3, -1)).toEqual('hi'); });

      it('should return empty string if start is greater than end', () => {
        expect(StringWrapper.slice(s, 4, 2)).toEqual('');
        expect(StringWrapper.slice(s, -2, -4)).toEqual('');
      });
    });

    describe('stripLeft', () => {
      it('should strip the first character of the string if it matches the provided input', () => {
        var input = '~angular2 is amazing';
        var expectedOutput = 'angular2 is amazing';

        expect(StringWrapper.stripLeft(input, '~')).toEqual(expectedOutput);
      });

      it('should keep stripping characters from the start until the first unmatched character',
         () => {
           var input = '#####hello';
           var expectedOutput = 'hello';
           expect(StringWrapper.stripLeft(input, '#')).toEqual(expectedOutput);
         });

      it('should not alter the provided input if the first character does not match the provided input',
         () => {
           var input = '+angular2 is amazing';
           expect(StringWrapper.stripLeft(input, '*')).toEqual(input);
         });

      it('should not do any alterations when an empty string or null value is passed in', () => {
        expect(StringWrapper.stripLeft('', 'S')).toEqual('');
        expect(StringWrapper.stripLeft(null, 'S')).toEqual(null);
      });
    });

    describe('stripRight', () => {
      it('should strip the first character of the string if it matches the provided input', () => {
        var input = 'angular2 is amazing!';
        var expectedOutput = 'angular2 is amazing';

        expect(StringWrapper.stripRight(input, '!')).toEqual(expectedOutput);
      });

      it('should not alter the provided input if the first character does not match the provided input',
         () => {
           var input = 'angular2 is amazing+';

           expect(StringWrapper.stripRight(input, '*')).toEqual(input);
         });

      it('should keep stripping characters from the end until the first unmatched character',
         () => {
           var input = 'hi&!&&&&&';
           var expectedOutput = 'hi&!';
           expect(StringWrapper.stripRight(input, '&')).toEqual(expectedOutput);
         });

      it('should not do any alterations when an empty string or null value is passed in', () => {
        expect(StringWrapper.stripRight('', 'S')).toEqual('');
        expect(StringWrapper.stripRight(null, 'S')).toEqual(null);
      });
    });

    describe('resolveEnumToken', () => {
      it('should resolve a token given an enum and index values', () => {
        var token = UsefulEnum.MyToken;
        expect(resolveEnumToken(UsefulEnum, token)).toEqual('MyToken');

        token = UsefulEnum.MyOtherToken;
        expect(resolveEnumToken(UsefulEnum, token)).toEqual('MyOtherToken');
      });
    });

    describe('hasConstructor', () => {
      it('should be true when the type matches',
         () => { expect(hasConstructor(new MySuperclass(), MySuperclass)).toEqual(true); });

      it('should be false for subtypes',
         () => { expect(hasConstructor(new MySubclass(), MySuperclass)).toEqual(false); });
    });
  });
示例#7
0
export function main() {
  describe('Router lifecycle hooks', () => {

    var tcb: TestComponentBuilder;
    var fixture: ComponentFixture;
    var rtr: Router;

    beforeEachProviders(() => TEST_ROUTER_PROVIDERS);

    beforeEach(inject(
        [TestComponentBuilder, Router], (tcBuilder: TestComponentBuilder, router: Router) => {
          tcb = tcBuilder;
          rtr = router;
          cmpInstanceCount = 0;
          log = [];
          eventBus = new EventEmitter();
        }));

    it('should call the routerOnActivate hook', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/on-activate'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('activate cmp');
               expect(log).toEqual(['activate: null -> /on-activate']);
               async.done();
             });
       }));

    it('should wait for a parent component\'s routerOnActivate hook to resolve before calling its child\'s',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => {
               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('parent activate')) {
                   completer.resolve(true);
                 }
               });
               rtr.navigateByUrl('/parent-activate/child-activate').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('parent {activate cmp}');
                 expect(log).toEqual([
                   'parent activate: null -> /parent-activate', 'activate: null -> /child-activate'
                 ]);
                 async.done();
               });
             });
       }));

    it('should call the routerOnDeactivate hook', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/on-deactivate'))
             .then((_) => rtr.navigateByUrl('/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('A');
               expect(log).toEqual(['deactivate: /on-deactivate -> /a']);
               async.done();
             });
       }));

    it('should wait for a child component\'s routerOnDeactivate hook to resolve before calling its parent\'s',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/parent-deactivate/child-deactivate'))
             .then((_) => {
               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('deactivate')) {
                   completer.resolve(true);
                   fixture.detectChanges();
                   expect(fixture.debugElement.nativeElement).toHaveText('parent {deactivate cmp}');
                 }
               });
               rtr.navigateByUrl('/a').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('A');
                 expect(log).toEqual([
                   'deactivate: /child-deactivate -> null',
                   'parent deactivate: /parent-deactivate -> /a'
                 ]);
                 async.done();
               });
             });
       }));

    it('should reuse a component when the routerCanReuse hook returns true',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/on-reuse/1/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(log).toEqual([]);
               expect(fixture.debugElement.nativeElement).toHaveText('reuse {A}');
               expect(cmpInstanceCount).toBe(1);
             })
             .then((_) => rtr.navigateByUrl('/on-reuse/2/b'))
             .then((_) => {
               fixture.detectChanges();
               expect(log).toEqual(['reuse: /on-reuse/1 -> /on-reuse/2']);
               expect(fixture.debugElement.nativeElement).toHaveText('reuse {B}');
               expect(cmpInstanceCount).toBe(1);
               async.done();
             });
       }));


    it('should not reuse a component when the routerCanReuse hook returns false',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/never-reuse/1/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(log).toEqual([]);
               expect(fixture.debugElement.nativeElement).toHaveText('reuse {A}');
               expect(cmpInstanceCount).toBe(1);
             })
             .then((_) => rtr.navigateByUrl('/never-reuse/2/b'))
             .then((_) => {
               fixture.detectChanges();
               expect(log).toEqual([]);
               expect(fixture.debugElement.nativeElement).toHaveText('reuse {B}');
               expect(cmpInstanceCount).toBe(2);
               async.done();
             });
       }));


    it('should navigate when routerCanActivate returns true',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => {
               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanActivate')) {
                   completer.resolve(true);
                 }
               });
               rtr.navigateByUrl('/can-activate/a').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('routerCanActivate {A}');
                 expect(log).toEqual(['routerCanActivate: null -> /can-activate']);
                 async.done();
               });
             });
       }));

    it('should not navigate when routerCanActivate returns false',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => {
               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanActivate')) {
                   completer.resolve(false);
                 }
               });
               rtr.navigateByUrl('/can-activate/a').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('');
                 expect(log).toEqual(['routerCanActivate: null -> /can-activate']);
                 async.done();
               });
             });
       }));

    it('should navigate away when routerCanDeactivate returns true',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/can-deactivate/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('routerCanDeactivate {A}');
               expect(log).toEqual([]);

               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanDeactivate')) {
                   completer.resolve(true);
                 }
               });

               rtr.navigateByUrl('/a').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('A');
                 expect(log).toEqual(['routerCanDeactivate: /can-deactivate -> /a']);
                 async.done();
               });
             });
       }));

    it('should not navigate away when routerCanDeactivate returns false',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/can-deactivate/a'))
             .then((_) => {
               fixture.detectChanges();
               expect(fixture.debugElement.nativeElement).toHaveText('routerCanDeactivate {A}');
               expect(log).toEqual([]);

               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanDeactivate')) {
                   completer.resolve(false);
                 }
               });

               rtr.navigateByUrl('/a').then((_) => {
                 fixture.detectChanges();
                 expect(fixture.debugElement.nativeElement).toHaveText('routerCanDeactivate {A}');
                 expect(log).toEqual(['routerCanDeactivate: /can-deactivate -> /a']);
                 async.done();
               });
             });
       }));


    it('should run activation and deactivation hooks in the correct order',
       inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/activation-hooks/child'))
             .then((_) => {
               expect(log).toEqual([
                 'routerCanActivate child: null -> /child',
                 'routerCanActivate parent: null -> /activation-hooks',
                 'routerOnActivate parent: null -> /activation-hooks',
                 'routerOnActivate child: null -> /child'
               ]);

               log = [];
               return rtr.navigateByUrl('/a');
             })
             .then((_) => {
               expect(log).toEqual([
                 'routerCanDeactivate parent: /activation-hooks -> /a',
                 'routerCanDeactivate child: /child -> null',
                 'routerOnDeactivate child: /child -> null',
                 'routerOnDeactivate parent: /activation-hooks -> /a'
               ]);
               async.done();
             });
       }));

    it('should only run reuse hooks when reusing', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((rtc) => {fixture = rtc})
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/reuse-hooks/1'))
             .then((_) => {
               expect(log).toEqual([
                 'routerCanActivate: null -> /reuse-hooks/1',
                 'routerOnActivate: null -> /reuse-hooks/1'
               ]);

               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanReuse')) {
                   completer.resolve(true);
                 }
               });


               log = [];
               return rtr.navigateByUrl('/reuse-hooks/2');
             })
             .then((_) => {
               expect(log).toEqual([
                 'routerCanReuse: /reuse-hooks/1 -> /reuse-hooks/2',
                 'routerOnReuse: /reuse-hooks/1 -> /reuse-hooks/2'
               ]);
               async.done();
             });
       }));

    it('should not run reuse hooks when not reusing', inject([AsyncTestCompleter], (async) => {
         compile(tcb)
             .then((_) => rtr.config([new Route({path: '/...', component: LifecycleCmp})]))
             .then((_) => rtr.navigateByUrl('/reuse-hooks/1'))
             .then((_) => {
               expect(log).toEqual([
                 'routerCanActivate: null -> /reuse-hooks/1',
                 'routerOnActivate: null -> /reuse-hooks/1'
               ]);

               ObservableWrapper.subscribe<string>(eventBus, (ev) => {
                 if (ev.startsWith('routerCanReuse')) {
                   completer.resolve(false);
                 }
               });

               log = [];
               return rtr.navigateByUrl('/reuse-hooks/2');
             })
             .then((_) => {
               expect(log).toEqual([
                 'routerCanReuse: /reuse-hooks/1 -> /reuse-hooks/2',
                 'routerCanActivate: /reuse-hooks/1 -> /reuse-hooks/2',
                 'routerCanDeactivate: /reuse-hooks/1 -> /reuse-hooks/2',
                 'routerOnDeactivate: /reuse-hooks/1 -> /reuse-hooks/2',
                 'routerOnActivate: /reuse-hooks/1 -> /reuse-hooks/2'
               ]);
               async.done();
             });
       }));
  });
}
示例#8
0
export function main() {
  describe('Location', () => {

    var locationStrategy, location;

    function makeLocation(baseHref: string = '/my/app', provider: any = CONST_EXPR([])): Location {
      locationStrategy = new MockLocationStrategy();
      locationStrategy.internalBaseHref = baseHref;
      let injector = Injector.resolveAndCreate(
          [Location, provide(LocationStrategy, {useValue: locationStrategy}), provider]);
      return location = injector.get(Location);
    }

    beforeEach(makeLocation);

    it('should not prepend urls with starting slash when an empty URL is provided',
       () => { expect(location.prepareExternalUrl('')).toEqual(locationStrategy.getBaseHref()); });

    it('should not prepend path with an extra slash when a baseHref has a trailing slash', () => {
      let location = makeLocation('/my/slashed/app/');
      expect(location.prepareExternalUrl('/page')).toEqual('/my/slashed/app/page');
    });

    it('should not append urls with leading slash on navigate', () => {
      location.go('/my/app/user/btford');
      expect(locationStrategy.path()).toEqual('/my/app/user/btford');
    });

    it('should normalize urls on popstate', inject([AsyncTestCompleter], (async) => {
         locationStrategy.simulatePopState('/my/app/user/btford');
         location.subscribe((ev) => {
           expect(ev['url']).toEqual('/user/btford');
           async.done();
         })
       }));

    it('should revert to the previous path when a back() operation is executed', () => {
      var locationStrategy = new MockLocationStrategy();
      var location = new Location(locationStrategy);

      function assertUrl(path) { expect(location.path()).toEqual(path); }

      location.go('/ready');
      assertUrl('/ready');

      location.go('/ready/set');
      assertUrl('/ready/set');

      location.go('/ready/set/go');
      assertUrl('/ready/set/go');

      location.back();
      assertUrl('/ready/set');

      location.back();
      assertUrl('/ready');
    });

    it('should incorporate the provided query values into the location change', () => {
      var locationStrategy = new MockLocationStrategy();
      var location = new Location(locationStrategy);

      location.go('/home', "key=value");
      expect(location.path()).toEqual("/home?key=value");
    });
  });
}
  describe('chrome driver extension', () => {
    var CHROME44_USER_AGENT =
        '"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/44.0.2403.0 Safari/537.36"';
    var CHROME45_USER_AGENT =
        '"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2499.0 Safari/537.36"';

    var log;
    var extension;

    var blinkEvents = new TraceEventFactory('blink.console', 'pid0');
    var v8Events = new TraceEventFactory('v8', 'pid0');
    var v8EventsOtherProcess = new TraceEventFactory('v8', 'pid1');
    var chromeTimelineEvents =
        new TraceEventFactory('disabled-by-default-devtools.timeline', 'pid0');
    var chrome45TimelineEvents = new TraceEventFactory('devtools.timeline', 'pid0');
    var chromeTimelineV8Events = new TraceEventFactory('devtools.timeline,v8', 'pid0');
    var chromeBlinkTimelineEvents = new TraceEventFactory('blink,devtools.timeline', 'pid0');
    var chromeBlinkUserTimingEvents = new TraceEventFactory('blink.user_timing', 'pid0');
    var benchmarkEvents = new TraceEventFactory('benchmark', 'pid0');
    var normEvents = new TraceEventFactory('timeline', 'pid0');

    function createExtension(perfRecords = null, userAgent = null,
                             messageMethod = 'Tracing.dataCollected') {
      if (isBlank(perfRecords)) {
        perfRecords = [];
      }
      if (isBlank(userAgent)) {
        userAgent = CHROME44_USER_AGENT;
      }
      log = [];
      extension = Injector.resolveAndCreate([
                            ChromeDriverExtension.BINDINGS,
                            bind(WebDriverAdapter)
                                .toValue(new MockDriverAdapter(log, perfRecords, messageMethod)),
                            bind(Options.USER_AGENT).toValue(userAgent)
                          ])
                      .get(ChromeDriverExtension);
      return extension;
    }

    it('should force gc via window.gc()', inject([AsyncTestCompleter], (async) => {
         createExtension().gc().then((_) => {
           expect(log).toEqual([['executeScript', 'window.gc()']]);
           async.done();
         });
       }));

    it('should mark the timeline via console.time()', inject([AsyncTestCompleter], (async) => {
         createExtension()
             .timeBegin('someName')
             .then((_) => {
               expect(log).toEqual([['executeScript', `console.time('someName');`]]);
               async.done();
             });
       }));

    it('should mark the timeline via console.timeEnd()', inject([AsyncTestCompleter], (async) => {
         createExtension()
             .timeEnd('someName')
             .then((_) => {
               expect(log).toEqual([['executeScript', `console.timeEnd('someName');`]]);
               async.done();
             });
       }));

    it('should mark the timeline via console.time() and console.timeEnd()',
       inject([AsyncTestCompleter], (async) => {
         createExtension()
             .timeEnd('name1', 'name2')
             .then((_) => {
               expect(log)
                   .toEqual([['executeScript', `console.timeEnd('name1');console.time('name2');`]]);
               async.done();
             });
       }));

    describe('readPerfLog Chrome44', () => {
      it('should normalize times to ms and forward ph and pid event properties',
         inject([AsyncTestCompleter], (async) => {
           createExtension([chromeTimelineEvents.complete('FunctionCall', 1100, 5500, null)])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.complete('script', 1.1, 5.5, null),
                 ]);
                 async.done();
               });
         }));

      it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
           var event = chromeTimelineEvents.create('X', 'FunctionCall', 1100, null);
           event['tdur'] = 5500;
           createExtension([event]).readPerfLog().then((events) => {
             expect(events).toEqual([
               normEvents.complete('script', 1.1, 5.5, null),
             ]);
             async.done();
           });
         }));

      it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
           createExtension([chromeTimelineEvents.start('FunctionCall', 0)])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('script', 0),
                 ]);
                 async.done();
               });
         }));

      it('should report gc', inject([AsyncTestCompleter], (async) => {
           createExtension([
             chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
             chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
           ])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
                   normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
                 ]);
                 async.done();
               });
         }));

      it('should ignore major gc from different processes',
         inject([AsyncTestCompleter], (async) => {
           createExtension([
             chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
             v8EventsOtherProcess.start('majorGC', 1100, null),
             v8EventsOtherProcess.end('majorGC', 1200, null),
             chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
           ])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
                   normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}),
                 ]);
                 async.done();
               });
         }));

      it('should report major gc', inject([AsyncTestCompleter], (async) => {
           createExtension([
             chromeTimelineEvents.start('GCEvent', 1000, {'usedHeapSizeBefore': 1000}),
             v8Events.start('majorGC', 1100, null),
             v8Events.end('majorGC', 1200, null),
             chromeTimelineEvents.end('GCEvent', 2000, {'usedHeapSizeAfter': 0}),
           ])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('gc', 1.0, {'usedHeapSize': 1000}),
                   normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}),
                 ]);
                 async.done();
               });
         }));

      ['RecalculateStyles', 'Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => {
        it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
             createExtension([
               chromeTimelineEvents.start(recordType, 1234),
               chromeTimelineEvents.end(recordType, 2345)
             ])
                 .readPerfLog()
                 .then((events) => {
                   expect(events).toEqual([
                     normEvents.start('render', 1.234),
                     normEvents.end('render', 2.345),
                   ]);
                   async.done();
                 });
           }));
      });

      it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
           createExtension([
             chromeTimelineEvents.start('FunctionCall', 0,
                                        {'data': {'scriptName': 'InjectedScript'}})
           ])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([]);
                 async.done();
               });
         }));


    });

    describe('readPerfLog Chrome45', () => {
      it('should normalize times to ms and forward ph and pid event properties',
         inject([AsyncTestCompleter], (async) => {
           createExtension([chromeTimelineV8Events.complete('FunctionCall', 1100, 5500, null)],
                           CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.complete('script', 1.1, 5.5, null),
                 ]);
                 async.done();
               });
         }));

      it('should normalize "tdur" to "dur"', inject([AsyncTestCompleter], (async) => {
           var event = chromeTimelineV8Events.create('X', 'FunctionCall', 1100, null);
           event['tdur'] = 5500;
           createExtension([event], CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.complete('script', 1.1, 5.5, null),
                 ]);
                 async.done();
               });
         }));

      it('should report FunctionCall events as "script"', inject([AsyncTestCompleter], (async) => {
           createExtension([chromeTimelineV8Events.start('FunctionCall', 0)], CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('script', 0),
                 ]);
                 async.done();
               });
         }));

      it('should report minor gc', inject([AsyncTestCompleter], (async) => {
           createExtension(
               [
                 chromeTimelineV8Events.start('MinorGC', 1000, {'usedHeapSizeBefore': 1000}),
                 chromeTimelineV8Events.end('MinorGC', 2000, {'usedHeapSizeAfter': 0}),
               ],
               CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events.length).toEqual(2);
                 expect(events[0]).toEqual(
                     normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': false}));
                 expect(events[1])
                     .toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': false}));
                 async.done();
               });
         }));

      it('should report major gc', inject([AsyncTestCompleter], (async) => {
           createExtension(
               [
                 chromeTimelineV8Events.start('MajorGC', 1000, {'usedHeapSizeBefore': 1000}),
                 chromeTimelineV8Events.end('MajorGC', 2000, {'usedHeapSizeAfter': 0}),
               ],
               CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events.length).toEqual(2);
                 expect(events[0])
                     .toEqual(normEvents.start('gc', 1.0, {'usedHeapSize': 1000, 'majorGc': true}));
                 expect(events[1])
                     .toEqual(normEvents.end('gc', 2.0, {'usedHeapSize': 0, 'majorGc': true}));
                 async.done();
               });
         }));

      ['Layout', 'UpdateLayerTree', 'Paint'].forEach((recordType) => {
        it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
             createExtension(
                 [
                   chrome45TimelineEvents.start(recordType, 1234),
                   chrome45TimelineEvents.end(recordType, 2345)
                 ],
                 CHROME45_USER_AGENT)
                 .readPerfLog()
                 .then((events) => {
                   expect(events).toEqual([
                     normEvents.start('render', 1.234),
                     normEvents.end('render', 2.345),
                   ]);
                   async.done();
                 });
           }));
      });

      it(`should report UpdateLayoutTree as "render"`, inject([AsyncTestCompleter], (async) => {
           createExtension(
               [
                 chromeBlinkTimelineEvents.start('UpdateLayoutTree', 1234),
                 chromeBlinkTimelineEvents.end('UpdateLayoutTree', 2345)
               ],
               CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.start('render', 1.234),
                   normEvents.end('render', 2.345),
                 ]);
                 async.done();
               });
         }));



      it('should ignore FunctionCalls from webdriver', inject([AsyncTestCompleter], (async) => {
           createExtension([
             chromeTimelineV8Events.start('FunctionCall', 0,
                                          {'data': {'scriptName': 'InjectedScript'}})
           ])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([]);
                 async.done();
               });
         }));

      it('should ignore FunctionCalls with empty scriptName',
         inject([AsyncTestCompleter], (async) => {
           createExtension(
               [chromeTimelineV8Events.start('FunctionCall', 0, {'data': {'scriptName': ''}})])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([]);
                 async.done();
               });
         }));

      it('should report navigationStart', inject([AsyncTestCompleter], (async) => {
           createExtension([chromeBlinkUserTimingEvents.start('navigationStart', 1234)],
                           CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([normEvents.start('navigationStart', 1.234)]);
                 async.done();
               });
         }));

      it('should report receivedData', inject([AsyncTestCompleter], (async) => {
           createExtension(
               [
                 chrome45TimelineEvents.instant('ResourceReceivedData', 1234,
                                                {'data': {'encodedDataLength': 987}})
               ],
               CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual(
                     [normEvents.instant('receivedData', 1.234, {'encodedDataLength': 987})]);
                 async.done();
               });
         }));

      it('should report sendRequest', inject([AsyncTestCompleter], (async) => {
           createExtension(
               [
                 chrome45TimelineEvents.instant(
                     'ResourceSendRequest', 1234,
                     {'data': {'url': 'http://here', 'requestMethod': 'GET'}})
               ],
               CHROME45_USER_AGENT)
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([
                   normEvents.instant('sendRequest', 1.234,
                                      {'url': 'http://here', 'method': 'GET'})
                 ]);
                 async.done();
               });
         }));
    });

    describe('readPerfLog (common)', () => {

      it('should execute a dummy script before reading them',
         inject([AsyncTestCompleter], (async) => {
           // TODO(tbosch): This seems to be a bug in ChromeDriver:
           // Sometimes it does not report the newest events of the performance log
           // to the WebDriver client unless a script is executed...
           createExtension([]).readPerfLog().then((_) => {
             expect(log).toEqual([['executeScript', '1+1'], ['logs', 'performance']]);
             async.done();
           });
         }));

      ['Rasterize', 'CompositeLayers'].forEach((recordType) => {
        it(`should report ${recordType} as "render"`, inject([AsyncTestCompleter], (async) => {
             createExtension(
                 [
                   chromeTimelineEvents.start(recordType, 1234),
                   chromeTimelineEvents.end(recordType, 2345)
                 ],
                 CHROME45_USER_AGENT)
                 .readPerfLog()
                 .then((events) => {
                   expect(events).toEqual([
                     normEvents.start('render', 1.234),
                     normEvents.end('render', 2.345),
                   ]);
                   async.done();
                 });
           }));
      });

      describe('frame metrics', () => {
        it('should report ImplThreadRenderingStats as frame event',
           inject([AsyncTestCompleter], (async) => {
             createExtension([
               benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
                                       {'data': {'frame_count': 1}})
             ])
                 .readPerfLog()
                 .then((events) => {
                   expect(events).toEqual([
                     normEvents.create('i', 'frame', 1.1),
                   ]);
                   async.done();
                 });
           }));

        it('should not report ImplThreadRenderingStats with zero frames',
           inject([AsyncTestCompleter], (async) => {
             createExtension([
               benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats', 1100,
                                       {'data': {'frame_count': 0}})
             ])
                 .readPerfLog()
                 .then((events) => {
                   expect(events).toEqual([]);
                   async.done();
                 });
           }));

        it('should throw when ImplThreadRenderingStats contains more than one frame',
           inject([AsyncTestCompleter], (async) => {
             PromiseWrapper.catchError(
                 createExtension([
                   benchmarkEvents.instant('BenchmarkInstrumentation::ImplThreadRenderingStats',
                                           1100, {'data': {'frame_count': 2}})
                 ]).readPerfLog(),
                 (err) => {
                   expect(() => { throw err; })
                       .toThrowError('multi-frame render stats not supported');
                   async.done();
                 });
           }));

      });

      it('should report begin timestamps', inject([AsyncTestCompleter], (async) => {
           createExtension([blinkEvents.create('S', 'someName', 1000)])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([normEvents.markStart('someName', 1.0)]);
                 async.done();
               });
         }));

      it('should report end timestamps', inject([AsyncTestCompleter], (async) => {
           createExtension([blinkEvents.create('F', 'someName', 1000)])
               .readPerfLog()
               .then((events) => {
                 expect(events).toEqual([normEvents.markEnd('someName', 1.0)]);
                 async.done();
               });
         }));

      it('should throw an error on buffer overflow', inject([AsyncTestCompleter], (async) => {
           PromiseWrapper.catchError(
               createExtension(
                   [
                     chromeTimelineEvents.start('FunctionCall', 1234),
                   ],
                   CHROME45_USER_AGENT, 'Tracing.bufferUsage')
                   .readPerfLog(),
               (err) => {
                 expect(() => { throw err; })
                     .toThrowError('The DevTools trace buffer filled during the test!');
                 async.done();
               });
         }));

      it('should match chrome browsers', () => {
        expect(createExtension().supports({'browserName': 'chrome'})).toBe(true);

        expect(createExtension().supports({'browserName': 'Chrome'})).toBe(true);
      });

    });

  });
  describe('DirectiveNormalizer', () => {
    var dirType: CompileTypeMetadata;

    beforeEachProviders(() => TEST_PROVIDERS);

    beforeEach(() => { dirType = new CompileTypeMetadata({name: 'SomeComp'}); });

    describe('loadTemplate', () => {
      describe('inline template', () => {
        it('should store the template',
           inject([AsyncTestCompleter, DirectiveNormalizer],
                  (async, normalizer: DirectiveNormalizer) => {
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: 'a',
                                                   templateUrl: null,
                                                   styles: [],
                                                   styleUrls: ['test.css'],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.template).toEqual('a');
                          expect(template.templateUrl).toEqual('package:some/module/a.js');
                          async.done();
                        });
                  }));

        it('should resolve styles on the annotation against the baseUrl',
           inject([AsyncTestCompleter, DirectiveNormalizer],
                  (async, normalizer: DirectiveNormalizer) => {
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: '',
                                                   templateUrl: null,
                                                   styles: [],
                                                   styleUrls: ['test.css'],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.styleUrls).toEqual(['package:some/module/test.css']);
                          async.done();
                        });
                  }));

        it('should resolve styles in the template against the baseUrl',
           inject([AsyncTestCompleter, DirectiveNormalizer],
                  (async, normalizer: DirectiveNormalizer) => {
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: '<style>@import test.css</style>',
                                                   templateUrl: null,
                                                   styles: [],
                                                   styleUrls: [],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.styleUrls).toEqual(['package:some/module/test.css']);
                          async.done();
                        });
                  }));
      });

      describe('templateUrl', () => {

        it('should load a template from a url that is resolved against baseUrl',
           inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
                  (async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
                    xhr.expect('package:some/module/sometplurl.html', 'a');
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: null,
                                                   templateUrl: 'sometplurl.html',
                                                   styles: [],
                                                   styleUrls: ['test.css'],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.template).toEqual('a');
                          expect(template.templateUrl)
                              .toEqual('package:some/module/sometplurl.html');
                          async.done();
                        });
                    xhr.flush();
                  }));

        it('should resolve styles on the annotation against the baseUrl',
           inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
                  (async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
                    xhr.expect('package:some/module/tpl/sometplurl.html', '');
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: null,
                                                   templateUrl: 'tpl/sometplurl.html',
                                                   styles: [],
                                                   styleUrls: ['test.css'],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.styleUrls).toEqual(['package:some/module/test.css']);
                          async.done();
                        });
                    xhr.flush();
                  }));

        it('should resolve styles in the template against the templateUrl',
           inject([AsyncTestCompleter, DirectiveNormalizer, XHR],
                  (async, normalizer: DirectiveNormalizer, xhr: MockXHR) => {
                    xhr.expect('package:some/module/tpl/sometplurl.html',
                               '<style>@import test.css</style>');
                    normalizer.normalizeTemplate(dirType, new CompileTemplateMetadata({
                                                   encapsulation: null,
                                                   template: null,
                                                   templateUrl: 'tpl/sometplurl.html',
                                                   styles: [],
                                                   styleUrls: [],
                                                   baseUrl: 'package:some/module/a.js'
                                                 }))
                        .then((template: CompileTemplateMetadata) => {
                          expect(template.styleUrls).toEqual(['package:some/module/tpl/test.css']);
                          async.done();
                        });
                    xhr.flush();
                  }));

      });

      it('should throw if no template was specified',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           expect(() => normalizer.normalizeTemplate(
                      dirType, new CompileTemplateMetadata(
                                   {encapsulation: null, styles: [], styleUrls: []})))
               .toThrowError('No template specified for component SomeComp');
         }));

    });

    describe('normalizeLoadedTemplate', () => {
      it('should store the viewEncapsulationin the result',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {

           var viewEncapsulation = ViewEncapsulation.Native;
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: viewEncapsulation,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '', 'package:some/module/');
           expect(template.encapsulation).toBe(viewEncapsulation);
         }));

      it('should keep the template as html',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             'a', 'package:some/module/');
           expect(template.template).toEqual('a')
         }));

      it('should collect ngContent',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '<ng-content select="a"></ng-content>',
                                                             'package:some/module/');
           expect(template.ngContentSelectors).toEqual(['a']);
         }));

      it('should normalize ngContent wildcard selector',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: [],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '<ng-content></ng-content><ng-content select></ng-content><ng-content select="*"></ng-content>',
               'package:some/module/');
           expect(template.ngContentSelectors).toEqual(['*', '*', '*']);
         }));

      it('should collect top level styles in the template',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template =
               normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                    encapsulation: null,
                                                    styles: [],
                                                    styleUrls: [],
                                                    baseUrl: 'package:some/module/a.js'
                                                  }),
                                                  '<style>a</style>', 'package:some/module/');
           expect(template.styles).toEqual(['a']);
         }));

      it('should collect styles inside in elements',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '<div><style>a</style></div>',
                                                             'package:some/module/');
           expect(template.styles).toEqual(['a']);
         }));

      it('should collect styleUrls in the template',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '<link rel="stylesheet" href="aUrl">',
                                                             'package:some/module/');
           expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
         }));

      it('should collect styleUrls in elements',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: [],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '<div><link rel="stylesheet" href="aUrl"></div>', 'package:some/module/');
           expect(template.styleUrls).toEqual(['package:some/module/aUrl']);
         }));

      it('should ignore link elements with non stylesheet rel attribute',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '<link href="b" rel="a">',
                                                             'package:some/module/');
           expect(template.styleUrls).toEqual([]);
         }));

      it('should ignore link elements with absolute urls but non package: scheme',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: [],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '<link href="http://some/external.css" rel="stylesheet">', 'package:some/module/');
           expect(template.styleUrls).toEqual([]);
         }));

      it('should extract @import style urls into styleAbsUrl',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: ['@import "test.css";'],
                                                               styleUrls: [],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '', 'package:some/module/id');
           expect(template.styles).toEqual(['']);
           expect(template.styleUrls).toEqual(['package:some/module/test.css']);
         }));

      it('should not resolve relative urls in inline styles',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: ['.foo{background-image: url(\'double.jpg\');'],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '', 'package:some/module/id');
           expect(template.styles).toEqual(['.foo{background-image: url(\'double.jpg\');']);
         }));

      it('should resolve relative style urls in styleUrls',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: ['test.css'],
                                                               baseUrl: 'package:some/module/a.js'
                                                             }),
                                                             '', 'package:some/module/id');
           expect(template.styles).toEqual([]);
           expect(template.styleUrls).toEqual(['package:some/module/test.css']);
         }));

      it('should resolve relative style urls in styleUrls with http directive url',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                               encapsulation: null,
                                                               styles: [],
                                                               styleUrls: ['test.css'],
                                                               baseUrl: 'http://some/module/a.js'
                                                             }),
                                                             '', 'http://some/module/id');
           expect(template.styles).toEqual([]);
           expect(template.styleUrls).toEqual(['http://some/module/test.css']);
         }));

      it('should normalize ViewEncapsulation.Emulated to ViewEncapsulation.None if there are no styles nor stylesheets',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template =
               normalizer.normalizeLoadedTemplate(dirType, new CompileTemplateMetadata({
                                                    encapsulation: ViewEncapsulation.Emulated,
                                                    styles: [],
                                                    styleUrls: [],
                                                    baseUrl: 'package:some/module/a.js'
                                                  }),
                                                  '', 'package:some/module/id');
           expect(template.encapsulation).toEqual(ViewEncapsulation.None);
         }));

      it('should ignore ng-content in elements with ngNonBindable',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: [],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '<div ngNonBindable><ng-content select="a"></ng-content></div>',
               'package:some/module/');
           expect(template.ngContentSelectors).toEqual([]);
         }));

      it('should still collect <style> in elements with ngNonBindable',
         inject([DirectiveNormalizer], (normalizer: DirectiveNormalizer) => {
           var template = normalizer.normalizeLoadedTemplate(
               dirType, new CompileTemplateMetadata({
                 encapsulation: null,
                 styles: [],
                 styleUrls: [],
                 baseUrl: 'package:some/module/a.js'
               }),
               '<div ngNonBindable><style>div {color:red}</style></div>', 'package:some/module/');
           expect(template.styles).toEqual(['div {color:red}']);
         }));
    });
  });