refactor(core): change module semantics
This contains major changes to the compiler, bootstrap of the platforms and test environment initialization. Main part of #10043 Closes #10164 BREAKING CHANGE: - Semantics and name of `@AppModule` (now `@NgModule`) changed quite a bit. This is actually not breaking as `@AppModules` were not part of rc.4. We will have detailed docs on `@NgModule` separately. - `coreLoadAndBootstrap` and `coreBootstrap` can't be used any more (without migration support). Use `bootstrapModule` / `bootstrapModuleFactory` instead. - All Components listed in routes have to be part of the `declarations` of an NgModule. Either directly on the bootstrap module / lazy loaded module, or in an NgModule imported by them.
This commit is contained in:
@ -1,256 +0,0 @@
|
||||
/**
|
||||
* @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 {beforeEach, ddescribe, describe, expect, iit, inject, it, xit,} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {CompileDirectiveMetadata, CompileTypeMetadata, CompileTemplateMetadata, CompileProviderMetadata, CompileDiDependencyMetadata, CompileQueryMetadata, CompileIdentifierMetadata, CompileFactoryMetadata, CompileTokenMetadata, CompileAnimationEntryMetadata, CompileAnimationStyleMetadata, CompileAnimationAnimateMetadata, CompileAnimationSequenceMetadata, CompileAnimationStateTransitionMetadata, CompileAnimationKeyframesSequenceMetadata, CompileAnimationGroupMetadata} from '@angular/compiler/src/compile_metadata';
|
||||
import {ViewEncapsulation} from '@angular/core/src/metadata/view';
|
||||
import {ChangeDetectionStrategy} from '@angular/core/src/change_detection';
|
||||
import {LifecycleHooks} from '@angular/core/src/metadata/lifecycle_hooks';
|
||||
|
||||
export function main() {
|
||||
describe('CompileMetadata', () => {
|
||||
var fullTypeMeta: CompileTypeMetadata;
|
||||
var fullTemplateMeta: CompileTemplateMetadata;
|
||||
var fullDirectiveMeta: CompileDirectiveMetadata;
|
||||
|
||||
beforeEach(() => {
|
||||
var diDep = new CompileDiDependencyMetadata({
|
||||
isAttribute: true,
|
||||
isSelf: true,
|
||||
isHost: true,
|
||||
isSkipSelf: true,
|
||||
isOptional: true,
|
||||
token: new CompileTokenMetadata({value: 'someToken'}),
|
||||
query: new CompileQueryMetadata({
|
||||
selectors: [new CompileTokenMetadata({value: 'one'})],
|
||||
descendants: true,
|
||||
first: true,
|
||||
propertyName: 'one'
|
||||
}),
|
||||
viewQuery: new CompileQueryMetadata({
|
||||
selectors: [new CompileTokenMetadata({value: 'one'})],
|
||||
descendants: true,
|
||||
first: true,
|
||||
propertyName: 'one'
|
||||
})
|
||||
});
|
||||
|
||||
fullTypeMeta = new CompileTypeMetadata(
|
||||
{name: 'SomeType', moduleUrl: 'someUrl', isHost: true, diDeps: [diDep]});
|
||||
fullTemplateMeta = new CompileTemplateMetadata({
|
||||
encapsulation: ViewEncapsulation.Emulated,
|
||||
template: '<a></a>',
|
||||
templateUrl: 'someTemplateUrl',
|
||||
styles: ['someStyle'],
|
||||
styleUrls: ['someStyleUrl'],
|
||||
animations: [new CompileAnimationEntryMetadata(
|
||||
'animation',
|
||||
[new CompileAnimationStateTransitionMetadata(
|
||||
'* => *', new CompileAnimationSequenceMetadata([
|
||||
new CompileAnimationStyleMetadata(0, [{'opacity': 0}]),
|
||||
new CompileAnimationAnimateMetadata(
|
||||
1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1}]))
|
||||
]))])],
|
||||
ngContentSelectors: ['*'],
|
||||
interpolation: ['{{', '}}']
|
||||
});
|
||||
fullDirectiveMeta = CompileDirectiveMetadata.create({
|
||||
selector: 'someSelector',
|
||||
isComponent: true,
|
||||
type: fullTypeMeta,
|
||||
template: fullTemplateMeta,
|
||||
changeDetection: ChangeDetectionStrategy.Default,
|
||||
inputs: ['someProp'],
|
||||
outputs: ['someEvent'],
|
||||
host: {'(event1)': 'handler1', '[prop1]': 'expr1', 'attr1': 'attrValue2'},
|
||||
lifecycleHooks: [LifecycleHooks.OnChanges],
|
||||
providers: [new CompileProviderMetadata({
|
||||
token: new CompileTokenMetadata({value: 'token'}),
|
||||
multi: true,
|
||||
useClass: fullTypeMeta,
|
||||
useExisting: new CompileTokenMetadata({
|
||||
identifier: new CompileIdentifierMetadata({name: 'someName'}),
|
||||
identifierIsInstance: true
|
||||
}),
|
||||
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
|
||||
useValue: 'someValue',
|
||||
})],
|
||||
viewProviders: [new CompileProviderMetadata({
|
||||
token: new CompileTokenMetadata({value: 'token'}),
|
||||
useClass: fullTypeMeta,
|
||||
useExisting: new CompileTokenMetadata(
|
||||
{identifier: new CompileIdentifierMetadata({name: 'someName'})}),
|
||||
useFactory: new CompileFactoryMetadata({name: 'someName', diDeps: [diDep]}),
|
||||
useValue: 'someValue'
|
||||
})],
|
||||
queries: [new CompileQueryMetadata({
|
||||
selectors: [new CompileTokenMetadata({value: 'selector'})],
|
||||
descendants: true,
|
||||
first: false,
|
||||
propertyName: 'prop',
|
||||
read: new CompileTokenMetadata({value: 'readToken'})
|
||||
})],
|
||||
viewQueries: [new CompileQueryMetadata({
|
||||
selectors: [new CompileTokenMetadata({value: 'selector'})],
|
||||
descendants: true,
|
||||
first: false,
|
||||
propertyName: 'prop',
|
||||
read: new CompileTokenMetadata({value: 'readToken'})
|
||||
})]
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('CompileIdentifierMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileIdentifierMetadata(
|
||||
{name: 'name', moduleUrl: 'module', value: ['one', ['two']]});
|
||||
expect(CompileIdentifierMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileIdentifierMetadata();
|
||||
expect(CompileIdentifierMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('DirectiveMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
expect(CompileDirectiveMetadata.fromJson(fullDirectiveMeta.toJson()))
|
||||
.toEqual(fullDirectiveMeta);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
var empty = CompileDirectiveMetadata.create();
|
||||
expect(CompileDirectiveMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TypeMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
expect(CompileTypeMetadata.fromJson(fullTypeMeta.toJson())).toEqual(fullTypeMeta);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
var empty = new CompileTypeMetadata();
|
||||
expect(CompileTypeMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('TemplateMetadata', () => {
|
||||
|
||||
it('should serialize with full data', () => {
|
||||
expect(CompileTemplateMetadata.fromJson(fullTemplateMeta.toJson()))
|
||||
.toEqual(fullTemplateMeta);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
var empty = new CompileTemplateMetadata();
|
||||
expect(CompileTemplateMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
|
||||
it('should throw an error with invalid interpolation symbols', () => {
|
||||
expect(() => new CompileTemplateMetadata(<any>{interpolation: ['{{']}))
|
||||
.toThrowError(`'interpolation' should have a start and an end symbol.`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationStyleMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationStyleMetadata(0, [{'opacity': 0, 'color': 'red'}]);
|
||||
expect(CompileAnimationStyleMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationStyleMetadata(0, []);
|
||||
expect(CompileAnimationStyleMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationAnimateMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationAnimateMetadata(
|
||||
'1s linear', new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'color': 'blue'}]));
|
||||
expect(CompileAnimationAnimateMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationAnimateMetadata();
|
||||
expect(CompileAnimationAnimateMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationSequenceMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationSequenceMetadata([
|
||||
new CompileAnimationStyleMetadata(0, [{'opacity': 0.5, 'width': 100}]),
|
||||
new CompileAnimationAnimateMetadata(
|
||||
1000, new CompileAnimationStyleMetadata(0, [{'opacity': 1, 'width': 0}]))
|
||||
]);
|
||||
expect(CompileAnimationSequenceMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationSequenceMetadata();
|
||||
expect(CompileAnimationSequenceMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationGroupMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationGroupMetadata([
|
||||
new CompileAnimationStyleMetadata(0, [{'width': 100, 'border': '1px solid red'}]),
|
||||
new CompileAnimationAnimateMetadata(
|
||||
1000, new CompileAnimationStyleMetadata(
|
||||
0, [{'width': 900, 'border': '10px solid blue'}]))
|
||||
]);
|
||||
expect(CompileAnimationGroupMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationGroupMetadata();
|
||||
expect(CompileAnimationGroupMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationKeyframesSequenceMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationKeyframesSequenceMetadata([
|
||||
new CompileAnimationStyleMetadata(0, [{'width': 0}]),
|
||||
new CompileAnimationStyleMetadata(0.5, [{'width': 100}]),
|
||||
new CompileAnimationStyleMetadata(1, [{'width': 200}]),
|
||||
]);
|
||||
expect(CompileAnimationKeyframesSequenceMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationKeyframesSequenceMetadata();
|
||||
expect(CompileAnimationKeyframesSequenceMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
|
||||
describe('CompileAnimationEntryMetadata', () => {
|
||||
it('should serialize with full data', () => {
|
||||
let full = new CompileAnimationEntryMetadata(
|
||||
'name', [new CompileAnimationStateTransitionMetadata(
|
||||
'key => value', new CompileAnimationSequenceMetadata([
|
||||
new CompileAnimationStyleMetadata(0, [{'color': 'red'}]),
|
||||
new CompileAnimationAnimateMetadata(
|
||||
1000, new CompileAnimationStyleMetadata(0, [{'color': 'blue'}]))
|
||||
]))]);
|
||||
expect(CompileAnimationEntryMetadata.fromJson(full.toJson())).toEqual(full);
|
||||
});
|
||||
|
||||
it('should serialize with no data', () => {
|
||||
let empty = new CompileAnimationEntryMetadata();
|
||||
expect(CompileAnimationEntryMetadata.fromJson(empty.toJson())).toEqual(empty);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
@ -12,6 +12,7 @@ import {LIFECYCLE_HOOKS_VALUES} from '@angular/core/src/metadata/lifecycle_hooks
|
||||
import {configureCompiler} from '@angular/core/testing';
|
||||
import {afterEach, beforeEach, beforeEachProviders, ddescribe, describe, expect, iit, inject, it, xdescribe, xit} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {CompileNgModuleMetadata} from '../src/compile_metadata';
|
||||
import {IS_DART, stringify} from '../src/facade/lang';
|
||||
import {CompileMetadataResolver} from '../src/metadata_resolver';
|
||||
|
||||
@ -22,7 +23,7 @@ export function main() {
|
||||
describe('CompileMetadataResolver', () => {
|
||||
beforeEach(() => { configureCompiler({providers: TEST_COMPILER_PROVIDERS}); });
|
||||
|
||||
describe('getMetadata', () => {
|
||||
describe('getDirectiveMetadata', () => {
|
||||
it('should read metadata',
|
||||
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
||||
var meta = resolver.getDirectiveMetadata(ComponentWithEverything);
|
||||
@ -102,35 +103,6 @@ export function main() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('getViewDirectivesMetadata', () => {
|
||||
|
||||
it('should return the directive metadatas',
|
||||
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
||||
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
|
||||
.toContain(resolver.getDirectiveMetadata(SomeDirective));
|
||||
}));
|
||||
|
||||
describe('platform directives', () => {
|
||||
beforeEach(() => {
|
||||
configureCompiler({
|
||||
providers: [{
|
||||
provide: CompilerConfig,
|
||||
useValue: new CompilerConfig(
|
||||
{genDebugInfo: true, deprecatedPlatformDirectives: [ADirective]})
|
||||
}]
|
||||
});
|
||||
});
|
||||
|
||||
it('should include platform directives when available',
|
||||
inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
|
||||
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
|
||||
.toContain(resolver.getDirectiveMetadata(ADirective));
|
||||
expect(resolver.getViewDirectivesMetadata(ComponentWithEverything))
|
||||
.toContain(resolver.getDirectiveMetadata(SomeDirective));
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @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 {beforeEach, ddescribe, describe, expect, iit, it, inject,} from '@angular/core/testing/testing_internal';
|
||||
|
||||
import {stringify, isBlank} from '../src/facade/lang';
|
||||
import {MockNgModuleResolver} from '../testing';
|
||||
import {NgModule, NgModuleMetadata, Injector} from '@angular/core';
|
||||
|
||||
export function main() {
|
||||
describe('MockNgModuleResolver', () => {
|
||||
var ngModuleResolver: MockNgModuleResolver;
|
||||
|
||||
beforeEach(inject([Injector], (injector: Injector) => {
|
||||
ngModuleResolver = new MockNgModuleResolver(injector);
|
||||
}));
|
||||
|
||||
describe('NgModule overriding', () => {
|
||||
it('should fallback to the default NgModuleResolver when templates are not overridden',
|
||||
() => {
|
||||
var ngModule = ngModuleResolver.resolve(SomeNgModule);
|
||||
expect(ngModule.declarations).toEqual([SomeDirective]);
|
||||
});
|
||||
|
||||
it('should allow overriding the @NgModule', () => {
|
||||
ngModuleResolver.setNgModule(
|
||||
SomeNgModule, new NgModuleMetadata({declarations: [SomeOtherDirective]}));
|
||||
var ngModule = ngModuleResolver.resolve(SomeNgModule);
|
||||
expect(ngModule.declarations).toEqual([SomeOtherDirective]);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
class SomeDirective {}
|
||||
|
||||
class SomeOtherDirective {}
|
||||
|
||||
@NgModule({declarations: [SomeDirective]})
|
||||
class SomeNgModule {
|
||||
}
|
53
modules/@angular/compiler/test/ng_module_resolver_spec.ts
Normal file
53
modules/@angular/compiler/test/ng_module_resolver_spec.ts
Normal file
@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @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 {NgModuleResolver} from '@angular/compiler/src/ng_module_resolver';
|
||||
import {NgModule, NgModuleMetadata} from '@angular/core/src/metadata';
|
||||
import {stringify} from '../src/facade/lang';
|
||||
|
||||
class SomeClass1 {}
|
||||
class SomeClass2 {}
|
||||
class SomeClass3 {}
|
||||
class SomeClass4 {}
|
||||
class SomeClass5 {}
|
||||
|
||||
@NgModule({
|
||||
declarations: [SomeClass1],
|
||||
imports: [SomeClass2],
|
||||
exports: [SomeClass3],
|
||||
providers: [SomeClass4],
|
||||
precompile: [SomeClass5]
|
||||
})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
class SimpleClass {}
|
||||
|
||||
export function main() {
|
||||
describe('NgModuleResolver', () => {
|
||||
var resolver: NgModuleResolver;
|
||||
|
||||
beforeEach(() => { resolver = new NgModuleResolver(); });
|
||||
|
||||
it('should read out the metadata from the class', () => {
|
||||
var viewMetadata = resolver.resolve(SomeModule);
|
||||
expect(viewMetadata).toEqual(new NgModuleMetadata({
|
||||
declarations: [SomeClass1],
|
||||
imports: [SomeClass2],
|
||||
exports: [SomeClass3],
|
||||
providers: [SomeClass4],
|
||||
precompile: [SomeClass5]
|
||||
}));
|
||||
});
|
||||
|
||||
it('should throw when simple class has no component decorator', () => {
|
||||
expect(() => resolver.resolve(SimpleClass))
|
||||
.toThrowError(`No NgModule metadata found for '${stringify(SimpleClass)}'.`);
|
||||
});
|
||||
});
|
||||
}
|
@ -8,7 +8,7 @@
|
||||
|
||||
import {beforeEach, ddescribe, xdescribe, describe, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, AppModule, AppModuleMetadata, AppModuleFactory} from '@angular/core';
|
||||
import {Injectable, Component, Input, ViewMetadata, Compiler, ComponentFactory, Injector, NgModule, NgModuleFactory} from '@angular/core';
|
||||
import {ConcreteType, stringify} from '../src/facade/lang';
|
||||
import {fakeAsync, tick, TestComponentBuilder, ComponentFixture, configureCompiler} from '@angular/core/testing';
|
||||
import {XHR, ViewResolver} from '@angular/compiler';
|
||||
@ -28,10 +28,6 @@ class SomeComp {
|
||||
class SomeCompWithUrlTemplate {
|
||||
}
|
||||
|
||||
@AppModule({})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
export function main() {
|
||||
describe('RuntimeCompiler', () => {
|
||||
let compiler: Compiler;
|
||||
@ -118,49 +114,61 @@ export function main() {
|
||||
}));
|
||||
});
|
||||
|
||||
describe('compileAppModuleAsync', () => {
|
||||
describe('compileModuleAsync', () => {
|
||||
it('should allow to use templateUrl components', fakeAsync(() => {
|
||||
@NgModule(
|
||||
{declarations: [SomeCompWithUrlTemplate], precompile: [SomeCompWithUrlTemplate]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
|
||||
let appModuleFactory: AppModuleFactory<any>;
|
||||
compiler
|
||||
.compileAppModuleAsync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}))
|
||||
.then((f) => appModuleFactory = f);
|
||||
let ngModuleFactory: NgModuleFactory<any>;
|
||||
compiler.compileModuleAsync(SomeModule).then((f) => ngModuleFactory = f);
|
||||
tick();
|
||||
expect(appModuleFactory.moduleType).toBe(SomeModule);
|
||||
expect(ngModuleFactory.moduleType).toBe(SomeModule);
|
||||
}));
|
||||
});
|
||||
|
||||
describe('compileAppModuleSync', () => {
|
||||
describe('compileModuleSync', () => {
|
||||
it('should throw when using a templateUrl that has not been compiled before', () => {
|
||||
@NgModule({declarations: [SomeCompWithUrlTemplate], precompile: [SomeCompWithUrlTemplate]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
||||
expect(
|
||||
() => compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]})))
|
||||
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], precompile: [SomeComp]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve(''));
|
||||
viewResolver.setView(
|
||||
SomeComp, new ViewMetadata({template: '', directives: [ChildComp]}));
|
||||
viewResolver.setView(ChildComp, new ViewMetadata({templateUrl: '/someTpl.html'}));
|
||||
expect(
|
||||
() => compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeComp]})))
|
||||
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], precompile: [SomeCompWithUrlTemplate]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
xhr.spy('get').andCallFake(() => Promise.resolve('hello'));
|
||||
tcb.createFakeAsync(SomeCompWithUrlTemplate);
|
||||
let appModuleFactory = compiler.compileAppModuleSync(
|
||||
SomeModule, new AppModuleMetadata({precompile: [SomeCompWithUrlTemplate]}));
|
||||
expect(appModuleFactory).toBeTruthy();
|
||||
compiler.compileModuleAsync(SomeModule);
|
||||
tick();
|
||||
|
||||
let ngModuleFactory = compiler.compileModuleSync(SomeModule);
|
||||
expect(ngModuleFactory).toBeTruthy();
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
@ -9,7 +9,7 @@
|
||||
import {AsyncTestCompleter, beforeEach, ddescribe, xdescribe, describe, iit, inject, beforeEachProviders, it, xit,} from '@angular/core/testing/testing_internal';
|
||||
import {expect} from '@angular/platform-browser/testing/matchers';
|
||||
import {TestComponentBuilder, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, withProviders} from '@angular/core/testing';
|
||||
import {Injectable, Component, Input, ViewMetadata} from '@angular/core';
|
||||
import {Injectable, Component, Input, ViewMetadata, Pipe, NgModule} from '@angular/core';
|
||||
import {NgIf} from '@angular/common';
|
||||
import {TimerWrapper} from '../src/facade/async';
|
||||
import {PromiseWrapper} from '../src/facade/promise';
|
||||
@ -327,6 +327,27 @@ export function main() {
|
||||
expect(componentFixture.nativeElement).toHaveText('Mock');
|
||||
}));
|
||||
|
||||
it('should create components synchronously with a custom module',
|
||||
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
|
||||
@Pipe({name: 'somePipe'})
|
||||
class SomePipe {
|
||||
transform(value: any) { return `transformed ${value}`; }
|
||||
}
|
||||
|
||||
@NgModule({declarations: [SomePipe]})
|
||||
class SomeModule {
|
||||
}
|
||||
|
||||
@Component({selector: 'comp', template: `{{'hello' | somePipe}}`})
|
||||
class SomeComponent {
|
||||
}
|
||||
|
||||
|
||||
let componentFixture = tcb.createSync(SomeComponent, SomeModule);
|
||||
componentFixture.detectChanges();
|
||||
expect(componentFixture.nativeElement).toHaveText('transformed hello');
|
||||
}));
|
||||
|
||||
describe('ComponentFixture', () => {
|
||||
it('should auto detect changes if autoDetectChanges is called',
|
||||
inject(
|
||||
|
Reference in New Issue
Block a user