BREAKING CHANGE: previously deprecated @Component.directives and @Component.pipes support was removed. All the components and pipes now must be declarated via an NgModule. NgModule is the basic compilation block passed into the Angular compiler via Compiler#compileModuleSync or #compileModuleAsync. Because of this change, the Compiler#compileComponentAsync and #compileComponentSync were removed as well - any code doing compilation should compile module instead using the apis mentioned above. Lastly, since modules are the basic compilation unit, the ngUpgrade module was modified to always require an NgModule to be passed into the UpgradeAdapter's constructor - previously this was optional.
174 lines
6.6 KiB
TypeScript
174 lines
6.6 KiB
TypeScript
/**
|
|
* @license
|
|
* Copyright Google Inc. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by an MIT-style license that can be
|
|
* found in the LICENSE file at https://angular.io/license
|
|
*/
|
|
|
|
import {DirectiveResolver, ResourceLoader} from '@angular/compiler';
|
|
import {MockDirectiveResolver} from '@angular/compiler/testing';
|
|
import {Compiler, Component, ComponentFactory, Injectable, Injector, Input, NgModule, NgModuleFactory, Type} from '@angular/core';
|
|
import {ComponentFixture, TestBed, async, fakeAsync, getTestBed, tick} from '@angular/core/testing';
|
|
import {beforeEach, beforeEachProviders, ddescribe, describe, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
|
|
import {expect} from '@angular/platform-browser/testing/matchers';
|
|
|
|
import {ViewMetadata} from '../core_private';
|
|
import {stringify} from '../src/facade/lang';
|
|
|
|
import {SpyResourceLoader} from './spies';
|
|
|
|
@Component({selector: 'child-cmp'})
|
|
class ChildComp {
|
|
}
|
|
|
|
@Component({selector: 'some-cmp', template: 'someComp'})
|
|
class SomeComp {
|
|
}
|
|
|
|
@Component({selector: 'some-cmp', templateUrl: './someTpl'})
|
|
class SomeCompWithUrlTemplate {
|
|
}
|
|
|
|
export function main() {
|
|
describe('RuntimeCompiler', () => {
|
|
|
|
describe('compilerComponentSync', () => {
|
|
describe('never resolving loader', () => {
|
|
class StubResourceLoader {
|
|
get(url: string) { return new Promise(() => {}); }
|
|
}
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureCompiler(
|
|
{providers: [{provide: ResourceLoader, useClass: StubResourceLoader}]});
|
|
});
|
|
|
|
it('should throw when using a templateUrl that has not been compiled before', async(() => {
|
|
TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]});
|
|
TestBed.compileComponents().then(() => {
|
|
expect(() => TestBed.createComponent(SomeCompWithUrlTemplate))
|
|
.toThrowError(
|
|
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
|
|
});
|
|
}));
|
|
|
|
it('should throw when using a templateUrl in a nested component that has not been compiled before',
|
|
() => {
|
|
TestBed.configureTestingModule({declarations: [SomeComp, ChildComp]});
|
|
TestBed.overrideComponent(ChildComp, {set: {templateUrl: '/someTpl.html'}});
|
|
TestBed.overrideComponent(SomeComp, {set: {template: '<child-cmp></child-cmp>'}});
|
|
TestBed.compileComponents().then(() => {
|
|
expect(() => TestBed.createComponent(SomeComp))
|
|
.toThrowError(
|
|
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('resolving loader', () => {
|
|
class StubResourceLoader {
|
|
get(url: string) { return Promise.resolve('hello'); }
|
|
}
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureCompiler(
|
|
{providers: [{provide: ResourceLoader, useClass: StubResourceLoader}]});
|
|
});
|
|
|
|
it('should allow to use templateUrl components that have been loaded before', async(() => {
|
|
TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]});
|
|
TestBed.compileComponents().then(() => {
|
|
const fixture = TestBed.createComponent(SomeCompWithUrlTemplate);
|
|
expect(fixture.nativeElement).toHaveText('hello');
|
|
});
|
|
}));
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('RuntimeCompiler', () => {
|
|
let compiler: Compiler;
|
|
let resourceLoader: SpyResourceLoader;
|
|
let dirResolver: MockDirectiveResolver;
|
|
let injector: Injector;
|
|
|
|
beforeEach(() => {
|
|
TestBed.configureCompiler(
|
|
{providers: [{provide: ResourceLoader, useClass: SpyResourceLoader}]});
|
|
});
|
|
|
|
beforeEach(fakeAsync(inject(
|
|
[Compiler, ResourceLoader, DirectiveResolver, Injector],
|
|
(_compiler: Compiler, _resourceLoader: SpyResourceLoader,
|
|
_dirResolver: MockDirectiveResolver, _injector: Injector) => {
|
|
compiler = _compiler;
|
|
resourceLoader = _resourceLoader;
|
|
dirResolver = _dirResolver;
|
|
injector = _injector;
|
|
})));
|
|
|
|
describe('compileModuleAsync', () => {
|
|
it('should allow to use templateUrl components', fakeAsync(() => {
|
|
@NgModule({
|
|
declarations: [SomeCompWithUrlTemplate],
|
|
entryComponents: [SomeCompWithUrlTemplate]
|
|
})
|
|
class SomeModule {
|
|
}
|
|
|
|
resourceLoader.spy('get').andCallFake(() => Promise.resolve('hello'));
|
|
let ngModuleFactory: NgModuleFactory<any>;
|
|
compiler.compileModuleAsync(SomeModule).then((f) => ngModuleFactory = f);
|
|
tick();
|
|
expect(ngModuleFactory.moduleType).toBe(SomeModule);
|
|
}));
|
|
});
|
|
|
|
describe('compileModuleSync', () => {
|
|
it('should throw when using a templateUrl that has not been compiled before', () => {
|
|
@NgModule(
|
|
{declarations: [SomeCompWithUrlTemplate], entryComponents: [SomeCompWithUrlTemplate]})
|
|
class SomeModule {
|
|
}
|
|
|
|
resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
|
|
expect(() => compiler.compileModuleSync(SomeModule))
|
|
.toThrowError(
|
|
`Can't compile synchronously as ${stringify(SomeCompWithUrlTemplate)} is still being loaded!`);
|
|
});
|
|
|
|
it('should throw when using a templateUrl in a nested component that has not been compiled before',
|
|
() => {
|
|
@NgModule({declarations: [SomeComp, ChildComp], entryComponents: [SomeComp]})
|
|
class SomeModule {
|
|
}
|
|
|
|
resourceLoader.spy('get').andCallFake(() => Promise.resolve(''));
|
|
dirResolver.setView(SomeComp, new ViewMetadata({template: ''}));
|
|
dirResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
|
|
expect(() => compiler.compileModuleSync(SomeModule))
|
|
.toThrowError(
|
|
`Can't compile synchronously as ${stringify(ChildComp)} is still being loaded!`);
|
|
});
|
|
|
|
it('should allow to use templateUrl components that have been loaded before',
|
|
fakeAsync(() => {
|
|
@NgModule({
|
|
declarations: [SomeCompWithUrlTemplate],
|
|
entryComponents: [SomeCompWithUrlTemplate]
|
|
})
|
|
class SomeModule {
|
|
}
|
|
|
|
resourceLoader.spy('get').andCallFake(() => Promise.resolve('hello'));
|
|
compiler.compileModuleAsync(SomeModule);
|
|
tick();
|
|
|
|
let ngModuleFactory = compiler.compileModuleSync(SomeModule);
|
|
expect(ngModuleFactory).toBeTruthy();
|
|
}));
|
|
});
|
|
});
|
|
}
|