feat(core): update reference and doc to change async
to waitAsync
. (#37583)
The last commit change `async` to `waitForAsync`. This commit update all usages in the code and also update aio doc. PR Close #37583
This commit is contained in:

committed by
Alex Rickabaugh

parent
8f074296c2
commit
8fbf40bf40
@ -1,31 +1,31 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { TemplateModule } from './template/template.module';
|
||||
import { ReactiveModule } from './reactive/reactive.module';
|
||||
import { TemplateModule } from './template/template.module';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ReactiveModule, TemplateModule],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [ReactiveModule, TemplateModule],
|
||||
declarations: [AppComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
it('should create the app', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
|
||||
it('should render title', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
it('should render title', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Forms Overview');
|
||||
}));
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Forms Overview');
|
||||
}));
|
||||
});
|
||||
|
@ -1,19 +1,18 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
|
||||
import { FavoriteColorComponent } from './favorite-color.component';
|
||||
import { createNewEvent } from '../../shared/utils';
|
||||
import { FavoriteColorComponent } from './favorite-color.component';
|
||||
|
||||
describe('Favorite Color Component', () => {
|
||||
let component: FavoriteColorComponent;
|
||||
let fixture: ComponentFixture<FavoriteColorComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ ReactiveFormsModule ],
|
||||
declarations: [ FavoriteColorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule(
|
||||
{imports: [ReactiveFormsModule], declarations: [FavoriteColorComponent]})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { async, ComponentFixture, TestBed, tick, fakeAsync } from '@angular/core/testing';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
import { FavoriteColorComponent } from './favorite-color.component';
|
||||
import { createNewEvent } from '../../shared/utils';
|
||||
import { FavoriteColorComponent } from './favorite-color.component';
|
||||
|
||||
describe('FavoriteColorComponent', () => {
|
||||
let component: FavoriteColorComponent;
|
||||
let fixture: ComponentFixture<FavoriteColorComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ FormsModule ],
|
||||
declarations: [ FavoriteColorComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({imports: [FormsModule], declarations: [FavoriteColorComponent]})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -28,29 +25,29 @@ describe('FavoriteColorComponent', () => {
|
||||
|
||||
// #docregion model-to-view
|
||||
it('should update the favorite color on the input field', fakeAsync(() => {
|
||||
component.favoriteColor = 'Blue';
|
||||
component.favoriteColor = 'Blue';
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
tick();
|
||||
tick();
|
||||
|
||||
const input = fixture.nativeElement.querySelector('input');
|
||||
const input = fixture.nativeElement.querySelector('input');
|
||||
|
||||
expect(input.value).toBe('Blue');
|
||||
}));
|
||||
expect(input.value).toBe('Blue');
|
||||
}));
|
||||
// #enddocregion model-to-view
|
||||
|
||||
// #docregion view-to-model
|
||||
it('should update the favorite color in the component', fakeAsync(() => {
|
||||
const input = fixture.nativeElement.querySelector('input');
|
||||
const event = createNewEvent('input');
|
||||
const input = fixture.nativeElement.querySelector('input');
|
||||
const event = createNewEvent('input');
|
||||
|
||||
input.value = 'Red';
|
||||
input.dispatchEvent(event);
|
||||
input.value = 'Red';
|
||||
input.dispatchEvent(event);
|
||||
|
||||
fixture.detectChanges();
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(component.favoriteColor).toEqual('Red');
|
||||
}));
|
||||
expect(component.favoriteColor).toEqual('Red');
|
||||
}));
|
||||
// #enddocregion view-to-model
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { MyLibComponent } from './my-lib.component';
|
||||
|
||||
@ -6,11 +6,8 @@ describe('MyLibComponent', () => {
|
||||
let component: MyLibComponent;
|
||||
let fixture: ComponentFixture<MyLibComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MyLibComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({declarations: [MyLibComponent]}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -1,19 +1,16 @@
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
let de: DebugElement;
|
||||
let comp: AppComponent;
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AppComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({declarations: [AppComponent]}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -22,12 +19,11 @@ describe('AppComponent', () => {
|
||||
de = fixture.debugElement.query(By.css('h1'));
|
||||
});
|
||||
|
||||
it('should create component', () => expect(comp).toBeDefined() );
|
||||
it('should create component', () => expect(comp).toBeDefined());
|
||||
|
||||
it('should have expected <h1> text', () => {
|
||||
fixture.detectChanges();
|
||||
const h1 = de.nativeElement;
|
||||
expect(h1.textContent).toMatch(/angular/i,
|
||||
'<h1> should say something about "Angular"');
|
||||
expect(h1.textContent).toMatch(/angular/i, '<h1> should say something about "Angular"');
|
||||
});
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
// #enddocregion
|
||||
import { AppComponent } from './app-initial.component';
|
||||
/*
|
||||
@ -12,29 +12,29 @@ describe('AppComponent', () => {
|
||||
*/
|
||||
describe('AppComponent (initial CLI version)', () => {
|
||||
// #docregion
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
it('should create the app', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
it(`should have as title 'app'`, async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('app');
|
||||
}));
|
||||
it('should render title', async(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [AppComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
it('should create the app', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
}));
|
||||
it(`should have as title 'app'`, waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('app');
|
||||
}));
|
||||
it('should render title', waitForAsync(() => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||
}));
|
||||
});
|
||||
// #enddocregion
|
||||
|
||||
@ -43,16 +43,13 @@ import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture } from '@angular/core/testing';
|
||||
|
||||
describe('AppComponent (initial CLI version - as it should be)', () => {
|
||||
|
||||
let app: AppComponent;
|
||||
let de: DebugElement;
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
declarations: [AppComponent],
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
@ -70,7 +67,6 @@ describe('AppComponent (initial CLI version - as it should be)', () => {
|
||||
|
||||
it('should render title in an h1 tag', () => {
|
||||
fixture.detectChanges();
|
||||
expect(de.nativeElement.querySelector('h1').textContent)
|
||||
.toContain('Welcome to app!');
|
||||
expect(de.nativeElement.querySelector('h1').textContent).toContain('Welcome to app!');
|
||||
});
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
// For more examples:
|
||||
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts
|
||||
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
import { waitForAsync, ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
|
||||
|
||||
import { asyncData } from '../testing';
|
||||
|
||||
@ -21,9 +21,9 @@ import { AppModule } from './app.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { AboutComponent } from './about/about.component';
|
||||
import { DashboardComponent } from './dashboard/dashboard.component';
|
||||
import { TwainService } from './twain/twain.service';
|
||||
|
||||
import { HeroService, TestHeroService } from './model/testing/test-hero.service';
|
||||
import { TwainService } from './twain/twain.service';
|
||||
|
||||
let comp: AppComponent;
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
@ -32,54 +32,51 @@ let router: Router;
|
||||
let location: SpyLocation;
|
||||
|
||||
describe('AppComponent & RouterTestingModule', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
],
|
||||
providers: [
|
||||
{ provide: HeroService, useClass: TestHeroService }
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [
|
||||
AppModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
],
|
||||
providers: [{provide: HeroService, useClass: TestHeroService}]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should navigate to "Dashboard" immediately', fakeAsync(() => {
|
||||
createComponent();
|
||||
tick(); // wait for async data to arrive
|
||||
expectPathToBe('/dashboard', 'after initialNavigation()');
|
||||
expectElementOf(DashboardComponent);
|
||||
}));
|
||||
createComponent();
|
||||
tick(); // wait for async data to arrive
|
||||
expectPathToBe('/dashboard', 'after initialNavigation()');
|
||||
expectElementOf(DashboardComponent);
|
||||
}));
|
||||
|
||||
it('should navigate to "About" on click', fakeAsync(() => {
|
||||
createComponent();
|
||||
click(page.aboutLinkDe);
|
||||
// page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom
|
||||
createComponent();
|
||||
click(page.aboutLinkDe);
|
||||
// page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom
|
||||
|
||||
advance();
|
||||
expectPathToBe('/about');
|
||||
expectElementOf(AboutComponent);
|
||||
}));
|
||||
advance();
|
||||
expectPathToBe('/about');
|
||||
expectElementOf(AboutComponent);
|
||||
}));
|
||||
|
||||
it('should navigate to "About" w/ browser location URL change', fakeAsync(() => {
|
||||
createComponent();
|
||||
location.simulateHashChange('/about');
|
||||
// location.go('/about'); // also works ... except, perhaps, in Stackblitz
|
||||
advance();
|
||||
expectPathToBe('/about');
|
||||
expectElementOf(AboutComponent);
|
||||
}));
|
||||
createComponent();
|
||||
location.simulateHashChange('/about');
|
||||
// location.go('/about'); // also works ... except, perhaps, in Stackblitz
|
||||
advance();
|
||||
expectPathToBe('/about');
|
||||
expectElementOf(AboutComponent);
|
||||
}));
|
||||
|
||||
// Can't navigate to lazy loaded modules with this technique
|
||||
xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => {
|
||||
createComponent();
|
||||
page.heroesLinkDe.nativeElement.click();
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
}));
|
||||
|
||||
createComponent();
|
||||
page.heroesLinkDe.nativeElement.click();
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
@ -94,37 +91,37 @@ let loader: SpyNgModuleFactoryLoader;
|
||||
|
||||
///////// Can't get lazy loaded Heroes to work yet
|
||||
xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
AppModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
],
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [
|
||||
AppModule,
|
||||
RouterTestingModule.withRoutes(routes),
|
||||
],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(fakeAsync(() => {
|
||||
createComponent();
|
||||
loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader;
|
||||
loader.stubbedModules = { expected: HeroModule };
|
||||
loader.stubbedModules = {expected: HeroModule};
|
||||
router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]);
|
||||
}));
|
||||
|
||||
it('should navigate to "Heroes" on click', async(() => {
|
||||
page.heroesLinkDe.nativeElement.click();
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
expectElementOf(HeroListComponent);
|
||||
}));
|
||||
it('should navigate to "Heroes" on click', waitForAsync(() => {
|
||||
page.heroesLinkDe.nativeElement.click();
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
expectElementOf(HeroListComponent);
|
||||
}));
|
||||
|
||||
it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => {
|
||||
location.go('/heroes');
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
expectElementOf(HeroListComponent);
|
||||
}));
|
||||
location.go('/heroes');
|
||||
advance();
|
||||
expectPathToBe('/heroes');
|
||||
expectElementOf(HeroListComponent);
|
||||
}));
|
||||
});
|
||||
|
||||
////// Helpers /////////
|
||||
@ -134,9 +131,9 @@ xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
|
||||
* Wait a tick, then detect changes, and tick again
|
||||
*/
|
||||
function advance(): void {
|
||||
tick(); // wait while navigating
|
||||
fixture.detectChanges(); // update view
|
||||
tick(); // wait for async data to arrive
|
||||
tick(); // wait while navigating
|
||||
fixture.detectChanges(); // update view
|
||||
tick(); // wait for async data to arrive
|
||||
}
|
||||
|
||||
function createComponent() {
|
||||
@ -148,8 +145,8 @@ function createComponent() {
|
||||
router = injector.get(Router);
|
||||
router.initialNavigation();
|
||||
spyOn(injector.get(TwainService), 'getQuote')
|
||||
// fake fast async observable
|
||||
.and.returnValue(asyncData('Test Quote'));
|
||||
// fake fast async observable
|
||||
.and.returnValue(asyncData('Test Quote'));
|
||||
advance();
|
||||
|
||||
page = new Page();
|
||||
@ -168,14 +165,14 @@ class Page {
|
||||
|
||||
constructor() {
|
||||
const links = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref));
|
||||
this.aboutLinkDe = links[2];
|
||||
this.aboutLinkDe = links[2];
|
||||
this.dashboardLinkDe = links[0];
|
||||
this.heroesLinkDe = links[1];
|
||||
this.heroesLinkDe = links[1];
|
||||
|
||||
// for debugging
|
||||
this.comp = comp;
|
||||
this.comp = comp;
|
||||
this.fixture = fixture;
|
||||
this.router = router;
|
||||
this.router = router;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,66 +1,70 @@
|
||||
// #docplaster
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
import { RouterLinkDirectiveStub } from '../testing';
|
||||
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
// #docregion component-stubs
|
||||
@Component({selector: 'app-banner', template: ''})
|
||||
class BannerStubComponent {}
|
||||
class BannerStubComponent {
|
||||
}
|
||||
|
||||
@Component({selector: 'router-outlet', template: ''})
|
||||
class RouterOutletStubComponent { }
|
||||
class RouterOutletStubComponent {
|
||||
}
|
||||
|
||||
@Component({selector: 'app-welcome', template: ''})
|
||||
class WelcomeStubComponent {}
|
||||
class WelcomeStubComponent {
|
||||
}
|
||||
// #enddocregion component-stubs
|
||||
|
||||
let comp: AppComponent;
|
||||
let fixture: ComponentFixture<AppComponent>;
|
||||
|
||||
describe('AppComponent & TestModule', () => {
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
// #docregion testbed-stubs
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
RouterLinkDirectiveStub,
|
||||
BannerStubComponent,
|
||||
RouterOutletStubComponent,
|
||||
WelcomeStubComponent
|
||||
]
|
||||
})
|
||||
// #enddocregion testbed-stubs
|
||||
.compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent, RouterLinkDirectiveStub, BannerStubComponent, RouterOutletStubComponent,
|
||||
WelcomeStubComponent
|
||||
]
|
||||
})
|
||||
// #enddocregion testbed-stubs
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
}));
|
||||
tests();
|
||||
});
|
||||
|
||||
//////// Testing w/ NO_ERRORS_SCHEMA //////
|
||||
describe('AppComponent & NO_ERRORS_SCHEMA', () => {
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
// #docregion no-errors-schema, mixed-setup
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
// #enddocregion no-errors-schema
|
||||
BannerStubComponent,
|
||||
// #docregion no-errors-schema
|
||||
RouterLinkDirectiveStub
|
||||
],
|
||||
schemas: [ NO_ERRORS_SCHEMA ]
|
||||
})
|
||||
// #enddocregion no-errors-schema, mixed-setup
|
||||
.compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
// #enddocregion no-errors-schema
|
||||
BannerStubComponent,
|
||||
// #docregion no-errors-schema
|
||||
RouterLinkDirectiveStub
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
// #enddocregion no-errors-schema, mixed-setup
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
}));
|
||||
tests();
|
||||
});
|
||||
@ -72,30 +76,23 @@ import { AppModule } from './app.module';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
|
||||
describe('AppComponent & AppModule', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({imports: [AppModule]})
|
||||
|
||||
beforeEach(async(() => {
|
||||
// Get rid of app's Router configuration otherwise many failures.
|
||||
// Doing so removes Router declarations; add the Router stubs
|
||||
.overrideModule(AppModule, {
|
||||
remove: {imports: [AppRoutingModule]},
|
||||
add: {declarations: [RouterLinkDirectiveStub, RouterOutletStubComponent]}
|
||||
})
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ AppModule ]
|
||||
})
|
||||
.compileComponents()
|
||||
|
||||
// Get rid of app's Router configuration otherwise many failures.
|
||||
// Doing so removes Router declarations; add the Router stubs
|
||||
.overrideModule(AppModule, {
|
||||
remove: {
|
||||
imports: [ AppRoutingModule ]
|
||||
},
|
||||
add: {
|
||||
declarations: [ RouterLinkDirectiveStub, RouterOutletStubComponent ]
|
||||
}
|
||||
})
|
||||
|
||||
.compileComponents()
|
||||
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(AppComponent);
|
||||
comp = fixture.componentInstance;
|
||||
});
|
||||
}));
|
||||
|
||||
tests();
|
||||
@ -107,11 +104,10 @@ function tests() {
|
||||
|
||||
// #docregion test-setup
|
||||
beforeEach(() => {
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
|
||||
// find DebugElements with an attached RouterLinkStubDirective
|
||||
linkDes = fixture.debugElement
|
||||
.queryAll(By.directive(RouterLinkDirectiveStub));
|
||||
linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));
|
||||
|
||||
// get attached link directive instances
|
||||
// using each DebugElement's injector
|
||||
@ -132,8 +128,8 @@ function tests() {
|
||||
});
|
||||
|
||||
it('can click Heroes link in template', () => {
|
||||
const heroesLinkDe = linkDes[1]; // heroes link DebugElement
|
||||
const heroesLink = routerLinks[1]; // heroes link directive
|
||||
const heroesLinkDe = linkDes[1]; // heroes link DebugElement
|
||||
const heroesLink = routerLinks[1]; // heroes link directive
|
||||
|
||||
expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet');
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion import-async
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
// #enddocregion import-async
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
@ -14,11 +14,12 @@ describe('BannerComponent (external files)', () => {
|
||||
|
||||
describe('Two beforeEach', () => {
|
||||
// #docregion async-before-each
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BannerComponent ],
|
||||
})
|
||||
.compileComponents(); // compile template and css
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [BannerComponent],
|
||||
})
|
||||
.compileComponents(); // compile template and css
|
||||
}));
|
||||
// #enddocregion async-before-each
|
||||
|
||||
@ -26,7 +27,7 @@ describe('BannerComponent (external files)', () => {
|
||||
// #docregion sync-before-each
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(BannerComponent);
|
||||
component = fixture.componentInstance; // BannerComponent test instance
|
||||
component = fixture.componentInstance; // BannerComponent test instance
|
||||
h1 = fixture.nativeElement.querySelector('h1');
|
||||
});
|
||||
// #enddocregion sync-before-each
|
||||
@ -36,16 +37,17 @@ describe('BannerComponent (external files)', () => {
|
||||
|
||||
describe('One beforeEach', () => {
|
||||
// #docregion one-before-each
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BannerComponent ],
|
||||
})
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(BannerComponent);
|
||||
component = fixture.componentInstance;
|
||||
h1 = fixture.nativeElement.querySelector('h1');
|
||||
});
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [BannerComponent],
|
||||
})
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(BannerComponent);
|
||||
component = fixture.componentInstance;
|
||||
h1 = fixture.nativeElement.querySelector('h1');
|
||||
});
|
||||
}));
|
||||
// #enddocregion one-before-each
|
||||
|
||||
@ -69,4 +71,3 @@ describe('BannerComponent (external files)', () => {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
// #docplaster
|
||||
// #docregion import-by
|
||||
import { By } from '@angular/platform-browser';
|
||||
// #enddocregion import-by
|
||||
// #docregion import-debug-element
|
||||
import { DebugElement } from '@angular/core';
|
||||
// #enddocregion import-debug-element
|
||||
// #docregion v1
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
// #enddocregion v1
|
||||
import { BannerComponent } from './banner-initial.component';
|
||||
|
||||
/*
|
||||
// #docregion v1
|
||||
import { BannerComponent } from './banner.component';
|
||||
@ -17,15 +19,12 @@ describe('BannerComponent', () => {
|
||||
// #enddocregion v1
|
||||
*/
|
||||
describe('BannerComponent (initial CLI generated)', () => {
|
||||
// #docregion v1
|
||||
// #docregion v1
|
||||
let component: BannerComponent;
|
||||
let fixture: ComponentFixture<BannerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BannerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({declarations: [BannerComponent]}).compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -44,9 +43,7 @@ describe('BannerComponent (initial CLI generated)', () => {
|
||||
describe('BannerComponent (minimal)', () => {
|
||||
it('should create', () => {
|
||||
// #docregion configureTestingModule
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BannerComponent ]
|
||||
});
|
||||
TestBed.configureTestingModule({declarations: [BannerComponent]});
|
||||
// #enddocregion configureTestingModule
|
||||
// #docregion createComponent
|
||||
const fixture = TestBed.createComponent(BannerComponent);
|
||||
@ -65,9 +62,7 @@ describe('BannerComponent (with beforeEach)', () => {
|
||||
let fixture: ComponentFixture<BannerComponent>;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ BannerComponent ]
|
||||
});
|
||||
TestBed.configureTestingModule({declarations: [BannerComponent]});
|
||||
fixture = TestBed.createComponent(BannerComponent);
|
||||
component = fixture.componentInstance;
|
||||
});
|
||||
|
@ -1,22 +1,21 @@
|
||||
|
||||
// #docplaster
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
|
||||
import { addMatchers, click } from '../../testing';
|
||||
|
||||
import { Hero } from '../model/hero';
|
||||
|
||||
import { DashboardHeroComponent } from './dashboard-hero.component';
|
||||
|
||||
beforeEach( addMatchers );
|
||||
beforeEach(addMatchers);
|
||||
|
||||
describe('DashboardHeroComponent class only', () => {
|
||||
// #docregion class-only
|
||||
it('raises the selected event when clicked', () => {
|
||||
const comp = new DashboardHeroComponent();
|
||||
const hero: Hero = { id: 42, name: 'Test' };
|
||||
const hero: Hero = {id: 42, name: 'Test'};
|
||||
comp.hero = hero;
|
||||
|
||||
comp.selected.subscribe((selectedHero: Hero) => expect(selectedHero).toBe(hero));
|
||||
@ -26,33 +25,31 @@ describe('DashboardHeroComponent class only', () => {
|
||||
});
|
||||
|
||||
describe('DashboardHeroComponent when tested directly', () => {
|
||||
|
||||
let comp: DashboardHeroComponent;
|
||||
let expectedHero: Hero;
|
||||
let fixture: ComponentFixture<DashboardHeroComponent>;
|
||||
let heroDe: DebugElement;
|
||||
let heroEl: HTMLElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
// #docregion setup, config-testbed
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardHeroComponent ]
|
||||
})
|
||||
// #enddocregion setup, config-testbed
|
||||
.compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({declarations: [DashboardHeroComponent]})
|
||||
// #enddocregion setup, config-testbed
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
// #docregion setup
|
||||
fixture = TestBed.createComponent(DashboardHeroComponent);
|
||||
comp = fixture.componentInstance;
|
||||
comp = fixture.componentInstance;
|
||||
|
||||
// find the hero's DebugElement and element
|
||||
heroDe = fixture.debugElement.query(By.css('.hero'));
|
||||
heroDe = fixture.debugElement.query(By.css('.hero'));
|
||||
heroEl = heroDe.nativeElement;
|
||||
|
||||
// mock the hero supplied by the parent component
|
||||
expectedHero = { id: 42, name: 'Test Name' };
|
||||
expectedHero = {id: 42, name: 'Test Name'};
|
||||
|
||||
// simulate the parent setting the input property with that hero
|
||||
comp.hero = expectedHero;
|
||||
@ -96,8 +93,8 @@ describe('DashboardHeroComponent when tested directly', () => {
|
||||
let selectedHero: Hero;
|
||||
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
||||
|
||||
click(heroDe); // click helper with DebugElement
|
||||
click(heroEl); // click helper with native element
|
||||
click(heroDe); // click helper with DebugElement
|
||||
click(heroEl); // click helper with native element
|
||||
|
||||
expect(selectedHero).toBe(expectedHero);
|
||||
});
|
||||
@ -111,22 +108,21 @@ describe('DashboardHeroComponent when inside a test host', () => {
|
||||
let fixture: ComponentFixture<TestHostComponent>;
|
||||
let heroEl: HTMLElement;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
// #docregion test-host-setup
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardHeroComponent, TestHostComponent ]
|
||||
})
|
||||
// #enddocregion test-host-setup
|
||||
.compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({declarations: [DashboardHeroComponent, TestHostComponent]})
|
||||
// #enddocregion test-host-setup
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
// #docregion test-host-setup
|
||||
// create TestHostComponent instead of DashboardHeroComponent
|
||||
fixture = TestBed.createComponent(TestHostComponent);
|
||||
fixture = TestBed.createComponent(TestHostComponent);
|
||||
testHost = fixture.componentInstance;
|
||||
heroEl = fixture.nativeElement.querySelector('.hero');
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
heroEl = fixture.nativeElement.querySelector('.hero');
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
// #enddocregion test-host-setup
|
||||
});
|
||||
|
||||
@ -155,8 +151,10 @@ import { Component } from '@angular/core';
|
||||
</dashboard-hero>`
|
||||
})
|
||||
class TestHostComponent {
|
||||
hero: Hero = {id: 42, name: 'Test Name' };
|
||||
hero: Hero = {id: 42, name: 'Test Name'};
|
||||
selectedHero: Hero;
|
||||
onSelected(hero: Hero) { this.selectedHero = hero; }
|
||||
onSelected(hero: Hero) {
|
||||
this.selectedHero = hero;
|
||||
}
|
||||
}
|
||||
// #enddocregion test-host
|
||||
|
@ -1,6 +1,5 @@
|
||||
// #docplaster
|
||||
import { async, inject, ComponentFixture, TestBed
|
||||
} from '@angular/core/testing';
|
||||
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { addMatchers, asyncData, click } from '../../testing';
|
||||
import { HeroService } from '../model/hero.service';
|
||||
@ -12,7 +11,7 @@ import { Router } from '@angular/router';
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { DashboardModule } from './dashboard.module';
|
||||
|
||||
beforeEach ( addMatchers );
|
||||
beforeEach(addMatchers);
|
||||
|
||||
let comp: DashboardComponent;
|
||||
let fixture: ComponentFixture<DashboardComponent>;
|
||||
@ -21,9 +20,7 @@ let fixture: ComponentFixture<DashboardComponent>;
|
||||
|
||||
describe('DashboardComponent (deep)', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ DashboardModule ]
|
||||
});
|
||||
TestBed.configureTestingModule({imports: [DashboardModule]});
|
||||
});
|
||||
|
||||
compileAndCreate();
|
||||
@ -43,10 +40,8 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
|
||||
describe('DashboardComponent (shallow)', () => {
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardComponent ],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
TestBed.configureTestingModule(
|
||||
{declarations: [DashboardComponent], schemas: [NO_ERRORS_SCHEMA]});
|
||||
});
|
||||
|
||||
compileAndCreate();
|
||||
@ -63,25 +58,26 @@ describe('DashboardComponent (shallow)', () => {
|
||||
/** Add TestBed providers, compile, and create DashboardComponent */
|
||||
function compileAndCreate() {
|
||||
// #docregion compile-and-create-body
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
// #docregion router-spy
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
|
||||
const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
providers: [
|
||||
{ provide: HeroService, useValue: heroServiceSpy },
|
||||
{ provide: Router, useValue: routerSpy }
|
||||
]
|
||||
})
|
||||
// #enddocregion router-spy
|
||||
.compileComponents().then(() => {
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
comp = fixture.componentInstance;
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
providers: [
|
||||
{provide: HeroService, useValue: heroServiceSpy}, {provide: Router, useValue: routerSpy}
|
||||
]
|
||||
})
|
||||
// #enddocregion router-spy
|
||||
.compileComponents()
|
||||
.then(() => {
|
||||
fixture = TestBed.createComponent(DashboardComponent);
|
||||
comp = fixture.componentInstance;
|
||||
|
||||
// getHeroes spy returns observable of test heroes
|
||||
heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes()));
|
||||
});
|
||||
// getHeroes spy returns observable of test heroes
|
||||
heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes()));
|
||||
});
|
||||
// #enddocregion compile-and-create-body
|
||||
}));
|
||||
}
|
||||
@ -93,23 +89,20 @@ function compileAndCreate() {
|
||||
function tests(heroClick: () => void) {
|
||||
|
||||
it('should NOT have heroes before ngOnInit', () => {
|
||||
expect(comp.heroes.length).toBe(0,
|
||||
'should not have heroes before ngOnInit');
|
||||
expect(comp.heroes.length).toBe(0, 'should not have heroes before ngOnInit');
|
||||
});
|
||||
|
||||
it('should NOT have heroes immediately after ngOnInit', () => {
|
||||
fixture.detectChanges(); // runs initial lifecycle hooks
|
||||
fixture.detectChanges(); // runs initial lifecycle hooks
|
||||
|
||||
expect(comp.heroes.length).toBe(0,
|
||||
'should not have heroes until service promise resolves');
|
||||
expect(comp.heroes.length).toBe(0, 'should not have heroes until service promise resolves');
|
||||
});
|
||||
|
||||
describe('after get dashboard heroes', () => {
|
||||
|
||||
let router: Router;
|
||||
|
||||
// Trigger component so it gets heroes and binds to them
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
router = fixture.debugElement.injector.get(Router);
|
||||
fixture.detectChanges(); // runs ngOnInit -> getHeroes
|
||||
fixture.whenStable() // No need for the `lastPromise` hack!
|
||||
@ -117,8 +110,8 @@ function tests(heroClick: () => void) {
|
||||
}));
|
||||
|
||||
it('should HAVE heroes', () => {
|
||||
expect(comp.heroes.length).toBeGreaterThan(0,
|
||||
'should have heroes after service promise resolves');
|
||||
expect(comp.heroes.length)
|
||||
.toBeGreaterThan(0, 'should have heroes after service promise resolves');
|
||||
});
|
||||
|
||||
it('should DISPLAY heroes', () => {
|
||||
@ -130,8 +123,7 @@ function tests(heroClick: () => void) {
|
||||
|
||||
// #docregion navigate-test
|
||||
it('should tell ROUTER to navigate when hero clicked', () => {
|
||||
|
||||
heroClick(); // trigger click on first inner <div class="hero">
|
||||
heroClick(); // trigger click on first inner <div class="hero">
|
||||
|
||||
// args passed to router.navigateByUrl() spy
|
||||
const spy = router.navigateByUrl as jasmine.Spy;
|
||||
@ -139,10 +131,8 @@ function tests(heroClick: () => void) {
|
||||
|
||||
// expecting to navigate to id of the component's first hero
|
||||
const id = comp.heroes[0].id;
|
||||
expect(navArgs).toBe('/heroes/' + id,
|
||||
'should nav to HeroDetail for first hero');
|
||||
expect(navArgs).toBe('/heroes/' + id, 'should nav to HeroDetail for first hero');
|
||||
});
|
||||
// #enddocregion navigate-test
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,23 @@
|
||||
// tslint:disable-next-line:no-unused-variable
|
||||
import { async, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { fakeAsync, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { interval, of } from 'rxjs';
|
||||
import { delay, take } from 'rxjs/operators';
|
||||
|
||||
describe('Angular async helper', () => {
|
||||
|
||||
describe('async', () => {
|
||||
let actuallyDone = false;
|
||||
|
||||
beforeEach(() => { actuallyDone = false; });
|
||||
beforeEach(() => {
|
||||
actuallyDone = false;
|
||||
});
|
||||
|
||||
afterEach(() => { expect(actuallyDone).toBe(true, 'actuallyDone should be true'); });
|
||||
afterEach(() => {
|
||||
expect(actuallyDone).toBe(true, 'actuallyDone should be true');
|
||||
});
|
||||
|
||||
it('should run normal test', () => { actuallyDone = true; });
|
||||
it('should run normal test', () => {
|
||||
actuallyDone = true;
|
||||
});
|
||||
|
||||
it('should run normal async test', (done: DoneFn) => {
|
||||
setTimeout(() => {
|
||||
@ -21,39 +26,50 @@ describe('Angular async helper', () => {
|
||||
}, 0);
|
||||
});
|
||||
|
||||
it('should run async test with task',
|
||||
async(() => { setTimeout(() => { actuallyDone = true; }, 0); }));
|
||||
it('should run async test with task', waitForAsync(() => {
|
||||
setTimeout(() => {
|
||||
actuallyDone = true;
|
||||
}, 0);
|
||||
}));
|
||||
|
||||
it('should run async test with task', async(() => {
|
||||
it('should run async test with task', waitForAsync(() => {
|
||||
const id = setInterval(() => {
|
||||
actuallyDone = true;
|
||||
clearInterval(id);
|
||||
}, 100);
|
||||
}));
|
||||
|
||||
it('should run async test with successful promise', async(() => {
|
||||
const p = new Promise(resolve => { setTimeout(resolve, 10); });
|
||||
p.then(() => { actuallyDone = true; });
|
||||
it('should run async test with successful promise', waitForAsync(() => {
|
||||
const p = new Promise(resolve => {
|
||||
setTimeout(resolve, 10);
|
||||
});
|
||||
p.then(() => {
|
||||
actuallyDone = true;
|
||||
});
|
||||
}));
|
||||
|
||||
it('should run async test with failed promise', async(() => {
|
||||
const p = new Promise((resolve, reject) => { setTimeout(reject, 10); });
|
||||
p.catch(() => { actuallyDone = true; });
|
||||
it('should run async test with failed promise', waitForAsync(() => {
|
||||
const p = new Promise((resolve, reject) => {
|
||||
setTimeout(reject, 10);
|
||||
});
|
||||
p.catch(() => {
|
||||
actuallyDone = true;
|
||||
});
|
||||
}));
|
||||
|
||||
// Use done. Can also use async or fakeAsync.
|
||||
it('should run async test with successful delayed Observable', (done: DoneFn) => {
|
||||
const source = of (true).pipe(delay(10));
|
||||
const source = of(true).pipe(delay(10));
|
||||
source.subscribe(val => actuallyDone = true, err => fail(err), done);
|
||||
});
|
||||
|
||||
it('should run async test with successful delayed Observable', async(() => {
|
||||
const source = of (true).pipe(delay(10));
|
||||
it('should run async test with successful delayed Observable', waitForAsync(() => {
|
||||
const source = of(true).pipe(delay(10));
|
||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||
}));
|
||||
|
||||
it('should run async test with successful delayed Observable', fakeAsync(() => {
|
||||
const source = of (true).pipe(delay(10));
|
||||
const source = of(true).pipe(delay(10));
|
||||
source.subscribe(val => actuallyDone = true, err => fail(err));
|
||||
|
||||
tick(10);
|
||||
@ -64,7 +80,9 @@ describe('Angular async helper', () => {
|
||||
// #docregion fake-async-test-tick
|
||||
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
|
||||
let called = false;
|
||||
setTimeout(() => { called = true; }, 100);
|
||||
setTimeout(() => {
|
||||
called = true;
|
||||
}, 100);
|
||||
tick(100);
|
||||
expect(called).toBe(true);
|
||||
}));
|
||||
@ -73,7 +91,9 @@ describe('Angular async helper', () => {
|
||||
// #docregion fake-async-test-tick-new-macro-task-sync
|
||||
it('should run new macro task callback with delay after call tick with millis',
|
||||
fakeAsync(() => {
|
||||
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); }
|
||||
function nestedTimer(cb: () => any): void {
|
||||
setTimeout(() => setTimeout(() => cb()));
|
||||
}
|
||||
const callback = jasmine.createSpy('callback');
|
||||
nestedTimer(callback);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@ -86,7 +106,9 @@ describe('Angular async helper', () => {
|
||||
// #docregion fake-async-test-tick-new-macro-task-async
|
||||
it('should not run new macro task callback with delay after call tick with millis',
|
||||
fakeAsync(() => {
|
||||
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); }
|
||||
function nestedTimer(cb: () => any): void {
|
||||
setTimeout(() => setTimeout(() => cb()));
|
||||
}
|
||||
const callback = jasmine.createSpy('callback');
|
||||
nestedTimer(callback);
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@ -112,7 +134,9 @@ describe('Angular async helper', () => {
|
||||
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
|
||||
// to patch rxjs scheduler
|
||||
let result = null;
|
||||
of ('hello').pipe(delay(1000)).subscribe(v => { result = v; });
|
||||
of('hello').pipe(delay(1000)).subscribe(v => {
|
||||
result = v;
|
||||
});
|
||||
expect(result).toBeNull();
|
||||
tick(1000);
|
||||
expect(result).toBe('hello');
|
||||
@ -133,12 +157,18 @@ describe('Angular async helper', () => {
|
||||
describe('use jasmine.clock()', () => {
|
||||
// need to config __zone_symbol__fakeAsyncPatchLock flag
|
||||
// before loading zone.js/dist/zone-testing
|
||||
beforeEach(() => { jasmine.clock().install(); });
|
||||
afterEach(() => { jasmine.clock().uninstall(); });
|
||||
beforeEach(() => {
|
||||
jasmine.clock().install();
|
||||
});
|
||||
afterEach(() => {
|
||||
jasmine.clock().uninstall();
|
||||
});
|
||||
it('should auto enter fakeAsync', () => {
|
||||
// is in fakeAsync now, don't need to call fakeAsync(testFn)
|
||||
let called = false;
|
||||
setTimeout(() => { called = true; }, 100);
|
||||
setTimeout(() => {
|
||||
called = true;
|
||||
}, 100);
|
||||
jasmine.clock().tick(100);
|
||||
expect(called).toBe(true);
|
||||
});
|
||||
@ -152,7 +182,7 @@ describe('Angular async helper', () => {
|
||||
}
|
||||
// need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag
|
||||
// before loading zone.js/dist/zone-testing
|
||||
it('should wait until promise.then is called', async(() => {
|
||||
it('should wait until promise.then is called', waitForAsync(() => {
|
||||
let finished = false;
|
||||
new Promise((res, rej) => {
|
||||
jsonp('localhost:8080/jsonp', () => {
|
||||
@ -168,5 +198,4 @@ describe('Angular async helper', () => {
|
||||
}));
|
||||
});
|
||||
// #enddocregion async-test-promise-then
|
||||
|
||||
});
|
||||
|
@ -24,17 +24,18 @@ import { FormsModule } from '@angular/forms';
|
||||
// Forms symbols imported only for a specific test below
|
||||
import { NgModel, NgControl } from '@angular/forms';
|
||||
|
||||
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick
|
||||
import {
|
||||
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { addMatchers, newEvent, click } from '../../testing';
|
||||
|
||||
export class NotProvided extends ValueService { /* example below */}
|
||||
beforeEach( addMatchers );
|
||||
export class NotProvided extends ValueService { /* example below */ }
|
||||
beforeEach(addMatchers);
|
||||
|
||||
describe('demo (with TestBed):', () => {
|
||||
|
||||
//////// Service Tests /////////////
|
||||
//////// Service Tests /////////////
|
||||
|
||||
// #docregion ValueService
|
||||
describe('ValueService', () => {
|
||||
@ -64,13 +65,13 @@ describe('demo (with TestBed):', () => {
|
||||
// #enddocregion testbed-get-w-null
|
||||
});
|
||||
|
||||
it('test should wait for ValueService.getPromiseValue', async(() => {
|
||||
it('test should wait for ValueService.getPromiseValue', waitForAsync(() => {
|
||||
service.getPromiseValue().then(
|
||||
value => expect(value).toBe('promise value')
|
||||
);
|
||||
}));
|
||||
|
||||
it('test should wait for ValueService.getObservableValue', async(() => {
|
||||
it('test should wait for ValueService.getObservableValue', waitForAsync(() => {
|
||||
service.getObservableValue().subscribe(
|
||||
value => expect(value).toBe('observable value')
|
||||
);
|
||||
@ -150,7 +151,7 @@ describe('demo (with TestBed):', () => {
|
||||
TestBed.configureTestingModule({ providers: [ValueService] });
|
||||
});
|
||||
|
||||
beforeEach(async(inject([ValueService], (service: ValueService) => {
|
||||
beforeEach(waitForAsync(inject([ValueService], (service: ValueService) => {
|
||||
service.getPromiseValue().then(value => serviceValue = value);
|
||||
})));
|
||||
|
||||
@ -159,11 +160,11 @@ describe('demo (with TestBed):', () => {
|
||||
});
|
||||
});
|
||||
|
||||
/////////// Component Tests //////////////////
|
||||
/////////// Component Tests //////////////////
|
||||
|
||||
describe('TestBed component tests', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [DemoModule],
|
||||
@ -235,7 +236,7 @@ describe('demo (with TestBed):', () => {
|
||||
// #docregion ButtonComp
|
||||
it('should support clicking a button', () => {
|
||||
const fixture = TestBed.createComponent(LightswitchComponent);
|
||||
const btn = fixture.debugElement.query(By.css('button'));
|
||||
const btn = fixture.debugElement.query(By.css('button'));
|
||||
const span = fixture.debugElement.query(By.css('span')).nativeElement;
|
||||
|
||||
fixture.detectChanges();
|
||||
@ -248,7 +249,7 @@ describe('demo (with TestBed):', () => {
|
||||
// #enddocregion ButtonComp
|
||||
|
||||
// ngModel is async so we must wait for it with promise-based `whenStable`
|
||||
it('should support entering text in input box (ngModel)', async(() => {
|
||||
it('should support entering text in input box (ngModel)', waitForAsync(() => {
|
||||
const expectedOrigName = 'John';
|
||||
const expectedNewName = 'Sally';
|
||||
|
||||
@ -278,10 +279,10 @@ describe('demo (with TestBed):', () => {
|
||||
input.dispatchEvent(newEvent('input'));
|
||||
return fixture.whenStable();
|
||||
})
|
||||
.then(() => {
|
||||
expect(comp.name).toBe(expectedNewName,
|
||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||
});
|
||||
.then(() => {
|
||||
expect(comp.name).toBe(expectedNewName,
|
||||
`After ngModel updates the model, comp.name should be ${expectedNewName} `);
|
||||
});
|
||||
}));
|
||||
|
||||
// fakeAsync version of ngModel input test enables sync test style
|
||||
@ -327,9 +328,9 @@ describe('demo (with TestBed):', () => {
|
||||
const fixture = TestBed.createComponent(ReversePipeComponent);
|
||||
fixture.detectChanges();
|
||||
|
||||
const comp = fixture.componentInstance;
|
||||
const comp = fixture.componentInstance;
|
||||
const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement;
|
||||
const span = fixture.debugElement.query(By.css('span')).nativeElement as HTMLElement;
|
||||
const span = fixture.debugElement.query(By.css('span')).nativeElement as HTMLElement;
|
||||
|
||||
// simulate user entering new name in input
|
||||
input.value = inputText;
|
||||
@ -381,12 +382,12 @@ describe('demo (with TestBed):', () => {
|
||||
|
||||
expect(el.styles.color).toBe(comp.color, 'color style');
|
||||
expect(el.styles.width).toBe(comp.width + 'px', 'width style');
|
||||
// #enddocregion dom-attributes
|
||||
// #enddocregion dom-attributes
|
||||
|
||||
// Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?
|
||||
// expect(el.properties['customProperty']).toBe(true, 'customProperty');
|
||||
|
||||
// #docregion dom-attributes
|
||||
// #docregion dom-attributes
|
||||
});
|
||||
// #enddocregion dom-attributes
|
||||
|
||||
@ -400,10 +401,10 @@ describe('demo (with TestBed):', () => {
|
||||
const fixture = TestBed.configureTestingModule({
|
||||
declarations: [Child1Component],
|
||||
})
|
||||
.overrideComponent(Child1Component, {
|
||||
set: { template: '<span>Fake</span>' }
|
||||
})
|
||||
.createComponent(Child1Component);
|
||||
.overrideComponent(Child1Component, {
|
||||
set: { template: '<span>Fake</span>' }
|
||||
})
|
||||
.createComponent(Child1Component);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture).toHaveText('Fake');
|
||||
@ -413,14 +414,14 @@ describe('demo (with TestBed):', () => {
|
||||
const fixture = TestBed.configureTestingModule({
|
||||
declarations: [TestProvidersComponent],
|
||||
})
|
||||
.overrideComponent(TestProvidersComponent, {
|
||||
remove: { providers: [ValueService]},
|
||||
add: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
.overrideComponent(TestProvidersComponent, {
|
||||
remove: { providers: [ValueService] },
|
||||
add: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
|
||||
// Or replace them all (this component has only one provider)
|
||||
// set: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
})
|
||||
.createComponent(TestProvidersComponent);
|
||||
// Or replace them all (this component has only one provider)
|
||||
// set: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
})
|
||||
.createComponent(TestProvidersComponent);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture).toHaveText('injected value: faked value', 'text');
|
||||
@ -436,14 +437,14 @@ describe('demo (with TestBed):', () => {
|
||||
const fixture = TestBed.configureTestingModule({
|
||||
declarations: [TestViewProvidersComponent],
|
||||
})
|
||||
.overrideComponent(TestViewProvidersComponent, {
|
||||
// remove: { viewProviders: [ValueService]},
|
||||
// add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
.overrideComponent(TestViewProvidersComponent, {
|
||||
// remove: { viewProviders: [ValueService]},
|
||||
// add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
|
||||
// Or replace them all (this component has only one viewProvider)
|
||||
set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
})
|
||||
.createComponent(TestViewProvidersComponent);
|
||||
// Or replace them all (this component has only one viewProvider)
|
||||
set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
|
||||
})
|
||||
.createComponent(TestViewProvidersComponent);
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(fixture).toHaveText('injected value: faked value');
|
||||
@ -453,20 +454,20 @@ describe('demo (with TestBed):', () => {
|
||||
|
||||
// TestComponent is parent of TestProvidersComponent
|
||||
@Component({ template: '<my-service-comp></my-service-comp>' })
|
||||
class TestComponent {}
|
||||
class TestComponent { }
|
||||
|
||||
// 3 levels of ValueService provider: module, TestCompomponent, TestProvidersComponent
|
||||
const fixture = TestBed.configureTestingModule({
|
||||
declarations: [TestComponent, TestProvidersComponent],
|
||||
providers: [ValueService]
|
||||
providers: [ValueService]
|
||||
})
|
||||
.overrideComponent(TestComponent, {
|
||||
set: { providers: [{ provide: ValueService, useValue: {} }] }
|
||||
})
|
||||
.overrideComponent(TestProvidersComponent, {
|
||||
set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }
|
||||
})
|
||||
.createComponent(TestComponent);
|
||||
.overrideComponent(TestComponent, {
|
||||
set: { providers: [{ provide: ValueService, useValue: {} }] }
|
||||
})
|
||||
.overrideComponent(TestProvidersComponent, {
|
||||
set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }
|
||||
})
|
||||
.createComponent(TestComponent);
|
||||
|
||||
let testBedProvider: ValueService;
|
||||
let tcProvider: ValueService;
|
||||
@ -489,10 +490,10 @@ describe('demo (with TestBed):', () => {
|
||||
const fixture = TestBed.configureTestingModule({
|
||||
declarations: [ShellComponent, NeedsContentComponent, Child1Component, Child2Component, Child3Component],
|
||||
})
|
||||
.overrideComponent(ShellComponent, {
|
||||
set: {
|
||||
selector: 'test-shell',
|
||||
template: `
|
||||
.overrideComponent(ShellComponent, {
|
||||
set: {
|
||||
selector: 'test-shell',
|
||||
template: `
|
||||
<needs-content #nc>
|
||||
<child-1 #content text="My"></child-1>
|
||||
<child-2 #content text="dog"></child-2>
|
||||
@ -501,9 +502,9 @@ describe('demo (with TestBed):', () => {
|
||||
<div #content>!</div>
|
||||
</needs-content>
|
||||
`
|
||||
}
|
||||
})
|
||||
.createComponent(ShellComponent);
|
||||
}
|
||||
})
|
||||
.createComponent(ShellComponent);
|
||||
|
||||
fixture.detectChanges();
|
||||
|
||||
@ -615,7 +616,7 @@ describe('demo (with TestBed):', () => {
|
||||
});
|
||||
|
||||
// must be async test to see child flow to parent
|
||||
it('changed child value flows to parent', async(() => {
|
||||
it('changed child value flows to parent', waitForAsync(() => {
|
||||
fixture.detectChanges();
|
||||
getChild();
|
||||
|
||||
@ -625,14 +626,14 @@ describe('demo (with TestBed):', () => {
|
||||
// Wait one JS engine turn!
|
||||
setTimeout(() => resolve(), 0);
|
||||
})
|
||||
.then(() => {
|
||||
fixture.detectChanges();
|
||||
.then(() => {
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(child.ngOnChangesCounter).toBe(2,
|
||||
'expected 2 changes: initial value and changed value');
|
||||
expect(parent.parentValue).toBe('bar',
|
||||
'parentValue should eq changed parent value');
|
||||
});
|
||||
expect(child.ngOnChangesCounter).toBe(2,
|
||||
'expected 2 changes: initial value and changed value');
|
||||
expect(parent.parentValue).toBe('bar',
|
||||
'parentValue should eq changed parent value');
|
||||
});
|
||||
|
||||
}));
|
||||
|
||||
|
@ -1,8 +1,5 @@
|
||||
// #docplaster
|
||||
import {
|
||||
async, ComponentFixture, fakeAsync, inject, TestBed, tick
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import {
|
||||
@ -36,59 +33,54 @@ describe('HeroDetailComponent', () => {
|
||||
function overrideSetup() {
|
||||
// #docregion hds-spy
|
||||
class HeroDetailServiceSpy {
|
||||
testHero: Hero = {id: 42, name: 'Test Hero' };
|
||||
testHero: Hero = {id: 42, name: 'Test Hero'};
|
||||
|
||||
/* emit cloned test hero */
|
||||
getHero = jasmine.createSpy('getHero').and.callFake(
|
||||
() => asyncData(Object.assign({}, this.testHero))
|
||||
);
|
||||
() => asyncData(Object.assign({}, this.testHero)));
|
||||
|
||||
/* emit clone of test hero, with changes merged in */
|
||||
saveHero = jasmine.createSpy('saveHero').and.callFake(
|
||||
(hero: Hero) => asyncData(Object.assign(this.testHero, hero))
|
||||
);
|
||||
saveHero = jasmine.createSpy('saveHero')
|
||||
.and.callFake((hero: Hero) => asyncData(Object.assign(this.testHero, hero)));
|
||||
}
|
||||
|
||||
// #enddocregion hds-spy
|
||||
|
||||
// the `id` value is irrelevant because ignored by service stub
|
||||
beforeEach(() => activatedRoute.setParamMap({ id: 99999 }));
|
||||
beforeEach(() => activatedRoute.setParamMap({id: 99999}));
|
||||
|
||||
// #docregion setup-override
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
const routerSpy = createRouterSpy();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ HeroModule ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||
{ provide: Router, useValue: routerSpy},
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [HeroModule],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
// #enddocregion setup-override
|
||||
// HeroDetailService at this level is IRRELEVANT!
|
||||
{ provide: HeroDetailService, useValue: {} }
|
||||
// HeroDetailService at this level is IRRELEVANT!
|
||||
{provide: HeroDetailService, useValue: {}}
|
||||
// #docregion setup-override
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
// Override component's own provider
|
||||
// #docregion override-component-method
|
||||
.overrideComponent(HeroDetailComponent, {
|
||||
set: {
|
||||
providers: [
|
||||
{ provide: HeroDetailService, useClass: HeroDetailServiceSpy }
|
||||
]
|
||||
}
|
||||
})
|
||||
// #enddocregion override-component-method
|
||||
// Override component's own provider
|
||||
// #docregion override-component-method
|
||||
.overrideComponent(
|
||||
HeroDetailComponent,
|
||||
{set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}})
|
||||
// #enddocregion override-component-method
|
||||
|
||||
.compileComponents();
|
||||
.compileComponents();
|
||||
}));
|
||||
// #enddocregion setup-override
|
||||
|
||||
// #docregion override-tests
|
||||
let hdsSpy: HeroDetailServiceSpy;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
createComponent();
|
||||
// get the component's injected HeroDetailServiceSpy
|
||||
hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any;
|
||||
@ -103,33 +95,32 @@ function overrideSetup() {
|
||||
});
|
||||
|
||||
it('should save stub hero change', fakeAsync(() => {
|
||||
const origName = hdsSpy.testHero.name;
|
||||
const newName = 'New Name';
|
||||
const origName = hdsSpy.testHero.name;
|
||||
const newName = 'New Name';
|
||||
|
||||
page.nameInput.value = newName;
|
||||
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
||||
page.nameInput.value = newName;
|
||||
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
|
||||
|
||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||
expect(component.hero.name).toBe(newName, 'component hero has new name');
|
||||
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
|
||||
|
||||
click(page.saveBtn);
|
||||
expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');
|
||||
click(page.saveBtn);
|
||||
expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');
|
||||
|
||||
tick(); // wait for async save to complete
|
||||
expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');
|
||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||
}));
|
||||
tick(); // wait for async save to complete
|
||||
expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');
|
||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||
}));
|
||||
// #enddocregion override-tests
|
||||
|
||||
it('fixture injected service is not the component injected service',
|
||||
// inject gets the service from the fixture
|
||||
inject([HeroDetailService], (fixtureService: HeroDetailService) => {
|
||||
// inject gets the service from the fixture
|
||||
inject([HeroDetailService], (fixtureService: HeroDetailService) => {
|
||||
// use `fixture.debugElement.injector` to get service from component
|
||||
const componentService = fixture.debugElement.injector.get(HeroDetailService);
|
||||
|
||||
// use `fixture.debugElement.injector` to get service from component
|
||||
const componentService = fixture.debugElement.injector.get(HeroDetailService);
|
||||
|
||||
expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
|
||||
}));
|
||||
expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
|
||||
}));
|
||||
}
|
||||
|
||||
////////////////////
|
||||
@ -139,21 +130,22 @@ const firstHero = getTestHeroes()[0];
|
||||
|
||||
function heroModuleSetup() {
|
||||
// #docregion setup-hero-module
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
const routerSpy = createRouterSpy();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ HeroModule ],
|
||||
// #enddocregion setup-hero-module
|
||||
// declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION
|
||||
// #docregion setup-hero-module
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||
{ provide: HeroService, useClass: TestHeroService },
|
||||
{ provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [HeroModule],
|
||||
// #enddocregion setup-hero-module
|
||||
// declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION
|
||||
// #docregion setup-hero-module
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
||||
{provide: HeroService, useClass: TestHeroService},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
// #enddocregion setup-hero-module
|
||||
|
||||
@ -161,17 +153,17 @@ function heroModuleSetup() {
|
||||
describe('when navigate to existing hero', () => {
|
||||
let expectedHero: Hero;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
expectedHero = firstHero;
|
||||
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||
activatedRoute.setParamMap({id: expectedHero.id});
|
||||
createComponent();
|
||||
}));
|
||||
|
||||
// #docregion selected-tests
|
||||
// #docregion selected-tests
|
||||
it('should display that hero\'s name', () => {
|
||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||
});
|
||||
// #enddocregion route-good-id
|
||||
// #enddocregion route-good-id
|
||||
|
||||
it('should navigate when click cancel', () => {
|
||||
click(page.cancelBtn);
|
||||
@ -190,10 +182,10 @@ function heroModuleSetup() {
|
||||
});
|
||||
|
||||
it('should navigate when click save and save resolves', fakeAsync(() => {
|
||||
click(page.saveBtn);
|
||||
tick(); // wait for async save to complete
|
||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||
}));
|
||||
click(page.saveBtn);
|
||||
tick(); // wait for async save to complete
|
||||
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
|
||||
}));
|
||||
|
||||
// #docregion title-case-pipe
|
||||
it('should convert hero name to Title Case', () => {
|
||||
@ -215,14 +207,14 @@ function heroModuleSetup() {
|
||||
expect(nameDisplay.textContent).toBe('Quick Brown Fox');
|
||||
});
|
||||
// #enddocregion title-case-pipe
|
||||
// #enddocregion selected-tests
|
||||
// #docregion route-good-id
|
||||
// #enddocregion selected-tests
|
||||
// #docregion route-good-id
|
||||
});
|
||||
// #enddocregion route-good-id
|
||||
|
||||
// #docregion route-no-id
|
||||
describe('when navigate with no hero id', () => {
|
||||
beforeEach(async( createComponent ));
|
||||
beforeEach(waitForAsync(createComponent));
|
||||
|
||||
it('should have hero.id === 0', () => {
|
||||
expect(component.hero.id).toBe(0);
|
||||
@ -236,8 +228,8 @@ function heroModuleSetup() {
|
||||
|
||||
// #docregion route-bad-id
|
||||
describe('when navigate to non-existent hero id', () => {
|
||||
beforeEach(async(() => {
|
||||
activatedRoute.setParamMap({ id: 99999 });
|
||||
beforeEach(waitForAsync(() => {
|
||||
activatedRoute.setParamMap({id: 99999});
|
||||
createComponent();
|
||||
}));
|
||||
|
||||
@ -253,11 +245,10 @@ function heroModuleSetup() {
|
||||
let service: HeroDetailService;
|
||||
fixture = TestBed.createComponent(HeroDetailComponent);
|
||||
expect(
|
||||
// Throws because `inject` only has access to TestBed's injector
|
||||
// which is an ancestor of the component's injector
|
||||
inject([HeroDetailService], (hds: HeroDetailService) => service = hds )
|
||||
)
|
||||
.toThrowError(/No provider for HeroDetailService/);
|
||||
// Throws because `inject` only has access to TestBed's injector
|
||||
// which is an ancestor of the component's injector
|
||||
inject([HeroDetailService], (hds: HeroDetailService) => service = hds))
|
||||
.toThrowError(/No provider for HeroDetailService/);
|
||||
|
||||
// get `HeroDetailService` with component's own injector
|
||||
service = fixture.debugElement.injector.get(HeroDetailService);
|
||||
@ -270,30 +261,31 @@ import { FormsModule } from '@angular/forms';
|
||||
import { TitleCasePipe } from '../shared/title-case.pipe';
|
||||
|
||||
function formsModuleSetup() {
|
||||
// #docregion setup-forms-module
|
||||
beforeEach(async(() => {
|
||||
// #docregion setup-forms-module
|
||||
beforeEach(waitForAsync(() => {
|
||||
const routerSpy = createRouterSpy();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ FormsModule ],
|
||||
declarations: [ HeroDetailComponent, TitleCasePipe ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||
{ provide: HeroService, useClass: TestHeroService },
|
||||
{ provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [FormsModule],
|
||||
declarations: [HeroDetailComponent, TitleCasePipe],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
||||
{provide: HeroService, useClass: TestHeroService},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
// #enddocregion setup-forms-module
|
||||
|
||||
it('should display 1st hero\'s name', async(() => {
|
||||
const expectedHero = firstHero;
|
||||
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||
createComponent().then(() => {
|
||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||
});
|
||||
}));
|
||||
it('should display 1st hero\'s name', waitForAsync(() => {
|
||||
const expectedHero = firstHero;
|
||||
activatedRoute.setParamMap({id: expectedHero.id});
|
||||
createComponent().then(() => {
|
||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
///////////////////////
|
||||
@ -301,29 +293,30 @@ import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
function sharedModuleSetup() {
|
||||
// #docregion setup-shared-module
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
const routerSpy = createRouterSpy();
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [ SharedModule ],
|
||||
declarations: [ HeroDetailComponent ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: activatedRoute },
|
||||
{ provide: HeroService, useClass: TestHeroService },
|
||||
{ provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [SharedModule],
|
||||
declarations: [HeroDetailComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: activatedRoute},
|
||||
{provide: HeroService, useClass: TestHeroService},
|
||||
{provide: Router, useValue: routerSpy},
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
// #enddocregion setup-shared-module
|
||||
|
||||
it('should display 1st hero\'s name', async(() => {
|
||||
const expectedHero = firstHero;
|
||||
activatedRoute.setParamMap({ id: expectedHero.id });
|
||||
createComponent().then(() => {
|
||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||
});
|
||||
}));
|
||||
it('should display 1st hero\'s name', waitForAsync(() => {
|
||||
const expectedHero = firstHero;
|
||||
activatedRoute.setParamMap({id: expectedHero.id});
|
||||
createComponent().then(() => {
|
||||
expect(page.nameDisplay.textContent).toBe(expectedHero.name);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
/////////// Helpers /////
|
||||
@ -347,11 +340,21 @@ function createComponent() {
|
||||
// #docregion page
|
||||
class Page {
|
||||
// getter properties wait to query the DOM until called.
|
||||
get buttons() { return this.queryAll<HTMLButtonElement>('button'); }
|
||||
get saveBtn() { return this.buttons[0]; }
|
||||
get cancelBtn() { return this.buttons[1]; }
|
||||
get nameDisplay() { return this.query<HTMLElement>('span'); }
|
||||
get nameInput() { return this.query<HTMLInputElement>('input'); }
|
||||
get buttons() {
|
||||
return this.queryAll<HTMLButtonElement>('button');
|
||||
}
|
||||
get saveBtn() {
|
||||
return this.buttons[0];
|
||||
}
|
||||
get cancelBtn() {
|
||||
return this.buttons[1];
|
||||
}
|
||||
get nameDisplay() {
|
||||
return this.query<HTMLElement>('span');
|
||||
}
|
||||
get nameInput() {
|
||||
return this.query<HTMLInputElement>('input');
|
||||
}
|
||||
|
||||
gotoListSpy: jasmine.Spy;
|
||||
navigateSpy: jasmine.Spy;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { async, ComponentFixture, fakeAsync, TestBed, tick
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
@ -7,13 +7,12 @@ import { DebugElement } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
import { addMatchers, newEvent } from '../../testing';
|
||||
|
||||
import { HeroService } from '../model/hero.service';
|
||||
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
|
||||
|
||||
import { HeroModule } from './hero.module';
|
||||
import { HeroListComponent } from './hero-list.component';
|
||||
import { HighlightDirective } from '../shared/highlight.directive';
|
||||
import { HeroService } from '../model/hero.service';
|
||||
|
||||
const HEROES = getTestHeroes();
|
||||
|
||||
@ -24,20 +23,20 @@ let page: Page;
|
||||
/////// Tests //////
|
||||
|
||||
describe('HeroListComponent', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
addMatchers();
|
||||
const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HeroModule],
|
||||
providers: [
|
||||
{ provide: HeroService, useClass: TestHeroService },
|
||||
{ provide: Router, useValue: routerSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents()
|
||||
.then(createComponent);
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
imports: [HeroModule],
|
||||
providers: [
|
||||
{provide: HeroService, useClass: TestHeroService},
|
||||
{provide: Router, useValue: routerSpy}
|
||||
]
|
||||
})
|
||||
.compileComponents()
|
||||
.then(createComponent);
|
||||
}));
|
||||
|
||||
it('should display heroes', () => {
|
||||
@ -52,36 +51,35 @@ describe('HeroListComponent', () => {
|
||||
});
|
||||
|
||||
it('should select hero on click', fakeAsync(() => {
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
tick();
|
||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||
expect(comp.selectedHero).toEqual(expectedHero);
|
||||
}));
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
tick();
|
||||
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
|
||||
expect(comp.selectedHero).toEqual(expectedHero);
|
||||
}));
|
||||
|
||||
it('should navigate to selected hero detail on click', fakeAsync(() => {
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
tick();
|
||||
const expectedHero = HEROES[1];
|
||||
const li = page.heroRows[1];
|
||||
li.dispatchEvent(newEvent('click'));
|
||||
tick();
|
||||
|
||||
// should have navigated
|
||||
expect(page.navSpy.calls.any()).toBe(true, 'navigate called');
|
||||
// should have navigated
|
||||
expect(page.navSpy.calls.any()).toBe(true, 'navigate called');
|
||||
|
||||
// composed hero detail will be URL like 'heroes/42'
|
||||
// expect link array with the route path and hero id
|
||||
// first argument to router.navigate is link array
|
||||
const navArgs = page.navSpy.calls.first().args[0];
|
||||
expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL');
|
||||
expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id');
|
||||
|
||||
}));
|
||||
// composed hero detail will be URL like 'heroes/42'
|
||||
// expect link array with the route path and hero id
|
||||
// first argument to router.navigate is link array
|
||||
const navArgs = page.navSpy.calls.first().args[0];
|
||||
expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL');
|
||||
expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id');
|
||||
}));
|
||||
|
||||
it('should find `HighlightDirective` with `By.directive', () => {
|
||||
// #docregion by
|
||||
// Can find DebugElement either by css selector or by directive
|
||||
const h2 = fixture.debugElement.query(By.css('h2'));
|
||||
const h2 = fixture.debugElement.query(By.css('h2'));
|
||||
const directive = fixture.debugElement.query(By.directive(HighlightDirective));
|
||||
// #enddocregion by
|
||||
expect(h2).toBe(directive);
|
||||
|
@ -1,6 +1,7 @@
|
||||
// #docplaster
|
||||
// #docregion without-toBlob-macrotask
|
||||
import { TestBed, async, tick, fakeAsync } from '@angular/core/testing';
|
||||
import { fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { CanvasComponent } from './canvas.component';
|
||||
|
||||
describe('CanvasComponent', () => {
|
||||
@ -10,29 +11,29 @@ describe('CanvasComponent', () => {
|
||||
(window as any).__zone_symbol__FakeAsyncTestMacroTask = [
|
||||
{
|
||||
source: 'HTMLCanvasElement.toBlob',
|
||||
callbackArgs: [{ size: 200 }],
|
||||
callbackArgs: [{size: 200}],
|
||||
},
|
||||
];
|
||||
});
|
||||
// #enddocregion enable-toBlob-macrotask
|
||||
// #docregion without-toBlob-macrotask
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
CanvasComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [CanvasComponent],
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
it('should be able to generate blob data from canvas', fakeAsync(() => {
|
||||
const fixture = TestBed.createComponent(CanvasComponent);
|
||||
const canvasComp = fixture.componentInstance;
|
||||
const fixture = TestBed.createComponent(CanvasComponent);
|
||||
const canvasComp = fixture.componentInstance;
|
||||
|
||||
fixture.detectChanges();
|
||||
expect(canvasComp.blobSize).toBe(0);
|
||||
fixture.detectChanges();
|
||||
expect(canvasComp.blobSize).toBe(0);
|
||||
|
||||
tick();
|
||||
expect(canvasComp.blobSize).toBeGreaterThan(0);
|
||||
}));
|
||||
tick();
|
||||
expect(canvasComp.blobSize).toBeGreaterThan(0);
|
||||
}));
|
||||
});
|
||||
// #enddocregion without-toBlob-macrotask
|
||||
|
@ -1,14 +1,13 @@
|
||||
// #docplaster
|
||||
import { async, fakeAsync, ComponentFixture, TestBed, tick } from '@angular/core/testing';
|
||||
import { fakeAsync, ComponentFixture, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
|
||||
import { asyncData, asyncError } from '../../testing';
|
||||
|
||||
import { of, throwError } from 'rxjs';
|
||||
|
||||
import { last } from 'rxjs/operators';
|
||||
|
||||
import { TwainService } from './twain.service';
|
||||
import { TwainComponent } from './twain.component';
|
||||
import { TwainService } from './twain.service';
|
||||
|
||||
describe('TwainComponent', () => {
|
||||
let component: TwainComponent;
|
||||
@ -32,14 +31,12 @@ describe('TwainComponent', () => {
|
||||
// Create a fake TwainService object with a `getQuote()` spy
|
||||
const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);
|
||||
// Make the spy return a synchronous Observable with the test data
|
||||
getQuoteSpy = twainService.getQuote.and.returnValue( of(testQuote) );
|
||||
getQuoteSpy = twainService.getQuote.and.returnValue(of(testQuote));
|
||||
// #enddocregion spy
|
||||
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ TwainComponent ],
|
||||
providers: [
|
||||
{ provide: TwainService, useValue: twainService }
|
||||
]
|
||||
declarations: [TwainComponent],
|
||||
providers: [{provide: TwainService, useValue: twainService}]
|
||||
});
|
||||
|
||||
fixture = TestBed.createComponent(TwainComponent);
|
||||
@ -58,7 +55,7 @@ describe('TwainComponent', () => {
|
||||
// The quote would not be immediately available if the service were truly async.
|
||||
// #docregion sync-test
|
||||
it('should show quote after component initialized', () => {
|
||||
fixture.detectChanges(); // onInit()
|
||||
fixture.detectChanges(); // onInit()
|
||||
|
||||
// sync spy result shows testQuote immediately after init
|
||||
expect(quoteEl.textContent).toBe(testQuote);
|
||||
@ -71,20 +68,19 @@ describe('TwainComponent', () => {
|
||||
// Use `fakeAsync` because the component error calls `setTimeout`
|
||||
// #docregion error-test
|
||||
it('should display error when TwainService fails', fakeAsync(() => {
|
||||
// tell spy to return an error observable
|
||||
getQuoteSpy.and.returnValue(
|
||||
throwError('TwainService test failure'));
|
||||
// tell spy to return an error observable
|
||||
getQuoteSpy.and.returnValue(throwError('TwainService test failure'));
|
||||
|
||||
fixture.detectChanges(); // onInit()
|
||||
// sync spy errors immediately after init
|
||||
fixture.detectChanges(); // onInit()
|
||||
// sync spy errors immediately after init
|
||||
|
||||
tick(); // flush the component's setTimeout()
|
||||
tick(); // flush the component's setTimeout()
|
||||
|
||||
fixture.detectChanges(); // update errorMessage within setTimeout()
|
||||
fixture.detectChanges(); // update errorMessage within setTimeout()
|
||||
|
||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
}));
|
||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
}));
|
||||
// #enddocregion error-test
|
||||
});
|
||||
|
||||
@ -113,28 +109,28 @@ describe('TwainComponent', () => {
|
||||
|
||||
// #docregion fake-async-test
|
||||
it('should show quote after getQuote (fakeAsync)', fakeAsync(() => {
|
||||
fixture.detectChanges(); // ngOnInit()
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
fixture.detectChanges(); // ngOnInit()
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
|
||||
tick(); // flush the observable to get the quote
|
||||
fixture.detectChanges(); // update view
|
||||
tick(); // flush the observable to get the quote
|
||||
fixture.detectChanges(); // update view
|
||||
|
||||
expect(quoteEl.textContent).toBe(testQuote, 'should show quote');
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
}));
|
||||
expect(quoteEl.textContent).toBe(testQuote, 'should show quote');
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
}));
|
||||
// #enddocregion fake-async-test
|
||||
|
||||
// #docregion async-test
|
||||
it('should show quote after getQuote (async)', async(() => {
|
||||
fixture.detectChanges(); // ngOnInit()
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
it('should show quote after getQuote (async)', waitForAsync(() => {
|
||||
fixture.detectChanges(); // ngOnInit()
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
|
||||
fixture.whenStable().then(() => { // wait for async getQuote
|
||||
fixture.detectChanges(); // update view with quote
|
||||
expect(quoteEl.textContent).toBe(testQuote);
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
});
|
||||
}));
|
||||
fixture.whenStable().then(() => { // wait for async getQuote
|
||||
fixture.detectChanges(); // update view with quote
|
||||
expect(quoteEl.textContent).toBe(testQuote);
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
});
|
||||
}));
|
||||
// #enddocregion async-test
|
||||
|
||||
|
||||
@ -142,8 +138,8 @@ describe('TwainComponent', () => {
|
||||
it('should show last quote (quote done)', (done: DoneFn) => {
|
||||
fixture.detectChanges();
|
||||
|
||||
component.quote.pipe( last() ).subscribe(() => {
|
||||
fixture.detectChanges(); // update view with quote
|
||||
component.quote.pipe(last()).subscribe(() => {
|
||||
fixture.detectChanges(); // update view with quote
|
||||
expect(quoteEl.textContent).toBe(testQuote);
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
done();
|
||||
@ -157,7 +153,7 @@ describe('TwainComponent', () => {
|
||||
|
||||
// the spy's most recent call returns the observable with the test quote
|
||||
getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => {
|
||||
fixture.detectChanges(); // update view with quote
|
||||
fixture.detectChanges(); // update view with quote
|
||||
expect(quoteEl.textContent).toBe(testQuote);
|
||||
expect(errorMessage()).toBeNull('should not show error');
|
||||
done();
|
||||
@ -167,16 +163,16 @@ describe('TwainComponent', () => {
|
||||
|
||||
// #docregion async-error-test
|
||||
it('should display error when TwainService fails', fakeAsync(() => {
|
||||
// tell spy to return an async error observable
|
||||
getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure'));
|
||||
// tell spy to return an async error observable
|
||||
getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure'));
|
||||
|
||||
fixture.detectChanges();
|
||||
tick(); // component shows error after a setTimeout()
|
||||
fixture.detectChanges(); // update error message
|
||||
fixture.detectChanges();
|
||||
tick(); // component shows error after a setTimeout()
|
||||
fixture.detectChanges(); // update error message
|
||||
|
||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
}));
|
||||
expect(errorMessage()).toMatch(/test failure/, 'should display error');
|
||||
expect(quoteEl.textContent).toBe('...', 'should show placeholder');
|
||||
}));
|
||||
// #enddocregion async-error-test
|
||||
});
|
||||
});
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
import { HeroSearchComponent } from '../hero-search/hero-search.component';
|
||||
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { of } from 'rxjs';
|
||||
import { HEROES } from '../mock-heroes';
|
||||
|
||||
import { HeroSearchComponent } from '../hero-search/hero-search.component';
|
||||
import { HeroService } from '../hero.service';
|
||||
import { HEROES } from '../mock-heroes';
|
||||
|
||||
import { DashboardComponent } from './dashboard.component';
|
||||
|
||||
describe('DashboardComponent', () => {
|
||||
let component: DashboardComponent;
|
||||
@ -14,23 +14,16 @@ describe('DashboardComponent', () => {
|
||||
let heroService;
|
||||
let getHeroesSpy;
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
heroService = jasmine.createSpyObj('HeroService', ['getHeroes']);
|
||||
getHeroesSpy = heroService.getHeroes.and.returnValue( of(HEROES) );
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
HeroSearchComponent
|
||||
],
|
||||
imports: [
|
||||
RouterTestingModule.withRoutes([])
|
||||
],
|
||||
providers: [
|
||||
{ provide: HeroService, useValue: heroService }
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
getHeroesSpy = heroService.getHeroes.and.returnValue(of(HEROES));
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [DashboardComponent, HeroSearchComponent],
|
||||
imports: [RouterTestingModule.withRoutes([])],
|
||||
providers: [{provide: HeroService, useValue: heroService}]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -47,12 +40,11 @@ describe('DashboardComponent', () => {
|
||||
expect(fixture.nativeElement.querySelector('h3').textContent).toEqual('Top Heroes');
|
||||
});
|
||||
|
||||
it('should call heroService', async(() => {
|
||||
expect(getHeroesSpy.calls.any()).toBe(true);
|
||||
}));
|
||||
|
||||
it('should display 4 links', async(() => {
|
||||
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
|
||||
}));
|
||||
it('should call heroService', waitForAsync(() => {
|
||||
expect(getHeroesSpy.calls.any()).toBe(true);
|
||||
}));
|
||||
|
||||
it('should display 4 links', waitForAsync(() => {
|
||||
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
|
||||
}));
|
||||
});
|
||||
|
@ -1,22 +1,16 @@
|
||||
// #docregion
|
||||
// #docregion activatedroute
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
// #enddocregion activatedroute
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PhoneDetailComponent } from './phone-detail.component';
|
||||
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||
import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
|
||||
|
||||
function xyzPhoneData(): PhoneData {
|
||||
return {
|
||||
name: 'phone xyz',
|
||||
snippet: '',
|
||||
images: ['image/url1.png', 'image/url2.png']
|
||||
};
|
||||
return {name: 'phone xyz', snippet: '', images: ['image/url1.png', 'image/url2.png']};
|
||||
}
|
||||
|
||||
class MockPhone {
|
||||
@ -34,10 +28,9 @@ class ActivatedRouteMock {
|
||||
// #enddocregion activatedroute
|
||||
|
||||
describe('PhoneDetailComponent', () => {
|
||||
|
||||
// #docregion activatedroute
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CheckmarkPipe, PhoneDetailComponent ],
|
||||
providers: [
|
||||
@ -55,5 +48,4 @@ describe('PhoneDetailComponent', () => {
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
/* tslint:disable */
|
||||
// #docregion
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { SpyLocation } from '@angular/common/testing';
|
||||
import {SpyLocation} from '@angular/common/testing';
|
||||
import {NO_ERRORS_SCHEMA} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {Observable, of} from 'rxjs';
|
||||
|
||||
import { PhoneListComponent } from './phone-list.component';
|
||||
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||
import {Phone, PhoneData} from '../core/phone/phone.service';
|
||||
|
||||
import {PhoneListComponent} from './phone-list.component';
|
||||
|
||||
class ActivatedRouteMock {
|
||||
constructor(public snapshot: any) {}
|
||||
@ -16,8 +17,7 @@ class ActivatedRouteMock {
|
||||
class MockPhone {
|
||||
query(): Observable<PhoneData[]> {
|
||||
return of([
|
||||
{name: 'Nexus S', snippet: '', images: []},
|
||||
{name: 'Motorola DROID', snippet: '', images: []}
|
||||
{name: 'Nexus S', snippet: '', images: []}, {name: 'Motorola DROID', snippet: '', images: []}
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -25,18 +25,18 @@ class MockPhone {
|
||||
let fixture: ComponentFixture<PhoneListComponent>;
|
||||
|
||||
describe('PhoneList', () => {
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ PhoneListComponent ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) },
|
||||
{ provide: Location, useClass: SpyLocation },
|
||||
{ provide: Phone, useClass: MockPhone },
|
||||
],
|
||||
schemas: [ NO_ERRORS_SCHEMA ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [PhoneListComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: new ActivatedRouteMock({params: {'phoneId': 1}})},
|
||||
{provide: Location, useClass: SpyLocation},
|
||||
{provide: Phone, useClass: MockPhone},
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -47,20 +47,15 @@ describe('PhoneList', () => {
|
||||
fixture.detectChanges();
|
||||
let compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
|
||||
expect(
|
||||
compiled.querySelector('.phone-list-item:nth-child(1)').textContent
|
||||
).toContain('Motorola DROID');
|
||||
expect(
|
||||
compiled.querySelector('.phone-list-item:nth-child(2)').textContent
|
||||
).toContain('Nexus S');
|
||||
expect(compiled.querySelector('.phone-list-item:nth-child(1)').textContent)
|
||||
.toContain('Motorola DROID');
|
||||
expect(compiled.querySelector('.phone-list-item:nth-child(2)').textContent)
|
||||
.toContain('Nexus S');
|
||||
});
|
||||
|
||||
xit('should set the default value of orderProp model', () => {
|
||||
fixture.detectChanges();
|
||||
let compiled = fixture.debugElement.nativeElement;
|
||||
expect(
|
||||
compiled.querySelector('select option:last-child').selected
|
||||
).toBe(true);
|
||||
expect(compiled.querySelector('select option:last-child').selected).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,22 +1,16 @@
|
||||
// #docregion
|
||||
// #docregion activatedroute
|
||||
import { TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
// #enddocregion activatedroute
|
||||
import { Observable, of } from 'rxjs';
|
||||
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { PhoneDetailComponent } from './phone-detail.component';
|
||||
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||
import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
|
||||
|
||||
function xyzPhoneData(): PhoneData {
|
||||
return {
|
||||
name: 'phone xyz',
|
||||
snippet: '',
|
||||
images: ['image/url1.png', 'image/url2.png']
|
||||
};
|
||||
return {name: 'phone xyz', snippet: '', images: ['image/url1.png', 'image/url2.png']};
|
||||
}
|
||||
|
||||
class MockPhone {
|
||||
@ -34,10 +28,9 @@ class ActivatedRouteMock {
|
||||
// #enddocregion activatedroute
|
||||
|
||||
describe('PhoneDetailComponent', () => {
|
||||
|
||||
// #docregion activatedroute
|
||||
|
||||
beforeEach(async(() => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CheckmarkPipe, PhoneDetailComponent ],
|
||||
providers: [
|
||||
@ -55,5 +48,4 @@ describe('PhoneDetailComponent', () => {
|
||||
const compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
/* tslint:disable */
|
||||
// #docregion routestuff
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { SpyLocation } from '@angular/common/testing';
|
||||
import {SpyLocation} from '@angular/common/testing';
|
||||
import {NO_ERRORS_SCHEMA} from '@angular/core';
|
||||
import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {Observable, of} from 'rxjs';
|
||||
|
||||
import { PhoneListComponent } from './phone-list.component';
|
||||
import { Phone, PhoneData } from '../core/phone/phone.service';
|
||||
import {Phone, PhoneData} from '../core/phone/phone.service';
|
||||
|
||||
import {PhoneListComponent} from './phone-list.component';
|
||||
|
||||
// #enddocregion routestuff
|
||||
|
||||
@ -18,8 +19,7 @@ class ActivatedRouteMock {
|
||||
class MockPhone {
|
||||
query(): Observable<PhoneData[]> {
|
||||
return of([
|
||||
{name: 'Nexus S', snippet: '', images: []},
|
||||
{name: 'Motorola DROID', snippet: '', images: []}
|
||||
{name: 'Nexus S', snippet: '', images: []}, {name: 'Motorola DROID', snippet: '', images: []}
|
||||
]);
|
||||
}
|
||||
}
|
||||
@ -27,20 +27,20 @@ class MockPhone {
|
||||
let fixture: ComponentFixture<PhoneListComponent>;
|
||||
|
||||
describe('PhoneList', () => {
|
||||
|
||||
// #docregion routestuff
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ PhoneListComponent ],
|
||||
providers: [
|
||||
{ provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) },
|
||||
{ provide: Location, useClass: SpyLocation },
|
||||
{ provide: Phone, useClass: MockPhone },
|
||||
],
|
||||
schemas: [ NO_ERRORS_SCHEMA ]
|
||||
})
|
||||
.compileComponents();
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed
|
||||
.configureTestingModule({
|
||||
declarations: [PhoneListComponent],
|
||||
providers: [
|
||||
{provide: ActivatedRoute, useValue: new ActivatedRouteMock({params: {'phoneId': 1}})},
|
||||
{provide: Location, useClass: SpyLocation},
|
||||
{provide: Phone, useClass: MockPhone},
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
@ -52,20 +52,15 @@ describe('PhoneList', () => {
|
||||
fixture.detectChanges();
|
||||
let compiled = fixture.debugElement.nativeElement;
|
||||
expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
|
||||
expect(
|
||||
compiled.querySelector('.phone-list-item:nth-child(1)').textContent
|
||||
).toContain('Motorola DROID');
|
||||
expect(
|
||||
compiled.querySelector('.phone-list-item:nth-child(2)').textContent
|
||||
).toContain('Nexus S');
|
||||
expect(compiled.querySelector('.phone-list-item:nth-child(1)').textContent)
|
||||
.toContain('Motorola DROID');
|
||||
expect(compiled.querySelector('.phone-list-item:nth-child(2)').textContent)
|
||||
.toContain('Nexus S');
|
||||
});
|
||||
|
||||
xit('should set the default value of orderProp model', () => {
|
||||
fixture.detectChanges();
|
||||
let compiled = fixture.debugElement.nativeElement;
|
||||
expect(
|
||||
compiled.querySelector('select option:last-child').selected
|
||||
).toBe(true);
|
||||
expect(compiled.querySelector('select option:last-child').selected).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -58,6 +58,7 @@ v9 - v12
|
||||
| `@angular/core` | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | <!--v9--> v11 |
|
||||
| `@angular/router` | [`loadChildren` string syntax](#loadChildren) | <!--v9--> v11 |
|
||||
| `@angular/core/testing` | [`TestBed.get`](#testing) | <!--v9--> v12 |
|
||||
| `@angular/core/testing` | [`async`](#testing) | <!--v9--> v12 |
|
||||
| `@angular/router` | [`ActivatedRoute` params and `queryParams` properties](#activatedroute-props) | unspecified |
|
||||
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> unspecified |
|
||||
| browser support | [`IE 9 and 10, IE mobile`](#ie-9-10-and-mobile) | <!--v10--> v11 |
|
||||
@ -108,6 +109,7 @@ Tip: In the [API reference section](api) of this doc site, deprecated APIs are i
|
||||
| API | Replacement | Deprecation announced | Notes |
|
||||
| --- | ----------- | --------------------- | ----- |
|
||||
| [`TestBed.get`](api/core/testing/TestBed#get) | [`TestBed.inject`](api/core/testing/TestBed#inject) | v9 | Same behavior, but type safe. |
|
||||
| [`async`](api/core/testing/async) | [`waitForAsync`](api/core/testing/waitForAsync) | v10 | Same behavior, but rename to avoid confusion. |
|
||||
|
||||
|
||||
{@a forms}
|
||||
@ -477,7 +479,7 @@ The final decision was made on three key points:
|
||||
|
||||
|
||||
{@a wrapped-value}
|
||||
### `WrappedValue`
|
||||
### `WrappedValue`
|
||||
|
||||
The purpose of `WrappedValue` is to allow the same object instance to be treated as different for the purposes of change detection.
|
||||
It is commonly used with the `async` pipe in the case where the `Observable` produces the same instance of the value.
|
||||
@ -487,7 +489,7 @@ No replacement is planned for this deprecation.
|
||||
|
||||
If you rely on the behavior that the same object instance should cause change detection, you have two options:
|
||||
- Clone the resulting value so that it has a new identity.
|
||||
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
||||
- Explicitly call [`ChangeDetectorRef.detectChanges()`](api/core/ChangeDetectorRef#detectchanges) to force the update.
|
||||
|
||||
{@a deprecated-cli-flags}
|
||||
## Deprecated CLI APIs and Options
|
||||
|
@ -159,10 +159,10 @@ It also generates an initial test file for the component, `banner-external.compo
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Because `compileComponents` is asynchronous, it uses
|
||||
the [`async`](api/core/testing/async) utility
|
||||
the [`waitForAsync`](api/core/testing/waitForAsync) utility
|
||||
function imported from `@angular/core/testing`.
|
||||
|
||||
Please refer to the [async](guide/testing-components-scenarios#async) section for more details.
|
||||
Please refer to the [waitForAsync](guide/testing-components-scenarios#waitForAsync) section for more details.
|
||||
|
||||
</div>
|
||||
|
||||
|
@ -402,7 +402,7 @@ There is no nested syntax (like a `Promise.then()`) to disrupt the flow of contr
|
||||
<div class="alert is-helpful">
|
||||
|
||||
Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` (XHR) call.
|
||||
XHR calls within a test are rare, but if you need to call XHR, see [`async()`](#async), below.
|
||||
XHR calls within a test are rare, but if you need to call XHR, see [`waitForAsync()`](#waitForAsync), below.
|
||||
|
||||
</div>
|
||||
|
||||
@ -587,41 +587,41 @@ Then call `detectChanges()` to tell Angular to update the screen.
|
||||
|
||||
Then you can assert that the quote element displays the expected text.
|
||||
|
||||
{@a async}
|
||||
{@a waitForAsync}
|
||||
|
||||
#### Async test with _async()_
|
||||
#### Async test with _waitForAsync()_
|
||||
|
||||
To use `async()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
|
||||
To use `waitForAsync()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
|
||||
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
|
||||
|
||||
The `fakeAsync()` utility function has a few limitations.
|
||||
In particular, it won't work if the test body makes an `XMLHttpRequest` (XHR) call.
|
||||
XHR calls within a test are rare so you can generally stick with [`fakeAsync()`](#fake-async).
|
||||
But if you ever do need to call `XMLHttpRequest`, you'll want to know about `async()`.
|
||||
But if you ever do need to call `XMLHttpRequest`, you'll want to know about `waitForAsync()`.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR`
|
||||
to read external template and css files during "just-in-time" compilation.
|
||||
Write tests that call `compileComponents()` with the `async()` utility.
|
||||
Write tests that call `compileComponents()` with the `waitForAsync()` utility.
|
||||
|
||||
</div>
|
||||
|
||||
Here's the previous `fakeAsync()` test, re-written with the `async()` utility.
|
||||
Here's the previous `fakeAsync()` test, re-written with the `waitForAsync()` utility.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/twain/twain.component.spec.ts"
|
||||
region="async-test">
|
||||
</code-example>
|
||||
|
||||
The `async()` utility hides some asynchronous boilerplate by arranging for the tester's code
|
||||
The `waitForAsync()` utility hides some asynchronous boilerplate by arranging for the tester's code
|
||||
to run in a special _async test zone_.
|
||||
You don't need to pass Jasmine's `done()` into the test and call `done()` because it is `undefined` in promise or observable callbacks.
|
||||
|
||||
But the test's asynchronous nature is revealed by the call to `fixture.whenStable()`,
|
||||
which breaks the linear flow of control.
|
||||
|
||||
When using an `intervalTimer()` such as `setInterval()` in `async()`, remember to cancel the timer with `clearInterval()` after the test, otherwise the `async()` never ends.
|
||||
When using an `intervalTimer()` such as `setInterval()` in `waitForAsync()`, remember to cancel the timer with `clearInterval()` after the test, otherwise the `waitForAsync()` never ends.
|
||||
|
||||
{@a when-stable}
|
||||
|
||||
@ -641,18 +641,18 @@ update the quote element with the expected text.
|
||||
|
||||
#### Jasmine _done()_
|
||||
|
||||
While the `async()` and `fakeAsync()` functions greatly
|
||||
While the `waitForAsync()` and `fakeAsync()` functions greatly
|
||||
simplify Angular asynchronous testing,
|
||||
you can still fall back to the traditional technique
|
||||
and pass `it` a function that takes a
|
||||
[`done` callback](https://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support).
|
||||
|
||||
You can't call `done()` in `async()` or `fakeAsync()` functions, because the `done parameter`
|
||||
You can't call `done()` in `waitForAsync()` or `fakeAsync()` functions, because the `done parameter`
|
||||
is `undefined`.
|
||||
|
||||
Now you are responsible for chaining promises, handling errors, and calling `done()` at the appropriate moments.
|
||||
|
||||
Writing test functions with `done()`, is more cumbersome than `async()`and `fakeAsync()`, but it is occasionally necessary when code involves the `intervalTimer()` like `setInterval`.
|
||||
Writing test functions with `done()`, is more cumbersome than `waitForAsync()`and `fakeAsync()`, but it is occasionally necessary when code involves the `intervalTimer()` like `setInterval`.
|
||||
|
||||
Here are two more versions of the previous test, written with `done()`.
|
||||
The first one subscribes to the `Observable` exposed to the template by the component's `quote` property.
|
||||
@ -738,7 +738,7 @@ you tell the `TestScheduler` to _flush_ its queue of prepared tasks like this.
|
||||
region="test-scheduler-flush"></code-example>
|
||||
|
||||
This step serves a purpose analogous to [tick()](api/core/testing/tick) and `whenStable()` in the
|
||||
earlier `fakeAsync()` and `async()` examples.
|
||||
earlier `fakeAsync()` and `waitForAsync()` examples.
|
||||
The balance of the test is the same as those examples.
|
||||
|
||||
#### Marble error testing
|
||||
@ -1535,7 +1535,7 @@ You must call `compileComponents()` within an asynchronous test function.
|
||||
<div class="alert is-critical">
|
||||
|
||||
If you neglect to make the test function async
|
||||
(e.g., forget to use `async()` as described below),
|
||||
(e.g., forget to use `waitForAsync()` as described below),
|
||||
you'll see this error message
|
||||
|
||||
<code-example language="sh" class="code-shell" hideCopy>
|
||||
@ -1549,7 +1549,7 @@ A typical approach is to divide the setup logic into two separate `beforeEach()`
|
||||
1. An async `beforeEach()` that compiles the components
|
||||
1. A synchronous `beforeEach()` that performs the remaining setup.
|
||||
|
||||
To follow this pattern, import the `async()` helper with the other testing symbols.
|
||||
To follow this pattern, import the `waitForAsync()` helper with the other testing symbols.
|
||||
|
||||
<code-example
|
||||
path="testing/src/app/banner/banner-external.component.spec.ts"
|
||||
@ -1565,7 +1565,7 @@ Write the first async `beforeEach` like this.
|
||||
region="async-before-each"
|
||||
header="app/banner/banner-external.component.spec.ts (async beforeEach)"></code-example>
|
||||
|
||||
The `async()` helper function takes a parameterless function with the body of the setup.
|
||||
The `waitForAsync()` helper function takes a parameterless function with the body of the setup.
|
||||
|
||||
The `TestBed.configureTestingModule()` method returns the `TestBed` class so you can chain
|
||||
calls to other `TestBed` static methods such as `compileComponents()`.
|
||||
|
@ -25,7 +25,7 @@ Here's a summary of the stand-alone functions, in order of likely utility:
|
||||
<td>
|
||||
|
||||
Runs the body of a test (`it`) or setup (`beforeEach`) function within a special _async test zone_.
|
||||
See [discussion above](guide/testing-components-scenarios#async).
|
||||
See [discussion above](guide/testing-components-scenarios#waitForAsync).
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -306,9 +306,9 @@ If you develop angular locally with `ng serve`, a `websocket` connection is set
|
||||
In Windows, by default, one application can only have 6 websocket connections, <a href="https://msdn.microsoft.com/library/ee330736%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396#websocket_maxconn" title="MSDN WebSocket settings">MSDN WebSocket Settings</a>.
|
||||
So when IE is refreshed (manually or automatically by `ng serve`), sometimes the websocket does not close properly. When websocket connections exceed the limitations, a `SecurityError` will be thrown. This error will not affect the angular application, you can just restart IE to clear this error, or modify the windows registry to update the limitations.
|
||||
|
||||
## Appendix: Test using `fakeAsync()/async()`
|
||||
## Appendix: Test using `fakeAsync()/waitForAsync()`
|
||||
|
||||
If you use the `fakeAsync()/async()` helper function to run unit tests (for details, read the [Testing guide](guide/testing-components-scenarios#fake-async)), you need to import `zone.js/dist/zone-testing` in your test setup file.
|
||||
If you use the `fakeAsync()/waitForAsync()` helper function to run unit tests (for details, read the [Testing guide](guide/testing-components-scenarios#fake-async)), you need to import `zone.js/dist/zone-testing` in your test setup file.
|
||||
|
||||
<div class="alert is-important">
|
||||
If you create project with `Angular/CLI`, it is already imported in `src/test.ts`.
|
||||
|
Reference in New Issue
Block a user