From aff1bc9f2d3ac8c394caa391d35b1c087b8ba336 Mon Sep 17 00:00:00 2001 From: Julie Ralph Date: Wed, 10 Aug 2016 11:51:40 -0700 Subject: [PATCH] refactor(tests): move public test APIs to TestBed (#10621) Completely remove deprecated TestComponentBuilder and friends. --- .../test/testing_public_browser_spec.ts | 35 +- .../test/testing_public_spec.ts | 936 ++++++++---------- 2 files changed, 456 insertions(+), 515 deletions(-) diff --git a/modules/@angular/platform-browser-dynamic/test/testing_public_browser_spec.ts b/modules/@angular/platform-browser-dynamic/test/testing_public_browser_spec.ts index 41b8e86fd5..771a42cb02 100644 --- a/modules/@angular/platform-browser-dynamic/test/testing_public_browser_spec.ts +++ b/modules/@angular/platform-browser-dynamic/test/testing_public_browser_spec.ts @@ -8,7 +8,7 @@ import {XHR} from '@angular/compiler'; import {Component, bind} from '@angular/core'; -import {TestComponentBuilder, addProviders, async, fakeAsync, inject, tick} from '@angular/core/testing'; +import {TestBed, async, fakeAsync, flushMicrotasks, inject, tick} from '@angular/core/testing'; import {XHRImpl} from '../src/xhr/xhr_impl'; @@ -56,7 +56,10 @@ export function main() { describe('using the test injector with the inject helper', () => { describe('setting up Providers', () => { - beforeEach(() => addProviders([{provide: FancyService, useValue: new FancyService()}])); + beforeEach(() => { + TestBed.configureTestingModule( + {providers: [{provide: FancyService, useValue: new FancyService()}]}); + }); it('provides a real XHR instance', inject([XHR], (xhr: XHR) => { expect(xhr instanceof XHRImpl).toBeTruthy(); })); @@ -96,10 +99,10 @@ export function main() { it('should fail when an XHR fails', (done: any /** TODO #9100 */) => { var itPromise = patchJasmineIt(); - it('should fail with an error from a promise', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - return tcb.createAsync(BadTemplateUrl); - }))); + it('should fail with an error from a promise', async(() => { + TestBed.configureTestingModule({declarations: [BadTemplateUrl]}); + TestBed.compileComponents(); + })); itPromise.then( () => { done.fail('Expected test to fail, but it did not'); }, @@ -113,17 +116,15 @@ export function main() { }); describe('test component builder', function() { - it('should allow an external templateUrl', - async(inject( - [TestComponentBuilder], - (tcb: TestComponentBuilder) => { - - tcb.createAsync(ExternalTemplateComp).then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement.textContent) - .toEqual('from external template\n'); - }); - })), + it('should allow an external templateUrl', async(() => { + TestBed.configureTestingModule({declarations: [ExternalTemplateComp]}); + TestBed.compileComponents().then(() => { + let componentFixture = TestBed.createComponent(ExternalTemplateComp); + componentFixture.detectChanges(); + expect(componentFixture.debugElement.nativeElement.textContent) + .toEqual('from external template\n'); + }); + }), 10000); // Long timeout here because this test makes an actual XHR, and is slow on Edge. }); }); diff --git a/modules/@angular/platform-browser/test/testing_public_spec.ts b/modules/@angular/platform-browser/test/testing_public_spec.ts index d8db44f848..e246052818 100644 --- a/modules/@angular/platform-browser/test/testing_public_spec.ts +++ b/modules/@angular/platform-browser/test/testing_public_spec.ts @@ -9,15 +9,14 @@ import {NgIf} from '@angular/common'; import {CompilerConfig, XHR} from '@angular/compiler'; import {CUSTOM_ELEMENTS_SCHEMA, Component, ComponentFactoryResolver, ComponentMetadata, Directive, DirectiveMetadata, HostBinding, Injectable, Input, NgModule, NgModuleMetadata, Pipe, PipeMetadata, ViewMetadata, provide} from '@angular/core'; -import {TestBed, TestComponentBuilder, addProviders, async, fakeAsync, inject, tick, withModule, withProviders} from '@angular/core/testing'; +import {TestBed, async, fakeAsync, inject, tick, withModule} from '@angular/core/testing'; import {expect} from '@angular/platform-browser/testing/matchers'; import {stringify} from '../src/facade/lang'; // Services, and components for the tests. -@Component( - {selector: 'child-comp', template: `Original {{childBinding}}`, directives: []}) +@Component({selector: 'child-comp', template: `Original {{childBinding}}`}) @Injectable() class ChildComp { childBinding: string; @@ -32,7 +31,6 @@ class MockChildComp { @Component({ selector: 'parent-comp', template: `Parent()`, - directives: [ChildComp] }) @Injectable() class ParentComp { @@ -52,7 +50,6 @@ class ChildChildComp { @Component({ selector: 'child-comp', template: `Original {{childBinding}}()`, - directives: [ChildChildComp] }) @Injectable() class ChildWithChildComp { @@ -60,11 +57,6 @@ class ChildWithChildComp { constructor() { this.childBinding = 'Child'; } } -@Component({selector: 'child-child-comp', template: `ChildChild Mock`}) -@Injectable() -class MockChildChildComp { -} - class FancyService { value: string = 'real value'; getAsyncValue() { return Promise.resolve('async value'); } @@ -123,546 +115,494 @@ class CompWithUrlTemplate { } export function main() { - describe('using the async helper', () => { - var actuallyDone: boolean; + describe('public testing API', () => { + describe('using the async helper', () => { + var actuallyDone: boolean; - beforeEach(() => { actuallyDone = false; }); + beforeEach(() => { actuallyDone = false; }); - afterEach(() => { expect(actuallyDone).toEqual(true); }); + afterEach(() => { expect(actuallyDone).toEqual(true); }); - it('should run normal tests', () => { actuallyDone = true; }); + it('should run normal tests', () => { actuallyDone = true; }); - it('should run normal async tests', (done: any /** TODO #9100 */) => { - setTimeout(() => { - actuallyDone = true; - done(); - }, 0); - }); + it('should run normal async tests', (done: any /** TODO #9100 */) => { + setTimeout(() => { + actuallyDone = true; + done(); + }, 0); + }); - it('should run async tests with tasks', - async(() => { setTimeout(() => { actuallyDone = true; }, 0); })); + it('should run async tests with tasks', + async(() => { setTimeout(() => { actuallyDone = true; }, 0); })); - it('should run async tests with promises', async(() => { - var p = new Promise((resolve, reject) => { setTimeout(resolve, 10); }); - p.then(() => { actuallyDone = true; }); - })); - }); - - describe('using the test injector with the inject helper', () => { - describe('setting up Providers', () => { - beforeEach(() => addProviders([{provide: FancyService, useValue: new FancyService()}])); - - it('should use set up providers', inject([FancyService], (service: any /** TODO #9100 */) => { - expect(service.value).toEqual('real value'); + it('should run async tests with promises', async(() => { + var p = new Promise((resolve, reject) => { setTimeout(resolve, 10); }); + p.then(() => { actuallyDone = true; }); })); - - it('should wait until returned promises', - async(inject([FancyService], (service: any /** TODO #9100 */) => { - service.getAsyncValue().then( - (value: any /** TODO #9100 */) => { expect(value).toEqual('async value'); }); - service.getTimeoutValue().then( - (value: any /** TODO #9100 */) => { expect(value).toEqual('timeout value'); }); - }))); - - it('should allow the use of fakeAsync', - fakeAsync(inject([FancyService], (service: any /** TODO #9100 */) => { - var value: any /** TODO #9100 */; - service.getAsyncValue().then(function(val: any /** TODO #9100 */) { value = val; }); - tick(); - expect(value).toEqual('async value'); - }))); - - it('should allow use of "done"', (done: any /** TODO #9100 */) => { - inject([FancyService], (service: any /** TODO #9100 */) => { - let count = 0; - let id = setInterval(() => { - count++; - if (count > 2) { - clearInterval(id); - done(); - } - }, 5); - })(); // inject needs to be invoked explicitly with (). - }); - - describe('using beforeEach', () => { - beforeEach(inject([FancyService], (service: any /** TODO #9100 */) => { - service.value = 'value modified in beforeEach'; - })); - - it('should use modified providers', - inject([FancyService], (service: any /** TODO #9100 */) => { - expect(service.value).toEqual('value modified in beforeEach'); - })); - }); - - describe('using async beforeEach', () => { - beforeEach(async(inject([FancyService], (service: any /** TODO #9100 */) => { - service.getAsyncValue().then( - (value: any /** TODO #9100 */) => { service.value = value; }); - }))); - - it('should use asynchronously modified value', - inject([FancyService], (service: any /** TODO #9100 */) => { - expect(service.value).toEqual('async value'); - })); - }); }); - describe('per test providers', () => { - it('should allow per test providers', - withProviders(() => [{provide: FancyService, useValue: new FancyService()}]) - .inject([FancyService], (service: any /** TODO #9100 */) => { + describe('using the test injector with the inject helper', () => { + describe('setting up Providers', () => { + beforeEach(() => { + TestBed.configureTestingModule( + {providers: [{provide: FancyService, useValue: new FancyService()}]}); + + it('should use set up providers', + inject([FancyService], (service: any /** TODO #9100 */) => { expect(service.value).toEqual('real value'); })); - it('should return value from inject', () => { - let retval = withProviders(() => [{provide: FancyService, useValue: new FancyService()}]) - .inject([FancyService], (service: any /** TODO #9100 */) => { - expect(service.value).toEqual('real value'); - return 10; - })(); - expect(retval).toBe(10); + it('should wait until returned promises', + async(inject([FancyService], (service: any /** TODO #9100 */) => { + service.getAsyncValue().then( + (value: any /** TODO #9100 */) => { expect(value).toEqual('async value'); }); + service.getTimeoutValue().then( + (value: any /** TODO #9100 */) => { expect(value).toEqual('timeout value'); }); + }))); + + it('should allow the use of fakeAsync', + fakeAsync(inject([FancyService], (service: any /** TODO #9100 */) => { + var value: any /** TODO #9100 */; + service.getAsyncValue().then(function(val: any /** TODO #9100 */) { value = val; }); + tick(); + expect(value).toEqual('async value'); + }))); + + it('should allow use of "done"', (done: any /** TODO #9100 */) => { + inject([FancyService], (service: any /** TODO #9100 */) => { + let count = 0; + let id = setInterval(() => { + count++; + if (count > 2) { + clearInterval(id); + done(); + } + }, 5); + })(); // inject needs to be invoked explicitly with (). + }); + + describe('using beforeEach', () => { + beforeEach(inject([FancyService], (service: any /** TODO #9100 */) => { + service.value = 'value modified in beforeEach'; + })); + + it('should use modified providers', + inject([FancyService], (service: any /** TODO #9100 */) => { + expect(service.value).toEqual('value modified in beforeEach'); + })); + }); + + describe('using async beforeEach', () => { + beforeEach(async(inject([FancyService], (service: any /** TODO #9100 */) => { + service.getAsyncValue().then( + (value: any /** TODO #9100 */) => { service.value = value; }); + }))); + + it('should use asynchronously modified value', + inject([FancyService], (service: any /** TODO #9100 */) => { + expect(service.value).toEqual('async value'); + })); + }); + }); }); }); - }); - describe('using the test injector with modules', () => { - let moduleConfig = { - providers: [FancyService], - imports: [SomeLibModule], - declarations: [SomeDirective, SomePipe, CompUsingModuleDirectiveAndPipe], - }; + describe('using the test injector with modules', () => { + let moduleConfig = { + providers: [FancyService], + imports: [SomeLibModule], + declarations: [SomeDirective, SomePipe, CompUsingModuleDirectiveAndPipe], + }; - describe('setting up a module', () => { - beforeEach(() => TestBed.configureTestingModule(moduleConfig)); + describe('setting up a module', () => { + beforeEach(() => TestBed.configureTestingModule(moduleConfig)); - it('should use set up providers', inject([FancyService], (service: FancyService) => { - expect(service.value).toEqual('real value'); - })); + it('should use set up providers', inject([FancyService], (service: FancyService) => { + expect(service.value).toEqual('real value'); + })); - it('should be able to create any declared components', () => { - const compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); - expect(compFixture.componentInstance).toBeAnInstanceOf(CompUsingModuleDirectiveAndPipe); + it('should be able to create any declared components', () => { + const compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); + expect(compFixture.componentInstance).toBeAnInstanceOf(CompUsingModuleDirectiveAndPipe); + }); + + it('should use set up directives and pipes', () => { + const compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); + let el = compFixture.debugElement; + + compFixture.detectChanges(); + expect(el.children[0].properties['title']).toBe('transformed someValue'); + }); + + it('should use set up imported modules', + inject([SomeLibModule], (libModule: SomeLibModule) => { + expect(libModule).toBeAnInstanceOf(SomeLibModule); + })); + + describe('provided schemas', () => { + @Component({template: ''}) + class ComponentUsingInvalidProperty { + } + + beforeEach(() => { + TestBed.configureTestingModule( + {schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ComponentUsingInvalidProperty]}); + }); + + it('should not error on unknown bound properties on custom elements when using the CUSTOM_ELEMENTS_SCHEMA', + () => { + expect(TestBed.createComponent(ComponentUsingInvalidProperty).componentInstance) + .toBeAnInstanceOf(ComponentUsingInvalidProperty); + }); + }); }); - it('should use set up directives and pipes', () => { - const compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); - let el = compFixture.debugElement; + describe('per test modules', () => { + it('should use set up providers', + withModule(moduleConfig).inject([FancyService], (service: FancyService) => { + expect(service.value).toEqual('real value'); + })); - compFixture.detectChanges(); - expect(el.children[0].properties['title']).toBe('transformed someValue'); + it('should use set up directives and pipes', withModule(moduleConfig, () => { + let compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); + let el = compFixture.debugElement; + + compFixture.detectChanges(); + expect(el.children[0].properties['title']).toBe('transformed someValue'); + })); + + it('should use set up library modules', + withModule(moduleConfig).inject([SomeLibModule], (libModule: SomeLibModule) => { + expect(libModule).toBeAnInstanceOf(SomeLibModule); + })); }); - it('should use set up imported modules', - inject([SomeLibModule], (libModule: SomeLibModule) => { - expect(libModule).toBeAnInstanceOf(SomeLibModule); - })); + describe('components with template url', () => { + beforeEach(async(() => { + TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]}); + TestBed.compileComponents(); + })); - describe('provided schemas', () => { + it('should allow to createSync components with templateUrl after explicit async compilation', + () => { + let fixture = TestBed.createComponent(CompWithUrlTemplate); + expect(fixture.nativeElement).toHaveText('from external template\n'); + }); + }); + + describe('overwriting metadata', () => { + @Pipe({name: 'undefined'}) + class SomePipe { + transform(value: string): string { return `transformed ${value}`; } + } + + @Directive({selector: '[undefined]'}) + class SomeDirective { + someProp = 'hello'; + } + + @Component({selector: 'comp', template: 'someText'}) + class SomeComponent { + } + + @Component({selector: 'comp', template: 'someOtherText'}) + class SomeOtherComponent { + } + + @NgModule({declarations: [SomeComponent, SomeDirective, SomePipe]}) + class SomeModule { + } + + beforeEach(() => { TestBed.configureTestingModule({imports: [SomeModule]}); }); + + describe('module', () => { + beforeEach(() => { + TestBed.overrideModule(SomeModule, {set: {declarations: [SomeOtherComponent]}}); + }); + it('should work', () => { + expect(TestBed.createComponent(SomeOtherComponent).componentInstance) + .toBeAnInstanceOf(SomeOtherComponent); + }); + }); + + describe('component', () => { + beforeEach(() => { + TestBed.overrideComponent( + SomeComponent, {set: {selector: 'comp', template: 'newText'}}); + }); + it('should work', () => { + expect(TestBed.createComponent(SomeComponent).nativeElement).toHaveText('newText'); + }); + }); + + describe('directive', () => { + beforeEach(() => { + TestBed + .overrideComponent( + SomeComponent, {set: {selector: 'comp', template: `
`}}) + .overrideDirective( + SomeDirective, {set: {selector: '[someDir]', host: {'[title]': 'someProp'}}}); + }); + it('should work', () => { + const compFixture = TestBed.createComponent(SomeComponent); + compFixture.detectChanges(); + expect(compFixture.debugElement.children[0].properties['title']).toEqual('hello'); + }); + }); + + describe('pipe', () => { + beforeEach(() => { + TestBed + .overrideComponent( + SomeComponent, {set: {selector: 'comp', template: `{{'hello' | somePipe}}`}}) + .overridePipe(SomePipe, {set: {name: 'somePipe'}}); + }); + it('should work', () => { + const compFixture = TestBed.createComponent(SomeComponent); + compFixture.detectChanges(); + expect(compFixture.nativeElement).toHaveText('transformed hello'); + }); + }); + }); + + describe('setting up the compiler', () => { + + describe('providers', () => { + beforeEach(() => { + let xhrGet = + jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); + TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]}); + TestBed.configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]}); + }); + + it('should use set up providers', fakeAsync(() => { + TestBed.compileComponents(); + tick(); + let compFixture = TestBed.createComponent(CompWithUrlTemplate); + expect(compFixture.nativeElement).toHaveText('Hello world!'); + })); + }); + + describe('useJit true', () => { + beforeEach(() => { TestBed.configureCompiler({useJit: true}); }); + it('should set the value into CompilerConfig', + inject([CompilerConfig], (config: CompilerConfig) => { + expect(config.useJit).toBe(true); + })); + }); + describe('useJit false', () => { + beforeEach(() => { TestBed.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; + + var patchJasmineIt = () => { + var resolve: (result: any) => void; + var reject: (error: any) => void; + var promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + originalJasmineIt = jasmine.getEnv().it; + jasmine.getEnv().it = (description: string, fn: any /** TODO #9100 */) => { + var done = () => { resolve(null); }; + (done).fail = (err: any /** TODO #9100 */) => { reject(err); }; + fn(done); + return null; + }; + return promise; + }; + + var restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; }; + + var patchJasmineBeforeEach = () => { + var resolve: (result: any) => void; + var reject: (error: any) => void; + var promise = new Promise((res, rej) => { + resolve = res; + reject = rej; + }); + originalJasmineBeforeEach = jasmine.getEnv().beforeEach; + jasmine.getEnv().beforeEach = (fn: any) => { + var done = () => { resolve(null); }; + (done).fail = (err: any /** TODO #9100 */) => { reject(err); }; + fn(done); + return null; + }; + return promise; + }; + + var restoreJasmineBeforeEach = + () => { jasmine.getEnv().beforeEach = originalJasmineBeforeEach; }; + + it('should fail when an asynchronous error is thrown', (done: any /** TODO #9100 */) => { + var itPromise = patchJasmineIt(); + var barError = new Error('bar'); + + it('throws an async error', + async(inject([], () => { setTimeout(() => { throw barError; }, 0); }))); + + itPromise.then( + () => { done.fail('Expected test to fail, but it did not'); }, + (err) => { + expect(err).toEqual(barError); + done(); + }); + restoreJasmineIt(); + }); + + it('should fail when a returned promise is rejected', (done: any /** TODO #9100 */) => { + var itPromise = patchJasmineIt(); + + it('should fail with an error from a promise', async(inject([], () => { + var reject: (error: any) => void; + var promise = new Promise((_, rej) => { reject = rej; }); + var p = promise.then(() => { expect(1).toEqual(2); }); + + reject('baz'); + return p; + }))); + + itPromise.then( + () => { done.fail('Expected test to fail, but it did not'); }, + (err) => { + expect(err.message).toEqual('Uncaught (in promise): baz'); + done(); + }); + restoreJasmineIt(); + }); + + describe('components', () => { + let xhrGet: jasmine.Spy; + beforeEach(() => { + xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); + TestBed.configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]}); + }); + + it('should report an error for declared components with templateUrl which never call TestBed.compileComponents', + () => { + var itPromise = patchJasmineIt(); + + expect( + () => it( + 'should fail', withModule( + {declarations: [CompWithUrlTemplate]}, + () => { TestBed.createComponent(CompWithUrlTemplate); }))) + .toThrowError( + `This test module uses the component ${stringify(CompWithUrlTemplate)} which is using a "templateUrl", but they were never compiled. ` + + `Please call "TestBed.compileComponents" before your test.`); + + restoreJasmineIt(); + }); + + }); + + it('should error on unknown bound properties on custom elements by default', () => { @Component({template: ''}) class ComponentUsingInvalidProperty { } - beforeEach(() => { - TestBed.configureTestingModule( - {schemas: [CUSTOM_ELEMENTS_SCHEMA], declarations: [ComponentUsingInvalidProperty]}); - }); + var itPromise = patchJasmineIt(); - it('should not error on unknown bound properties on custom elements when using the CUSTOM_ELEMENTS_SCHEMA', - () => { - expect(TestBed.createComponent(ComponentUsingInvalidProperty).componentInstance) - .toBeAnInstanceOf(ComponentUsingInvalidProperty); - }); + expect( + () => + it('should fail', + withModule( + {declarations: [ComponentUsingInvalidProperty]}, + () => { TestBed.createComponent(ComponentUsingInvalidProperty); }))) + .toThrowError(/Can't bind to 'someUnknownProp'/); + + restoreJasmineIt(); }); }); - describe('per test modules', () => { - it('should use set up providers', - withModule(moduleConfig).inject([FancyService], (service: FancyService) => { - expect(service.value).toEqual('real value'); - })); + describe('creating components', function() { - it('should use set up directives and pipes', withModule(moduleConfig, () => { - let compFixture = TestBed.createComponent(CompUsingModuleDirectiveAndPipe); - let el = compFixture.debugElement; - - compFixture.detectChanges(); - expect(el.children[0].properties['title']).toBe('transformed someValue'); - })); - - it('should use set up library modules', - withModule(moduleConfig).inject([SomeLibModule], (libModule: SomeLibModule) => { - expect(libModule).toBeAnInstanceOf(SomeLibModule); - })); - }); - - describe('components with template url', () => { - beforeEach(async(() => { - TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]}); - TestBed.compileComponents(); - })); - - it('should allow to createSync components with templateUrl after explicit async compilation', - () => { - let fixture = TestBed.createComponent(CompWithUrlTemplate); - expect(fixture.nativeElement).toHaveText('from external template\n'); - }); - }); - - describe('overwrite metadata', () => { - @Pipe({name: 'undefined'}) - class SomePipe { - transform(value: string): string { return `transformed ${value}`; } - } - - @Directive({selector: '[undefined]'}) - class SomeDirective { - someProp = 'hello'; - } - - @Component({selector: 'comp', template: 'someText'}) - class SomeComponent { - } - - @Component({selector: 'othercomp', template: 'someOtherText'}) - class SomeOtherComponent { - } - - @NgModule({declarations: [SomeComponent, SomeDirective, SomePipe]}) - class SomeModule { - } - - beforeEach(() => { TestBed.configureTestingModule({imports: [SomeModule]}); }); - - describe('module', () => { - beforeEach(() => { - TestBed.overrideModule(SomeModule, {set: {declarations: [SomeOtherComponent]}}); - }); - it('should work', () => { - expect(TestBed.createComponent(SomeOtherComponent).componentInstance) - .toBeAnInstanceOf(SomeOtherComponent); - }); - }); - - describe('component', () => { - beforeEach(() => { - TestBed.overrideComponent(SomeComponent, {set: {selector: 'comp', template: 'newText'}}); - }); - it('should work', () => { - expect(TestBed.createComponent(SomeComponent).nativeElement).toHaveText('newText'); - }); - }); - - describe('directive', () => { - beforeEach(() => { - TestBed - .overrideComponent( - SomeComponent, {set: {selector: 'comp', template: `
`}}) - .overrideDirective( - SomeDirective, {set: {selector: '[someDir]', host: {'[title]': 'someProp'}}}); - }); - it('should work', () => { - const compFixture = TestBed.createComponent(SomeComponent); - compFixture.detectChanges(); - expect(compFixture.debugElement.children[0].properties['title']).toEqual('hello'); - }); - }); - - describe('pipe', () => { - beforeEach(() => { - TestBed - .overrideComponent( - SomeComponent, {set: {selector: 'comp', template: `{{'hello' | somePipe}}`}}) - .overridePipe(SomePipe, {set: {name: 'somePipe'}}); - }); - it('should work', () => { - const compFixture = TestBed.createComponent(SomeComponent); - compFixture.detectChanges(); - expect(compFixture.nativeElement).toHaveText('transformed hello'); - }); - }); - }); - - describe('setting up the compiler', () => { - - describe('providers', () => { - beforeEach(() => { - let xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); - TestBed.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(() => { TestBed.configureCompiler({useJit: true}); }); - it('should set the value into CompilerConfig', - inject([CompilerConfig], (config: CompilerConfig) => { - expect(config.useJit).toBe(true); - })); - }); - describe('useJit false', () => { - beforeEach(() => { TestBed.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; - - var patchJasmineIt = () => { - var resolve: (result: any) => void; - var reject: (error: any) => void; - var promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - originalJasmineIt = jasmine.getEnv().it; - jasmine.getEnv().it = (description: string, fn: any /** TODO #9100 */) => { - var done = () => { resolve(null); }; - (done).fail = (err: any /** TODO #9100 */) => { reject(err); }; - fn(done); - return null; - }; - return promise; - }; - - var restoreJasmineIt = () => { jasmine.getEnv().it = originalJasmineIt; }; - - var patchJasmineBeforeEach = () => { - var resolve: (result: any) => void; - var reject: (error: any) => void; - var promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - originalJasmineBeforeEach = jasmine.getEnv().beforeEach; - jasmine.getEnv().beforeEach = (fn: any) => { - var done = () => { resolve(null); }; - (done).fail = (err: any /** TODO #9100 */) => { reject(err); }; - fn(done); - return null; - }; - return promise; - }; - - var restoreJasmineBeforeEach = - () => { jasmine.getEnv().beforeEach = originalJasmineBeforeEach; }; - - it('should fail when an asynchronous error is thrown', (done: any /** TODO #9100 */) => { - var itPromise = patchJasmineIt(); - var barError = new Error('bar'); - - it('throws an async error', - async(inject([], () => { setTimeout(() => { throw barError; }, 0); }))); - - itPromise.then( - () => { done.fail('Expected test to fail, but it did not'); }, - (err) => { - expect(err).toEqual(barError); - done(); - }); - restoreJasmineIt(); - }); - - it('should fail when a returned promise is rejected', (done: any /** TODO #9100 */) => { - var itPromise = patchJasmineIt(); - - it('should fail with an error from a promise', async(inject([], () => { - var reject: (error: any) => void; - var promise = new Promise((_, rej) => { reject = rej; }); - var p = promise.then(() => { expect(1).toEqual(2); }); - - reject('baz'); - return p; - }))); - - itPromise.then( - () => { done.fail('Expected test to fail, but it did not'); }, - (err) => { - expect(err.message).toEqual('Uncaught (in promise): baz'); - done(); - }); - restoreJasmineIt(); - }); - - describe('using addProviders', () => { - beforeEach(() => addProviders([{provide: FancyService, useValue: new FancyService()}])); - - beforeEach(inject([FancyService], (service: any /** TODO #9100 */) => { - expect(service.value).toEqual('real value'); - })); - - describe('nested addProviders', () => { - - it('should fail when the injector has already been used', () => { - patchJasmineBeforeEach(); - expect(() => { - beforeEach(() => addProviders([{provide: FancyService, useValue: new FancyService()}])); - }) - .toThrowError( - `Cannot configure the test module when the test module has already been instantiated. ` + - `Make sure you are not using \`inject\` before \`TestBed.configureTestingModule\`.`); - restoreJasmineBeforeEach(); - }); - }); - }); - - describe('components', () => { - let xhrGet: jasmine.Spy; beforeEach(() => { - xhrGet = jasmine.createSpy('xhrGet').and.returnValue(Promise.resolve('Hello world!')); - TestBed.configureCompiler({providers: [{provide: XHR, useValue: {get: xhrGet}}]}); + TestBed.configureTestingModule({ + declarations: [ + ChildComp, + MyIfComp, + ChildChildComp, + ParentComp, + TestProvidersComp, + TestViewProvidersComp, + ] + }); }); - it('should report an error for declared components with templateUrl which never call TestBed.compileComponents', - () => { - var itPromise = patchJasmineIt(); + it('should instantiate a component with valid DOM', async(() => { + var fixture = TestBed.createComponent(ChildComp); + fixture.detectChanges(); - expect( - () => - it('should fail', withModule( - {declarations: [CompWithUrlTemplate]}, - () => { TestBed.createComponent(CompWithUrlTemplate); }))) - .toThrowError( - `This test module uses the component ${stringify(CompWithUrlTemplate)} which is using a "templateUrl", but they were never compiled. ` + - `Please call "TestBed.compileComponents" before your test.`); + expect(fixture.debugElement.nativeElement).toHaveText('Original Child'); + })); - restoreJasmineIt(); - }); + it('should allow changing members of the component', async(() => { - }); - - it('should error on unknown bound properties on custom elements by default', () => { - @Component({template: ''}) - class ComponentUsingInvalidProperty { - } - - var itPromise = patchJasmineIt(); - - expect( - () => - it('should fail', - withModule( - {declarations: [ComponentUsingInvalidProperty]}, - () => { TestBed.createComponent(ComponentUsingInvalidProperty); }))) - .toThrowError(/Can't bind to 'someUnknownProp'/); - - restoreJasmineIt(); - }); - }); - - describe('test component builder', function() { - it('should instantiate a component with valid DOM', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.createAsync(ChildComp).then((componentFixture) => { - componentFixture.detectChanges(); - - expect(componentFixture.debugElement.nativeElement).toHaveText('Original Child'); - }); - }))); - - it('should allow changing members of the component', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.createAsync(MyIfComp).then((componentFixture) => { + var componentFixture = TestBed.createComponent(MyIfComp); componentFixture.detectChanges(); expect(componentFixture.debugElement.nativeElement).toHaveText('MyIf()'); componentFixture.debugElement.componentInstance.showMore = true; componentFixture.detectChanges(); expect(componentFixture.debugElement.nativeElement).toHaveText('MyIf(More)'); - }); - }))); + })); - it('should override a template', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + it('should override a template', async(() => { + TestBed.overrideComponent(ChildComp, {set: {template: 'Mock'}}); + let componentFixture = TestBed.createComponent(ChildComp); + componentFixture.detectChanges(); + expect(componentFixture.debugElement.nativeElement).toHaveText('Mock'); - tcb.overrideTemplate(MockChildComp, 'Mock') - .createAsync(MockChildComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement).toHaveText('Mock'); + })); - }); - }))); - - it('should override a view', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.overrideView( - ChildComp, new ViewMetadata({template: 'Modified {{childBinding}}'})) - .createAsync(ChildComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement).toHaveText('Modified Child'); - - }); - }))); - - it('should override component dependencies', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.overrideDirective(ParentComp, ChildComp, MockChildComp) - .createAsync(ParentComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement).toHaveText('Parent(Mock)'); - - }); - }))); + it('should override a provider', async(() => { + TestBed.overrideComponent( + TestProvidersComp, + {set: {providers: [{provide: FancyService, useClass: MockFancyService}]}}); + var componentFixture = TestBed.createComponent(TestProvidersComp); + componentFixture.detectChanges(); + expect(componentFixture.debugElement.nativeElement) + .toHaveText('injected value: mocked out value'); + })); - it('should override child component\'s dependencies', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { + it('should override a viewProvider', async(() => { + TestBed.overrideComponent( + TestViewProvidersComp, + {set: {viewProviders: [{provide: FancyService, useClass: MockFancyService}]}}); - tcb.overrideDirective(ParentComp, ChildComp, ChildWithChildComp) - .overrideDirective(ChildWithChildComp, ChildChildComp, MockChildChildComp) - .createAsync(ParentComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement) - .toHaveText('Parent(Original Child(ChildChild Mock))'); + var componentFixture = TestBed.createComponent(TestViewProvidersComp); + componentFixture.detectChanges(); + expect(componentFixture.debugElement.nativeElement) + .toHaveText('injected value: mocked out value'); + })); + }); + describe('using alternate components', () => { + beforeEach(() => { + TestBed.configureTestingModule({ + declarations: [ + MockChildComp, + ParentComp, + ] + }); + }); - }); - }))); + it('should override component dependencies', async(() => { - it('should override a provider', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.overrideProviders( - TestProvidersComp, [{provide: FancyService, useClass: MockFancyService}]) - .createAsync(TestProvidersComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement) - .toHaveText('injected value: mocked out value'); - }); - }))); - - - it('should override a viewProvider', - async(inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { - - tcb.overrideViewProviders( - TestViewProvidersComp, [{provide: FancyService, useClass: MockFancyService}]) - .createAsync(TestViewProvidersComp) - .then((componentFixture) => { - componentFixture.detectChanges(); - expect(componentFixture.debugElement.nativeElement) - .toHaveText('injected value: mocked out value'); - }); - }))); + let componentFixture = TestBed.createComponent(ParentComp); + componentFixture.detectChanges(); + expect(componentFixture.debugElement.nativeElement).toHaveText('Parent(Mock)'); + })); + }); }); }