Ejemplo n.º 1
0
    it('should not reexport type symbols mentioned in constructors', () => {
      const libInput: MockDirectory = {
        'lib': {
          'base.ts': `
            export type AType = {};

            export class AClass {
              constructor(a: AType) {}
            }
          `
        }
      };
      const appInput: MockDirectory = {
        'app': {
          'main.ts': `
            export * from '../lib/base';
          `
        }
      };

      const {outDir: libOutDir} = compile([libInput, angularSummaryFiles], {useSummaries: true});
      const {genFiles: appGenFiles} =
          compile([appInput, libOutDir, angularSummaryFiles], {useSummaries: true});
      const appNgFactory = appGenFiles.find((f) => f.genFileUrl === '/app/main.ngfactory.ts');
      expect(toTypeScript(appNgFactory)).not.toContain('AType');
    });
Ejemplo n.º 2
0
  it('should create @Injectable summaries', () => {
    const appDir = {
      'app.module.ts': `
        import { Injectable } from '@angular/core';

        export class Dep {}

        @Injectable()
        export class MyService {
          constructor(d: Dep) {}
        }
      `
    };
    const rootDir = {'app': appDir};

    const genFile =
        compileApp(rootDir).genFiles.find(f => f.genFileUrl === '/app/app.module.ngsummary.ts');
    const genSource = toTypeScript(genFile);

    expect(genSource).toContain(`import * as i0 from '/app/app.module'`);
    expect(genSource).toContain('export function MyServiceNgSummary()');
    // Note: CompileSummaryKind.Injectable = 3
    expect(genSource).toMatch(/summaryKind:3,\s*type:\{\s*reference:i0.MyService/);
    expect(genSource).toContain('token:{identifier:{reference:i0.Dep}}');
  });
Ejemplo n.º 3
0
    it('should not reexport already exported symbols except for lowered symbols', () => {
      const libInput: MockDirectory = {
        'lib': {
          'base.ts': `
            export const exportedVar = 1;

            // A symbol introduced by lowering expressions
            export const ɵ1 = 'lowered symbol';
          `
        }
      };
      const appInput: MockDirectory = {
        'app': {
          'main.ts': `export * from '../lib/base';`,
        }
      };

      const {outDir: libOutDir} = compile([libInput, angularSummaryFiles], {useSummaries: true});
      const {genFiles: appGenFiles} =
          compile([appInput, libOutDir, angularSummaryFiles], {useSummaries: true});
      const appNgFactory = appGenFiles.find((f) => f.genFileUrl === '/app/main.ngfactory.ts');
      const appNgFactoryTs = toTypeScript(appNgFactory);

      // we don't need to reexport exported symbols via the .ngfactory
      // as we can refer to them via the reexport.
      expect(appNgFactoryTs).not.toContain('exportedVar');

      // although ɵ1 is reexported via `export *`, we still need to reexport it
      // via the .ngfactory as tsickle expands `export *` into named exports,
      // and doesn't know about our lowered symbols as we introduce them
      // after the typecheck phase.
      expect(appNgFactoryTs).toContain('ɵ1');
    });
Ejemplo n.º 4
0
  it('should embed useClass provider summaries into @NgModule summaries', () => {
    const appDir = {
      'app.service.ts': `
        import { Injectable } from '@angular/core';

        export class Dep {}

        @Injectable()
        export class MyService {
          constructor(d: Dep) {}
        }
      `,
      'app.module.ts': `
        import { NgModule } from '@angular/core';
        import { MyService } from './app.service';

        @NgModule({
          providers: [MyService]
        })
        export class MyModule {}
      `
    };
    const rootDir = {'app': appDir};

    const genFile =
        compileApp(rootDir).genFiles.find(f => f.genFileUrl === '/app/app.module.ngsummary.ts');
    const genSource = toTypeScript(genFile);

    expect(genSource).toMatch(/useClass:\{\s*reference:i1.MyService/);
    // Note: CompileSummaryKind.Injectable = 3
    expect(genSource).toMatch(/summaryKind:3,\s*type:\{\s*reference:i1.MyService/);
    expect(genSource).toContain('token:{identifier:{reference:i1.Dep}}');
  });
Ejemplo n.º 5
0
  it('should create @Directive summaries', () => {
    const appDir = {
      'app.module.ts': `
        import { Directive, NgModule } from '@angular/core';

        export class Dep {}

        @Directive({selector: '[myDir]'})
        export class MyDirective {
          constructor(a: Dep) {}
        }

        @NgModule({declarations: [MyDirective]})
        export class MyModule {}
      `
    };
    const rootDir = {'app': appDir};

    const genFile =
        compileApp(rootDir).genFiles.find(f => f.genFileUrl === '/app/app.module.ngsummary.ts');
    const genSource = toTypeScript(genFile);

    expect(genSource).toContain(`import * as i0 from '/app/app.module'`);
    expect(genSource).toContain('export function MyDirectiveNgSummary()');
    // Note: CompileSummaryKind.Directive = 1
    expect(genSource).toMatch(/summaryKind:1,\s*type:\{\s*reference:i0.MyDirective/);
    expect(genSource).toContain('token:{identifier:{reference:i0.Dep}}');
  });
Ejemplo n.º 6
0
      it('should map non template parts to the source file', () => {
        appDir['app.component.ts'] = createComponentSource(templateDecorator('Hello World!'));

        const genFile = compileApp();
        const genSource = toTypeScript(genFile);
        const sourceMap = extractSourceMap(genSource) !;
        expect(originalPositionFor(sourceMap, {line: 1, column: 0}))
            .toEqual({line: 1, column: 0, source: ngComponentPath});
      });
Ejemplo n.º 7
0
      it('should map events correctly to the source', () => {
        const template = `<div>\n   <span (click)="someMethod()"></span></div>`;

        appDir['app.component.ts'] = createComponentSource(templateDecorator(template));

        const genFile = compileApp();
        const genSource = toTypeScript(genFile);
        const sourceMap = extractSourceMap(genSource) !;
        expect(originalPositionFor(sourceMap, findLineAndColumn(genSource, `someMethod()`)))
            .toEqual({line: 2, column: 9, source: ngUrl});
      });
Ejemplo n.º 8
0
       () => {
         const lib1Input: MockDirectory = {
           'lib1': {
             'base.ts': `
            export class AParam {}

            export class Base {
              constructor(a: AParam) {}
              ngOnDestroy() {}
            }
          `
           }
         };

         const lib2Input: MockDirectory = {
           'lib2': {
             'middle.ts': `
            import {Base} from '../lib1/base';
            export class Middle extends Base {}
          `
           }
         };


         const appInput: MockDirectory = {
           'app': {
             'main.ts': `
            import {NgModule, Component} from '@angular/core';
            import {Middle} from '../lib2/middle';

            @Component({template: ''})
            export class Extends extends Middle {}

            @NgModule({
              declarations: [Extends]
            })
            export class MyModule {}
          `
           }
         };
         const {outDir: lib1OutDir} =
             compile([lib1Input, getAngularSummaryFiles()], {useSummaries: true});
         const {outDir: lib2OutDir} =
             compile([lib1OutDir, lib2Input, getAngularSummaryFiles()], {useSummaries: true});
         const {genFiles} = compile(
             [lib1OutDir, lib2OutDir, appInput, getAngularSummaryFiles()], {useSummaries: true});

         const mainNgFactory = genFiles.find(gf => gf.srcFileUrl === '/app/main.ts') !;
         const flags = NodeFlags.TypeDirective | NodeFlags.Component | NodeFlags.OnDestroy;
         const mainNgFactorySource = toTypeScript(mainNgFactory);
         expect(mainNgFactorySource).toContain(`import * as i2 from '/lib1/base';`);
         expect(mainNgFactorySource).toContain(`${flags},(null as any),0,i1.Extends,[i2.AParam]`);
       });
Ejemplo n.º 9
0
  it('should detect an entry component via an indirection', () => {
    const FILES = {
      app: {
        'app.ts': `
          import {NgModule, ANALYZE_FOR_ENTRY_COMPONENTS} from '@angular/core';
          import {AppComponent} from './app.component';
          import {COMPONENT_VALUE, MyComponent} from './my-component';

          @NgModule({
            declarations: [ AppComponent, MyComponent ],
            bootstrap: [ AppComponent ],
            providers: [{
              provide: ANALYZE_FOR_ENTRY_COMPONENTS,
              multi: true,
              useValue: COMPONENT_VALUE
            }],
          })
          export class AppModule { }
        `,
        'app.component.ts': `
          import {Component} from '@angular/core';

          @Component({
            selector: 'app-component',
            template: '<div></div>',
          })
          export class AppComponent { }
        `,
        'my-component.ts': `
          import {Component} from '@angular/core';

          @Component({
            selector: 'my-component',
            template: '<div></div>',
          })
          export class MyComponent {}

          export const COMPONENT_VALUE = [{a: 'b', component: MyComponent}];
        `
      }
    };
    const result = compile([FILES, angularFiles]);
    const appModuleFactory =
        result.genFiles.find(f => /my-component\.ngfactory/.test(f.genFileUrl));
    expect(appModuleFactory).toBeDefined();
    if (appModuleFactory) {
      expect(toTypeScript(appModuleFactory)).toContain('MyComponentNgFactory');
    }
  });
Ejemplo n.º 10
0
    it('should include inputs, outputs and ng-content selectors in the component factory', () => {
      const FILES: MockDirectory = {
        app: {
          'app.ts': `
                import {Component, NgModule, Input, Output} from '@angular/core';

                @Component({
                  selector: 'my-comp',
                  template:
                  '<ng-content select="child1"></ng-content>' +
                  '<ng-content></ng-content>' +
                  '<ng-template><ng-content select="child2"></ng-content></ng-template>' +
                  '<ng-content select="child3"></ng-content>' +
                  '<ng-content select="child1"></ng-content>'
                })
                export class MyComp {
                  @Input('aInputName')
                  aInputProp: string;

                  @Output('aOutputName')
                  aOutputProp: any;
                }

                @NgModule({
                  declarations: [MyComp]
                })
                export class MyModule {}
              `
        }
      };
      const {genFiles} = compile([FILES, angularFiles]);
      const genFile = genFiles.find(genFile => genFile.srcFileUrl === '/app/app.ts') !;
      const genSource = toTypeScript(genFile);
      const createComponentFactoryCall = /ɵccf\([^)]*\)/m.exec(genSource) ![0].replace(/\s*/g, '');
      // selector
      expect(createComponentFactoryCall).toContain('my-comp');
      // inputs
      expect(createComponentFactoryCall).toContain(`{aInputProp:'aInputName'}`);
      // outputs
      expect(createComponentFactoryCall).toContain(`{aOutputProp:'aOutputName'}`);
      // ngContentSelectors - note that the catch-all doesn't have to appear at the start
      expect(createComponentFactoryCall).toContain(`['child1','*','child2','child3','child1']`);
    });