diff --git a/modules/@angular/compiler/testing/test_component_builder.ts b/modules/@angular/compiler/testing/test_component_builder.ts index 6c9660ed93..87c6995dc6 100644 --- a/modules/@angular/compiler/testing/test_component_builder.ts +++ b/modules/@angular/compiler/testing/test_component_builder.ts @@ -6,37 +6,44 @@ * found in the LICENSE file at https://angular.io/license */ -import {AnimationEntryMetadata, ChangeDetectorRef, ComponentFactory, ComponentRef, ComponentResolver, DebugElement, ElementRef, Injectable, Injector, NgZone, NgZoneError, OpaqueToken, ViewMetadata, getDebugNode} from '@angular/core'; -import {ComponentFixture, tick} from '@angular/core/testing'; +import {AnimationEntryMetadata, ComponentFactory, ComponentResolver, Injectable, Injector, NgZone, ViewMetadata} from '@angular/core'; +import {ComponentFixture, ComponentFixtureNoNgZone, TestComponentBuilder} from '@angular/core/testing'; import {DirectiveResolver, ViewResolver} from '../index'; -import {ObservableWrapper, PromiseCompleter, PromiseWrapper} from '../src/facade/async'; -import {ListWrapper, MapWrapper} from '../src/facade/collection'; -import {BaseException} from '../src/facade/exceptions'; -import {IS_DART, Type, isBlank, isPresent, scheduleMicroTask} from '../src/facade/lang'; +import {MapWrapper} from '../src/facade/collection'; +import {IS_DART, Type, isPresent} from '../src/facade/lang'; /** - * @deprecated - * Import ComponentFixture from @angular/core/testing instead. + * @deprecated Import TestComponentRenderer from @angular/core/testing + */ +export {TestComponentRenderer} from '@angular/core/testing'; + +/** + * @deprecated Import TestComponentBuilder from @angular/core/testing + */ +export {TestComponentBuilder} from '@angular/core/testing'; + +/** + * @deprecated Import ComponentFixture from @angular/core/testing */ export {ComponentFixture} from '@angular/core/testing'; + /** - * An abstract class for inserting the root test component element in a platform independent way. + * @deprecated Import ComponentFixtureNoNgZone from @angular/core/testing */ -export class TestComponentRenderer { - insertRootElement(rootElementId: string) {} -} - -export var ComponentFixtureAutoDetect = new OpaqueToken('ComponentFixtureAutoDetect'); -export var ComponentFixtureNoNgZone = new OpaqueToken('ComponentFixtureNoNgZone'); - -var _nextRootElementId = 0; +export {ComponentFixtureNoNgZone} from '@angular/core/testing'; /** - * Builds a ComponentFixture for use in component level tests. + * @deprecated Import ComponentFixtureAutoDetect from @angular/core/testing + */ +export {ComponentFixtureAutoDetect} from '@angular/core/testing'; + + +/** + * A TestComponentBuilder that allows overriding based on the compiler. */ @Injectable() -export class TestComponentBuilder { +export class OverridingTestComponentBuilder extends TestComponentBuilder { /** @internal */ _bindingsOverrides = new Map(); /** @internal */ @@ -51,11 +58,12 @@ export class TestComponentBuilder { _viewOverrides = new Map(); - constructor(private _injector: Injector) {} + + constructor(injector: Injector) { super(injector); } /** @internal */ - _clone(): TestComponentBuilder { - let clone = new TestComponentBuilder(this._injector); + _clone(): OverridingTestComponentBuilder { + let clone = new OverridingTestComponentBuilder(this._injector); clone._viewOverrides = MapWrapper.clone(this._viewOverrides); clone._directiveOverrides = MapWrapper.clone(this._directiveOverrides); clone._templateOverrides = MapWrapper.clone(this._templateOverrides); @@ -64,11 +72,7 @@ export class TestComponentBuilder { return clone; } - /** - * Overrides only the html of a {@link ComponentMetadata}. - * All the other properties of the component's {@link ViewMetadata} are preserved. - */ - overrideTemplate(componentType: Type, template: string): TestComponentBuilder { + overrideTemplate(componentType: Type, template: string): OverridingTestComponentBuilder { let clone = this._clone(); clone._templateOverrides.set(componentType, template); return clone; @@ -81,19 +85,13 @@ export class TestComponentBuilder { return clone; } - /** - * Overrides a component's {@link ViewMetadata}. - */ - overrideView(componentType: Type, view: ViewMetadata): TestComponentBuilder { + overrideView(componentType: Type, view: ViewMetadata): OverridingTestComponentBuilder { let clone = this._clone(); clone._viewOverrides.set(componentType, view); return clone; } - /** - * Overrides the directives from the component {@link ViewMetadata}. - */ - overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder { + overrideDirective(componentType: Type, from: Type, to: Type): OverridingTestComponentBuilder { let clone = this._clone(); let overridesForComponent = clone._directiveOverrides.get(componentType); if (!isPresent(overridesForComponent)) { @@ -104,65 +102,18 @@ export class TestComponentBuilder { return clone; } - /** - * Overrides one or more injectables configured via `providers` metadata property of a directive - * or - * component. - * Very useful when certain providers need to be mocked out. - * - * The providers specified via this method are appended to the existing `providers` causing the - * duplicated providers to - * be overridden. - */ - overrideProviders(type: Type, providers: any[]): TestComponentBuilder { + overrideProviders(type: Type, providers: any[]): OverridingTestComponentBuilder { let clone = this._clone(); clone._bindingsOverrides.set(type, providers); return clone; } - /** - * @deprecated - */ - overrideBindings(type: Type, providers: any[]): TestComponentBuilder { - return this.overrideProviders(type, providers); - } - - /** - * Overrides one or more injectables configured via `providers` metadata property of a directive - * or - * component. - * Very useful when certain providers need to be mocked out. - * - * The providers specified via this method are appended to the existing `providers` causing the - * duplicated providers to - * be overridden. - */ - overrideViewProviders(type: Type, providers: any[]): TestComponentBuilder { + overrideViewProviders(type: Type, providers: any[]): OverridingTestComponentBuilder { let clone = this._clone(); clone._viewBindingsOverrides.set(type, providers); return clone; } - /** - * @deprecated - */ - overrideViewBindings(type: Type, providers: any[]): TestComponentBuilder { - return this.overrideViewProviders(type, providers); - } - - private _create(ngZone: NgZone, componentFactory: ComponentFactory): ComponentFixture { - let rootElId = `root${_nextRootElementId++}`; - var testComponentRenderer: TestComponentRenderer = this._injector.get(TestComponentRenderer); - testComponentRenderer.insertRootElement(rootElId); - - var componentRef = componentFactory.create(this._injector, [], `#${rootElId}`); - let autoDetect: boolean = this._injector.get(ComponentFixtureAutoDetect, false); - return new ComponentFixture(componentRef, ngZone, autoDetect); - } - - /** - * Builds and returns a ComponentFixture. - */ createAsync(rootComponentType: Type): Promise> { let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false); let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null); @@ -186,30 +137,9 @@ export class TestComponentBuilder { let promise: Promise> = this._injector.get(ComponentResolver).resolveComponent(rootComponentType); - return promise.then(componentFactory => this._create(ngZone, componentFactory)); + return promise.then(componentFactory => this.createFromFactory(ngZone, componentFactory)); }; return ngZone == null ? initComponent() : ngZone.run(initComponent); } - - createFakeAsync(rootComponentType: Type): ComponentFixture { - let result: any /** TODO #9100 */; - let error: any /** TODO #9100 */; - PromiseWrapper.then( - this.createAsync(rootComponentType), (_result) => { result = _result; }, - (_error) => { error = _error; }); - tick(); - if (isPresent(error)) { - throw error; - } - return result; - } - - createSync(componentFactory: ComponentFactory): ComponentFixture { - let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false); - let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null); - - let initComponent = () => this._create(ngZone, componentFactory); - return ngZone == null ? initComponent() : ngZone.run(initComponent); - } } diff --git a/modules/@angular/core/testing.ts b/modules/@angular/core/testing.ts index 252e3fc8b6..71e7c6eaff 100644 --- a/modules/@angular/core/testing.ts +++ b/modules/@angular/core/testing.ts @@ -9,5 +9,6 @@ export * from './testing/async'; export * from './testing/component_fixture'; export * from './testing/fake_async'; +export * from './testing/test_component_builder'; export * from './testing/test_injector'; export * from './testing/testing'; diff --git a/modules/@angular/core/testing/test_component_builder.ts b/modules/@angular/core/testing/test_component_builder.ts new file mode 100644 index 0000000000..d5d9caae16 --- /dev/null +++ b/modules/@angular/core/testing/test_component_builder.ts @@ -0,0 +1,148 @@ +/** + * @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 {AnimationEntryMetadata, ComponentFactory, ComponentResolver, Injectable, Injector, NgZone, OpaqueToken, ViewMetadata} from '../index'; +import {PromiseWrapper} from '../src/facade/async'; +import {IS_DART, Type, isPresent} from '../src/facade/lang'; + +import {ComponentFixture} from './component_fixture'; +import {tick} from './fake_async'; + + +/** + * An abstract class for inserting the root test component element in a platform independent way. + */ +export class TestComponentRenderer { + insertRootElement(rootElementId: string) {} +} + +export var ComponentFixtureAutoDetect = new OpaqueToken('ComponentFixtureAutoDetect'); +export var ComponentFixtureNoNgZone = new OpaqueToken('ComponentFixtureNoNgZone'); + +var _nextRootElementId = 0; + +/** + * Builds a ComponentFixture for use in component level tests. + */ +@Injectable() +export class TestComponentBuilder { + constructor(protected _injector: Injector) {} + + /** + * Overrides only the html of a {@link ComponentMetadata}. + * All the other properties of the component's {@link ViewMetadata} are preserved. + */ + overrideTemplate(componentType: Type, template: string): TestComponentBuilder { + throw new Error( + 'overrideTemplate is not supported in this implementation of TestComponentBuilder.'); + } + + /** + * Overrides a component's {@link ViewMetadata}. + */ + overrideView(componentType: Type, view: ViewMetadata): TestComponentBuilder { + throw new Error( + 'overrideView is not supported in this implementation of TestComponentBuilder.'); + } + + /** + * Overrides the directives from the component {@link ViewMetadata}. + */ + overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder { + throw new Error( + 'overrideDirective is not supported in this implementation of TestComponentBuilder.'); + } + + /** + * Overrides one or more injectables configured via `providers` metadata property of a directive + * or + * component. + * Very useful when certain providers need to be mocked out. + * + * The providers specified via this method are appended to the existing `providers` causing the + * duplicated providers to + * be overridden. + */ + overrideProviders(type: Type, providers: any[]): TestComponentBuilder { + throw new Error( + 'overrideProviders is not supported in this implementation of TestComponentBuilder.'); + } + + /** + * Overrides one or more injectables configured via `providers` metadata property of a directive + * or + * component. + * Very useful when certain providers need to be mocked out. + * + * The providers specified via this method are appended to the existing `providers` causing the + * duplicated providers to + * be overridden. + */ + overrideViewProviders(type: Type, providers: any[]): TestComponentBuilder { + throw new Error( + 'overrideViewProviders is not supported in this implementation of TestComponentBuilder.'); + } + + overrideAnimations(componentType: Type, animations: AnimationEntryMetadata[]): + TestComponentBuilder { + throw new Error( + 'overrideAnimations is not supported in this implementation of TestComponentBuilder.'); + } + + protected createFromFactory(ngZone: NgZone, componentFactory: ComponentFactory): + ComponentFixture { + let rootElId = `root${_nextRootElementId++}`; + var testComponentRenderer: TestComponentRenderer = this._injector.get(TestComponentRenderer); + testComponentRenderer.insertRootElement(rootElId); + + var componentRef = componentFactory.create(this._injector, [], `#${rootElId}`); + let autoDetect: boolean = this._injector.get(ComponentFixtureAutoDetect, false); + return new ComponentFixture(componentRef, ngZone, autoDetect); + } + + /** + * Builds and returns a ComponentFixture. + */ + createAsync(rootComponentType: Type): Promise> { + let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false); + let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null); + + let initComponent = () => { + let promise: Promise> = + this._injector.get(ComponentResolver).resolveComponent(rootComponentType); + return promise.then(componentFactory => this.createFromFactory(ngZone, componentFactory)); + }; + + return ngZone == null ? initComponent() : ngZone.run(initComponent); + } + + createFakeAsync(rootComponentType: Type): ComponentFixture { + let result: any /** TODO #9100 */; + let error: any /** TODO #9100 */; + PromiseWrapper.then( + this.createAsync(rootComponentType), (_result) => { result = _result; }, + (_error) => { error = _error; }); + tick(); + if (isPresent(error)) { + throw error; + } + return result; + } + + /** + * @deprecated createSync will be replaced with the ability to precompile components from within + * the test. + */ + createSync(componentFactory: ComponentFactory): ComponentFixture { + let noNgZone = IS_DART || this._injector.get(ComponentFixtureNoNgZone, false); + let ngZone: NgZone = noNgZone ? null : this._injector.get(NgZone, null); + + let initComponent = () => this.createFromFactory(ngZone, componentFactory); + return ngZone == null ? initComponent() : ngZone.run(initComponent); + } +} diff --git a/modules/@angular/platform-browser-dynamic/testing.ts b/modules/@angular/platform-browser-dynamic/testing.ts index fe0b47d294..27303a6b77 100644 --- a/modules/@angular/platform-browser-dynamic/testing.ts +++ b/modules/@angular/platform-browser-dynamic/testing.ts @@ -7,7 +7,8 @@ */ import {DirectiveResolver, ViewResolver} from '@angular/compiler'; -import {MockDirectiveResolver, MockViewResolver, TestComponentBuilder, TestComponentRenderer} from '@angular/compiler/testing'; +import {MockDirectiveResolver, MockViewResolver, OverridingTestComponentBuilder} from '@angular/compiler/testing'; +import {TestComponentBuilder, TestComponentRenderer} from '@angular/core/testing'; import {TEST_BROWSER_APPLICATION_PROVIDERS, TEST_BROWSER_PLATFORM_PROVIDERS} from '@angular/platform-browser/testing'; import {BROWSER_APP_COMPILER_PROVIDERS} from './index'; @@ -27,9 +28,9 @@ export const TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS: Array = [ TEST_BROWSER_APPLICATION_PROVIDERS, BROWSER_APP_COMPILER_PROVIDERS, [ + {provide: TestComponentBuilder, useClass: OverridingTestComponentBuilder}, {provide: DirectiveResolver, useClass: MockDirectiveResolver}, {provide: ViewResolver, useClass: MockViewResolver}, - TestComponentBuilder, {provide: TestComponentRenderer, useClass: DOMTestComponentRenderer}, ] ]; diff --git a/modules/@angular/platform-server/testing/server.ts b/modules/@angular/platform-server/testing/server.ts index 10bd463c97..de165a0f51 100644 --- a/modules/@angular/platform-server/testing/server.ts +++ b/modules/@angular/platform-server/testing/server.ts @@ -7,8 +7,9 @@ */ import {COMPILER_PROVIDERS, DirectiveResolver, ViewResolver, XHR} from '@angular/compiler'; -import {MockDirectiveResolver, MockViewResolver, TestComponentBuilder, TestComponentRenderer} from '@angular/compiler/testing'; +import {MockDirectiveResolver, MockViewResolver, OverridingTestComponentBuilder} from '@angular/compiler/testing'; import {APPLICATION_COMMON_PROVIDERS, APP_ID, NgZone, PLATFORM_COMMON_PROVIDERS, PLATFORM_INITIALIZER, RootRenderer} from '@angular/core'; +import {TestComponentBuilder, TestComponentRenderer} from '@angular/core/testing'; import {AnimationDriver, NoOpAnimationDriver} from '../core_private'; import {DOMTestComponentRenderer} from '../platform_browser_dynamic_testing_private'; @@ -71,9 +72,9 @@ export const TEST_SERVER_APPLICATION_PROVIDERS: Array>; - createFakeAsync(rootComponentType: Type): ComponentFixture; - createSync(componentFactory: ComponentFactory): ComponentFixture; overrideAnimations(componentType: Type, animations: AnimationEntryMetadata[]): TestComponentBuilder; - overrideBindings(type: Type, providers: any[]): TestComponentBuilder; - overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder; - overrideProviders(type: Type, providers: any[]): TestComponentBuilder; - overrideTemplate(componentType: Type, template: string): TestComponentBuilder; - overrideView(componentType: Type, view: ViewMetadata): TestComponentBuilder; - overrideViewBindings(type: Type, providers: any[]): TestComponentBuilder; - overrideViewProviders(type: Type, providers: any[]): TestComponentBuilder; -} - -export declare class TestComponentRenderer { - insertRootElement(rootElementId: string): void; + overrideDirective(componentType: Type, from: Type, to: Type): OverridingTestComponentBuilder; + overrideProviders(type: Type, providers: any[]): OverridingTestComponentBuilder; + overrideTemplate(componentType: Type, template: string): OverridingTestComponentBuilder; + overrideView(componentType: Type, view: ViewMetadata): OverridingTestComponentBuilder; + overrideViewProviders(type: Type, providers: any[]): OverridingTestComponentBuilder; } diff --git a/tools/public_api_guard/core/testing.d.ts b/tools/public_api_guard/core/testing.d.ts index ada5369118..b664f5476a 100644 --- a/tools/public_api_guard/core/testing.d.ts +++ b/tools/public_api_guard/core/testing.d.ts @@ -23,6 +23,10 @@ export declare class ComponentFixture { whenStable(): Promise; } +export declare var ComponentFixtureAutoDetect: OpaqueToken; + +export declare var ComponentFixtureNoNgZone: OpaqueToken; + export declare var ddescribe: Function; export declare var describe: Function; @@ -56,6 +60,25 @@ export declare function resetBaseTestProviders(): void; export declare function setBaseTestProviders(platformProviders: Array, applicationProviders: Array): void; +export declare class TestComponentBuilder { + protected _injector: Injector; + constructor(_injector: Injector); + createAsync(rootComponentType: Type): Promise>; + createFakeAsync(rootComponentType: Type): ComponentFixture; + protected createFromFactory(ngZone: NgZone, componentFactory: ComponentFactory): ComponentFixture; + createSync(componentFactory: ComponentFactory): ComponentFixture; + overrideAnimations(componentType: Type, animations: AnimationEntryMetadata[]): TestComponentBuilder; + overrideDirective(componentType: Type, from: Type, to: Type): TestComponentBuilder; + overrideProviders(type: Type, providers: any[]): TestComponentBuilder; + overrideTemplate(componentType: Type, template: string): TestComponentBuilder; + overrideView(componentType: Type, view: ViewMetadata): TestComponentBuilder; + overrideViewProviders(type: Type, providers: any[]): TestComponentBuilder; +} + +export declare class TestComponentRenderer { + insertRootElement(rootElementId: string): void; +} + export declare class TestInjector { applicationProviders: Array; platformProviders: Array;