@ -11,6 +11,7 @@ const sourcemaps = require('rollup-plugin-sourcemaps');
|
||||
|
||||
const globals = {
|
||||
'@angular/core': 'ng.core',
|
||||
'@angular/compiler': 'ng.compiler',
|
||||
'rxjs': 'rxjs',
|
||||
};
|
||||
|
||||
|
131
packages/core/testing/src/metadata_overrider.ts
Normal file
131
packages/core/testing/src/metadata_overrider.ts
Normal file
@ -0,0 +1,131 @@
|
||||
/**
|
||||
* @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 {ɵstringify as stringify} from '@angular/core';
|
||||
import {MetadataOverride} from './metadata_override';
|
||||
|
||||
type StringMap = {
|
||||
[key: string]: any
|
||||
};
|
||||
|
||||
let _nextReferenceId = 0;
|
||||
|
||||
export class MetadataOverrider {
|
||||
private _references = new Map<any, string>();
|
||||
/**
|
||||
* Creates a new instance for the given metadata class
|
||||
* based on an old instance and overrides.
|
||||
*/
|
||||
overrideMetadata<C extends T, T>(
|
||||
metadataClass: {new (options: T): C;}, oldMetadata: C, override: MetadataOverride<T>): C {
|
||||
const props: StringMap = {};
|
||||
if (oldMetadata) {
|
||||
_valueProps(oldMetadata).forEach((prop) => props[prop] = (<any>oldMetadata)[prop]);
|
||||
}
|
||||
|
||||
if (override.set) {
|
||||
if (override.remove || override.add) {
|
||||
throw new Error(`Cannot set and add/remove ${stringify(metadataClass)} at the same time!`);
|
||||
}
|
||||
setMetadata(props, override.set);
|
||||
}
|
||||
if (override.remove) {
|
||||
removeMetadata(props, override.remove, this._references);
|
||||
}
|
||||
if (override.add) {
|
||||
addMetadata(props, override.add);
|
||||
}
|
||||
return new metadataClass(<any>props);
|
||||
}
|
||||
}
|
||||
|
||||
function removeMetadata(metadata: StringMap, remove: any, references: Map<any, string>) {
|
||||
const removeObjects = new Set<string>();
|
||||
for (const prop in remove) {
|
||||
const removeValue = remove[prop];
|
||||
if (removeValue instanceof Array) {
|
||||
removeValue.forEach(
|
||||
(value: any) => { removeObjects.add(_propHashKey(prop, value, references)); });
|
||||
} else {
|
||||
removeObjects.add(_propHashKey(prop, removeValue, references));
|
||||
}
|
||||
}
|
||||
|
||||
for (const prop in metadata) {
|
||||
const propValue = metadata[prop];
|
||||
if (propValue instanceof Array) {
|
||||
metadata[prop] = propValue.filter(
|
||||
(value: any) => !removeObjects.has(_propHashKey(prop, value, references)));
|
||||
} else {
|
||||
if (removeObjects.has(_propHashKey(prop, propValue, references))) {
|
||||
metadata[prop] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addMetadata(metadata: StringMap, add: any) {
|
||||
for (const prop in add) {
|
||||
const addValue = add[prop];
|
||||
const propValue = metadata[prop];
|
||||
if (propValue != null && propValue instanceof Array) {
|
||||
metadata[prop] = propValue.concat(addValue);
|
||||
} else {
|
||||
metadata[prop] = addValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setMetadata(metadata: StringMap, set: any) {
|
||||
for (const prop in set) {
|
||||
metadata[prop] = set[prop];
|
||||
}
|
||||
}
|
||||
|
||||
function _propHashKey(propName: any, propValue: any, references: Map<any, string>): string {
|
||||
const replacer = (key: any, value: any) => {
|
||||
if (typeof value === 'function') {
|
||||
value = _serializeReference(value, references);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
|
||||
return `${propName}:${JSON.stringify(propValue, replacer)}`;
|
||||
}
|
||||
|
||||
function _serializeReference(ref: any, references: Map<any, string>): string {
|
||||
let id = references.get(ref);
|
||||
if (!id) {
|
||||
id = `${stringify(ref)}${_nextReferenceId++}`;
|
||||
references.set(ref, id);
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
function _valueProps(obj: any): string[] {
|
||||
const props: string[] = [];
|
||||
// regular public props
|
||||
Object.keys(obj).forEach((prop) => {
|
||||
if (!prop.startsWith('_')) {
|
||||
props.push(prop);
|
||||
}
|
||||
});
|
||||
|
||||
// getters
|
||||
let proto = obj;
|
||||
while (proto = Object.getPrototypeOf(proto)) {
|
||||
Object.keys(proto).forEach((protoProp) => {
|
||||
const desc = Object.getOwnPropertyDescriptor(proto, protoProp);
|
||||
if (!protoProp.startsWith('_') && desc && 'get' in desc) {
|
||||
props.push(protoProp);
|
||||
}
|
||||
});
|
||||
}
|
||||
return props;
|
||||
}
|
604
packages/core/testing/src/r3_test_bed.ts
Normal file
604
packages/core/testing/src/r3_test_bed.ts
Normal file
@ -0,0 +1,604 @@
|
||||
/**
|
||||
* @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 {Component, Directive, Injector, NgModule, Pipe, PlatformRef, Provider, RendererFactory2, SchemaMetadata, Type, ɵNgModuleDefInternal as NgModuleDefInternal, ɵNgModuleTransitiveScopes as NgModuleTransitiveScopes, ɵRender3ComponentFactory as ComponentFactory, ɵRender3DebugRendererFactory2 as Render3DebugRendererFactory2, ɵRender3NgModuleRef as NgModuleRef, ɵWRAP_RENDERER_FACTORY2 as WRAP_RENDERER_FACTORY2, ɵcompileComponent as compileComponent, ɵcompileDirective as compileDirective, ɵcompileNgModuleDefs as compileNgModuleDefs, ɵcompilePipe as compilePipe, ɵpatchComponentDefWithScope as patchComponentDefWithScope, ɵstringify as stringify} from '@angular/core';
|
||||
|
||||
import {ComponentFixture} from './component_fixture';
|
||||
import {MetadataOverride} from './metadata_override';
|
||||
import {ComponentResolver, DirectiveResolver, NgModuleResolver, PipeResolver, Resolver} from './resolvers';
|
||||
import {ComponentFixtureAutoDetect, TestComponentRenderer, TestModuleMetadata} from './test_bed_common';
|
||||
|
||||
let _nextRootElementId = 0;
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Configures and initializes environment for unit testing and provides methods for
|
||||
* creating components and services in unit tests.
|
||||
*
|
||||
* TestBed is the primary api for writing unit tests for Angular applications and libraries.
|
||||
*
|
||||
* Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
|
||||
* according to the compiler used.
|
||||
*/
|
||||
export class TestBedRender3 {
|
||||
/**
|
||||
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an
|
||||
* angular module. These are common to every test in the suite.
|
||||
*
|
||||
* This may only be called once, to set up the common providers for the current test
|
||||
* suite on the current platform. If you absolutely need to change the providers,
|
||||
* first use `resetTestEnvironment`.
|
||||
*
|
||||
* Test modules and platforms for individual platforms are available from
|
||||
* '@angular/<platform_name>/testing'.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
static initTestEnvironment(
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef,
|
||||
aotSummaries?: () => any[]): TestBedRender3 {
|
||||
const testBed = _getTestBedRender3();
|
||||
testBed.initTestEnvironment(ngModule, platform, aotSummaries);
|
||||
return testBed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the providers for the test injector.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
static resetTestEnvironment(): void { _getTestBedRender3().resetTestEnvironment(); }
|
||||
|
||||
static configureCompiler(config: {providers?: any[]; useJit?: boolean;}): typeof TestBedRender3 {
|
||||
_getTestBedRender3().configureCompiler(config);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows overriding default providers, directives, pipes, modules of the test injector,
|
||||
* which are defined in test_injector.js
|
||||
*/
|
||||
static configureTestingModule(moduleDef: TestModuleMetadata): typeof TestBedRender3 {
|
||||
_getTestBedRender3().configureTestingModule(moduleDef);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile components with a `templateUrl` for the test's NgModule.
|
||||
* It is necessary to call this function
|
||||
* as fetching urls is asynchronous.
|
||||
*/
|
||||
static compileComponents(): Promise<any> { return _getTestBedRender3().compileComponents(); }
|
||||
|
||||
static overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>):
|
||||
typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideModule(ngModule, override);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
static overrideComponent(component: Type<any>, override: MetadataOverride<Component>):
|
||||
typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideComponent(component, override);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
static overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>):
|
||||
typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideDirective(directive, override);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
static overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): typeof TestBedRender3 {
|
||||
_getTestBedRender3().overridePipe(pipe, override);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
static overrideTemplate(component: Type<any>, template: string): typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideComponent(component, {set: {template, templateUrl: null !}});
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the template of the given component, compiling the template
|
||||
* in the context of the TestingModule.
|
||||
*
|
||||
* Note: This works for JIT and AOTed components as well.
|
||||
*/
|
||||
static overrideTemplateUsingTestingModule(component: Type<any>, template: string):
|
||||
typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideTemplateUsingTestingModule(component, template);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
overrideTemplateUsingTestingModule(component: Type<any>, template: string): void {
|
||||
throw new Error('Render3TestBed.overrideTemplateUsingTestingModule is not implemented yet');
|
||||
}
|
||||
|
||||
static overrideProvider(token: any, provider: {
|
||||
useFactory: Function,
|
||||
deps: any[],
|
||||
}): typeof TestBedRender3;
|
||||
static overrideProvider(token: any, provider: {useValue: any;}): typeof TestBedRender3;
|
||||
static overrideProvider(token: any, provider: {
|
||||
useFactory?: Function,
|
||||
useValue?: any,
|
||||
deps?: any[],
|
||||
}): typeof TestBedRender3 {
|
||||
_getTestBedRender3().overrideProvider(token, provider);
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites all providers for the given token with the given provider definition.
|
||||
*
|
||||
* @deprecated as it makes all NgModules lazy. Introduced only for migrating off of it.
|
||||
*/
|
||||
static deprecatedOverrideProvider(token: any, provider: {
|
||||
useFactory: Function,
|
||||
deps: any[],
|
||||
}): void;
|
||||
static deprecatedOverrideProvider(token: any, provider: {useValue: any;}): void;
|
||||
static deprecatedOverrideProvider(token: any, provider: {
|
||||
useFactory?: Function,
|
||||
useValue?: any,
|
||||
deps?: any[],
|
||||
}): typeof TestBedRender3 {
|
||||
throw new Error('Render3TestBed.deprecatedOverrideProvider is not implemented');
|
||||
}
|
||||
|
||||
static get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
||||
return _getTestBedRender3().get(token, notFoundValue);
|
||||
}
|
||||
|
||||
static createComponent<T>(component: Type<T>): ComponentFixture<T> {
|
||||
return _getTestBedRender3().createComponent(component);
|
||||
}
|
||||
|
||||
static resetTestingModule(): typeof TestBedRender3 {
|
||||
_getTestBedRender3().resetTestingModule();
|
||||
return TestBedRender3;
|
||||
}
|
||||
|
||||
// Properties
|
||||
|
||||
platform: PlatformRef = null !;
|
||||
ngModule: Type<any>|Type<any>[] = null !;
|
||||
|
||||
// metadata overrides
|
||||
private _moduleOverrides: [Type<any>, MetadataOverride<NgModule>][] = [];
|
||||
private _componentOverrides: [Type<any>, MetadataOverride<Component>][] = [];
|
||||
private _directiveOverrides: [Type<any>, MetadataOverride<Directive>][] = [];
|
||||
private _pipeOverrides: [Type<any>, MetadataOverride<Pipe>][] = [];
|
||||
private _providerOverrides: Provider[] = [];
|
||||
private _rootProviderOverrides: Provider[] = [];
|
||||
|
||||
// test module configuration
|
||||
private _providers: Provider[] = [];
|
||||
private _declarations: Array<Type<any>|any[]|any> = [];
|
||||
private _imports: Array<Type<any>|any[]|any> = [];
|
||||
private _schemas: Array<SchemaMetadata|any[]> = [];
|
||||
|
||||
private _activeFixtures: ComponentFixture<any>[] = [];
|
||||
|
||||
private _moduleRef: NgModuleRef<any> = null !;
|
||||
|
||||
private _instantiated: boolean = false;
|
||||
|
||||
/**
|
||||
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an
|
||||
* angular module. These are common to every test in the suite.
|
||||
*
|
||||
* This may only be called once, to set up the common providers for the current test
|
||||
* suite on the current platform. If you absolutely need to change the providers,
|
||||
* first use `resetTestEnvironment`.
|
||||
*
|
||||
* Test modules and platforms for individual platforms are available from
|
||||
* '@angular/<platform_name>/testing'.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
initTestEnvironment(
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void {
|
||||
if (this.platform || this.ngModule) {
|
||||
throw new Error('Cannot set base providers because it has already been called');
|
||||
}
|
||||
this.platform = platform;
|
||||
this.ngModule = ngModule;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the providers for the test injector.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
resetTestEnvironment(): void {
|
||||
this.resetTestingModule();
|
||||
this.platform = null !;
|
||||
this.ngModule = null !;
|
||||
}
|
||||
|
||||
resetTestingModule(): void {
|
||||
// reset metadata overrides
|
||||
this._moduleOverrides = [];
|
||||
this._componentOverrides = [];
|
||||
this._directiveOverrides = [];
|
||||
this._pipeOverrides = [];
|
||||
this._providerOverrides = [];
|
||||
this._rootProviderOverrides = [];
|
||||
|
||||
// reset test module config
|
||||
this._providers = [];
|
||||
this._declarations = [];
|
||||
this._imports = [];
|
||||
this._schemas = [];
|
||||
this._moduleRef = null !;
|
||||
|
||||
this._instantiated = false;
|
||||
this._activeFixtures.forEach((fixture) => {
|
||||
try {
|
||||
fixture.destroy();
|
||||
} catch (e) {
|
||||
console.error('Error during cleanup of component', {
|
||||
component: fixture.componentInstance,
|
||||
stacktrace: e,
|
||||
});
|
||||
}
|
||||
});
|
||||
this._activeFixtures = [];
|
||||
}
|
||||
|
||||
configureCompiler(config: {providers?: any[]; useJit?: boolean;}): void {
|
||||
throw new Error('the Render3 compiler is not configurable !');
|
||||
}
|
||||
|
||||
configureTestingModule(moduleDef: TestModuleMetadata): void {
|
||||
this._assertNotInstantiated('R3TestBed.configureTestingModule', 'configure the test module');
|
||||
if (moduleDef.providers) {
|
||||
this._providers.push(...moduleDef.providers);
|
||||
}
|
||||
if (moduleDef.declarations) {
|
||||
this._declarations.push(...moduleDef.declarations);
|
||||
}
|
||||
if (moduleDef.imports) {
|
||||
this._imports.push(...moduleDef.imports);
|
||||
}
|
||||
if (moduleDef.schemas) {
|
||||
this._schemas.push(...moduleDef.schemas);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(vicb): implement
|
||||
compileComponents(): Promise<any> {
|
||||
throw new Error('Render3TestBed.compileComponents is not implemented yet');
|
||||
}
|
||||
|
||||
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
||||
this._initIfNeeded();
|
||||
if (token === TestBedRender3) {
|
||||
return this;
|
||||
}
|
||||
return this._moduleRef.injector.get(token, notFoundValue);
|
||||
}
|
||||
|
||||
execute(tokens: any[], fn: Function, context?: any): any {
|
||||
this._initIfNeeded();
|
||||
const params = tokens.map(t => this.get(t));
|
||||
return fn.apply(context, params);
|
||||
}
|
||||
|
||||
overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): void {
|
||||
this._assertNotInstantiated('overrideModule', 'override module metadata');
|
||||
this._moduleOverrides.push([ngModule, override]);
|
||||
}
|
||||
|
||||
overrideComponent(component: Type<any>, override: MetadataOverride<Component>): void {
|
||||
this._assertNotInstantiated('overrideComponent', 'override component metadata');
|
||||
this._componentOverrides.push([component, override]);
|
||||
}
|
||||
|
||||
overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>): void {
|
||||
this._assertNotInstantiated('overrideDirective', 'override directive metadata');
|
||||
this._directiveOverrides.push([directive, override]);
|
||||
}
|
||||
|
||||
overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): void {
|
||||
this._assertNotInstantiated('overridePipe', 'override pipe metadata');
|
||||
this._pipeOverrides.push([pipe, override]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites all providers for the given token with the given provider definition.
|
||||
*/
|
||||
overrideProvider(token: any, provider: {useFactory?: Function, useValue?: any, deps?: any[]}):
|
||||
void {
|
||||
const isRoot =
|
||||
(typeof token !== 'string' && token.ngInjectableDef &&
|
||||
token.ngInjectableDef.providedIn === 'root');
|
||||
const overrides = isRoot ? this._rootProviderOverrides : this._providerOverrides;
|
||||
|
||||
if (provider.useFactory) {
|
||||
overrides.push({provide: token, useFactory: provider.useFactory, deps: provider.deps || []});
|
||||
} else {
|
||||
overrides.push({provide: token, useValue: provider.useValue});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites all providers for the given token with the given provider definition.
|
||||
*
|
||||
* @deprecated as it makes all NgModules lazy. Introduced only for migrating off of it.
|
||||
*/
|
||||
deprecatedOverrideProvider(token: any, provider: {
|
||||
useFactory: Function,
|
||||
deps: any[],
|
||||
}): void;
|
||||
deprecatedOverrideProvider(token: any, provider: {useValue: any;}): void;
|
||||
deprecatedOverrideProvider(
|
||||
token: any, provider: {useFactory?: Function, useValue?: any, deps?: any[]}): void {
|
||||
throw new Error('No implemented in IVY');
|
||||
}
|
||||
|
||||
createComponent<T>(type: Type<T>): ComponentFixture<T> {
|
||||
this._initIfNeeded();
|
||||
|
||||
const testComponentRenderer: TestComponentRenderer = this.get(TestComponentRenderer);
|
||||
const rootElId = `root${_nextRootElementId++}`;
|
||||
testComponentRenderer.insertRootElement(rootElId);
|
||||
|
||||
const componentDef = (type as any).ngComponentDef;
|
||||
|
||||
if (!componentDef) {
|
||||
throw new Error(
|
||||
`It looks like '${stringify(type)}' has not been IVY compiled - it has no 'ngComponentDef' field`);
|
||||
}
|
||||
|
||||
const componentFactory = new ComponentFactory(componentDef);
|
||||
const componentRef =
|
||||
componentFactory.create(Injector.NULL, [], `#${rootElId}`, this._moduleRef);
|
||||
const autoDetect: boolean = this.get(ComponentFixtureAutoDetect, false);
|
||||
const fixture = new ComponentFixture<any>(componentRef, null, autoDetect);
|
||||
this._activeFixtures.push(fixture);
|
||||
return fixture;
|
||||
}
|
||||
|
||||
// internal methods
|
||||
|
||||
private _initIfNeeded(): void {
|
||||
if (this._instantiated) {
|
||||
return;
|
||||
}
|
||||
|
||||
const resolvers = this._getResolvers();
|
||||
const testModuleType = this._createTestModule();
|
||||
|
||||
compileNgModule(testModuleType, resolvers);
|
||||
|
||||
const parentInjector = this.platform.injector;
|
||||
this._moduleRef = new NgModuleRef(testModuleType, parentInjector);
|
||||
|
||||
this._instantiated = true;
|
||||
}
|
||||
|
||||
// creates resolvers taking overrides into account
|
||||
private _getResolvers() {
|
||||
const module = new NgModuleResolver();
|
||||
module.setOverrides(this._moduleOverrides);
|
||||
|
||||
const component = new ComponentResolver();
|
||||
component.setOverrides(this._componentOverrides);
|
||||
|
||||
const directive = new DirectiveResolver();
|
||||
directive.setOverrides(this._directiveOverrides);
|
||||
|
||||
const pipe = new PipeResolver();
|
||||
pipe.setOverrides(this._pipeOverrides);
|
||||
|
||||
return {module, component, directive, pipe};
|
||||
}
|
||||
|
||||
private _assertNotInstantiated(methodName: string, methodDescription: string) {
|
||||
if (this._instantiated) {
|
||||
throw new Error(
|
||||
`Cannot ${methodDescription} when the test module has already been instantiated. ` +
|
||||
`Make sure you are not using \`inject\` before \`${methodName}\`.`);
|
||||
}
|
||||
}
|
||||
|
||||
private _createTestModule(): Type<any> {
|
||||
const rootProviderOverrides = this._rootProviderOverrides;
|
||||
|
||||
const rendererFactoryWrapper = {
|
||||
provide: WRAP_RENDERER_FACTORY2,
|
||||
useFactory: () => (rf: RendererFactory2) => new Render3DebugRendererFactory2(rf),
|
||||
};
|
||||
|
||||
@NgModule({
|
||||
providers: [...rootProviderOverrides, rendererFactoryWrapper],
|
||||
jit: true,
|
||||
})
|
||||
class RootScopeModule {
|
||||
}
|
||||
|
||||
const providers = [...this._providers, ...this._providerOverrides];
|
||||
|
||||
const declarations = this._declarations;
|
||||
const imports = [RootScopeModule, this.ngModule, this._imports];
|
||||
const schemas = this._schemas;
|
||||
|
||||
@NgModule({providers, declarations, imports, schemas, jit: true})
|
||||
class DynamicTestModule {
|
||||
}
|
||||
|
||||
return DynamicTestModule;
|
||||
}
|
||||
}
|
||||
|
||||
let testBed: TestBedRender3;
|
||||
|
||||
export function _getTestBedRender3(): TestBedRender3 {
|
||||
return testBed = testBed || new TestBedRender3();
|
||||
}
|
||||
|
||||
|
||||
// Module compiler
|
||||
|
||||
const EMPTY_ARRAY: Type<any>[] = [];
|
||||
|
||||
// Resolvers for Angular decorators
|
||||
type Resolvers = {
|
||||
module: Resolver<NgModule>,
|
||||
component: Resolver<Directive>,
|
||||
directive: Resolver<Component>,
|
||||
pipe: Resolver<Pipe>,
|
||||
};
|
||||
|
||||
function compileNgModule(moduleType: Type<any>, resolvers: Resolvers): void {
|
||||
const ngModule = resolvers.module.resolve(moduleType);
|
||||
|
||||
if (ngModule === null) {
|
||||
throw new Error(`${stringify(moduleType)} has not @NgModule annotation`);
|
||||
}
|
||||
|
||||
compileNgModuleDefs(moduleType, ngModule);
|
||||
|
||||
const declarations: Type<any>[] = flatten(ngModule.declarations || EMPTY_ARRAY);
|
||||
|
||||
const compiledComponents: Type<any>[] = [];
|
||||
|
||||
// Compile the components, directives and pipes declared by this module
|
||||
declarations.forEach(declaration => {
|
||||
const component = resolvers.component.resolve(declaration);
|
||||
if (component) {
|
||||
compileComponent(declaration, component);
|
||||
compiledComponents.push(declaration);
|
||||
return;
|
||||
}
|
||||
|
||||
const directive = resolvers.directive.resolve(declaration);
|
||||
if (directive) {
|
||||
compileDirective(declaration, directive);
|
||||
return;
|
||||
}
|
||||
|
||||
const pipe = resolvers.pipe.resolve(declaration);
|
||||
if (pipe) {
|
||||
compilePipe(declaration, pipe);
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Compile transitive modules, components, directives and pipes
|
||||
const transitiveScope = transitiveScopesFor(moduleType, resolvers);
|
||||
compiledComponents.forEach(
|
||||
cmp => patchComponentDefWithScope((cmp as any).ngComponentDef, transitiveScope));
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the pair of transitive scopes (compilation scope and exported scope) for a given module.
|
||||
*
|
||||
* This operation is memoized and the result is cached on the module's definition. It can be called
|
||||
* on modules with components that have not fully compiled yet, but the result should not be used
|
||||
* until they have.
|
||||
*/
|
||||
function transitiveScopesFor<T>(
|
||||
moduleType: Type<T>, resolvers: Resolvers): NgModuleTransitiveScopes {
|
||||
if (!isNgModule(moduleType)) {
|
||||
throw new Error(`${moduleType.name} does not have an ngModuleDef`);
|
||||
}
|
||||
const def = moduleType.ngModuleDef;
|
||||
|
||||
if (def.transitiveCompileScopes !== null) {
|
||||
return def.transitiveCompileScopes;
|
||||
}
|
||||
|
||||
const scopes: NgModuleTransitiveScopes = {
|
||||
compilation: {
|
||||
directives: new Set<any>(),
|
||||
pipes: new Set<any>(),
|
||||
},
|
||||
exported: {
|
||||
directives: new Set<any>(),
|
||||
pipes: new Set<any>(),
|
||||
},
|
||||
};
|
||||
|
||||
def.declarations.forEach(declared => {
|
||||
const declaredWithDefs = declared as Type<any>& { ngPipeDef?: any; };
|
||||
|
||||
if (declaredWithDefs.ngPipeDef !== undefined) {
|
||||
scopes.compilation.pipes.add(declared);
|
||||
} else {
|
||||
scopes.compilation.directives.add(declared);
|
||||
}
|
||||
});
|
||||
|
||||
def.imports.forEach(<I>(imported: Type<I>) => {
|
||||
const ngModule = resolvers.module.resolve(imported);
|
||||
|
||||
if (ngModule === null) {
|
||||
throw new Error(`Importing ${imported.name} which does not have an @ngModule`);
|
||||
} else {
|
||||
compileNgModule(imported, resolvers);
|
||||
}
|
||||
|
||||
// When this module imports another, the imported module's exported directives and pipes are
|
||||
// added to the compilation scope of this module.
|
||||
const importedScope = transitiveScopesFor(imported, resolvers);
|
||||
importedScope.exported.directives.forEach(entry => scopes.compilation.directives.add(entry));
|
||||
importedScope.exported.pipes.forEach(entry => scopes.compilation.pipes.add(entry));
|
||||
});
|
||||
|
||||
def.exports.forEach(<E>(exported: Type<E>) => {
|
||||
const exportedTyped = exported as Type<E>& {
|
||||
// Components, Directives, NgModules, and Pipes can all be exported.
|
||||
ngComponentDef?: any;
|
||||
ngDirectiveDef?: any;
|
||||
ngModuleDef?: NgModuleDefInternal<E>;
|
||||
ngPipeDef?: any;
|
||||
};
|
||||
|
||||
// Either the type is a module, a pipe, or a component/directive (which may not have an
|
||||
// ngComponentDef as it might be compiled asynchronously).
|
||||
if (isNgModule(exportedTyped)) {
|
||||
// When this module exports another, the exported module's exported directives and pipes are
|
||||
// added to both the compilation and exported scopes of this module.
|
||||
const exportedScope = transitiveScopesFor(exportedTyped, resolvers);
|
||||
exportedScope.exported.directives.forEach(entry => {
|
||||
scopes.compilation.directives.add(entry);
|
||||
scopes.exported.directives.add(entry);
|
||||
});
|
||||
exportedScope.exported.pipes.forEach(entry => {
|
||||
scopes.compilation.pipes.add(entry);
|
||||
scopes.exported.pipes.add(entry);
|
||||
});
|
||||
} else if (exportedTyped.ngPipeDef !== undefined) {
|
||||
scopes.exported.pipes.add(exportedTyped);
|
||||
} else {
|
||||
scopes.exported.directives.add(exportedTyped);
|
||||
}
|
||||
});
|
||||
|
||||
def.transitiveCompileScopes = scopes;
|
||||
return scopes;
|
||||
}
|
||||
|
||||
function flatten<T>(values: any[]): T[] {
|
||||
const out: T[] = [];
|
||||
values.forEach(value => {
|
||||
if (Array.isArray(value)) {
|
||||
out.push(...flatten<T>(value));
|
||||
} else {
|
||||
out.push(value);
|
||||
}
|
||||
});
|
||||
return out;
|
||||
}
|
||||
|
||||
function isNgModule<T>(value: Type<T>): value is Type<T>&{ngModuleDef: NgModuleDefInternal<T>} {
|
||||
return (value as{ngModuleDef?: NgModuleDefInternal<T>}).ngModuleDef !== undefined;
|
||||
}
|
73
packages/core/testing/src/resolvers.ts
Normal file
73
packages/core/testing/src/resolvers.ts
Normal file
@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @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 {Component, Directive, NgModule, Pipe, Type, ɵReflectionCapabilities as ReflectionCapabilities} from '@angular/core';
|
||||
|
||||
import {MetadataOverride} from './metadata_override';
|
||||
import {MetadataOverrider} from './metadata_overrider';
|
||||
|
||||
const reflection = new ReflectionCapabilities();
|
||||
|
||||
/**
|
||||
* Base interface to resolve `@Component`, `@Directive`, `@Pipe` and `@NgModule`.
|
||||
*/
|
||||
export interface Resolver<T> { resolve(type: Type<any>): T|null; }
|
||||
|
||||
/**
|
||||
* Allows to override ivy metadata for tests (via the `TestBed`).
|
||||
*/
|
||||
abstract class OverrideResolver<T> implements Resolver<T> {
|
||||
private overrides = new Map<Type<any>, MetadataOverride<T>>();
|
||||
private resolved = new Map<Type<any>, T|null>();
|
||||
|
||||
abstract get type(): any;
|
||||
|
||||
setOverrides(overrides: Array<[Type<any>, MetadataOverride<T>]>) {
|
||||
this.overrides.clear();
|
||||
overrides.forEach(([type, override]) => this.overrides.set(type, override));
|
||||
}
|
||||
|
||||
getAnnotation(type: Type<any>): T|null {
|
||||
return reflection.annotations(type).find(a => a instanceof this.type) || null;
|
||||
}
|
||||
|
||||
resolve(type: Type<any>): T|null {
|
||||
let resolved = this.resolved.get(type) || null;
|
||||
|
||||
if (!resolved) {
|
||||
resolved = this.getAnnotation(type);
|
||||
if (resolved) {
|
||||
const override = this.overrides.get(type);
|
||||
if (override) {
|
||||
const overrider = new MetadataOverrider();
|
||||
resolved = overrider.overrideMetadata(this.type, resolved, override);
|
||||
}
|
||||
}
|
||||
this.resolved.set(type, resolved);
|
||||
}
|
||||
|
||||
return resolved;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export class DirectiveResolver extends OverrideResolver<Directive> {
|
||||
get type() { return Directive; }
|
||||
}
|
||||
|
||||
export class ComponentResolver extends OverrideResolver<Component> {
|
||||
get type() { return Component; }
|
||||
}
|
||||
|
||||
export class PipeResolver extends OverrideResolver<Pipe> {
|
||||
get type() { return Pipe; }
|
||||
}
|
||||
|
||||
export class NgModuleResolver extends OverrideResolver<NgModule> {
|
||||
get type() { return NgModule; }
|
||||
}
|
@ -6,56 +6,31 @@
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {ApplicationInitStatus, CompilerOptions, Component, Directive, InjectionToken, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetComponentViewDefinitionFactory as getComponentViewDefinitionFactory, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify} from '@angular/core';
|
||||
import {ApplicationInitStatus, CompilerOptions, Component, Directive, Injector, NgModule, NgModuleFactory, NgModuleRef, NgZone, Optional, Pipe, PlatformRef, Provider, SchemaMetadata, SkipSelf, StaticProvider, Type, ɵAPP_ROOT as APP_ROOT, ɵDepFlags as DepFlags, ɵNodeFlags as NodeFlags, ɵclearOverrides as clearOverrides, ɵgetComponentViewDefinitionFactory as getComponentViewDefinitionFactory, ɵivyEnabled as ivyEnabled, ɵoverrideComponentView as overrideComponentView, ɵoverrideProvider as overrideProvider, ɵstringify as stringify} from '@angular/core';
|
||||
|
||||
import {AsyncTestCompleter} from './async_test_completer';
|
||||
import {ComponentFixture} from './component_fixture';
|
||||
import {MetadataOverride} from './metadata_override';
|
||||
import {TestBedRender3, _getTestBedRender3} from './r3_test_bed';
|
||||
import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestComponentRenderer, TestModuleMetadata} from './test_bed_common';
|
||||
import {TestingCompiler, TestingCompilerFactory} from './test_compiler';
|
||||
|
||||
const UNDEFINED = new Object();
|
||||
|
||||
/**
|
||||
* An abstract class for inserting the root test component element in a platform independent way.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export class TestComponentRenderer {
|
||||
insertRootElement(rootElementId: string) {}
|
||||
}
|
||||
|
||||
let _nextRootElementId = 0;
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export const ComponentFixtureAutoDetect =
|
||||
new InjectionToken<boolean[]>('ComponentFixtureAutoDetect');
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export const ComponentFixtureNoNgZone = new InjectionToken<boolean[]>('ComponentFixtureNoNgZone');
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export type TestModuleMetadata = {
|
||||
providers?: any[],
|
||||
declarations?: any[],
|
||||
imports?: any[],
|
||||
schemas?: Array<SchemaMetadata|any[]>,
|
||||
aotSummaries?: () => any[],
|
||||
};
|
||||
|
||||
/**
|
||||
* @description
|
||||
* Configures and initializes environment for unit testing and provides methods for
|
||||
* creating components and services in unit tests.
|
||||
*
|
||||
* TestBed is the primary api for writing unit tests for Angular applications and libraries.
|
||||
* `TestBed` is the primary api for writing unit tests for Angular applications and libraries.
|
||||
*
|
||||
* Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
|
||||
* according to the compiler used.
|
||||
*/
|
||||
export class TestBed implements Injector {
|
||||
export class TestBedViewEngine implements Injector {
|
||||
/**
|
||||
* Initialize the environment for testing with a compiler factory, a PlatformRef, and an
|
||||
* angular module. These are common to every test in the suite.
|
||||
@ -70,8 +45,9 @@ export class TestBed implements Injector {
|
||||
* @experimental
|
||||
*/
|
||||
static initTestEnvironment(
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): TestBed {
|
||||
const testBed = getTestBed();
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef,
|
||||
aotSummaries?: () => any[]): TestBedViewEngine {
|
||||
const testBed = _getTestBedViewEngine();
|
||||
testBed.initTestEnvironment(ngModule, platform, aotSummaries);
|
||||
return testBed;
|
||||
}
|
||||
@ -81,10 +57,10 @@ export class TestBed implements Injector {
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
static resetTestEnvironment() { getTestBed().resetTestEnvironment(); }
|
||||
static resetTestEnvironment(): void { _getTestBedViewEngine().resetTestEnvironment(); }
|
||||
|
||||
static resetTestingModule(): typeof TestBed {
|
||||
getTestBed().resetTestingModule();
|
||||
_getTestBedViewEngine().resetTestingModule();
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
@ -93,7 +69,7 @@ export class TestBed implements Injector {
|
||||
* which are defined in test_injector.js
|
||||
*/
|
||||
static configureCompiler(config: {providers?: any[]; useJit?: boolean;}): typeof TestBed {
|
||||
getTestBed().configureCompiler(config);
|
||||
_getTestBedViewEngine().configureCompiler(config);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
@ -102,7 +78,7 @@ export class TestBed implements Injector {
|
||||
* which are defined in test_injector.js
|
||||
*/
|
||||
static configureTestingModule(moduleDef: TestModuleMetadata): typeof TestBed {
|
||||
getTestBed().configureTestingModule(moduleDef);
|
||||
_getTestBedViewEngine().configureTestingModule(moduleDef);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
@ -114,29 +90,29 @@ export class TestBed implements Injector {
|
||||
static compileComponents(): Promise<any> { return getTestBed().compileComponents(); }
|
||||
|
||||
static overrideModule(ngModule: Type<any>, override: MetadataOverride<NgModule>): typeof TestBed {
|
||||
getTestBed().overrideModule(ngModule, override);
|
||||
_getTestBedViewEngine().overrideModule(ngModule, override);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
static overrideComponent(component: Type<any>, override: MetadataOverride<Component>):
|
||||
typeof TestBed {
|
||||
getTestBed().overrideComponent(component, override);
|
||||
_getTestBedViewEngine().overrideComponent(component, override);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
static overrideDirective(directive: Type<any>, override: MetadataOverride<Directive>):
|
||||
typeof TestBed {
|
||||
getTestBed().overrideDirective(directive, override);
|
||||
_getTestBedViewEngine().overrideDirective(directive, override);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
static overridePipe(pipe: Type<any>, override: MetadataOverride<Pipe>): typeof TestBed {
|
||||
getTestBed().overridePipe(pipe, override);
|
||||
_getTestBedViewEngine().overridePipe(pipe, override);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
static overrideTemplate(component: Type<any>, template: string): typeof TestBed {
|
||||
getTestBed().overrideComponent(component, {set: {template, templateUrl: null !}});
|
||||
_getTestBedViewEngine().overrideComponent(component, {set: {template, templateUrl: null !}});
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
@ -148,11 +124,10 @@ export class TestBed implements Injector {
|
||||
*/
|
||||
static overrideTemplateUsingTestingModule(component: Type<any>, template: string):
|
||||
typeof TestBed {
|
||||
getTestBed().overrideTemplateUsingTestingModule(component, template);
|
||||
_getTestBedViewEngine().overrideTemplateUsingTestingModule(component, template);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overwrites all providers for the given token with the given provider definition.
|
||||
*
|
||||
@ -168,7 +143,7 @@ export class TestBed implements Injector {
|
||||
useValue?: any,
|
||||
deps?: any[],
|
||||
}): typeof TestBed {
|
||||
getTestBed().overrideProvider(token, provider as any);
|
||||
_getTestBedViewEngine().overrideProvider(token, provider as any);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
@ -187,16 +162,16 @@ export class TestBed implements Injector {
|
||||
useValue?: any,
|
||||
deps?: any[],
|
||||
}): typeof TestBed {
|
||||
getTestBed().deprecatedOverrideProvider(token, provider as any);
|
||||
_getTestBedViewEngine().deprecatedOverrideProvider(token, provider as any);
|
||||
return TestBed;
|
||||
}
|
||||
|
||||
static get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND) {
|
||||
return getTestBed().get(token, notFoundValue);
|
||||
return _getTestBedViewEngine().get(token, notFoundValue);
|
||||
}
|
||||
|
||||
static createComponent<T>(component: Type<T>): ComponentFixture<T> {
|
||||
return getTestBed().createComponent(component);
|
||||
return _getTestBedViewEngine().createComponent(component);
|
||||
}
|
||||
|
||||
private _instantiated: boolean = false;
|
||||
@ -243,7 +218,7 @@ export class TestBed implements Injector {
|
||||
* @experimental
|
||||
*/
|
||||
initTestEnvironment(
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]) {
|
||||
ngModule: Type<any>|Type<any>[], platform: PlatformRef, aotSummaries?: () => any[]): void {
|
||||
if (this.platform || this.ngModule) {
|
||||
throw new Error('Cannot set base providers because it has already been called');
|
||||
}
|
||||
@ -259,14 +234,14 @@ export class TestBed implements Injector {
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
resetTestEnvironment() {
|
||||
resetTestEnvironment(): void {
|
||||
this.resetTestingModule();
|
||||
this.platform = null !;
|
||||
this.ngModule = null !;
|
||||
this._testEnvAotSummaries = () => [];
|
||||
}
|
||||
|
||||
resetTestingModule() {
|
||||
resetTestingModule(): void {
|
||||
clearOverrides();
|
||||
this._aotSummaries = [];
|
||||
this._templateOverrides = [];
|
||||
@ -300,12 +275,12 @@ export class TestBed implements Injector {
|
||||
this._activeFixtures = [];
|
||||
}
|
||||
|
||||
configureCompiler(config: {providers?: any[], useJit?: boolean}) {
|
||||
configureCompiler(config: {providers?: any[], useJit?: boolean}): void {
|
||||
this._assertNotInstantiated('TestBed.configureCompiler', 'configure the compiler');
|
||||
this._compilerOptions.push(config);
|
||||
}
|
||||
|
||||
configureTestingModule(moduleDef: TestModuleMetadata) {
|
||||
configureTestingModule(moduleDef: TestModuleMetadata): void {
|
||||
this._assertNotInstantiated('TestBed.configureTestingModule', 'configure the test module');
|
||||
if (moduleDef.providers) {
|
||||
this._providers.push(...moduleDef.providers);
|
||||
@ -336,7 +311,7 @@ export class TestBed implements Injector {
|
||||
});
|
||||
}
|
||||
|
||||
private _initIfNeeded() {
|
||||
private _initIfNeeded(): void {
|
||||
if (this._instantiated) {
|
||||
return;
|
||||
}
|
||||
@ -425,7 +400,7 @@ export class TestBed implements Injector {
|
||||
}
|
||||
}
|
||||
|
||||
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND) {
|
||||
get(token: any, notFoundValue: any = Injector.THROW_IF_NOT_FOUND): any {
|
||||
this._initIfNeeded();
|
||||
if (token === TestBed) {
|
||||
return this;
|
||||
@ -574,13 +549,32 @@ export class TestBed implements Injector {
|
||||
}
|
||||
}
|
||||
|
||||
let _testBed: TestBed = null !;
|
||||
/**
|
||||
* @description
|
||||
* Configures and initializes environment for unit testing and provides methods for
|
||||
* creating components and services in unit tests.
|
||||
*
|
||||
* `TestBed` is the primary api for writing unit tests for Angular applications and libraries.
|
||||
*
|
||||
* Note: Use `TestBed` in tests. It will be set to either `TestBedViewEngine` or `TestBedRender3`
|
||||
* according to the compiler used.
|
||||
*/
|
||||
export const TestBed = ivyEnabled ? TestBedRender3 : TestBedViewEngine;
|
||||
|
||||
/**
|
||||
* Returns a singleton of the applicable `TestBed`.
|
||||
*
|
||||
* It will be either an instance of `TestBedViewEngine` or `TestBedRender3`.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export function getTestBed(): TestBed {
|
||||
return _testBed = _testBed || new TestBed();
|
||||
export const getTestBed: () => TestBedRender3 | TestBedViewEngine =
|
||||
ivyEnabled ? _getTestBedRender3 : _getTestBedViewEngine;
|
||||
|
||||
let testBed: TestBedViewEngine;
|
||||
|
||||
function _getTestBedViewEngine(): TestBedViewEngine {
|
||||
return testBed = testBed || new TestBedViewEngine();
|
||||
}
|
||||
|
||||
/**
|
||||
|
40
packages/core/testing/src/test_bed_common.ts
Normal file
40
packages/core/testing/src/test_bed_common.ts
Normal file
@ -0,0 +1,40 @@
|
||||
/**
|
||||
* @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 {InjectionToken, SchemaMetadata} from '@angular/core';
|
||||
|
||||
/**
|
||||
* An abstract class for inserting the root test component element in a platform independent way.
|
||||
*
|
||||
* @experimental
|
||||
*/
|
||||
export class TestComponentRenderer {
|
||||
insertRootElement(rootElementId: string) {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export const ComponentFixtureAutoDetect =
|
||||
new InjectionToken<boolean[]>('ComponentFixtureAutoDetect');
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export const ComponentFixtureNoNgZone = new InjectionToken<boolean[]>('ComponentFixtureNoNgZone');
|
||||
|
||||
/**
|
||||
* @experimental
|
||||
*/
|
||||
export type TestModuleMetadata = {
|
||||
providers?: any[],
|
||||
declarations?: any[],
|
||||
imports?: any[],
|
||||
schemas?: Array<SchemaMetadata|any[]>,
|
||||
aotSummaries?: () => any[],
|
||||
};
|
@ -16,6 +16,9 @@ export * from './async';
|
||||
export * from './component_fixture';
|
||||
export * from './fake_async';
|
||||
export * from './test_bed';
|
||||
export * from './test_bed_common';
|
||||
export * from './r3_test_bed';
|
||||
export * from './before_each';
|
||||
export * from './metadata_override';
|
||||
export * from './metadata_overrider';
|
||||
export * from './private_export_testing';
|
||||
|
@ -1,27 +1,31 @@
|
||||
{
|
||||
"extends": "../tsconfig-build.json",
|
||||
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"rootDir": "../",
|
||||
"paths": {
|
||||
"rxjs/*": ["../../../node_modules/rxjs/*"],
|
||||
"@angular/core": ["../../../dist/packages/core"]
|
||||
"rxjs/*": [
|
||||
"../../../node_modules/rxjs/*"
|
||||
],
|
||||
"@angular/core": [
|
||||
"../../../dist/packages/core"
|
||||
],
|
||||
"@angular/compiler": [
|
||||
"../../../dist/packages/compiler"
|
||||
],
|
||||
},
|
||||
"outDir": "../../../dist/packages/core"
|
||||
},
|
||||
|
||||
"files": [
|
||||
"public_api.ts",
|
||||
"../../../node_modules/zone.js/dist/zone.js.d.ts",
|
||||
"../../system.d.ts",
|
||||
"../../types.d.ts"
|
||||
],
|
||||
|
||||
"angularCompilerOptions": {
|
||||
"strictMetadataEmit": false,
|
||||
"skipTemplateCodegen": true,
|
||||
"flatModuleOutFile": "testing.js",
|
||||
"flatModuleId": "@angular/core/testing"
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user