feat(testing): add implicit test module

Every test now has an implicit module. It can be configured via `configureModule` (from @angular/core/testing)
to add providers, directives, pipes, ...

The compiler now has to be configured separately via `configureCompiler` (from @angular/core/testing)
to add providers or define whether to use jit.

BREAKING CHANGE:
- Application providers can no longer inject compiler internals (i.e. everything
  from `@angular/compiler). Inject `Compiler` instead. This reflects the
  changes to `bootstrap` for module support (3f55aa609f).
- Compiler providers can no longer be added via `addProviders` / `withProviders`.
  Use the new method `configureCompiler` instead.
- Platform directives / pipes need to be provided via
  `configureModule` and can no longer be provided via the
  `PLATFORM_PIPES` / `PLATFORM_DIRECTIVES` tokens.
- `setBaseTestProviders()` was renamed into `initTestEnvironment` and 
  now takes a `PlatformRef` and a factory for a
  `Compiler`.
- E.g. for the browser platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS} from ‘@angular/platform-browser-dynamic/testing’;
  
  setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
      TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {browserTestCompiler, browserDynamicTestPlatform,
      BrowserDynamicTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      browserTestCompiler,
      browserDynamicTestPlatform(),
      BrowserDynamicTestModule);

  ```
- E.g. for the server platform:
  
  BEFORE:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS} from ‘@angular/platform-server/testing/server’;
  
  setBaseTestProviders(TEST_SERVER_PLATFORM_PROVIDERS,
      TEST_SERVER_APPLICATION_PROVIDERS);   
  ```

  AFTER:
  ```
  import {setBaseTestProviders} from ‘@angular/core/testing’;
  import {serverTestCompiler, serverTestPlatform,
      ServerTestModule} from ‘@angular/platform-browser-dynamic/testing’;
  
  initTestEnvironment(
      serverTestCompiler,
      serverTestPlatform(),
      ServerTestModule);

  ```

Related to #9726
Closes #9846
This commit is contained in:
Tobias Bosch
2016-07-04 09:37:30 -07:00
parent 37e6da6dfb
commit 8d746e3f67
38 changed files with 1000 additions and 497 deletions

View File

@ -6,11 +6,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import {addProviders, inject, fakeAsync, async, withProviders, tick,} from '@angular/core/testing';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
import {Injectable, provide, Component, ViewMetadata} from '@angular/core';
import {NgIf} from '@angular/common';
import {CompilerConfig, XHR} from '@angular/compiler';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {AppModule, Component, ComponentFactoryResolver, Directive, Injectable, Input, Pipe, ViewMetadata, provide} from '@angular/core';
import {addProviders, async, configureCompiler, configureModule, fakeAsync, inject, tick, withModule, withProviders} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/matchers';
import {stringify} from '../../http/src/facade/lang';
import {PromiseWrapper} from '../../http/src/facade/promise';
// Services, and components for the tests.
@ -98,6 +101,29 @@ class TestViewProvidersComp {
constructor(private fancyService: FancyService) {}
}
@Directive({selector: '[someDir]', host: {'[title]': 'someDir'}})
class SomeDirective {
@Input()
someDir: string;
}
@Pipe({name: 'somePipe'})
class SomePipe {
transform(value: string): any { return `transformed ${value}`; }
}
@Component({selector: 'comp', template: `<div [someDir]="'someValue' | somePipe"></div>`})
class CompUsingModuleDirectiveAndPipe {
}
@AppModule({})
class SomeNestedModule {
}
@Component({selector: 'comp', templateUrl: 'someTemplate.html'})
class CompWithUrlTemplate {
}
export function main() {
describe('using the async helper', () => {
var actuallyDone: boolean;
@ -203,6 +229,133 @@ export function main() {
});
});
describe('using the test injector with modules', () => {
let moduleConfig: any;
beforeEach(() => {
moduleConfig = {
providers: [FancyService],
directives: [SomeDirective],
pipes: [SomePipe],
precompile: [CompUsingModuleDirectiveAndPipe],
modules: [SomeNestedModule]
};
});
describe('setting up a module', () => {
beforeEach(() => configureModule(moduleConfig));
it('should use set up providers', inject([FancyService], (service: FancyService) => {
expect(service.value).toEqual('real value');
}));
it('should use set up directives and pipes',
inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
let compFixture = tcb.createSync(CompUsingModuleDirectiveAndPipe);
let el = compFixture.debugElement;
compFixture.detectChanges();
expect(el.children[0].properties['title']).toBe('transformed someValue');
}));
it('should use set up nested modules',
inject([SomeNestedModule], (nestedModule: SomeNestedModule) => {
expect(nestedModule).toBeAnInstanceOf(SomeNestedModule);
}));
it('should use set up precompile components',
inject([ComponentFactoryResolver], (resolver: ComponentFactoryResolver) => {
expect(resolver.resolveComponentFactory(CompUsingModuleDirectiveAndPipe).componentType)
.toBe(CompUsingModuleDirectiveAndPipe);
}));
});
describe('per test modules', () => {
it('should use set up providers',
withModule(() => moduleConfig).inject([FancyService], (service: FancyService) => {
expect(service.value).toEqual('real value');
}));
it('should use set up directives and pipes',
withModule(() => moduleConfig)
.inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
let compFixture = tcb.createSync(CompUsingModuleDirectiveAndPipe);
let el = compFixture.debugElement;
compFixture.detectChanges();
expect(el.children[0].properties['title']).toBe('transformed someValue');
}));
it('should use set up nested modules',
withModule(() => moduleConfig)
.inject([SomeNestedModule], (nestedModule: SomeNestedModule) => {
expect(nestedModule).toBeAnInstanceOf(SomeNestedModule);
}));
it('should use set up precompile components',
withModule(() => moduleConfig)
.inject([ComponentFactoryResolver], (resolver: ComponentFactoryResolver) => {
expect(
resolver.resolveComponentFactory(CompUsingModuleDirectiveAndPipe).componentType)
.toBe(CompUsingModuleDirectiveAndPipe);
}));
});
describe('precompile components with template url', () => {
let xhrGet: jasmine.Spy;
beforeEach(() => {
xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!'));
configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]});
});
it('should allow to precompile components with templateUrl using the async helper',
async(withModule(() => {
return {precompile: [CompWithUrlTemplate]};
}).inject([ComponentFactoryResolver], (resolver: ComponentFactoryResolver) => {
expect(resolver.resolveComponentFactory(CompWithUrlTemplate).componentType)
.toBe(CompWithUrlTemplate);
})));
it('should allow to precompile components with templateUrl using the fakeAsync helper',
fakeAsync(withModule(() => {
return {precompile: [CompWithUrlTemplate]};
}).inject([ComponentFactoryResolver], (resolver: ComponentFactoryResolver) => {
expect(resolver.resolveComponentFactory(CompWithUrlTemplate).componentType)
.toBe(CompWithUrlTemplate);
})));
});
describe('setting up the compiler', () => {
describe('providers', () => {
beforeEach(() => {
let xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!'));
configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]});
});
it('should use set up providers',
fakeAsync(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
let compFixture = tcb.createFakeAsync(CompWithUrlTemplate);
expect(compFixture.nativeElement).toHaveText('Hello world!');
})));
});
describe('useJit true', () => {
beforeEach(() => { configureCompiler({useJit: true}); });
it('should set the value into CompilerConfig',
inject([CompilerConfig], (config: CompilerConfig) => {
expect(config.useJit).toBe(true);
}));
});
describe('useJit false', () => {
beforeEach(() => { configureCompiler({useJit: false}); });
it('should set the value into CompilerConfig',
inject([CompilerConfig], (config: CompilerConfig) => {
expect(config.useJit).toBe(false);
}));
});
});
});
describe('errors', () => {
var originalJasmineIt: any;
var originalJasmineBeforeEach: any;
@ -294,6 +447,36 @@ export function main() {
});
});
});
describe('precompile', () => {
let xhrGet: jasmine.Spy;
beforeEach(() => {
xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!'));
configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]});
});
it('should report an error for precompile components with templateUrl and sync tests', () => {
var itPromise = patchJasmineIt();
expect(
() => it(
'should fail',
withModule(() => { return {precompile: [CompWithUrlTemplate]}; })
.inject(
[ComponentFactoryResolver],
(resolver: ComponentFactoryResolver) => {
expect(
resolver.resolveComponentFactory(CompWithUrlTemplate).componentType)
.toBe(CompWithUrlTemplate);
})))
.toThrowError(
`This test module precompiles the component ${stringify(CompWithUrlTemplate)} which is using a "templateUrl", but the test is synchronous. ` +
'Please use the "async(...)" or "fakeAsync(...)" helper functions to make the test asynchronous.');
restoreJasmineIt();
});
});
});
describe('test component builder', function() {

View File

@ -8,10 +8,10 @@
import {inject, ddescribe, describe, it, iit, expect, beforeEach, beforeEachProviders,} from '@angular/core/testing/testing_internal';
import {AsyncTestCompleter} from '@angular/core/testing/testing_internal';
import {TestInjector} from '@angular/core/testing';
import {TestInjector, configureModule} from '@angular/core/testing';
import {TestComponentBuilder} from '@angular/compiler/testing';
import {getDOM} from '@angular/platform-browser/src/dom/dom_adapter';
import {provide, Injector, ViewMetadata, Component, Injectable, ComponentRef} from '@angular/core';
import {provide, Injector, ViewMetadata, Component, Injectable, ComponentRef, ReflectiveInjector, getPlatform} from '@angular/core';
import {NgIf} from '@angular/common';
import {WebWorkerRootRenderer} from '@angular/platform-browser/src/web_workers/worker/renderer';
import {ClientMessageBrokerFactory, ClientMessageBrokerFactory_} from '@angular/platform-browser/src/web_workers/shared/client_message_broker';
@ -25,7 +25,8 @@ import {createPairedMessageBuses, PairedMessageBuses} from '../shared/web_worker
import {ServiceMessageBrokerFactory_} from '@angular/platform-browser/src/web_workers/shared/service_message_broker';
import {CompilerConfig} from '@angular/compiler';
import {dispatchEvent} from '../../../../platform-browser/testing/browser_util';
import {TEST_BROWSER_PLATFORM_PROVIDERS, TEST_BROWSER_APPLICATION_PROVIDERS} from '@angular/platform-browser/testing';
import {BrowserTestModule} from '@angular/platform-browser/testing';
import {browserTestCompiler, browserDynamicTestPlatform} from '@angular/platform-browser-dynamic/testing'
export function main() {
function createWebWorkerBrokerFactory(
@ -58,199 +59,206 @@ export function main() {
return new DebugDomRootRenderer(workerRootRenderer);
}
describe('Web Worker Renderer', () => {
var uiInjector: Injector;
var uiRenderStore: RenderStore;
var workerRenderStore: RenderStore;
describe(
'Web Worker Renderer',
() => {
var uiInjector: Injector;
var uiRenderStore: RenderStore;
var workerRenderStore: RenderStore;
beforeEachProviders(() => {
uiRenderStore = new RenderStore();
var testUiInjector = new TestInjector();
testUiInjector.platformProviders = TEST_BROWSER_PLATFORM_PROVIDERS;
testUiInjector.applicationProviders = TEST_BROWSER_APPLICATION_PROVIDERS;
testUiInjector.addProviders([
Serializer, {provide: RenderStore, useValue: uiRenderStore},
{provide: DomRootRenderer, useClass: DomRootRenderer_},
{provide: RootRenderer, useExisting: DomRootRenderer}
]);
uiInjector = testUiInjector.createInjector();
var uiSerializer = uiInjector.get(Serializer);
var domRootRenderer = uiInjector.get(DomRootRenderer);
workerRenderStore = new RenderStore();
return [
Serializer, {provide: CompilerConfig, useValue: new CompilerConfig({genDebugInfo: true})},
{provide: RenderStore, useValue: workerRenderStore}, {
provide: RootRenderer,
useFactory: (workerSerializer: Serializer) => {
return createWorkerRenderer(
workerSerializer, uiSerializer, domRootRenderer, uiRenderStore, workerRenderStore);
},
deps: [Serializer]
beforeEach(() => {
uiRenderStore = new RenderStore();
var testUiInjector = new TestInjector();
testUiInjector.platform = browserDynamicTestPlatform();
testUiInjector.compilerFactory = browserTestCompiler;
testUiInjector.appModule = BrowserTestModule;
testUiInjector.configureModule({
providers: [
Serializer, {provide: RenderStore, useValue: uiRenderStore},
{provide: DomRootRenderer, useClass: DomRootRenderer_},
{provide: RootRenderer, useExisting: DomRootRenderer}
]
});
uiInjector = testUiInjector.createInjectorSync();
var uiSerializer = uiInjector.get(Serializer);
var domRootRenderer = uiInjector.get(DomRootRenderer);
workerRenderStore = new RenderStore();
configureModule({
providers: [
Serializer, {provide: RenderStore, useValue: workerRenderStore}, {
provide: RootRenderer,
useFactory: (workerSerializer: Serializer) => {
return createWorkerRenderer(
workerSerializer, uiSerializer, domRootRenderer, uiRenderStore,
workerRenderStore);
},
deps: [Serializer]
}
]
});
});
function getRenderElement(workerEl: any) {
var id = workerRenderStore.serialize(workerEl);
return uiRenderStore.deserialize(id);
}
];
});
function getRenderElement(workerEl: any) {
var id = workerRenderStore.serialize(workerEl);
return uiRenderStore.deserialize(id);
}
function getRenderer(componentRef: ComponentRef<any>) {
return (<any>componentRef.hostView).internalView.renderer;
}
function getRenderer(componentRef: ComponentRef<any>) {
return (<any>componentRef.hostView).internalView.renderer;
}
it('should update text nodes',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({template: '<div>{{ctxProp}}</div>'}))
.createAsync(MyComp2)
.then((fixture) => {
var renderEl = getRenderElement(fixture.debugElement.nativeElement);
expect(renderEl).toHaveText('');
it('should update text nodes',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({template: '<div>{{ctxProp}}</div>'}))
.createAsync(MyComp2)
.then((fixture) => {
var renderEl = getRenderElement(fixture.debugElement.nativeElement);
expect(renderEl).toHaveText('');
fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
expect(renderEl).toHaveText('Hello World!');
async.done();
fixture.debugElement.componentInstance.ctxProp = 'Hello World!';
fixture.detectChanges();
expect(renderEl).toHaveText('Hello World!');
async.done();
});
}));
});
}));
it('should update any element property/attributes/class/style(s) independent of the compilation on the root element and other elements',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(
MyComp2, new ViewMetadata(
{template: '<input [title]="y" style="position:absolute">'}))
.createAsync(MyComp2)
.then((fixture) => {
var checkSetters =
(componentRef: any /** TODO #9100 */,
workerEl: any /** TODO #9100 */) => {
var renderer = getRenderer(componentRef);
var el = getRenderElement(workerEl);
renderer.setElementProperty(workerEl, 'tabIndex', 1);
expect((<HTMLInputElement>el).tabIndex).toEqual(1);
it('should update any element property/attributes/class/style(s) independent of the compilation on the root element and other elements',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(
MyComp2,
new ViewMetadata({template: '<input [title]="y" style="position:absolute">'}))
.createAsync(MyComp2)
.then((fixture) => {
var checkSetters =
(componentRef: any /** TODO #9100 */, workerEl: any /** TODO #9100 */) => {
var renderer = getRenderer(componentRef);
var el = getRenderElement(workerEl);
renderer.setElementProperty(workerEl, 'tabIndex', 1);
expect((<HTMLInputElement>el).tabIndex).toEqual(1);
renderer.setElementClass(workerEl, 'a', true);
expect(getDOM().hasClass(el, 'a')).toBe(true);
renderer.setElementClass(workerEl, 'a', false);
expect(getDOM().hasClass(el, 'a')).toBe(false);
renderer.setElementClass(workerEl, 'a', true);
expect(getDOM().hasClass(el, 'a')).toBe(true);
renderer.setElementClass(workerEl, 'a', false);
expect(getDOM().hasClass(el, 'a')).toBe(false);
renderer.setElementStyle(workerEl, 'width', '10px');
expect(getDOM().getStyle(el, 'width')).toEqual('10px');
renderer.setElementStyle(workerEl, 'width', null);
expect(getDOM().getStyle(el, 'width')).toEqual('');
renderer.setElementStyle(workerEl, 'width', '10px');
expect(getDOM().getStyle(el, 'width')).toEqual('10px');
renderer.setElementStyle(workerEl, 'width', null);
expect(getDOM().getStyle(el, 'width')).toEqual('');
renderer.setElementAttribute(workerEl, 'someattr', 'someValue');
expect(getDOM().getAttribute(el, 'someattr')).toEqual('someValue');
};
renderer.setElementAttribute(workerEl, 'someattr', 'someValue');
expect(getDOM().getAttribute(el, 'someattr')).toEqual('someValue');
};
// root element
checkSetters(fixture.componentRef, fixture.debugElement.nativeElement);
// nested elements
checkSetters(
fixture.componentRef, fixture.debugElement.children[0].nativeElement);
// root element
checkSetters(fixture.componentRef, fixture.debugElement.nativeElement);
// nested elements
checkSetters(
fixture.componentRef, fixture.debugElement.children[0].nativeElement);
async.done();
});
}));
async.done();
});
}));
it('should update any template comment property/attributes',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var tpl = '<template [ngIf]="ctxBoolProp"></template>';
tcb.overrideView(MyComp2, new ViewMetadata({template: tpl, directives: [NgIf]}))
it('should update any template comment property/attributes',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
var tpl = '<template [ngIf]="ctxBoolProp"></template>';
tcb.overrideView(MyComp2, new ViewMetadata({template: tpl, directives: [NgIf]}))
.createAsync(MyComp2)
.then((fixture) => {
(<MyComp2>fixture.debugElement.componentInstance).ctxBoolProp = true;
fixture.detectChanges();
var el = getRenderElement(fixture.debugElement.nativeElement);
expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"');
async.done();
});
}));
.createAsync(MyComp2)
.then((fixture) => {
(<MyComp2>fixture.debugElement.componentInstance).ctxBoolProp = true;
fixture.detectChanges();
var el = getRenderElement(fixture.debugElement.nativeElement);
expect(getDOM().getInnerHTML(el)).toContain('"ng-reflect-ng-if": "true"');
async.done();
});
}));
it('should add and remove fragments',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({
template: '<template [ngIf]="ctxBoolProp">hello</template>',
directives: [NgIf]
}))
.createAsync(MyComp2)
.then((fixture) => {
it('should add and remove fragments',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({
template: '<template [ngIf]="ctxBoolProp">hello</template>',
directives: [NgIf]
}))
.createAsync(MyComp2)
.then((fixture) => {
var rootEl = getRenderElement(fixture.debugElement.nativeElement);
expect(rootEl).toHaveText('');
var rootEl = getRenderElement(fixture.debugElement.nativeElement);
expect(rootEl).toHaveText('');
fixture.debugElement.componentInstance.ctxBoolProp = true;
fixture.detectChanges();
expect(rootEl).toHaveText('hello');
fixture.debugElement.componentInstance.ctxBoolProp = true;
fixture.detectChanges();
expect(rootEl).toHaveText('hello');
fixture.debugElement.componentInstance.ctxBoolProp = false;
fixture.detectChanges();
expect(rootEl).toHaveText('');
fixture.debugElement.componentInstance.ctxBoolProp = false;
fixture.detectChanges();
expect(rootEl).toHaveText('');
async.done();
});
}));
async.done();
});
}));
if (getDOM().supportsDOMEvents()) {
it('should call actions on the element',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({template: '<input [title]="y">'}))
.createAsync(MyComp2)
.then((fixture) => {
var el = fixture.debugElement.children[0];
getRenderer(fixture.componentRef)
.invokeElementMethod(el.nativeElement, 'setAttribute', ['a', 'b']);
if (getDOM().supportsDOMEvents()) {
it('should call actions on the element',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(MyComp2, new ViewMetadata({template: '<input [title]="y">'}))
.createAsync(MyComp2)
.then((fixture) => {
var el = fixture.debugElement.children[0];
getRenderer(fixture.componentRef)
.invokeElementMethod(el.nativeElement, 'setAttribute', ['a', 'b']);
expect(getDOM().getAttribute(getRenderElement(el.nativeElement), 'a'))
.toEqual('b');
async.done();
});
}));
expect(getDOM().getAttribute(getRenderElement(el.nativeElement), 'a'))
.toEqual('b');
async.done();
});
}));
it('should listen to events',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(
MyComp2,
new ViewMetadata({template: '<input (change)="ctxNumProp = 1">'}))
.createAsync(MyComp2)
.then((fixture) => {
var el = fixture.debugElement.children[0];
dispatchEvent(getRenderElement(el.nativeElement), 'change');
expect(fixture.componentInstance.ctxNumProp).toBe(1);
it('should listen to events',
inject(
[TestComponentBuilder, AsyncTestCompleter],
(tcb: TestComponentBuilder, async: AsyncTestCompleter) => {
tcb.overrideView(
MyComp2, new ViewMetadata({template: '<input (change)="ctxNumProp = 1">'}))
.createAsync(MyComp2)
.then((fixture) => {
var el = fixture.debugElement.children[0];
dispatchEvent(getRenderElement(el.nativeElement), 'change');
expect(fixture.componentInstance.ctxNumProp).toBe(1);
fixture.destroy();
fixture.destroy();
async.done();
});
}));
}
});
async.done();
});
}));
}
});
}
@Component({selector: 'my-comp', directives: []})
@Injectable()
class MyComp2 {
ctxProp: string;
ctxNumProp: any /** TODO #9100 */;
ctxBoolProp: boolean;
constructor() {
@Component(
{selector: 'my-comp',
directives: []}) @Injectable() class MyComp2 {
ctxProp: string; ctxNumProp: any /** TODO #9100 */; ctxBoolProp: boolean; constructor() {
this.ctxProp = 'initial value';
this.ctxNumProp = 0;
this.ctxBoolProp = false;
}
throwError() { throw 'boom'; }
throwError() { throw 'boom';}
}