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:
JiaLiPassion 2020-08-01 04:43:18 +09:00 committed by Alex Rickabaugh
parent 8f074296c2
commit 8fbf40bf40
78 changed files with 1363 additions and 1368 deletions

View File

@ -1,31 +1,31 @@
import { TestBed, async } from '@angular/core/testing'; import { TestBed, waitForAsync } from '@angular/core/testing';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { TemplateModule } from './template/template.module';
import { ReactiveModule } from './reactive/reactive.module'; import { ReactiveModule } from './reactive/reactive.module';
import { TemplateModule } from './template/template.module';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(waitForAsync(() => {
beforeEach(async(() => { TestBed
TestBed.configureTestingModule({ .configureTestingModule({
imports: [ReactiveModule, TemplateModule], imports: [ReactiveModule, TemplateModule],
declarations: [ declarations: [AppComponent],
AppComponent })
], .compileComponents();
}).compileComponents();
})); }));
it('should create the app', async(() => { it('should create the app', waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance; const app = fixture.componentInstance;
expect(app).toBeTruthy(); expect(app).toBeTruthy();
})); }));
it('should render title', async(() => { it('should render title', waitForAsync(() => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Forms Overview'); expect(compiled.querySelector('h1').textContent).toContain('Forms Overview');
})); }));
}); });

View File

@ -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 { ReactiveFormsModule } from '@angular/forms';
import { FavoriteColorComponent } from './favorite-color.component';
import { createNewEvent } from '../../shared/utils'; import { createNewEvent } from '../../shared/utils';
import { FavoriteColorComponent } from './favorite-color.component';
describe('Favorite Color Component', () => { describe('Favorite Color Component', () => {
let component: FavoriteColorComponent; let component: FavoriteColorComponent;
let fixture: ComponentFixture<FavoriteColorComponent>; let fixture: ComponentFixture<FavoriteColorComponent>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
imports: [ ReactiveFormsModule ], .configureTestingModule(
declarations: [ FavoriteColorComponent ] {imports: [ReactiveFormsModule], declarations: [FavoriteColorComponent]})
}) .compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -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 { FormsModule } from '@angular/forms';
import { FavoriteColorComponent } from './favorite-color.component';
import { createNewEvent } from '../../shared/utils'; import { createNewEvent } from '../../shared/utils';
import { FavoriteColorComponent } from './favorite-color.component';
describe('FavoriteColorComponent', () => { describe('FavoriteColorComponent', () => {
let component: FavoriteColorComponent; let component: FavoriteColorComponent;
let fixture: ComponentFixture<FavoriteColorComponent>; let fixture: ComponentFixture<FavoriteColorComponent>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({imports: [FormsModule], declarations: [FavoriteColorComponent]})
imports: [ FormsModule ], .compileComponents();
declarations: [ FavoriteColorComponent ]
})
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -28,29 +25,29 @@ describe('FavoriteColorComponent', () => {
// #docregion model-to-view // #docregion model-to-view
it('should update the favorite color on the input field', fakeAsync(() => { 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 // #enddocregion model-to-view
// #docregion view-to-model // #docregion view-to-model
it('should update the favorite color in the component', fakeAsync(() => { it('should update the favorite color in the component', fakeAsync(() => {
const input = fixture.nativeElement.querySelector('input'); const input = fixture.nativeElement.querySelector('input');
const event = createNewEvent('input'); const event = createNewEvent('input');
input.value = 'Red'; input.value = 'Red';
input.dispatchEvent(event); input.dispatchEvent(event);
fixture.detectChanges(); fixture.detectChanges();
expect(component.favoriteColor).toEqual('Red'); expect(component.favoriteColor).toEqual('Red');
})); }));
// #enddocregion view-to-model // #enddocregion view-to-model
}); });

View File

@ -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'; import { MyLibComponent } from './my-lib.component';
@ -6,11 +6,8 @@ describe('MyLibComponent', () => {
let component: MyLibComponent; let component: MyLibComponent;
let fixture: ComponentFixture<MyLibComponent>; let fixture: ComponentFixture<MyLibComponent>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({declarations: [MyLibComponent]}).compileComponents();
declarations: [ MyLibComponent ]
})
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {

View File

@ -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 { 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', () => { describe('AppComponent', () => {
let de: DebugElement; let de: DebugElement;
let comp: AppComponent; let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({declarations: [AppComponent]}).compileComponents();
declarations: [ AppComponent ]
})
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -22,12 +19,11 @@ describe('AppComponent', () => {
de = fixture.debugElement.query(By.css('h1')); 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', () => { it('should have expected <h1> text', () => {
fixture.detectChanges(); fixture.detectChanges();
const h1 = de.nativeElement; const h1 = de.nativeElement;
expect(h1.textContent).toMatch(/angular/i, expect(h1.textContent).toMatch(/angular/i, '<h1> should say something about "Angular"');
'<h1> should say something about "Angular"');
}); });
}); });

View File

@ -1,6 +1,6 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { TestBed, async } from '@angular/core/testing'; import { TestBed, waitForAsync } from '@angular/core/testing';
// #enddocregion // #enddocregion
import { AppComponent } from './app-initial.component'; import { AppComponent } from './app-initial.component';
/* /*
@ -12,29 +12,29 @@ describe('AppComponent', () => {
*/ */
describe('AppComponent (initial CLI version)', () => { describe('AppComponent (initial CLI version)', () => {
// #docregion // #docregion
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent declarations: [AppComponent],
], })
}).compileComponents(); .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!');
})); }));
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 // #enddocregion
@ -43,16 +43,13 @@ import { DebugElement } from '@angular/core';
import { ComponentFixture } from '@angular/core/testing'; import { ComponentFixture } from '@angular/core/testing';
describe('AppComponent (initial CLI version - as it should be)', () => { describe('AppComponent (initial CLI version - as it should be)', () => {
let app: AppComponent; let app: AppComponent;
let de: DebugElement; let de: DebugElement;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ declarations: [AppComponent],
AppComponent
],
}); });
fixture = TestBed.createComponent(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', () => { it('should render title in an h1 tag', () => {
fixture.detectChanges(); fixture.detectChanges();
expect(de.nativeElement.querySelector('h1').textContent) expect(de.nativeElement.querySelector('h1').textContent).toContain('Welcome to app!');
.toContain('Welcome to app!');
}); });
}); });

View File

@ -1,7 +1,7 @@
// For more examples: // For more examples:
// https://github.com/angular/angular/blob/master/modules/@angular/router/test/integration.spec.ts // 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'; import { asyncData } from '../testing';
@ -21,9 +21,9 @@ import { AppModule } from './app.module';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { AboutComponent } from './about/about.component'; import { AboutComponent } from './about/about.component';
import { DashboardComponent } from './dashboard/dashboard.component'; import { DashboardComponent } from './dashboard/dashboard.component';
import { TwainService } from './twain/twain.service';
import { HeroService, TestHeroService } from './model/testing/test-hero.service'; import { HeroService, TestHeroService } from './model/testing/test-hero.service';
import { TwainService } from './twain/twain.service';
let comp: AppComponent; let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
@ -32,54 +32,51 @@ let router: Router;
let location: SpyLocation; let location: SpyLocation;
describe('AppComponent & RouterTestingModule', () => { describe('AppComponent & RouterTestingModule', () => {
beforeEach(waitForAsync(() => {
beforeEach(async(() => { TestBed
TestBed.configureTestingModule({ .configureTestingModule({
imports: [ imports: [
AppModule, AppModule,
RouterTestingModule.withRoutes(routes), RouterTestingModule.withRoutes(routes),
], ],
providers: [ providers: [{provide: HeroService, useClass: TestHeroService}]
{ provide: HeroService, useClass: TestHeroService } })
] .compileComponents();
})
.compileComponents();
})); }));
it('should navigate to "Dashboard" immediately', fakeAsync(() => { it('should navigate to "Dashboard" immediately', fakeAsync(() => {
createComponent(); createComponent();
tick(); // wait for async data to arrive tick(); // wait for async data to arrive
expectPathToBe('/dashboard', 'after initialNavigation()'); expectPathToBe('/dashboard', 'after initialNavigation()');
expectElementOf(DashboardComponent); expectElementOf(DashboardComponent);
})); }));
it('should navigate to "About" on click', fakeAsync(() => { it('should navigate to "About" on click', fakeAsync(() => {
createComponent(); createComponent();
click(page.aboutLinkDe); click(page.aboutLinkDe);
// page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom // page.aboutLinkDe.nativeElement.click(); // ok but fails in phantom
advance(); advance();
expectPathToBe('/about'); expectPathToBe('/about');
expectElementOf(AboutComponent); expectElementOf(AboutComponent);
})); }));
it('should navigate to "About" w/ browser location URL change', fakeAsync(() => { it('should navigate to "About" w/ browser location URL change', fakeAsync(() => {
createComponent(); createComponent();
location.simulateHashChange('/about'); location.simulateHashChange('/about');
// location.go('/about'); // also works ... except, perhaps, in Stackblitz // location.go('/about'); // also works ... except, perhaps, in Stackblitz
advance(); advance();
expectPathToBe('/about'); expectPathToBe('/about');
expectElementOf(AboutComponent); expectElementOf(AboutComponent);
})); }));
// Can't navigate to lazy loaded modules with this technique // Can't navigate to lazy loaded modules with this technique
xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => { xit('should navigate to "Heroes" on click (not working yet)', fakeAsync(() => {
createComponent(); createComponent();
page.heroesLinkDe.nativeElement.click(); page.heroesLinkDe.nativeElement.click();
advance(); advance();
expectPathToBe('/heroes'); expectPathToBe('/heroes');
})); }));
}); });
@ -94,37 +91,37 @@ let loader: SpyNgModuleFactoryLoader;
///////// Can't get lazy loaded Heroes to work yet ///////// Can't get lazy loaded Heroes to work yet
xdescribe('AppComponent & Lazy Loading (not working yet)', () => { xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
beforeEach(waitForAsync(() => {
beforeEach(async(() => { TestBed
TestBed.configureTestingModule({ .configureTestingModule({
imports: [ imports: [
AppModule, AppModule,
RouterTestingModule.withRoutes(routes), RouterTestingModule.withRoutes(routes),
], ],
}) })
.compileComponents(); .compileComponents();
})); }));
beforeEach(fakeAsync(() => { beforeEach(fakeAsync(() => {
createComponent(); createComponent();
loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader; loader = TestBed.inject(NgModuleFactoryLoader) as SpyNgModuleFactoryLoader;
loader.stubbedModules = { expected: HeroModule }; loader.stubbedModules = {expected: HeroModule};
router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]); router.resetConfig([{path: 'heroes', loadChildren: 'expected'}]);
})); }));
it('should navigate to "Heroes" on click', async(() => { it('should navigate to "Heroes" on click', waitForAsync(() => {
page.heroesLinkDe.nativeElement.click(); page.heroesLinkDe.nativeElement.click();
advance(); advance();
expectPathToBe('/heroes'); expectPathToBe('/heroes');
expectElementOf(HeroListComponent); expectElementOf(HeroListComponent);
})); }));
it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => { it('can navigate to "Heroes" w/ browser location URL change', fakeAsync(() => {
location.go('/heroes'); location.go('/heroes');
advance(); advance();
expectPathToBe('/heroes'); expectPathToBe('/heroes');
expectElementOf(HeroListComponent); expectElementOf(HeroListComponent);
})); }));
}); });
////// Helpers ///////// ////// Helpers /////////
@ -134,9 +131,9 @@ xdescribe('AppComponent & Lazy Loading (not working yet)', () => {
* Wait a tick, then detect changes, and tick again * Wait a tick, then detect changes, and tick again
*/ */
function advance(): void { function advance(): void {
tick(); // wait while navigating tick(); // wait while navigating
fixture.detectChanges(); // update view fixture.detectChanges(); // update view
tick(); // wait for async data to arrive tick(); // wait for async data to arrive
} }
function createComponent() { function createComponent() {
@ -148,8 +145,8 @@ function createComponent() {
router = injector.get(Router); router = injector.get(Router);
router.initialNavigation(); router.initialNavigation();
spyOn(injector.get(TwainService), 'getQuote') spyOn(injector.get(TwainService), 'getQuote')
// fake fast async observable // fake fast async observable
.and.returnValue(asyncData('Test Quote')); .and.returnValue(asyncData('Test Quote'));
advance(); advance();
page = new Page(); page = new Page();
@ -168,14 +165,14 @@ class Page {
constructor() { constructor() {
const links = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref)); const links = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref));
this.aboutLinkDe = links[2]; this.aboutLinkDe = links[2];
this.dashboardLinkDe = links[0]; this.dashboardLinkDe = links[0];
this.heroesLinkDe = links[1]; this.heroesLinkDe = links[1];
// for debugging // for debugging
this.comp = comp; this.comp = comp;
this.fixture = fixture; this.fixture = fixture;
this.router = router; this.router = router;
} }
} }

View File

@ -1,66 +1,70 @@
// #docplaster // #docplaster
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core'; import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { RouterLinkDirectiveStub } from '../testing'; import { RouterLinkDirectiveStub } from '../testing';
import { AppComponent } from './app.component';
// #docregion component-stubs // #docregion component-stubs
@Component({selector: 'app-banner', template: ''}) @Component({selector: 'app-banner', template: ''})
class BannerStubComponent {} class BannerStubComponent {
}
@Component({selector: 'router-outlet', template: ''}) @Component({selector: 'router-outlet', template: ''})
class RouterOutletStubComponent { } class RouterOutletStubComponent {
}
@Component({selector: 'app-welcome', template: ''}) @Component({selector: 'app-welcome', template: ''})
class WelcomeStubComponent {} class WelcomeStubComponent {
}
// #enddocregion component-stubs // #enddocregion component-stubs
let comp: AppComponent; let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
describe('AppComponent & TestModule', () => { describe('AppComponent & TestModule', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
// #docregion testbed-stubs // #docregion testbed-stubs
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent, declarations: [
RouterLinkDirectiveStub, AppComponent, RouterLinkDirectiveStub, BannerStubComponent, RouterOutletStubComponent,
BannerStubComponent, WelcomeStubComponent
RouterOutletStubComponent, ]
WelcomeStubComponent })
] // #enddocregion testbed-stubs
}) .compileComponents()
// #enddocregion testbed-stubs .then(() => {
.compileComponents().then(() => { fixture = TestBed.createComponent(AppComponent);
fixture = TestBed.createComponent(AppComponent); comp = fixture.componentInstance;
comp = fixture.componentInstance; });
});
})); }));
tests(); tests();
}); });
//////// Testing w/ NO_ERRORS_SCHEMA ////// //////// Testing w/ NO_ERRORS_SCHEMA //////
describe('AppComponent & NO_ERRORS_SCHEMA', () => { describe('AppComponent & NO_ERRORS_SCHEMA', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
// #docregion no-errors-schema, mixed-setup // #docregion no-errors-schema, mixed-setup
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent, declarations: [
// #enddocregion no-errors-schema AppComponent,
BannerStubComponent, // #enddocregion no-errors-schema
// #docregion no-errors-schema BannerStubComponent,
RouterLinkDirectiveStub // #docregion no-errors-schema
], RouterLinkDirectiveStub
schemas: [ NO_ERRORS_SCHEMA ] ],
}) schemas: [NO_ERRORS_SCHEMA]
// #enddocregion no-errors-schema, mixed-setup })
.compileComponents().then(() => { // #enddocregion no-errors-schema, mixed-setup
fixture = TestBed.createComponent(AppComponent); .compileComponents()
comp = fixture.componentInstance; .then(() => {
}); fixture = TestBed.createComponent(AppComponent);
comp = fixture.componentInstance;
});
})); }));
tests(); tests();
}); });
@ -72,30 +76,23 @@ import { AppModule } from './app.module';
import { AppRoutingModule } from './app-routing.module'; import { AppRoutingModule } from './app-routing.module';
describe('AppComponent & AppModule', () => { 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({ .compileComponents()
imports: [ AppModule ]
})
// Get rid of app's Router configuration otherwise many failures. .then(() => {
// Doing so removes Router declarations; add the Router stubs fixture = TestBed.createComponent(AppComponent);
.overrideModule(AppModule, { comp = fixture.componentInstance;
remove: { });
imports: [ AppRoutingModule ]
},
add: {
declarations: [ RouterLinkDirectiveStub, RouterOutletStubComponent ]
}
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(AppComponent);
comp = fixture.componentInstance;
});
})); }));
tests(); tests();
@ -107,11 +104,10 @@ function tests() {
// #docregion test-setup // #docregion test-setup
beforeEach(() => { beforeEach(() => {
fixture.detectChanges(); // trigger initial data binding fixture.detectChanges(); // trigger initial data binding
// find DebugElements with an attached RouterLinkStubDirective // find DebugElements with an attached RouterLinkStubDirective
linkDes = fixture.debugElement linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));
.queryAll(By.directive(RouterLinkDirectiveStub));
// get attached link directive instances // get attached link directive instances
// using each DebugElement's injector // using each DebugElement's injector
@ -132,8 +128,8 @@ function tests() {
}); });
it('can click Heroes link in template', () => { it('can click Heroes link in template', () => {
const heroesLinkDe = linkDes[1]; // heroes link DebugElement const heroesLinkDe = linkDes[1]; // heroes link DebugElement
const heroesLink = routerLinks[1]; // heroes link directive const heroesLink = routerLinks[1]; // heroes link directive
expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet'); expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet');

View File

@ -1,6 +1,6 @@
// #docplaster // #docplaster
// #docregion import-async // #docregion import-async
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
// #enddocregion import-async // #enddocregion import-async
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
@ -14,11 +14,12 @@ describe('BannerComponent (external files)', () => {
describe('Two beforeEach', () => { describe('Two beforeEach', () => {
// #docregion async-before-each // #docregion async-before-each
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ BannerComponent ], .configureTestingModule({
}) declarations: [BannerComponent],
.compileComponents(); // compile template and css })
.compileComponents(); // compile template and css
})); }));
// #enddocregion async-before-each // #enddocregion async-before-each
@ -26,7 +27,7 @@ describe('BannerComponent (external files)', () => {
// #docregion sync-before-each // #docregion sync-before-each
beforeEach(() => { beforeEach(() => {
fixture = TestBed.createComponent(BannerComponent); fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance; // BannerComponent test instance component = fixture.componentInstance; // BannerComponent test instance
h1 = fixture.nativeElement.querySelector('h1'); h1 = fixture.nativeElement.querySelector('h1');
}); });
// #enddocregion sync-before-each // #enddocregion sync-before-each
@ -36,16 +37,17 @@ describe('BannerComponent (external files)', () => {
describe('One beforeEach', () => { describe('One beforeEach', () => {
// #docregion one-before-each // #docregion one-before-each
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ BannerComponent ], .configureTestingModule({
}) declarations: [BannerComponent],
.compileComponents() })
.then(() => { .compileComponents()
fixture = TestBed.createComponent(BannerComponent); .then(() => {
component = fixture.componentInstance; fixture = TestBed.createComponent(BannerComponent);
h1 = fixture.nativeElement.querySelector('h1'); component = fixture.componentInstance;
}); h1 = fixture.nativeElement.querySelector('h1');
});
})); }));
// #enddocregion one-before-each // #enddocregion one-before-each
@ -69,4 +71,3 @@ describe('BannerComponent (external files)', () => {
}); });
} }
}); });

View File

@ -1,14 +1,16 @@
// #docplaster // #docplaster
// #docregion import-by // #docregion import-by
import { By } from '@angular/platform-browser';
// #enddocregion import-by // #enddocregion import-by
// #docregion import-debug-element // #docregion import-debug-element
import { DebugElement } from '@angular/core'; import { DebugElement } from '@angular/core';
// #enddocregion import-debug-element // #enddocregion import-debug-element
// #docregion v1 // #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 // #enddocregion v1
import { BannerComponent } from './banner-initial.component'; import { BannerComponent } from './banner-initial.component';
/* /*
// #docregion v1 // #docregion v1
import { BannerComponent } from './banner.component'; import { BannerComponent } from './banner.component';
@ -17,15 +19,12 @@ describe('BannerComponent', () => {
// #enddocregion v1 // #enddocregion v1
*/ */
describe('BannerComponent (initial CLI generated)', () => { describe('BannerComponent (initial CLI generated)', () => {
// #docregion v1 // #docregion v1
let component: BannerComponent; let component: BannerComponent;
let fixture: ComponentFixture<BannerComponent>; let fixture: ComponentFixture<BannerComponent>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({declarations: [BannerComponent]}).compileComponents();
declarations: [ BannerComponent ]
})
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -44,9 +43,7 @@ describe('BannerComponent (initial CLI generated)', () => {
describe('BannerComponent (minimal)', () => { describe('BannerComponent (minimal)', () => {
it('should create', () => { it('should create', () => {
// #docregion configureTestingModule // #docregion configureTestingModule
TestBed.configureTestingModule({ TestBed.configureTestingModule({declarations: [BannerComponent]});
declarations: [ BannerComponent ]
});
// #enddocregion configureTestingModule // #enddocregion configureTestingModule
// #docregion createComponent // #docregion createComponent
const fixture = TestBed.createComponent(BannerComponent); const fixture = TestBed.createComponent(BannerComponent);
@ -65,9 +62,7 @@ describe('BannerComponent (with beforeEach)', () => {
let fixture: ComponentFixture<BannerComponent>; let fixture: ComponentFixture<BannerComponent>;
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({declarations: [BannerComponent]});
declarations: [ BannerComponent ]
});
fixture = TestBed.createComponent(BannerComponent); fixture = TestBed.createComponent(BannerComponent);
component = fixture.componentInstance; component = fixture.componentInstance;
}); });

View File

@ -1,22 +1,21 @@
// #docplaster // #docplaster
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core'; 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 { addMatchers, click } from '../../testing';
import { Hero } from '../model/hero'; import { Hero } from '../model/hero';
import { DashboardHeroComponent } from './dashboard-hero.component'; import { DashboardHeroComponent } from './dashboard-hero.component';
beforeEach( addMatchers ); beforeEach(addMatchers);
describe('DashboardHeroComponent class only', () => { describe('DashboardHeroComponent class only', () => {
// #docregion class-only // #docregion class-only
it('raises the selected event when clicked', () => { it('raises the selected event when clicked', () => {
const comp = new DashboardHeroComponent(); const comp = new DashboardHeroComponent();
const hero: Hero = { id: 42, name: 'Test' }; const hero: Hero = {id: 42, name: 'Test'};
comp.hero = hero; comp.hero = hero;
comp.selected.subscribe((selectedHero: Hero) => expect(selectedHero).toBe(hero)); comp.selected.subscribe((selectedHero: Hero) => expect(selectedHero).toBe(hero));
@ -26,33 +25,31 @@ describe('DashboardHeroComponent class only', () => {
}); });
describe('DashboardHeroComponent when tested directly', () => { describe('DashboardHeroComponent when tested directly', () => {
let comp: DashboardHeroComponent; let comp: DashboardHeroComponent;
let expectedHero: Hero; let expectedHero: Hero;
let fixture: ComponentFixture<DashboardHeroComponent>; let fixture: ComponentFixture<DashboardHeroComponent>;
let heroDe: DebugElement; let heroDe: DebugElement;
let heroEl: HTMLElement; let heroEl: HTMLElement;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
// #docregion setup, config-testbed // #docregion setup, config-testbed
TestBed.configureTestingModule({ TestBed
declarations: [ DashboardHeroComponent ] .configureTestingModule({declarations: [DashboardHeroComponent]})
}) // #enddocregion setup, config-testbed
// #enddocregion setup, config-testbed .compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
// #docregion setup // #docregion setup
fixture = TestBed.createComponent(DashboardHeroComponent); fixture = TestBed.createComponent(DashboardHeroComponent);
comp = fixture.componentInstance; comp = fixture.componentInstance;
// find the hero's DebugElement and element // find the hero's DebugElement and element
heroDe = fixture.debugElement.query(By.css('.hero')); heroDe = fixture.debugElement.query(By.css('.hero'));
heroEl = heroDe.nativeElement; heroEl = heroDe.nativeElement;
// mock the hero supplied by the parent component // 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 // simulate the parent setting the input property with that hero
comp.hero = expectedHero; comp.hero = expectedHero;
@ -96,8 +93,8 @@ describe('DashboardHeroComponent when tested directly', () => {
let selectedHero: Hero; let selectedHero: Hero;
comp.selected.subscribe((hero: Hero) => selectedHero = hero); comp.selected.subscribe((hero: Hero) => selectedHero = hero);
click(heroDe); // click helper with DebugElement click(heroDe); // click helper with DebugElement
click(heroEl); // click helper with native element click(heroEl); // click helper with native element
expect(selectedHero).toBe(expectedHero); expect(selectedHero).toBe(expectedHero);
}); });
@ -111,22 +108,21 @@ describe('DashboardHeroComponent when inside a test host', () => {
let fixture: ComponentFixture<TestHostComponent>; let fixture: ComponentFixture<TestHostComponent>;
let heroEl: HTMLElement; let heroEl: HTMLElement;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
// #docregion test-host-setup // #docregion test-host-setup
TestBed.configureTestingModule({ TestBed
declarations: [ DashboardHeroComponent, TestHostComponent ] .configureTestingModule({declarations: [DashboardHeroComponent, TestHostComponent]})
}) // #enddocregion test-host-setup
// #enddocregion test-host-setup .compileComponents();
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
// #docregion test-host-setup // #docregion test-host-setup
// create TestHostComponent instead of DashboardHeroComponent // create TestHostComponent instead of DashboardHeroComponent
fixture = TestBed.createComponent(TestHostComponent); fixture = TestBed.createComponent(TestHostComponent);
testHost = fixture.componentInstance; testHost = fixture.componentInstance;
heroEl = fixture.nativeElement.querySelector('.hero'); heroEl = fixture.nativeElement.querySelector('.hero');
fixture.detectChanges(); // trigger initial data binding fixture.detectChanges(); // trigger initial data binding
// #enddocregion test-host-setup // #enddocregion test-host-setup
}); });
@ -155,8 +151,10 @@ import { Component } from '@angular/core';
</dashboard-hero>` </dashboard-hero>`
}) })
class TestHostComponent { class TestHostComponent {
hero: Hero = {id: 42, name: 'Test Name' }; hero: Hero = {id: 42, name: 'Test Name'};
selectedHero: Hero; selectedHero: Hero;
onSelected(hero: Hero) { this.selectedHero = hero; } onSelected(hero: Hero) {
this.selectedHero = hero;
}
} }
// #enddocregion test-host // #enddocregion test-host

View File

@ -1,6 +1,5 @@
// #docplaster // #docplaster
import { async, inject, ComponentFixture, TestBed import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
} from '@angular/core/testing';
import { addMatchers, asyncData, click } from '../../testing'; import { addMatchers, asyncData, click } from '../../testing';
import { HeroService } from '../model/hero.service'; import { HeroService } from '../model/hero.service';
@ -12,7 +11,7 @@ import { Router } from '@angular/router';
import { DashboardComponent } from './dashboard.component'; import { DashboardComponent } from './dashboard.component';
import { DashboardModule } from './dashboard.module'; import { DashboardModule } from './dashboard.module';
beforeEach ( addMatchers ); beforeEach(addMatchers);
let comp: DashboardComponent; let comp: DashboardComponent;
let fixture: ComponentFixture<DashboardComponent>; let fixture: ComponentFixture<DashboardComponent>;
@ -21,9 +20,7 @@ let fixture: ComponentFixture<DashboardComponent>;
describe('DashboardComponent (deep)', () => { describe('DashboardComponent (deep)', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({imports: [DashboardModule]});
imports: [ DashboardModule ]
});
}); });
compileAndCreate(); compileAndCreate();
@ -43,10 +40,8 @@ import { NO_ERRORS_SCHEMA } from '@angular/core';
describe('DashboardComponent (shallow)', () => { describe('DashboardComponent (shallow)', () => {
beforeEach(() => { beforeEach(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule(
declarations: [ DashboardComponent ], {declarations: [DashboardComponent], schemas: [NO_ERRORS_SCHEMA]});
schemas: [NO_ERRORS_SCHEMA]
});
}); });
compileAndCreate(); compileAndCreate();
@ -63,25 +58,26 @@ describe('DashboardComponent (shallow)', () => {
/** Add TestBed providers, compile, and create DashboardComponent */ /** Add TestBed providers, compile, and create DashboardComponent */
function compileAndCreate() { function compileAndCreate() {
// #docregion compile-and-create-body // #docregion compile-and-create-body
beforeEach(async(() => { beforeEach(waitForAsync(() => {
// #docregion router-spy // #docregion router-spy
const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']); const routerSpy = jasmine.createSpyObj('Router', ['navigateByUrl']);
const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']); const heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);
TestBed.configureTestingModule({ TestBed
providers: [ .configureTestingModule({
{ provide: HeroService, useValue: heroServiceSpy }, providers: [
{ provide: Router, useValue: routerSpy } {provide: HeroService, useValue: heroServiceSpy}, {provide: Router, useValue: routerSpy}
] ]
}) })
// #enddocregion router-spy // #enddocregion router-spy
.compileComponents().then(() => { .compileComponents()
fixture = TestBed.createComponent(DashboardComponent); .then(() => {
comp = fixture.componentInstance; fixture = TestBed.createComponent(DashboardComponent);
comp = fixture.componentInstance;
// getHeroes spy returns observable of test heroes // getHeroes spy returns observable of test heroes
heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes())); heroServiceSpy.getHeroes.and.returnValue(asyncData(getTestHeroes()));
}); });
// #enddocregion compile-and-create-body // #enddocregion compile-and-create-body
})); }));
} }
@ -93,23 +89,20 @@ function compileAndCreate() {
function tests(heroClick: () => void) { function tests(heroClick: () => void) {
it('should NOT have heroes before ngOnInit', () => { it('should NOT have heroes before ngOnInit', () => {
expect(comp.heroes.length).toBe(0, expect(comp.heroes.length).toBe(0, 'should not have heroes before ngOnInit');
'should not have heroes before ngOnInit');
}); });
it('should NOT have heroes immediately after 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, expect(comp.heroes.length).toBe(0, 'should not have heroes until service promise resolves');
'should not have heroes until service promise resolves');
}); });
describe('after get dashboard heroes', () => { describe('after get dashboard heroes', () => {
let router: Router; let router: Router;
// Trigger component so it gets heroes and binds to them // Trigger component so it gets heroes and binds to them
beforeEach(async(() => { beforeEach(waitForAsync(() => {
router = fixture.debugElement.injector.get(Router); router = fixture.debugElement.injector.get(Router);
fixture.detectChanges(); // runs ngOnInit -> getHeroes fixture.detectChanges(); // runs ngOnInit -> getHeroes
fixture.whenStable() // No need for the `lastPromise` hack! fixture.whenStable() // No need for the `lastPromise` hack!
@ -117,8 +110,8 @@ function tests(heroClick: () => void) {
})); }));
it('should HAVE heroes', () => { it('should HAVE heroes', () => {
expect(comp.heroes.length).toBeGreaterThan(0, expect(comp.heroes.length)
'should have heroes after service promise resolves'); .toBeGreaterThan(0, 'should have heroes after service promise resolves');
}); });
it('should DISPLAY heroes', () => { it('should DISPLAY heroes', () => {
@ -130,8 +123,7 @@ function tests(heroClick: () => void) {
// #docregion navigate-test // #docregion navigate-test
it('should tell ROUTER to navigate when hero clicked', () => { 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 // args passed to router.navigateByUrl() spy
const spy = router.navigateByUrl as jasmine.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 // expecting to navigate to id of the component's first hero
const id = comp.heroes[0].id; const id = comp.heroes[0].id;
expect(navArgs).toBe('/heroes/' + id, expect(navArgs).toBe('/heroes/' + id, 'should nav to HeroDetail for first hero');
'should nav to HeroDetail for first hero');
}); });
// #enddocregion navigate-test // #enddocregion navigate-test
}); });
} }

View File

@ -1,18 +1,23 @@
// tslint:disable-next-line:no-unused-variable // 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 { interval, of } from 'rxjs';
import { delay, take } from 'rxjs/operators'; import { delay, take } from 'rxjs/operators';
describe('Angular async helper', () => { describe('Angular async helper', () => {
describe('async', () => { describe('async', () => {
let actuallyDone = false; 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) => { it('should run normal async test', (done: DoneFn) => {
setTimeout(() => { setTimeout(() => {
@ -21,39 +26,50 @@ describe('Angular async helper', () => {
}, 0); }, 0);
}); });
it('should run async test with task', it('should run async test with task', waitForAsync(() => {
async(() => { setTimeout(() => { actuallyDone = true; }, 0); })); setTimeout(() => {
actuallyDone = true;
}, 0);
}));
it('should run async test with task', async(() => { it('should run async test with task', waitForAsync(() => {
const id = setInterval(() => { const id = setInterval(() => {
actuallyDone = true; actuallyDone = true;
clearInterval(id); clearInterval(id);
}, 100); }, 100);
})); }));
it('should run async test with successful promise', async(() => { it('should run async test with successful promise', waitForAsync(() => {
const p = new Promise(resolve => { setTimeout(resolve, 10); }); const p = new Promise(resolve => {
p.then(() => { actuallyDone = true; }); setTimeout(resolve, 10);
});
p.then(() => {
actuallyDone = true;
});
})); }));
it('should run async test with failed promise', async(() => { it('should run async test with failed promise', waitForAsync(() => {
const p = new Promise((resolve, reject) => { setTimeout(reject, 10); }); const p = new Promise((resolve, reject) => {
p.catch(() => { actuallyDone = true; }); setTimeout(reject, 10);
});
p.catch(() => {
actuallyDone = true;
});
})); }));
// Use done. Can also use async or fakeAsync. // Use done. Can also use async or fakeAsync.
it('should run async test with successful delayed Observable', (done: DoneFn) => { 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); source.subscribe(val => actuallyDone = true, err => fail(err), done);
}); });
it('should run async test with successful delayed Observable', async(() => { it('should run async test with successful delayed Observable', waitForAsync(() => {
const source = of (true).pipe(delay(10)); const source = of(true).pipe(delay(10));
source.subscribe(val => actuallyDone = true, err => fail(err)); source.subscribe(val => actuallyDone = true, err => fail(err));
})); }));
it('should run async test with successful delayed Observable', fakeAsync(() => { 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)); source.subscribe(val => actuallyDone = true, err => fail(err));
tick(10); tick(10);
@ -64,7 +80,9 @@ describe('Angular async helper', () => {
// #docregion fake-async-test-tick // #docregion fake-async-test-tick
it('should run timeout callback with delay after call tick with millis', fakeAsync(() => { it('should run timeout callback with delay after call tick with millis', fakeAsync(() => {
let called = false; let called = false;
setTimeout(() => { called = true; }, 100); setTimeout(() => {
called = true;
}, 100);
tick(100); tick(100);
expect(called).toBe(true); expect(called).toBe(true);
})); }));
@ -73,7 +91,9 @@ describe('Angular async helper', () => {
// #docregion fake-async-test-tick-new-macro-task-sync // #docregion fake-async-test-tick-new-macro-task-sync
it('should run new macro task callback with delay after call tick with millis', it('should run new macro task callback with delay after call tick with millis',
fakeAsync(() => { fakeAsync(() => {
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); } function nestedTimer(cb: () => any): void {
setTimeout(() => setTimeout(() => cb()));
}
const callback = jasmine.createSpy('callback'); const callback = jasmine.createSpy('callback');
nestedTimer(callback); nestedTimer(callback);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
@ -86,7 +106,9 @@ describe('Angular async helper', () => {
// #docregion fake-async-test-tick-new-macro-task-async // #docregion fake-async-test-tick-new-macro-task-async
it('should not run new macro task callback with delay after call tick with millis', it('should not run new macro task callback with delay after call tick with millis',
fakeAsync(() => { fakeAsync(() => {
function nestedTimer(cb: () => any): void { setTimeout(() => setTimeout(() => cb())); } function nestedTimer(cb: () => any): void {
setTimeout(() => setTimeout(() => cb()));
}
const callback = jasmine.createSpy('callback'); const callback = jasmine.createSpy('callback');
nestedTimer(callback); nestedTimer(callback);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
@ -112,7 +134,9 @@ describe('Angular async helper', () => {
// need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async' // need to add `import 'zone.js/dist/zone-patch-rxjs-fake-async'
// to patch rxjs scheduler // to patch rxjs scheduler
let result = null; let result = null;
of ('hello').pipe(delay(1000)).subscribe(v => { result = v; }); of('hello').pipe(delay(1000)).subscribe(v => {
result = v;
});
expect(result).toBeNull(); expect(result).toBeNull();
tick(1000); tick(1000);
expect(result).toBe('hello'); expect(result).toBe('hello');
@ -133,12 +157,18 @@ describe('Angular async helper', () => {
describe('use jasmine.clock()', () => { describe('use jasmine.clock()', () => {
// need to config __zone_symbol__fakeAsyncPatchLock flag // need to config __zone_symbol__fakeAsyncPatchLock flag
// before loading zone.js/dist/zone-testing // before loading zone.js/dist/zone-testing
beforeEach(() => { jasmine.clock().install(); }); beforeEach(() => {
afterEach(() => { jasmine.clock().uninstall(); }); jasmine.clock().install();
});
afterEach(() => {
jasmine.clock().uninstall();
});
it('should auto enter fakeAsync', () => { it('should auto enter fakeAsync', () => {
// is in fakeAsync now, don't need to call fakeAsync(testFn) // is in fakeAsync now, don't need to call fakeAsync(testFn)
let called = false; let called = false;
setTimeout(() => { called = true; }, 100); setTimeout(() => {
called = true;
}, 100);
jasmine.clock().tick(100); jasmine.clock().tick(100);
expect(called).toBe(true); expect(called).toBe(true);
}); });
@ -152,7 +182,7 @@ describe('Angular async helper', () => {
} }
// need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag // need to config __zone_symbol__supportWaitUnResolvedChainedPromise flag
// before loading zone.js/dist/zone-testing // 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; let finished = false;
new Promise((res, rej) => { new Promise((res, rej) => {
jsonp('localhost:8080/jsonp', () => { jsonp('localhost:8080/jsonp', () => {
@ -168,5 +198,4 @@ describe('Angular async helper', () => {
})); }));
}); });
// #enddocregion async-test-promise-then // #enddocregion async-test-promise-then
}); });

View File

@ -24,17 +24,18 @@ import { FormsModule } from '@angular/forms';
// Forms symbols imported only for a specific test below // Forms symbols imported only for a specific test below
import { NgModel, NgControl } from '@angular/forms'; import { NgModel, NgControl } from '@angular/forms';
import { async, ComponentFixture, fakeAsync, inject, TestBed, tick import {
ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync
} from '@angular/core/testing'; } from '@angular/core/testing';
import { addMatchers, newEvent, click } from '../../testing'; import { addMatchers, newEvent, click } from '../../testing';
export class NotProvided extends ValueService { /* example below */} export class NotProvided extends ValueService { /* example below */ }
beforeEach( addMatchers ); beforeEach(addMatchers);
describe('demo (with TestBed):', () => { describe('demo (with TestBed):', () => {
//////// Service Tests ///////////// //////// Service Tests /////////////
// #docregion ValueService // #docregion ValueService
describe('ValueService', () => { describe('ValueService', () => {
@ -64,13 +65,13 @@ describe('demo (with TestBed):', () => {
// #enddocregion testbed-get-w-null // #enddocregion testbed-get-w-null
}); });
it('test should wait for ValueService.getPromiseValue', async(() => { it('test should wait for ValueService.getPromiseValue', waitForAsync(() => {
service.getPromiseValue().then( service.getPromiseValue().then(
value => expect(value).toBe('promise value') 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( service.getObservableValue().subscribe(
value => expect(value).toBe('observable value') value => expect(value).toBe('observable value')
); );
@ -150,7 +151,7 @@ describe('demo (with TestBed):', () => {
TestBed.configureTestingModule({ providers: [ValueService] }); TestBed.configureTestingModule({ providers: [ValueService] });
}); });
beforeEach(async(inject([ValueService], (service: ValueService) => { beforeEach(waitForAsync(inject([ValueService], (service: ValueService) => {
service.getPromiseValue().then(value => serviceValue = value); service.getPromiseValue().then(value => serviceValue = value);
}))); })));
@ -159,11 +160,11 @@ describe('demo (with TestBed):', () => {
}); });
}); });
/////////// Component Tests ////////////////// /////////// Component Tests //////////////////
describe('TestBed component tests', () => { describe('TestBed component tests', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed TestBed
.configureTestingModule({ .configureTestingModule({
imports: [DemoModule], imports: [DemoModule],
@ -235,7 +236,7 @@ describe('demo (with TestBed):', () => {
// #docregion ButtonComp // #docregion ButtonComp
it('should support clicking a button', () => { it('should support clicking a button', () => {
const fixture = TestBed.createComponent(LightswitchComponent); 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; const span = fixture.debugElement.query(By.css('span')).nativeElement;
fixture.detectChanges(); fixture.detectChanges();
@ -248,7 +249,7 @@ describe('demo (with TestBed):', () => {
// #enddocregion ButtonComp // #enddocregion ButtonComp
// ngModel is async so we must wait for it with promise-based `whenStable` // 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 expectedOrigName = 'John';
const expectedNewName = 'Sally'; const expectedNewName = 'Sally';
@ -278,10 +279,10 @@ describe('demo (with TestBed):', () => {
input.dispatchEvent(newEvent('input')); input.dispatchEvent(newEvent('input'));
return fixture.whenStable(); return fixture.whenStable();
}) })
.then(() => { .then(() => {
expect(comp.name).toBe(expectedNewName, expect(comp.name).toBe(expectedNewName,
`After ngModel updates the model, comp.name should be ${expectedNewName} `); `After ngModel updates the model, comp.name should be ${expectedNewName} `);
}); });
})); }));
// fakeAsync version of ngModel input test enables sync test style // fakeAsync version of ngModel input test enables sync test style
@ -327,9 +328,9 @@ describe('demo (with TestBed):', () => {
const fixture = TestBed.createComponent(ReversePipeComponent); const fixture = TestBed.createComponent(ReversePipeComponent);
fixture.detectChanges(); fixture.detectChanges();
const comp = fixture.componentInstance; const comp = fixture.componentInstance;
const input = fixture.debugElement.query(By.css('input')).nativeElement as HTMLInputElement; 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 // simulate user entering new name in input
input.value = inputText; input.value = inputText;
@ -381,12 +382,12 @@ describe('demo (with TestBed):', () => {
expect(el.styles.color).toBe(comp.color, 'color style'); expect(el.styles.color).toBe(comp.color, 'color style');
expect(el.styles.width).toBe(comp.width + 'px', 'width 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? // Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?
// expect(el.properties['customProperty']).toBe(true, 'customProperty'); // expect(el.properties['customProperty']).toBe(true, 'customProperty');
// #docregion dom-attributes // #docregion dom-attributes
}); });
// #enddocregion dom-attributes // #enddocregion dom-attributes
@ -400,10 +401,10 @@ describe('demo (with TestBed):', () => {
const fixture = TestBed.configureTestingModule({ const fixture = TestBed.configureTestingModule({
declarations: [Child1Component], declarations: [Child1Component],
}) })
.overrideComponent(Child1Component, { .overrideComponent(Child1Component, {
set: { template: '<span>Fake</span>' } set: { template: '<span>Fake</span>' }
}) })
.createComponent(Child1Component); .createComponent(Child1Component);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture).toHaveText('Fake'); expect(fixture).toHaveText('Fake');
@ -413,14 +414,14 @@ describe('demo (with TestBed):', () => {
const fixture = TestBed.configureTestingModule({ const fixture = TestBed.configureTestingModule({
declarations: [TestProvidersComponent], declarations: [TestProvidersComponent],
}) })
.overrideComponent(TestProvidersComponent, { .overrideComponent(TestProvidersComponent, {
remove: { providers: [ValueService]}, remove: { providers: [ValueService] },
add: { providers: [{ provide: ValueService, useClass: FakeValueService }] }, add: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
// Or replace them all (this component has only one provider) // Or replace them all (this component has only one provider)
// set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }, // set: { providers: [{ provide: ValueService, useClass: FakeValueService }] },
}) })
.createComponent(TestProvidersComponent); .createComponent(TestProvidersComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture).toHaveText('injected value: faked value', 'text'); expect(fixture).toHaveText('injected value: faked value', 'text');
@ -436,14 +437,14 @@ describe('demo (with TestBed):', () => {
const fixture = TestBed.configureTestingModule({ const fixture = TestBed.configureTestingModule({
declarations: [TestViewProvidersComponent], declarations: [TestViewProvidersComponent],
}) })
.overrideComponent(TestViewProvidersComponent, { .overrideComponent(TestViewProvidersComponent, {
// remove: { viewProviders: [ValueService]}, // remove: { viewProviders: [ValueService]},
// add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] }, // add: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
// Or replace them all (this component has only one viewProvider) // Or replace them all (this component has only one viewProvider)
set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] }, set: { viewProviders: [{ provide: ValueService, useClass: FakeValueService }] },
}) })
.createComponent(TestViewProvidersComponent); .createComponent(TestViewProvidersComponent);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture).toHaveText('injected value: faked value'); expect(fixture).toHaveText('injected value: faked value');
@ -453,20 +454,20 @@ describe('demo (with TestBed):', () => {
// TestComponent is parent of TestProvidersComponent // TestComponent is parent of TestProvidersComponent
@Component({ template: '<my-service-comp></my-service-comp>' }) @Component({ template: '<my-service-comp></my-service-comp>' })
class TestComponent {} class TestComponent { }
// 3 levels of ValueService provider: module, TestCompomponent, TestProvidersComponent // 3 levels of ValueService provider: module, TestCompomponent, TestProvidersComponent
const fixture = TestBed.configureTestingModule({ const fixture = TestBed.configureTestingModule({
declarations: [TestComponent, TestProvidersComponent], declarations: [TestComponent, TestProvidersComponent],
providers: [ValueService] providers: [ValueService]
}) })
.overrideComponent(TestComponent, { .overrideComponent(TestComponent, {
set: { providers: [{ provide: ValueService, useValue: {} }] } set: { providers: [{ provide: ValueService, useValue: {} }] }
}) })
.overrideComponent(TestProvidersComponent, { .overrideComponent(TestProvidersComponent, {
set: { providers: [{ provide: ValueService, useClass: FakeValueService }] } set: { providers: [{ provide: ValueService, useClass: FakeValueService }] }
}) })
.createComponent(TestComponent); .createComponent(TestComponent);
let testBedProvider: ValueService; let testBedProvider: ValueService;
let tcProvider: ValueService; let tcProvider: ValueService;
@ -489,10 +490,10 @@ describe('demo (with TestBed):', () => {
const fixture = TestBed.configureTestingModule({ const fixture = TestBed.configureTestingModule({
declarations: [ShellComponent, NeedsContentComponent, Child1Component, Child2Component, Child3Component], declarations: [ShellComponent, NeedsContentComponent, Child1Component, Child2Component, Child3Component],
}) })
.overrideComponent(ShellComponent, { .overrideComponent(ShellComponent, {
set: { set: {
selector: 'test-shell', selector: 'test-shell',
template: ` template: `
<needs-content #nc> <needs-content #nc>
<child-1 #content text="My"></child-1> <child-1 #content text="My"></child-1>
<child-2 #content text="dog"></child-2> <child-2 #content text="dog"></child-2>
@ -501,9 +502,9 @@ describe('demo (with TestBed):', () => {
<div #content>!</div> <div #content>!</div>
</needs-content> </needs-content>
` `
} }
}) })
.createComponent(ShellComponent); .createComponent(ShellComponent);
fixture.detectChanges(); fixture.detectChanges();
@ -615,7 +616,7 @@ describe('demo (with TestBed):', () => {
}); });
// must be async test to see child flow to parent // 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(); fixture.detectChanges();
getChild(); getChild();
@ -625,14 +626,14 @@ describe('demo (with TestBed):', () => {
// Wait one JS engine turn! // Wait one JS engine turn!
setTimeout(() => resolve(), 0); setTimeout(() => resolve(), 0);
}) })
.then(() => { .then(() => {
fixture.detectChanges(); fixture.detectChanges();
expect(child.ngOnChangesCounter).toBe(2, expect(child.ngOnChangesCounter).toBe(2,
'expected 2 changes: initial value and changed value'); 'expected 2 changes: initial value and changed value');
expect(parent.parentValue).toBe('bar', expect(parent.parentValue).toBe('bar',
'parentValue should eq changed parent value'); 'parentValue should eq changed parent value');
}); });
})); }));

View File

@ -1,8 +1,5 @@
// #docplaster // #docplaster
import { import { ComponentFixture, fakeAsync, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
async, ComponentFixture, fakeAsync, inject, TestBed, tick
} from '@angular/core/testing';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { import {
@ -36,59 +33,54 @@ describe('HeroDetailComponent', () => {
function overrideSetup() { function overrideSetup() {
// #docregion hds-spy // #docregion hds-spy
class HeroDetailServiceSpy { class HeroDetailServiceSpy {
testHero: Hero = {id: 42, name: 'Test Hero' }; testHero: Hero = {id: 42, name: 'Test Hero'};
/* emit cloned test hero */ /* emit cloned test hero */
getHero = jasmine.createSpy('getHero').and.callFake( 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 */ /* emit clone of test hero, with changes merged in */
saveHero = jasmine.createSpy('saveHero').and.callFake( saveHero = jasmine.createSpy('saveHero')
(hero: Hero) => asyncData(Object.assign(this.testHero, hero)) .and.callFake((hero: Hero) => asyncData(Object.assign(this.testHero, hero)));
);
} }
// #enddocregion hds-spy // #enddocregion hds-spy
// the `id` value is irrelevant because ignored by service stub // the `id` value is irrelevant because ignored by service stub
beforeEach(() => activatedRoute.setParamMap({ id: 99999 })); beforeEach(() => activatedRoute.setParamMap({id: 99999}));
// #docregion setup-override // #docregion setup-override
beforeEach(async(() => { beforeEach(waitForAsync(() => {
const routerSpy = createRouterSpy(); const routerSpy = createRouterSpy();
TestBed.configureTestingModule({ TestBed
imports: [ HeroModule ], .configureTestingModule({
providers: [ imports: [HeroModule],
{ provide: ActivatedRoute, useValue: activatedRoute }, providers: [
{ provide: Router, useValue: routerSpy}, {provide: ActivatedRoute, useValue: activatedRoute},
{provide: Router, useValue: routerSpy},
// #enddocregion setup-override // #enddocregion setup-override
// HeroDetailService at this level is IRRELEVANT! // HeroDetailService at this level is IRRELEVANT!
{ provide: HeroDetailService, useValue: {} } {provide: HeroDetailService, useValue: {}}
// #docregion setup-override // #docregion setup-override
] ]
}) })
// Override component's own provider // Override component's own provider
// #docregion override-component-method // #docregion override-component-method
.overrideComponent(HeroDetailComponent, { .overrideComponent(
set: { HeroDetailComponent,
providers: [ {set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}})
{ provide: HeroDetailService, useClass: HeroDetailServiceSpy } // #enddocregion override-component-method
]
}
})
// #enddocregion override-component-method
.compileComponents(); .compileComponents();
})); }));
// #enddocregion setup-override // #enddocregion setup-override
// #docregion override-tests // #docregion override-tests
let hdsSpy: HeroDetailServiceSpy; let hdsSpy: HeroDetailServiceSpy;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
createComponent(); createComponent();
// get the component's injected HeroDetailServiceSpy // get the component's injected HeroDetailServiceSpy
hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any; hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any;
@ -103,33 +95,32 @@ function overrideSetup() {
}); });
it('should save stub hero change', fakeAsync(() => { it('should save stub hero change', fakeAsync(() => {
const origName = hdsSpy.testHero.name; const origName = hdsSpy.testHero.name;
const newName = 'New Name'; const newName = 'New Name';
page.nameInput.value = newName; page.nameInput.value = newName;
page.nameInput.dispatchEvent(newEvent('input')); // tell Angular page.nameInput.dispatchEvent(newEvent('input')); // tell Angular
expect(component.hero.name).toBe(newName, 'component hero has new name'); expect(component.hero.name).toBe(newName, 'component hero has new name');
expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save'); expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');
click(page.saveBtn); click(page.saveBtn);
expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once'); expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');
tick(); // wait for async save to complete tick(); // wait for async save to complete
expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save'); expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called'); expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
})); }));
// #enddocregion override-tests // #enddocregion override-tests
it('fixture injected service is not the component injected service', it('fixture injected service is not the component injected service',
// inject gets the service from the fixture // inject gets the service from the fixture
inject([HeroDetailService], (fixtureService: HeroDetailService) => { 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 expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
const componentService = fixture.debugElement.injector.get(HeroDetailService); }));
expect(fixtureService).not.toBe(componentService, 'service injected from fixture');
}));
} }
//////////////////// ////////////////////
@ -139,21 +130,22 @@ const firstHero = getTestHeroes()[0];
function heroModuleSetup() { function heroModuleSetup() {
// #docregion setup-hero-module // #docregion setup-hero-module
beforeEach(async(() => { beforeEach(waitForAsync(() => {
const routerSpy = createRouterSpy(); const routerSpy = createRouterSpy();
TestBed.configureTestingModule({ TestBed
imports: [ HeroModule ], .configureTestingModule({
// #enddocregion setup-hero-module imports: [HeroModule],
// declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION // #enddocregion setup-hero-module
// #docregion setup-hero-module // declarations: [ HeroDetailComponent ], // NO! DOUBLE DECLARATION
providers: [ // #docregion setup-hero-module
{ provide: ActivatedRoute, useValue: activatedRoute }, providers: [
{ provide: HeroService, useClass: TestHeroService }, {provide: ActivatedRoute, useValue: activatedRoute},
{ provide: Router, useValue: routerSpy}, {provide: HeroService, useClass: TestHeroService},
] {provide: Router, useValue: routerSpy},
}) ]
.compileComponents(); })
.compileComponents();
})); }));
// #enddocregion setup-hero-module // #enddocregion setup-hero-module
@ -161,17 +153,17 @@ function heroModuleSetup() {
describe('when navigate to existing hero', () => { describe('when navigate to existing hero', () => {
let expectedHero: Hero; let expectedHero: Hero;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
expectedHero = firstHero; expectedHero = firstHero;
activatedRoute.setParamMap({ id: expectedHero.id }); activatedRoute.setParamMap({id: expectedHero.id});
createComponent(); createComponent();
})); }));
// #docregion selected-tests // #docregion selected-tests
it('should display that hero\'s name', () => { it('should display that hero\'s name', () => {
expect(page.nameDisplay.textContent).toBe(expectedHero.name); expect(page.nameDisplay.textContent).toBe(expectedHero.name);
}); });
// #enddocregion route-good-id // #enddocregion route-good-id
it('should navigate when click cancel', () => { it('should navigate when click cancel', () => {
click(page.cancelBtn); click(page.cancelBtn);
@ -190,10 +182,10 @@ function heroModuleSetup() {
}); });
it('should navigate when click save and save resolves', fakeAsync(() => { it('should navigate when click save and save resolves', fakeAsync(() => {
click(page.saveBtn); click(page.saveBtn);
tick(); // wait for async save to complete tick(); // wait for async save to complete
expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called'); expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');
})); }));
// #docregion title-case-pipe // #docregion title-case-pipe
it('should convert hero name to Title Case', () => { it('should convert hero name to Title Case', () => {
@ -215,14 +207,14 @@ function heroModuleSetup() {
expect(nameDisplay.textContent).toBe('Quick Brown Fox'); expect(nameDisplay.textContent).toBe('Quick Brown Fox');
}); });
// #enddocregion title-case-pipe // #enddocregion title-case-pipe
// #enddocregion selected-tests // #enddocregion selected-tests
// #docregion route-good-id // #docregion route-good-id
}); });
// #enddocregion route-good-id // #enddocregion route-good-id
// #docregion route-no-id // #docregion route-no-id
describe('when navigate with no hero id', () => { describe('when navigate with no hero id', () => {
beforeEach(async( createComponent )); beforeEach(waitForAsync(createComponent));
it('should have hero.id === 0', () => { it('should have hero.id === 0', () => {
expect(component.hero.id).toBe(0); expect(component.hero.id).toBe(0);
@ -236,8 +228,8 @@ function heroModuleSetup() {
// #docregion route-bad-id // #docregion route-bad-id
describe('when navigate to non-existent hero id', () => { describe('when navigate to non-existent hero id', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
activatedRoute.setParamMap({ id: 99999 }); activatedRoute.setParamMap({id: 99999});
createComponent(); createComponent();
})); }));
@ -253,11 +245,10 @@ function heroModuleSetup() {
let service: HeroDetailService; let service: HeroDetailService;
fixture = TestBed.createComponent(HeroDetailComponent); fixture = TestBed.createComponent(HeroDetailComponent);
expect( expect(
// Throws because `inject` only has access to TestBed's injector // Throws because `inject` only has access to TestBed's injector
// which is an ancestor of the component's injector // which is an ancestor of the component's injector
inject([HeroDetailService], (hds: HeroDetailService) => service = hds ) inject([HeroDetailService], (hds: HeroDetailService) => service = hds))
) .toThrowError(/No provider for HeroDetailService/);
.toThrowError(/No provider for HeroDetailService/);
// get `HeroDetailService` with component's own injector // get `HeroDetailService` with component's own injector
service = fixture.debugElement.injector.get(HeroDetailService); service = fixture.debugElement.injector.get(HeroDetailService);
@ -270,30 +261,31 @@ import { FormsModule } from '@angular/forms';
import { TitleCasePipe } from '../shared/title-case.pipe'; import { TitleCasePipe } from '../shared/title-case.pipe';
function formsModuleSetup() { function formsModuleSetup() {
// #docregion setup-forms-module // #docregion setup-forms-module
beforeEach(async(() => { beforeEach(waitForAsync(() => {
const routerSpy = createRouterSpy(); const routerSpy = createRouterSpy();
TestBed.configureTestingModule({ TestBed
imports: [ FormsModule ], .configureTestingModule({
declarations: [ HeroDetailComponent, TitleCasePipe ], imports: [FormsModule],
providers: [ declarations: [HeroDetailComponent, TitleCasePipe],
{ provide: ActivatedRoute, useValue: activatedRoute }, providers: [
{ provide: HeroService, useClass: TestHeroService }, {provide: ActivatedRoute, useValue: activatedRoute},
{ provide: Router, useValue: routerSpy}, {provide: HeroService, useClass: TestHeroService},
] {provide: Router, useValue: routerSpy},
}) ]
.compileComponents(); })
.compileComponents();
})); }));
// #enddocregion setup-forms-module // #enddocregion setup-forms-module
it('should display 1st hero\'s name', async(() => { it('should display 1st hero\'s name', waitForAsync(() => {
const expectedHero = firstHero; const expectedHero = firstHero;
activatedRoute.setParamMap({ id: expectedHero.id }); activatedRoute.setParamMap({id: expectedHero.id});
createComponent().then(() => { createComponent().then(() => {
expect(page.nameDisplay.textContent).toBe(expectedHero.name); expect(page.nameDisplay.textContent).toBe(expectedHero.name);
}); });
})); }));
} }
/////////////////////// ///////////////////////
@ -301,29 +293,30 @@ import { SharedModule } from '../shared/shared.module';
function sharedModuleSetup() { function sharedModuleSetup() {
// #docregion setup-shared-module // #docregion setup-shared-module
beforeEach(async(() => { beforeEach(waitForAsync(() => {
const routerSpy = createRouterSpy(); const routerSpy = createRouterSpy();
TestBed.configureTestingModule({ TestBed
imports: [ SharedModule ], .configureTestingModule({
declarations: [ HeroDetailComponent ], imports: [SharedModule],
providers: [ declarations: [HeroDetailComponent],
{ provide: ActivatedRoute, useValue: activatedRoute }, providers: [
{ provide: HeroService, useClass: TestHeroService }, {provide: ActivatedRoute, useValue: activatedRoute},
{ provide: Router, useValue: routerSpy}, {provide: HeroService, useClass: TestHeroService},
] {provide: Router, useValue: routerSpy},
}) ]
.compileComponents(); })
.compileComponents();
})); }));
// #enddocregion setup-shared-module // #enddocregion setup-shared-module
it('should display 1st hero\'s name', async(() => { it('should display 1st hero\'s name', waitForAsync(() => {
const expectedHero = firstHero; const expectedHero = firstHero;
activatedRoute.setParamMap({ id: expectedHero.id }); activatedRoute.setParamMap({id: expectedHero.id});
createComponent().then(() => { createComponent().then(() => {
expect(page.nameDisplay.textContent).toBe(expectedHero.name); expect(page.nameDisplay.textContent).toBe(expectedHero.name);
}); });
})); }));
} }
/////////// Helpers ///// /////////// Helpers /////
@ -347,11 +340,21 @@ function createComponent() {
// #docregion page // #docregion page
class Page { class Page {
// getter properties wait to query the DOM until called. // getter properties wait to query the DOM until called.
get buttons() { return this.queryAll<HTMLButtonElement>('button'); } get buttons() {
get saveBtn() { return this.buttons[0]; } return this.queryAll<HTMLButtonElement>('button');
get cancelBtn() { return this.buttons[1]; } }
get nameDisplay() { return this.query<HTMLElement>('span'); } get saveBtn() {
get nameInput() { return this.query<HTMLInputElement>('input'); } 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; gotoListSpy: jasmine.Spy;
navigateSpy: jasmine.Spy; navigateSpy: jasmine.Spy;

View File

@ -1,4 +1,4 @@
import { async, ComponentFixture, fakeAsync, TestBed, tick import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync
} from '@angular/core/testing'; } from '@angular/core/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
@ -7,13 +7,12 @@ import { DebugElement } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { addMatchers, newEvent } from '../../testing'; import { addMatchers, newEvent } from '../../testing';
import { HeroService } from '../model/hero.service';
import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service'; import { getTestHeroes, TestHeroService } from '../model/testing/test-hero.service';
import { HeroModule } from './hero.module'; import { HeroModule } from './hero.module';
import { HeroListComponent } from './hero-list.component'; import { HeroListComponent } from './hero-list.component';
import { HighlightDirective } from '../shared/highlight.directive'; import { HighlightDirective } from '../shared/highlight.directive';
import { HeroService } from '../model/hero.service';
const HEROES = getTestHeroes(); const HEROES = getTestHeroes();
@ -24,20 +23,20 @@ let page: Page;
/////// Tests ////// /////// Tests //////
describe('HeroListComponent', () => { describe('HeroListComponent', () => {
beforeEach(waitForAsync(() => {
beforeEach(async(() => {
addMatchers(); addMatchers();
const routerSpy = jasmine.createSpyObj('Router', ['navigate']); const routerSpy = jasmine.createSpyObj('Router', ['navigate']);
TestBed.configureTestingModule({ TestBed
imports: [HeroModule], .configureTestingModule({
providers: [ imports: [HeroModule],
{ provide: HeroService, useClass: TestHeroService }, providers: [
{ provide: Router, useValue: routerSpy} {provide: HeroService, useClass: TestHeroService},
] {provide: Router, useValue: routerSpy}
}) ]
.compileComponents() })
.then(createComponent); .compileComponents()
.then(createComponent);
})); }));
it('should display heroes', () => { it('should display heroes', () => {
@ -52,36 +51,35 @@ describe('HeroListComponent', () => {
}); });
it('should select hero on click', fakeAsync(() => { it('should select hero on click', fakeAsync(() => {
const expectedHero = HEROES[1]; const expectedHero = HEROES[1];
const li = page.heroRows[1]; const li = page.heroRows[1];
li.dispatchEvent(newEvent('click')); li.dispatchEvent(newEvent('click'));
tick(); tick();
// `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService // `.toEqual` because selectedHero is clone of expectedHero; see FakeHeroService
expect(comp.selectedHero).toEqual(expectedHero); expect(comp.selectedHero).toEqual(expectedHero);
})); }));
it('should navigate to selected hero detail on click', fakeAsync(() => { it('should navigate to selected hero detail on click', fakeAsync(() => {
const expectedHero = HEROES[1]; const expectedHero = HEROES[1];
const li = page.heroRows[1]; const li = page.heroRows[1];
li.dispatchEvent(newEvent('click')); li.dispatchEvent(newEvent('click'));
tick(); tick();
// should have navigated // should have navigated
expect(page.navSpy.calls.any()).toBe(true, 'navigate called'); expect(page.navSpy.calls.any()).toBe(true, 'navigate called');
// composed hero detail will be URL like 'heroes/42' // composed hero detail will be URL like 'heroes/42'
// expect link array with the route path and hero id // expect link array with the route path and hero id
// first argument to router.navigate is link array // first argument to router.navigate is link array
const navArgs = page.navSpy.calls.first().args[0]; const navArgs = page.navSpy.calls.first().args[0];
expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL'); expect(navArgs[0]).toContain('heroes', 'nav to heroes detail URL');
expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id'); expect(navArgs[1]).toBe(expectedHero.id, 'expected hero.id');
}));
}));
it('should find `HighlightDirective` with `By.directive', () => { it('should find `HighlightDirective` with `By.directive', () => {
// #docregion by // #docregion by
// Can find DebugElement either by css selector or by directive // 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)); const directive = fixture.debugElement.query(By.directive(HighlightDirective));
// #enddocregion by // #enddocregion by
expect(h2).toBe(directive); expect(h2).toBe(directive);

View File

@ -1,6 +1,7 @@
// #docplaster // #docplaster
// #docregion without-toBlob-macrotask // #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'; import { CanvasComponent } from './canvas.component';
describe('CanvasComponent', () => { describe('CanvasComponent', () => {
@ -10,29 +11,29 @@ describe('CanvasComponent', () => {
(window as any).__zone_symbol__FakeAsyncTestMacroTask = [ (window as any).__zone_symbol__FakeAsyncTestMacroTask = [
{ {
source: 'HTMLCanvasElement.toBlob', source: 'HTMLCanvasElement.toBlob',
callbackArgs: [{ size: 200 }], callbackArgs: [{size: 200}],
}, },
]; ];
}); });
// #enddocregion enable-toBlob-macrotask // #enddocregion enable-toBlob-macrotask
// #docregion without-toBlob-macrotask // #docregion without-toBlob-macrotask
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
CanvasComponent declarations: [CanvasComponent],
], })
}).compileComponents(); .compileComponents();
})); }));
it('should be able to generate blob data from canvas', fakeAsync(() => { it('should be able to generate blob data from canvas', fakeAsync(() => {
const fixture = TestBed.createComponent(CanvasComponent); const fixture = TestBed.createComponent(CanvasComponent);
const canvasComp = fixture.componentInstance; const canvasComp = fixture.componentInstance;
fixture.detectChanges(); fixture.detectChanges();
expect(canvasComp.blobSize).toBe(0); expect(canvasComp.blobSize).toBe(0);
tick(); tick();
expect(canvasComp.blobSize).toBeGreaterThan(0); expect(canvasComp.blobSize).toBeGreaterThan(0);
})); }));
}); });
// #enddocregion without-toBlob-macrotask // #enddocregion without-toBlob-macrotask

View File

@ -1,14 +1,13 @@
// #docplaster // #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 { asyncData, asyncError } from '../../testing';
import { of, throwError } from 'rxjs'; import { of, throwError } from 'rxjs';
import { last } from 'rxjs/operators'; import { last } from 'rxjs/operators';
import { TwainService } from './twain.service';
import { TwainComponent } from './twain.component'; import { TwainComponent } from './twain.component';
import { TwainService } from './twain.service';
describe('TwainComponent', () => { describe('TwainComponent', () => {
let component: TwainComponent; let component: TwainComponent;
@ -32,14 +31,12 @@ describe('TwainComponent', () => {
// Create a fake TwainService object with a `getQuote()` spy // Create a fake TwainService object with a `getQuote()` spy
const twainService = jasmine.createSpyObj('TwainService', ['getQuote']); const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);
// Make the spy return a synchronous Observable with the test data // 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 // #enddocregion spy
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ TwainComponent ], declarations: [TwainComponent],
providers: [ providers: [{provide: TwainService, useValue: twainService}]
{ provide: TwainService, useValue: twainService }
]
}); });
fixture = TestBed.createComponent(TwainComponent); fixture = TestBed.createComponent(TwainComponent);
@ -58,7 +55,7 @@ describe('TwainComponent', () => {
// The quote would not be immediately available if the service were truly async. // The quote would not be immediately available if the service were truly async.
// #docregion sync-test // #docregion sync-test
it('should show quote after component initialized', () => { it('should show quote after component initialized', () => {
fixture.detectChanges(); // onInit() fixture.detectChanges(); // onInit()
// sync spy result shows testQuote immediately after init // sync spy result shows testQuote immediately after init
expect(quoteEl.textContent).toBe(testQuote); expect(quoteEl.textContent).toBe(testQuote);
@ -71,20 +68,19 @@ describe('TwainComponent', () => {
// Use `fakeAsync` because the component error calls `setTimeout` // Use `fakeAsync` because the component error calls `setTimeout`
// #docregion error-test // #docregion error-test
it('should display error when TwainService fails', fakeAsync(() => { it('should display error when TwainService fails', fakeAsync(() => {
// tell spy to return an error observable // tell spy to return an error observable
getQuoteSpy.and.returnValue( getQuoteSpy.and.returnValue(throwError('TwainService test failure'));
throwError('TwainService test failure'));
fixture.detectChanges(); // onInit() fixture.detectChanges(); // onInit()
// sync spy errors immediately after init // 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(errorMessage()).toMatch(/test failure/, 'should display error');
expect(quoteEl.textContent).toBe('...', 'should show placeholder'); expect(quoteEl.textContent).toBe('...', 'should show placeholder');
})); }));
// #enddocregion error-test // #enddocregion error-test
}); });
@ -113,28 +109,28 @@ describe('TwainComponent', () => {
// #docregion fake-async-test // #docregion fake-async-test
it('should show quote after getQuote (fakeAsync)', fakeAsync(() => { it('should show quote after getQuote (fakeAsync)', fakeAsync(() => {
fixture.detectChanges(); // ngOnInit() fixture.detectChanges(); // ngOnInit()
expect(quoteEl.textContent).toBe('...', 'should show placeholder'); expect(quoteEl.textContent).toBe('...', 'should show placeholder');
tick(); // flush the observable to get the quote tick(); // flush the observable to get the quote
fixture.detectChanges(); // update view fixture.detectChanges(); // update view
expect(quoteEl.textContent).toBe(testQuote, 'should show quote'); expect(quoteEl.textContent).toBe(testQuote, 'should show quote');
expect(errorMessage()).toBeNull('should not show error'); expect(errorMessage()).toBeNull('should not show error');
})); }));
// #enddocregion fake-async-test // #enddocregion fake-async-test
// #docregion async-test // #docregion async-test
it('should show quote after getQuote (async)', async(() => { it('should show quote after getQuote (async)', waitForAsync(() => {
fixture.detectChanges(); // ngOnInit() fixture.detectChanges(); // ngOnInit()
expect(quoteEl.textContent).toBe('...', 'should show placeholder'); expect(quoteEl.textContent).toBe('...', 'should show placeholder');
fixture.whenStable().then(() => { // wait for async getQuote fixture.whenStable().then(() => { // wait for async getQuote
fixture.detectChanges(); // update view with quote fixture.detectChanges(); // update view with quote
expect(quoteEl.textContent).toBe(testQuote); expect(quoteEl.textContent).toBe(testQuote);
expect(errorMessage()).toBeNull('should not show error'); expect(errorMessage()).toBeNull('should not show error');
}); });
})); }));
// #enddocregion async-test // #enddocregion async-test
@ -142,8 +138,8 @@ describe('TwainComponent', () => {
it('should show last quote (quote done)', (done: DoneFn) => { it('should show last quote (quote done)', (done: DoneFn) => {
fixture.detectChanges(); fixture.detectChanges();
component.quote.pipe( last() ).subscribe(() => { component.quote.pipe(last()).subscribe(() => {
fixture.detectChanges(); // update view with quote fixture.detectChanges(); // update view with quote
expect(quoteEl.textContent).toBe(testQuote); expect(quoteEl.textContent).toBe(testQuote);
expect(errorMessage()).toBeNull('should not show error'); expect(errorMessage()).toBeNull('should not show error');
done(); done();
@ -157,7 +153,7 @@ describe('TwainComponent', () => {
// the spy's most recent call returns the observable with the test quote // the spy's most recent call returns the observable with the test quote
getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => { getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => {
fixture.detectChanges(); // update view with quote fixture.detectChanges(); // update view with quote
expect(quoteEl.textContent).toBe(testQuote); expect(quoteEl.textContent).toBe(testQuote);
expect(errorMessage()).toBeNull('should not show error'); expect(errorMessage()).toBeNull('should not show error');
done(); done();
@ -167,16 +163,16 @@ describe('TwainComponent', () => {
// #docregion async-error-test // #docregion async-error-test
it('should display error when TwainService fails', fakeAsync(() => { it('should display error when TwainService fails', fakeAsync(() => {
// tell spy to return an async error observable // tell spy to return an async error observable
getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure')); getQuoteSpy.and.returnValue(asyncError<string>('TwainService test failure'));
fixture.detectChanges(); fixture.detectChanges();
tick(); // component shows error after a setTimeout() tick(); // component shows error after a setTimeout()
fixture.detectChanges(); // update error message fixture.detectChanges(); // update error message
expect(errorMessage()).toMatch(/test failure/, 'should display error'); expect(errorMessage()).toMatch(/test failure/, 'should display error');
expect(quoteEl.textContent).toBe('...', 'should show placeholder'); expect(quoteEl.textContent).toBe('...', 'should show placeholder');
})); }));
// #enddocregion async-error-test // #enddocregion async-error-test
}); });
}); });

View File

@ -1,12 +1,12 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { DashboardComponent } from './dashboard.component';
import { HeroSearchComponent } from '../hero-search/hero-search.component';
import { RouterTestingModule } from '@angular/router/testing'; import { RouterTestingModule } from '@angular/router/testing';
import { of } from 'rxjs'; import { of } from 'rxjs';
import { HEROES } from '../mock-heroes';
import { HeroSearchComponent } from '../hero-search/hero-search.component';
import { HeroService } from '../hero.service'; import { HeroService } from '../hero.service';
import { HEROES } from '../mock-heroes';
import { DashboardComponent } from './dashboard.component';
describe('DashboardComponent', () => { describe('DashboardComponent', () => {
let component: DashboardComponent; let component: DashboardComponent;
@ -14,23 +14,16 @@ describe('DashboardComponent', () => {
let heroService; let heroService;
let getHeroesSpy; let getHeroesSpy;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
heroService = jasmine.createSpyObj('HeroService', ['getHeroes']); heroService = jasmine.createSpyObj('HeroService', ['getHeroes']);
getHeroesSpy = heroService.getHeroes.and.returnValue( of(HEROES) ); getHeroesSpy = heroService.getHeroes.and.returnValue(of(HEROES));
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
DashboardComponent, declarations: [DashboardComponent, HeroSearchComponent],
HeroSearchComponent imports: [RouterTestingModule.withRoutes([])],
], providers: [{provide: HeroService, useValue: heroService}]
imports: [ })
RouterTestingModule.withRoutes([]) .compileComponents();
],
providers: [
{ provide: HeroService, useValue: heroService }
]
})
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -47,12 +40,11 @@ describe('DashboardComponent', () => {
expect(fixture.nativeElement.querySelector('h3').textContent).toEqual('Top Heroes'); expect(fixture.nativeElement.querySelector('h3').textContent).toEqual('Top Heroes');
}); });
it('should call heroService', async(() => { it('should call heroService', waitForAsync(() => {
expect(getHeroesSpy.calls.any()).toBe(true); expect(getHeroesSpy.calls.any()).toBe(true);
})); }));
it('should display 4 links', async(() => {
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
}));
it('should display 4 links', waitForAsync(() => {
expect(fixture.nativeElement.querySelectorAll('a').length).toEqual(4);
}));
}); });

View File

@ -1,22 +1,16 @@
// #docregion // #docregion
// #docregion activatedroute // #docregion activatedroute
import { TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
// #enddocregion activatedroute // #enddocregion activatedroute
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { async, TestBed } from '@angular/core/testing';
import { PhoneDetailComponent } from './phone-detail.component'; import { PhoneDetailComponent } from './phone-detail.component';
import { Phone, PhoneData } from '../core/phone/phone.service'; import { Phone, PhoneData } from '../core/phone/phone.service';
import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe'; import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
function xyzPhoneData(): PhoneData { function xyzPhoneData(): PhoneData {
return { return {name: 'phone xyz', snippet: '', images: ['image/url1.png', 'image/url2.png']};
name: 'phone xyz',
snippet: '',
images: ['image/url1.png', 'image/url2.png']
};
} }
class MockPhone { class MockPhone {
@ -34,10 +28,9 @@ class ActivatedRouteMock {
// #enddocregion activatedroute // #enddocregion activatedroute
describe('PhoneDetailComponent', () => { describe('PhoneDetailComponent', () => {
// #docregion activatedroute // #docregion activatedroute
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ CheckmarkPipe, PhoneDetailComponent ], declarations: [ CheckmarkPipe, PhoneDetailComponent ],
providers: [ providers: [
@ -55,5 +48,4 @@ describe('PhoneDetailComponent', () => {
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name); expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name);
}); });
}); });

View File

@ -1,13 +1,14 @@
/* tslint:disable */ /* tslint:disable */
// #docregion // #docregion
import { NO_ERRORS_SCHEMA } from '@angular/core'; import {SpyLocation} from '@angular/common/testing';
import { ActivatedRoute } from '@angular/router'; import {NO_ERRORS_SCHEMA} from '@angular/core';
import { Observable, of } from 'rxjs'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import {ActivatedRoute} from '@angular/router';
import { SpyLocation } from '@angular/common/testing'; 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 { class ActivatedRouteMock {
constructor(public snapshot: any) {} constructor(public snapshot: any) {}
@ -16,8 +17,7 @@ class ActivatedRouteMock {
class MockPhone { class MockPhone {
query(): Observable<PhoneData[]> { query(): Observable<PhoneData[]> {
return of([ return of([
{name: 'Nexus S', snippet: '', images: []}, {name: 'Nexus S', snippet: '', images: []}, {name: 'Motorola DROID', snippet: '', images: []}
{name: 'Motorola DROID', snippet: '', images: []}
]); ]);
} }
} }
@ -25,18 +25,18 @@ class MockPhone {
let fixture: ComponentFixture<PhoneListComponent>; let fixture: ComponentFixture<PhoneListComponent>;
describe('PhoneList', () => { describe('PhoneList', () => {
beforeEach(waitForAsync(() => {
beforeEach(async(() => { TestBed
TestBed.configureTestingModule({ .configureTestingModule({
declarations: [ PhoneListComponent ], declarations: [PhoneListComponent],
providers: [ providers: [
{ provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) }, {provide: ActivatedRoute, useValue: new ActivatedRouteMock({params: {'phoneId': 1}})},
{ provide: Location, useClass: SpyLocation }, {provide: Location, useClass: SpyLocation},
{ provide: Phone, useClass: MockPhone }, {provide: Phone, useClass: MockPhone},
], ],
schemas: [ NO_ERRORS_SCHEMA ] schemas: [NO_ERRORS_SCHEMA]
}) })
.compileComponents(); .compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -47,20 +47,15 @@ describe('PhoneList', () => {
fixture.detectChanges(); fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement; let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2); expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
expect( expect(compiled.querySelector('.phone-list-item:nth-child(1)').textContent)
compiled.querySelector('.phone-list-item:nth-child(1)').textContent .toContain('Motorola DROID');
).toContain('Motorola DROID'); expect(compiled.querySelector('.phone-list-item:nth-child(2)').textContent)
expect( .toContain('Nexus S');
compiled.querySelector('.phone-list-item:nth-child(2)').textContent
).toContain('Nexus S');
}); });
xit('should set the default value of orderProp model', () => { xit('should set the default value of orderProp model', () => {
fixture.detectChanges(); fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement; let compiled = fixture.debugElement.nativeElement;
expect( expect(compiled.querySelector('select option:last-child').selected).toBe(true);
compiled.querySelector('select option:last-child').selected
).toBe(true);
}); });
}); });

View File

@ -1,22 +1,16 @@
// #docregion // #docregion
// #docregion activatedroute // #docregion activatedroute
import { TestBed, waitForAsync } from '@angular/core/testing';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
// #enddocregion activatedroute // #enddocregion activatedroute
import { Observable, of } from 'rxjs'; import { Observable, of } from 'rxjs';
import { async, TestBed } from '@angular/core/testing';
import { PhoneDetailComponent } from './phone-detail.component'; import { PhoneDetailComponent } from './phone-detail.component';
import { Phone, PhoneData } from '../core/phone/phone.service'; import { Phone, PhoneData } from '../core/phone/phone.service';
import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe'; import { CheckmarkPipe } from '../core/checkmark/checkmark.pipe';
function xyzPhoneData(): PhoneData { function xyzPhoneData(): PhoneData {
return { return {name: 'phone xyz', snippet: '', images: ['image/url1.png', 'image/url2.png']};
name: 'phone xyz',
snippet: '',
images: ['image/url1.png', 'image/url2.png']
};
} }
class MockPhone { class MockPhone {
@ -34,10 +28,9 @@ class ActivatedRouteMock {
// #enddocregion activatedroute // #enddocregion activatedroute
describe('PhoneDetailComponent', () => { describe('PhoneDetailComponent', () => {
// #docregion activatedroute // #docregion activatedroute
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ CheckmarkPipe, PhoneDetailComponent ], declarations: [ CheckmarkPipe, PhoneDetailComponent ],
providers: [ providers: [
@ -55,5 +48,4 @@ describe('PhoneDetailComponent', () => {
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name); expect(compiled.querySelector('h1').textContent).toContain(xyzPhoneData().name);
}); });
}); });

View File

@ -1,13 +1,14 @@
/* tslint:disable */ /* tslint:disable */
// #docregion routestuff // #docregion routestuff
import { NO_ERRORS_SCHEMA } from '@angular/core'; import {SpyLocation} from '@angular/common/testing';
import { ActivatedRoute } from '@angular/router'; import {NO_ERRORS_SCHEMA} from '@angular/core';
import { Observable, of } from 'rxjs'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; import {ActivatedRoute} from '@angular/router';
import { SpyLocation } from '@angular/common/testing'; 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 // #enddocregion routestuff
@ -18,8 +19,7 @@ class ActivatedRouteMock {
class MockPhone { class MockPhone {
query(): Observable<PhoneData[]> { query(): Observable<PhoneData[]> {
return of([ return of([
{name: 'Nexus S', snippet: '', images: []}, {name: 'Nexus S', snippet: '', images: []}, {name: 'Motorola DROID', snippet: '', images: []}
{name: 'Motorola DROID', snippet: '', images: []}
]); ]);
} }
} }
@ -27,20 +27,20 @@ class MockPhone {
let fixture: ComponentFixture<PhoneListComponent>; let fixture: ComponentFixture<PhoneListComponent>;
describe('PhoneList', () => { describe('PhoneList', () => {
// #docregion routestuff // #docregion routestuff
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ PhoneListComponent ], .configureTestingModule({
providers: [ declarations: [PhoneListComponent],
{ provide: ActivatedRoute, useValue: new ActivatedRouteMock({ params: { 'phoneId': 1 } }) }, providers: [
{ provide: Location, useClass: SpyLocation }, {provide: ActivatedRoute, useValue: new ActivatedRouteMock({params: {'phoneId': 1}})},
{ provide: Phone, useClass: MockPhone }, {provide: Location, useClass: SpyLocation},
], {provide: Phone, useClass: MockPhone},
schemas: [ NO_ERRORS_SCHEMA ] ],
}) schemas: [NO_ERRORS_SCHEMA]
.compileComponents(); })
.compileComponents();
})); }));
beforeEach(() => { beforeEach(() => {
@ -52,20 +52,15 @@ describe('PhoneList', () => {
fixture.detectChanges(); fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement; let compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2); expect(compiled.querySelectorAll('.phone-list-item').length).toBe(2);
expect( expect(compiled.querySelector('.phone-list-item:nth-child(1)').textContent)
compiled.querySelector('.phone-list-item:nth-child(1)').textContent .toContain('Motorola DROID');
).toContain('Motorola DROID'); expect(compiled.querySelector('.phone-list-item:nth-child(2)').textContent)
expect( .toContain('Nexus S');
compiled.querySelector('.phone-list-item:nth-child(2)').textContent
).toContain('Nexus S');
}); });
xit('should set the default value of orderProp model', () => { xit('should set the default value of orderProp model', () => {
fixture.detectChanges(); fixture.detectChanges();
let compiled = fixture.debugElement.nativeElement; let compiled = fixture.debugElement.nativeElement;
expect( expect(compiled.querySelector('select option:last-child').selected).toBe(true);
compiled.querySelector('select option:last-child').selected
).toBe(true);
}); });
}); });

View File

@ -58,6 +58,7 @@ v9 - v12
| `@angular/core` | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | <!--v9--> v11 | | `@angular/core` | [`ANALYZE_FOR_ENTRY_COMPONENTS`](api/core/ANALYZE_FOR_ENTRY_COMPONENTS) | <!--v9--> v11 |
| `@angular/router` | [`loadChildren` string syntax](#loadChildren) | <!--v9--> v11 | | `@angular/router` | [`loadChildren` string syntax](#loadChildren) | <!--v9--> v11 |
| `@angular/core/testing` | [`TestBed.get`](#testing) | <!--v9--> v12 | | `@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 | | `@angular/router` | [`ActivatedRoute` params and `queryParams` properties](#activatedroute-props) | unspecified |
| template syntax | [`/deep/`, `>>>`, and `::ng-deep`](#deep-component-style-selector) | <!--v7--> 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 | | 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 | | 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. | | [`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} {@a forms}
@ -477,7 +479,7 @@ The final decision was made on three key points:
{@a wrapped-value} {@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. 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. 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: 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. - 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} {@a deprecated-cli-flags}
## Deprecated CLI APIs and Options ## Deprecated CLI APIs and Options

View File

@ -159,10 +159,10 @@ It also generates an initial test file for the component, `banner-external.compo
<div class="alert is-helpful"> <div class="alert is-helpful">
Because `compileComponents` is asynchronous, it uses 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`. 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> </div>

View File

@ -402,7 +402,7 @@ There is no nested syntax (like a `Promise.then()`) to disrupt the flow of contr
<div class="alert is-helpful"> <div class="alert is-helpful">
Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` (XHR) call. 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> </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. 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`. 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. The `fakeAsync()` utility function has a few limitations.
In particular, it won't work if the test body makes an `XMLHttpRequest` (XHR) call. 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). 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"> <div class="alert is-helpful">
The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR` The `TestBed.compileComponents()` method (see [below](#compile-components)) calls `XHR`
to read external template and css files during "just-in-time" compilation. 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> </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 <code-example
path="testing/src/app/twain/twain.component.spec.ts" path="testing/src/app/twain/twain.component.spec.ts"
region="async-test"> region="async-test">
</code-example> </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_. 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. 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()`, But the test's asynchronous nature is revealed by the call to `fixture.whenStable()`,
which breaks the linear flow of control. 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} {@a when-stable}
@ -641,18 +641,18 @@ update the quote element with the expected text.
#### Jasmine _done()_ #### Jasmine _done()_
While the `async()` and `fakeAsync()` functions greatly While the `waitForAsync()` and `fakeAsync()` functions greatly
simplify Angular asynchronous testing, simplify Angular asynchronous testing,
you can still fall back to the traditional technique you can still fall back to the traditional technique
and pass `it` a function that takes a and pass `it` a function that takes a
[`done` callback](https://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support). [`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`. is `undefined`.
Now you are responsible for chaining promises, handling errors, and calling `done()` at the appropriate moments. 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()`. 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. 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> region="test-scheduler-flush"></code-example>
This step serves a purpose analogous to [tick()](api/core/testing/tick) and `whenStable()` in the 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. The balance of the test is the same as those examples.
#### Marble error testing #### Marble error testing
@ -1535,7 +1535,7 @@ You must call `compileComponents()` within an asynchronous test function.
<div class="alert is-critical"> <div class="alert is-critical">
If you neglect to make the test function async 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 you'll see this error message
<code-example language="sh" class="code-shell" hideCopy> <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. An async `beforeEach()` that compiles the components
1. A synchronous `beforeEach()` that performs the remaining setup. 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 <code-example
path="testing/src/app/banner/banner-external.component.spec.ts" 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" region="async-before-each"
header="app/banner/banner-external.component.spec.ts (async beforeEach)"></code-example> 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 The `TestBed.configureTestingModule()` method returns the `TestBed` class so you can chain
calls to other `TestBed` static methods such as `compileComponents()`. calls to other `TestBed` static methods such as `compileComponents()`.

View File

@ -25,7 +25,7 @@ Here's a summary of the stand-alone functions, in order of likely utility:
<td> <td>
Runs the body of a test (`it`) or setup (`beforeEach`) function within a special _async test zone_. 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> </td>
</tr> </tr>

View File

@ -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>. 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. 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"> <div class="alert is-important">
If you create project with `Angular/CLI`, it is already imported in `src/test.ts`. If you create project with `Angular/CLI`, it is already imported in `src/test.ts`.

View File

@ -1,6 +1,7 @@
/** @codeGenApi */ /** @codeGenApi */
export declare const __core_private_testing_placeholder__ = ""; export declare const __core_private_testing_placeholder__ = "";
/** @deprecated */
export declare function async(fn: Function): (done: any) => any; export declare function async(fn: Function): (done: any) => any;
export declare class ComponentFixture<T> { export declare class ComponentFixture<T> {
@ -141,5 +142,7 @@ export declare function tick(millis?: number, tickOptions?: {
processNewMacroTasksSynchronously: boolean; processNewMacroTasksSynchronously: boolean;
}): void; }): void;
export declare function waitForAsync(fn: Function): (done: any) => any;
export declare function withModule(moduleDef: TestModuleMetadata): InjectSetupWrapper; export declare function withModule(moduleDef: TestModuleMetadata): InjectSetupWrapper;
export declare function withModule(moduleDef: TestModuleMetadata, fn: Function): () => any; export declare function withModule(moduleDef: TestModuleMetadata, fn: Function): () => any;

View File

@ -1,13 +1,13 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent declarations: [AppComponent],
], })
}).compileComponents(); .compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {
@ -26,6 +26,7 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('cli-hello-world-ivy-compat app is running!'); expect(compiled.querySelector('.content span').textContent)
.toContain('cli-hello-world-ivy-compat app is running!');
}); });
}); });

View File

@ -1,13 +1,13 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent declarations: [AppComponent],
], })
}).compileComponents(); .compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {

View File

@ -1,17 +1,15 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; import {RouterTestingModule} from '@angular/router/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
imports: [ .configureTestingModule({
RouterTestingModule imports: [RouterTestingModule],
], declarations: [AppComponent],
declarations: [ })
AppComponent .compileComponents();
],
}).compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {
@ -30,6 +28,7 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('cli-hello-world-lazy-rollup app is running!'); expect(compiled.querySelector('.content span').textContent)
.toContain('cli-hello-world-lazy-rollup app is running!');
}); });
}); });

View File

@ -1,17 +1,15 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing'; import {RouterTestingModule} from '@angular/router/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
imports: [ .configureTestingModule({
RouterTestingModule imports: [RouterTestingModule],
], declarations: [AppComponent],
declarations: [ })
AppComponent .compileComponents();
],
}).compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {
@ -30,6 +28,7 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('cli-hello-world-lazy app is running!'); expect(compiled.querySelector('.content span').textContent)
.toContain('cli-hello-world-lazy app is running!');
}); });
}); });

View File

@ -1,13 +1,13 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent declarations: [AppComponent],
], })
}).compileComponents(); .compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {
@ -26,6 +26,7 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent); const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges(); fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement; const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('.content span').textContent).toContain('cli-hello-world app is running!'); expect(compiled.querySelector('.content span').textContent)
.toContain('cli-hello-world app is running!');
}); });
}); });

View File

@ -1,13 +1,13 @@
import { TestBed, async } from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import { AppComponent } from './app.component'; import {AppComponent} from './app.component';
describe('AppComponent', () => { describe('AppComponent', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed
declarations: [ .configureTestingModule({
AppComponent declarations: [AppComponent],
], })
}).compileComponents(); .compileComponents();
})); }));
it('should create the app', () => { it('should create the app', () => {

View File

@ -7,7 +7,7 @@
*/ */
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
{ {
describe('binding to CSS class list', () => { describe('binding to CSS class list', () => {
@ -37,7 +37,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
}); });
}); });
it('should clean up when the directive is destroyed', async(() => { it('should clean up when the directive is destroyed', waitForAsync(() => {
fixture = createTestComponent('<div *ngFor="let item of items" [ngClass]="item"></div>'); fixture = createTestComponent('<div *ngFor="let item of items" [ngClass]="item"></div>');
getComponent().items = [['0']]; getComponent().items = [['0']];
@ -47,21 +47,22 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
describe('expressions evaluating to objects', () => { describe('expressions evaluating to objects', () => {
it('should add classes specified in an object literal', async(() => { it('should add classes specified in an object literal', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="{foo: true, bar: false}"></div>'); fixture = createTestComponent('<div [ngClass]="{foo: true, bar: false}"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
})); }));
it('should add classes specified in an object literal without change in class names', it('should add classes specified in an object literal without change in class names',
async(() => { waitForAsync(() => {
fixture = fixture =
createTestComponent(`<div [ngClass]="{'foo-bar': true, 'fooBar': true}"></div>`); createTestComponent(`<div [ngClass]="{'foo-bar': true, 'fooBar': true}"></div>`);
detectChangesAndExpectClassName('foo-bar fooBar'); detectChangesAndExpectClassName('foo-bar fooBar');
})); }));
it('should add and remove classes based on changes in object literal values', async(() => { it('should add and remove classes based on changes in object literal values',
waitForAsync(() => {
fixture = fixture =
createTestComponent('<div [ngClass]="{foo: condition, bar: !condition}"></div>'); createTestComponent('<div [ngClass]="{foo: condition, bar: !condition}"></div>');
@ -71,7 +72,8 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('bar'); detectChangesAndExpectClassName('bar');
})); }));
it('should add and remove classes based on changes to the expression object', async(() => { it('should add and remove classes based on changes to the expression object',
waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr"></div>');
const objExpr = getComponent().objExpr; const objExpr = getComponent().objExpr;
@ -88,7 +90,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should add and remove classes based on reference changes to the expression object', it('should add and remove classes based on reference changes to the expression object',
async(() => { waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -100,7 +102,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('baz'); detectChangesAndExpectClassName('baz');
})); }));
it('should remove active classes when expression evaluates to null', async(() => { it('should remove active classes when expression evaluates to null', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -113,7 +115,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should allow multiple classes per expression', async(() => { it('should allow multiple classes per expression', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr"></div>');
getComponent().objExpr = {'bar baz': true, 'bar1 baz1': true}; getComponent().objExpr = {'bar baz': true, 'bar1 baz1': true};
@ -123,7 +125,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('bar1 baz1'); detectChangesAndExpectClassName('bar1 baz1');
})); }));
it('should split by one or more spaces between classes', async(() => { it('should split by one or more spaces between classes', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr"></div>');
getComponent().objExpr = {'foo bar baz': true}; getComponent().objExpr = {'foo bar baz': true};
@ -132,14 +134,14 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
}); });
describe('expressions evaluating to lists', () => { describe('expressions evaluating to lists', () => {
it('should add classes specified in a list literal', async(() => { it('should add classes specified in a list literal', waitForAsync(() => {
fixture = fixture =
createTestComponent(`<div [ngClass]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`); createTestComponent(`<div [ngClass]="['foo', 'bar', 'foo-bar', 'fooBar']"></div>`);
detectChangesAndExpectClassName('foo bar foo-bar fooBar'); detectChangesAndExpectClassName('foo bar foo-bar fooBar');
})); }));
it('should add and remove classes based on changes to the expression', async(() => { it('should add and remove classes based on changes to the expression', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div [ngClass]="arrExpr"></div>');
const arrExpr = getComponent().arrExpr; const arrExpr = getComponent().arrExpr;
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -154,7 +156,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
})); }));
it('should add and remove classes when a reference changes', async(() => { it('should add and remove classes when a reference changes', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div [ngClass]="arrExpr"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -162,7 +164,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('bar'); detectChangesAndExpectClassName('bar');
})); }));
it('should take initial classes into account when a reference changes', async(() => { it('should take initial classes into account when a reference changes', waitForAsync(() => {
fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -170,13 +172,13 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('foo bar'); detectChangesAndExpectClassName('foo bar');
})); }));
it('should ignore empty or blank class names', async(() => { it('should ignore empty or blank class names', waitForAsync(() => {
fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>');
getComponent().arrExpr = ['', ' ']; getComponent().arrExpr = ['', ' '];
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
})); }));
it('should trim blanks from class names', async(() => { it('should trim blanks from class names', waitForAsync(() => {
fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div class="foo" [ngClass]="arrExpr"></div>');
getComponent().arrExpr = [' bar ']; getComponent().arrExpr = [' bar '];
@ -184,7 +186,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should allow multiple classes per item in arrays', async(() => { it('should allow multiple classes per item in arrays', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="arrExpr"></div>'); fixture = createTestComponent('<div [ngClass]="arrExpr"></div>');
getComponent().arrExpr = ['foo bar baz', 'foo1 bar1 baz1']; getComponent().arrExpr = ['foo bar baz', 'foo1 bar1 baz1'];
@ -203,7 +205,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
}); });
describe('expressions evaluating to sets', () => { describe('expressions evaluating to sets', () => {
it('should add and remove classes if the set instance changed', async(() => { it('should add and remove classes if the set instance changed', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="setExpr"></div>'); fixture = createTestComponent('<div [ngClass]="setExpr"></div>');
let setExpr = new Set<string>(); let setExpr = new Set<string>();
setExpr.add('bar'); setExpr.add('bar');
@ -218,12 +220,12 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
}); });
describe('expressions evaluating to string', () => { describe('expressions evaluating to string', () => {
it('should add classes specified in a string literal', async(() => { it('should add classes specified in a string literal', waitForAsync(() => {
fixture = createTestComponent(`<div [ngClass]="'foo bar foo-bar fooBar'"></div>`); fixture = createTestComponent(`<div [ngClass]="'foo bar foo-bar fooBar'"></div>`);
detectChangesAndExpectClassName('foo bar foo-bar fooBar'); detectChangesAndExpectClassName('foo bar foo-bar fooBar');
})); }));
it('should add and remove classes based on changes to the expression', async(() => { it('should add and remove classes based on changes to the expression', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="strExpr"></div>'); fixture = createTestComponent('<div [ngClass]="strExpr"></div>');
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -235,7 +237,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('baz'); detectChangesAndExpectClassName('baz');
})); }));
it('should remove active classes when switching from string to null', async(() => { it('should remove active classes when switching from string to null', waitForAsync(() => {
fixture = createTestComponent(`<div [ngClass]="strExpr"></div>`); fixture = createTestComponent(`<div [ngClass]="strExpr"></div>`);
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -244,7 +246,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should take initial classes into account when switching from string to null', it('should take initial classes into account when switching from string to null',
async(() => { waitForAsync(() => {
fixture = createTestComponent(`<div class="foo" [ngClass]="strExpr"></div>`); fixture = createTestComponent(`<div class="foo" [ngClass]="strExpr"></div>`);
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -252,7 +254,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
})); }));
it('should ignore empty and blank strings', async(() => { it('should ignore empty and blank strings', waitForAsync(() => {
fixture = createTestComponent(`<div class="foo" [ngClass]="strExpr"></div>`); fixture = createTestComponent(`<div class="foo" [ngClass]="strExpr"></div>`);
getComponent().strExpr = ''; getComponent().strExpr = '';
detectChangesAndExpectClassName('foo'); detectChangesAndExpectClassName('foo');
@ -260,7 +262,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
}); });
describe('cooperation with other class-changing constructs', () => { describe('cooperation with other class-changing constructs', () => {
it('should co-operate with the class attribute', async(() => { it('should co-operate with the class attribute', waitForAsync(() => {
fixture = createTestComponent('<div [ngClass]="objExpr" class="init foo"></div>'); fixture = createTestComponent('<div [ngClass]="objExpr" class="init foo"></div>');
const objExpr = getComponent().objExpr; const objExpr = getComponent().objExpr;
@ -274,7 +276,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName('init foo'); detectChangesAndExpectClassName('init foo');
})); }));
it('should co-operate with the interpolated class attribute', async(() => { it('should co-operate with the interpolated class attribute', waitForAsync(() => {
fixture = createTestComponent(`<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`); fixture = createTestComponent(`<div [ngClass]="objExpr" class="{{'init foo'}}"></div>`);
const objExpr = getComponent().objExpr; const objExpr = getComponent().objExpr;
@ -289,7 +291,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should co-operate with the interpolated class attribute when interpolation changes', it('should co-operate with the interpolated class attribute when interpolation changes',
async(() => { waitForAsync(() => {
fixture = createTestComponent( fixture = createTestComponent(
`<div [ngClass]="{large: false, small: true}" class="{{strExpr}}"></div>`); `<div [ngClass]="{large: false, small: true}" class="{{strExpr}}"></div>`);
@ -299,7 +301,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName(`bar small`); detectChangesAndExpectClassName(`bar small`);
})); }));
it('should co-operate with the class attribute and binding to it', async(() => { it('should co-operate with the class attribute and binding to it', waitForAsync(() => {
fixture = fixture =
createTestComponent(`<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`); createTestComponent(`<div [ngClass]="objExpr" class="init" [class]="'foo'"></div>`);
const objExpr = getComponent().objExpr; const objExpr = getComponent().objExpr;
@ -314,7 +316,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
detectChangesAndExpectClassName(`init foo`); detectChangesAndExpectClassName(`init foo`);
})); }));
it('should co-operate with the class attribute and class.name binding', async(() => { it('should co-operate with the class attribute and class.name binding', waitForAsync(() => {
const template = const template =
'<div class="init foo" [ngClass]="objExpr" [class.baz]="condition"></div>'; '<div class="init foo" [ngClass]="objExpr" [class.baz]="condition"></div>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -333,7 +335,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should co-operate with initial class and class attribute binding when binding changes', it('should co-operate with initial class and class attribute binding when binding changes',
async(() => { waitForAsync(() => {
const template = '<div class="init" [ngClass]="objExpr" [class]="strExpr"></div>'; const template = '<div class="init" [ngClass]="objExpr" [class]="strExpr"></div>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
const cmp = getComponent(); const cmp = getComponent();

View File

@ -9,7 +9,7 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet'; import {NgComponentOutlet} from '@angular/common/src/directives/ng_component_outlet';
import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NgModule, NgModuleFactory, NO_ERRORS_SCHEMA, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core'; import {Compiler, Component, ComponentRef, Inject, InjectionToken, Injector, NgModule, NgModuleFactory, NO_ERRORS_SCHEMA, Optional, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {async, TestBed} from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('insert/remove', () => { describe('insert/remove', () => {
@ -17,7 +17,7 @@ describe('insert/remove', () => {
TestBed.configureTestingModule({imports: [TestModule]}); TestBed.configureTestingModule({imports: [TestModule]});
}); });
it('should do nothing if component is null', async(() => { it('should do nothing if component is null', waitForAsync(() => {
const template = `<ng-template *ngComponentOutlet="currentComponent"></ng-template>`; const template = `<ng-template *ngComponentOutlet="currentComponent"></ng-template>`;
TestBed.overrideComponent(TestComponent, {set: {template: template}}); TestBed.overrideComponent(TestComponent, {set: {template: template}});
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
@ -28,7 +28,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
})); }));
it('should insert content specified by a component', async(() => { it('should insert content specified by a component', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
@ -40,7 +40,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('foo'); expect(fixture.nativeElement).toHaveText('foo');
})); }));
it('should emit a ComponentRef once a component was created', async(() => { it('should emit a ComponentRef once a component was created', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
@ -56,7 +56,7 @@ describe('insert/remove', () => {
})); }));
it('should clear view if component becomes null', async(() => { it('should clear view if component becomes null', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
@ -74,7 +74,7 @@ describe('insert/remove', () => {
})); }));
it('should swap content if component changes', async(() => { it('should swap content if component changes', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
fixture.detectChanges(); fixture.detectChanges();
@ -91,7 +91,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('bar'); expect(fixture.nativeElement).toHaveText('bar');
})); }));
it('should use the injector, if one supplied', async(() => { it('should use the injector, if one supplied', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
const uniqueValue = {}; const uniqueValue = {};
@ -107,7 +107,7 @@ describe('insert/remove', () => {
})); }));
it('should resolve with an injector', async(() => { it('should resolve with an injector', waitForAsync(() => {
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
// We are accessing a ViewChild (ngComponentOutlet) before change detection has run // We are accessing a ViewChild (ngComponentOutlet) before change detection has run
@ -120,7 +120,7 @@ describe('insert/remove', () => {
expect(cmpRef.instance.testToken).toBeNull(); expect(cmpRef.instance.testToken).toBeNull();
})); }));
it('should render projectable nodes, if supplied', async(() => { it('should render projectable nodes, if supplied', waitForAsync(() => {
const template = `<ng-template>projected foo</ng-template>${TEST_CMP_TEMPLATE}`; const template = `<ng-template>projected foo</ng-template>${TEST_CMP_TEMPLATE}`;
TestBed.overrideComponent(TestComponent, {set: {template: template}}) TestBed.overrideComponent(TestComponent, {set: {template: template}})
.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}); .configureTestingModule({schemas: [NO_ERRORS_SCHEMA]});
@ -144,7 +144,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('projected foo'); expect(fixture.nativeElement).toHaveText('projected foo');
})); }));
it('should resolve components from other modules, if supplied', async(() => { it('should resolve components from other modules, if supplied', waitForAsync(() => {
const compiler = TestBed.inject(Compiler); const compiler = TestBed.inject(Compiler);
let fixture = TestBed.createComponent(TestComponent); let fixture = TestBed.createComponent(TestComponent);
@ -158,7 +158,7 @@ describe('insert/remove', () => {
expect(fixture.nativeElement).toHaveText('baz'); expect(fixture.nativeElement).toHaveText('baz');
})); }));
it('should clean up moduleRef, if supplied', async(() => { it('should clean up moduleRef, if supplied', waitForAsync(() => {
let destroyed = false; let destroyed = false;
const compiler = TestBed.inject(Compiler); const compiler = TestBed.inject(Compiler);
const fixture = TestBed.createComponent(TestComponent); const fixture = TestBed.createComponent(TestComponent);
@ -174,7 +174,7 @@ describe('insert/remove', () => {
expect(moduleRef.destroy).toHaveBeenCalled(); expect(moduleRef.destroy).toHaveBeenCalled();
})); }));
it('should not re-create moduleRef when it didn\'t actually change', async(() => { it('should not re-create moduleRef when it didn\'t actually change', waitForAsync(() => {
const compiler = TestBed.inject(Compiler); const compiler = TestBed.inject(Compiler);
const fixture = TestBed.createComponent(TestComponent); const fixture = TestBed.createComponent(TestComponent);
@ -191,7 +191,7 @@ describe('insert/remove', () => {
expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']); expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']);
})); }));
it('should re-create moduleRef when changed', async(() => { it('should re-create moduleRef when changed', waitForAsync(() => {
const compiler = TestBed.inject(Compiler); const compiler = TestBed.inject(Compiler);
const fixture = TestBed.createComponent(TestComponent); const fixture = TestBed.createComponent(TestComponent);
fixture.componentInstance.module = compiler.compileModuleSync(TestModule2); fixture.componentInstance.module = compiler.compileModuleSync(TestModule2);

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -38,27 +38,27 @@ let thisArg: any;
}); });
}); });
it('should reflect initial elements', async(() => { it('should reflect initial elements', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
detectChangesAndExpectText('1;2;'); detectChangesAndExpectText('1;2;');
})); }));
it('should reflect added elements', async(() => { it('should reflect added elements', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
fixture.detectChanges(); fixture.detectChanges();
getComponent().items.push(3); getComponent().items.push(3);
detectChangesAndExpectText('1;2;3;'); detectChangesAndExpectText('1;2;3;');
})); }));
it('should reflect removed elements', async(() => { it('should reflect removed elements', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
fixture.detectChanges(); fixture.detectChanges();
getComponent().items.splice(1, 1); getComponent().items.splice(1, 1);
detectChangesAndExpectText('1;'); detectChangesAndExpectText('1;');
})); }));
it('should reflect moved elements', async(() => { it('should reflect moved elements', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
fixture.detectChanges(); fixture.detectChanges();
getComponent().items.splice(0, 1); getComponent().items.splice(0, 1);
@ -66,7 +66,7 @@ let thisArg: any;
detectChangesAndExpectText('2;1;'); detectChangesAndExpectText('2;1;');
})); }));
it('should reflect a mix of all changes (additions/removals/moves)', async(() => { it('should reflect a mix of all changes (additions/removals/moves)', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
getComponent().items = [0, 1, 2, 3, 4, 5]; getComponent().items = [0, 1, 2, 3, 4, 5];
@ -77,7 +77,7 @@ let thisArg: any;
detectChangesAndExpectText('6;2;7;0;4;8;'); detectChangesAndExpectText('6;2;7;0;4;8;');
})); }));
it('should iterate over an array of objects', async(() => { it('should iterate over an array of objects', waitForAsync(() => {
const template = '<ul><li *ngFor="let item of items">{{item["name"]}};</li></ul>'; const template = '<ul><li *ngFor="let item of items">{{item["name"]}};</li></ul>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -95,14 +95,14 @@ let thisArg: any;
detectChangesAndExpectText('shyam;'); detectChangesAndExpectText('shyam;');
})); }));
it('should gracefully handle nulls', async(() => { it('should gracefully handle nulls', waitForAsync(() => {
const template = '<ul><li *ngFor="let item of null">{{item}};</li></ul>'; const template = '<ul><li *ngFor="let item of null">{{item}};</li></ul>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
detectChangesAndExpectText(''); detectChangesAndExpectText('');
})); }));
it('should gracefully handle ref changing to null and back', async(() => { it('should gracefully handle ref changing to null and back', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
detectChangesAndExpectText('1;2;'); detectChangesAndExpectText('1;2;');
@ -114,7 +114,7 @@ let thisArg: any;
detectChangesAndExpectText('1;2;3;'); detectChangesAndExpectText('1;2;3;');
})); }));
it('should throw on non-iterable ref and suggest using an array', async(() => { it('should throw on non-iterable ref and suggest using an array', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
getComponent().items = <any>'whaaa'; getComponent().items = <any>'whaaa';
@ -123,7 +123,7 @@ let thisArg: any;
/Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables such as Arrays/); /Cannot find a differ supporting object 'whaaa' of type 'string'. NgFor only supports binding to Iterables such as Arrays/);
})); }));
it('should throw on ref changing to string', async(() => { it('should throw on ref changing to string', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
detectChangesAndExpectText('1;2;'); detectChangesAndExpectText('1;2;');
@ -132,7 +132,7 @@ let thisArg: any;
expect(() => fixture.detectChanges()).toThrowError(); expect(() => fixture.detectChanges()).toThrowError();
})); }));
it('should works with duplicates', async(() => { it('should works with duplicates', waitForAsync(() => {
fixture = createTestComponent(); fixture = createTestComponent();
const a = new Foo(); const a = new Foo();
@ -140,7 +140,7 @@ let thisArg: any;
detectChangesAndExpectText('foo;foo;'); detectChangesAndExpectText('foo;foo;');
})); }));
it('should repeat over nested arrays', async(() => { it('should repeat over nested arrays', waitForAsync(() => {
const template = '<div *ngFor="let item of items">' + const template = '<div *ngFor="let item of items">' +
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>|' + '<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>|' +
'</div>'; '</div>';
@ -153,7 +153,7 @@ let thisArg: any;
detectChangesAndExpectText('e-1;|f-2;g-2;|'); detectChangesAndExpectText('e-1;|f-2;g-2;|');
})); }));
it('should repeat over nested arrays with no intermediate element', async(() => { it('should repeat over nested arrays with no intermediate element', waitForAsync(() => {
const template = '<div *ngFor="let item of items">' + const template = '<div *ngFor="let item of items">' +
'<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>' + '<div *ngFor="let subitem of item">{{subitem}}-{{item.length}};</div>' +
'</div>'; '</div>';
@ -166,7 +166,8 @@ let thisArg: any;
detectChangesAndExpectText('e-1;f-2;g-2;'); detectChangesAndExpectText('e-1;f-2;g-2;');
})); }));
it('should repeat over nested ngIf that are the last node in the ngFor template', async(() => { it('should repeat over nested ngIf that are the last node in the ngFor template',
waitForAsync(() => {
const template = `<div *ngFor="let item of items; let i=index">` + const template = `<div *ngFor="let item of items; let i=index">` +
`<div>{{i}}|</div>` + `<div>{{i}}|</div>` +
`<div *ngIf="i % 2 == 0">even|</div>` + `<div *ngIf="i % 2 == 0">even|</div>` +
@ -185,7 +186,7 @@ let thisArg: any;
detectChangesAndExpectText('0|even|1|2|even|'); detectChangesAndExpectText('0|even|1|2|even|');
})); }));
it('should allow of saving the collection', async(() => { it('should allow of saving the collection', waitForAsync(() => {
const template = const template =
'<ul><li *ngFor="let item of items as collection; index as i">{{i}}/{{collection.length}} - {{item}};</li></ul>'; '<ul><li *ngFor="let item of items as collection; index as i">{{i}}/{{collection.length}} - {{item}};</li></ul>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -196,7 +197,7 @@ let thisArg: any;
detectChangesAndExpectText('0/3 - 1;1/3 - 2;2/3 - 3;'); detectChangesAndExpectText('0/3 - 1;1/3 - 2;2/3 - 3;');
})); }));
it('should display indices correctly', async(() => { it('should display indices correctly', waitForAsync(() => {
const template = '<span *ngFor ="let item of items; let i=index">{{i.toString()}}</span>'; const template = '<span *ngFor ="let item of items; let i=index">{{i.toString()}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -207,7 +208,7 @@ let thisArg: any;
detectChangesAndExpectText('0123456789'); detectChangesAndExpectText('0123456789');
})); }));
it('should display count correctly', async(() => { it('should display count correctly', waitForAsync(() => {
const template = '<span *ngFor="let item of items; let len=count">{{len}}</span>'; const template = '<span *ngFor="let item of items; let len=count">{{len}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -218,7 +219,7 @@ let thisArg: any;
detectChangesAndExpectText('666666'); detectChangesAndExpectText('666666');
})); }));
it('should display first item correctly', async(() => { it('should display first item correctly', waitForAsync(() => {
const template = const template =
'<span *ngFor="let item of items; let isFirst=first">{{isFirst.toString()}}</span>'; '<span *ngFor="let item of items; let isFirst=first">{{isFirst.toString()}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -230,7 +231,7 @@ let thisArg: any;
detectChangesAndExpectText('truefalse'); detectChangesAndExpectText('truefalse');
})); }));
it('should display last item correctly', async(() => { it('should display last item correctly', waitForAsync(() => {
const template = const template =
'<span *ngFor="let item of items; let isLast=last">{{isLast.toString()}}</span>'; '<span *ngFor="let item of items; let isLast=last">{{isLast.toString()}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -242,7 +243,7 @@ let thisArg: any;
detectChangesAndExpectText('falsetrue'); detectChangesAndExpectText('falsetrue');
})); }));
it('should display even items correctly', async(() => { it('should display even items correctly', waitForAsync(() => {
const template = const template =
'<span *ngFor="let item of items; let isEven=even">{{isEven.toString()}}</span>'; '<span *ngFor="let item of items; let isEven=even">{{isEven.toString()}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -254,7 +255,7 @@ let thisArg: any;
detectChangesAndExpectText('truefalse'); detectChangesAndExpectText('truefalse');
})); }));
it('should display odd items correctly', async(() => { it('should display odd items correctly', waitForAsync(() => {
const template = const template =
'<span *ngFor="let item of items; let isOdd=odd">{{isOdd.toString()}}</span>'; '<span *ngFor="let item of items; let isOdd=odd">{{isOdd.toString()}}</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -266,7 +267,7 @@ let thisArg: any;
detectChangesAndExpectText('falsetrue'); detectChangesAndExpectText('falsetrue');
})); }));
it('should allow to use a custom template', async(() => { it('should allow to use a custom template', waitForAsync(() => {
const template = const template =
'<ng-container *ngFor="let item of items; template: tpl"></ng-container>' + '<ng-container *ngFor="let item of items; template: tpl"></ng-container>' +
'<ng-template let-item let-i="index" #tpl><p>{{i}}: {{item}};</p></ng-template>'; '<ng-template let-item let-i="index" #tpl><p>{{i}}: {{item}};</p></ng-template>';
@ -276,7 +277,7 @@ let thisArg: any;
detectChangesAndExpectText('0: a;1: b;2: c;'); detectChangesAndExpectText('0: a;1: b;2: c;');
})); }));
it('should use a default template if a custom one is null', async(() => { it('should use a default template if a custom one is null', waitForAsync(() => {
const template = const template =
`<ul><ng-container *ngFor="let item of items; template: null; let i=index">{{i}}: {{item}};</ng-container></ul>`; `<ul><ng-container *ngFor="let item of items; template: null; let i=index">{{i}}: {{item}};</ng-container></ul>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -285,7 +286,8 @@ let thisArg: any;
detectChangesAndExpectText('0: a;1: b;2: c;'); detectChangesAndExpectText('0: a;1: b;2: c;');
})); }));
it('should use a custom template when both default and a custom one are present', async(() => { it('should use a custom template when both default and a custom one are present',
waitForAsync(() => {
const template = const template =
'<ng-container *ngFor="let item of items; template: tpl">{{i}};</ng-container>' + '<ng-container *ngFor="let item of items; template: tpl">{{i}};</ng-container>' +
'<ng-template let-item let-i="index" #tpl>{{i}}: {{item}};</ng-template>'; '<ng-template let-item let-i="index" #tpl>{{i}}: {{item}};</ng-template>';
@ -296,7 +298,7 @@ let thisArg: any;
})); }));
describe('track by', () => { describe('track by', () => {
it('should console.warn if trackBy is not a function', async(() => { it('should console.warn if trackBy is not a function', waitForAsync(() => {
// TODO(vicb): expect a warning message when we have a proper log service // TODO(vicb): expect a warning message when we have a proper log service
const template = `<p *ngFor="let item of items; trackBy: value"></p>`; const template = `<p *ngFor="let item of items; trackBy: value"></p>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -304,7 +306,7 @@ let thisArg: any;
fixture.detectChanges(); fixture.detectChanges();
})); }));
it('should track by identity when trackBy is to `null` or `undefined`', async(() => { it('should track by identity when trackBy is to `null` or `undefined`', waitForAsync(() => {
// TODO(vicb): expect no warning message when we have a proper log service // TODO(vicb): expect no warning message when we have a proper log service
const template = `<p *ngFor="let item of items; trackBy: value">{{ item }}</p>`; const template = `<p *ngFor="let item of items; trackBy: value">{{ item }}</p>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -315,7 +317,7 @@ let thisArg: any;
detectChangesAndExpectText('abc'); detectChangesAndExpectText('abc');
})); }));
it('should set the context to the component instance', async(() => { it('should set the context to the component instance', waitForAsync(() => {
const template = const template =
`<p *ngFor="let item of items; trackBy: trackByContext.bind(this)"></p>`; `<p *ngFor="let item of items; trackBy: trackByContext.bind(this)"></p>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -325,7 +327,7 @@ let thisArg: any;
expect(thisArg).toBe(getComponent()); expect(thisArg).toBe(getComponent());
})); }));
it('should not replace tracked items', async(() => { it('should not replace tracked items', waitForAsync(() => {
const template = const template =
`<p *ngFor="let item of items; trackBy: trackById; let i=index">{{items[i]}}</p>`; `<p *ngFor="let item of items; trackBy: trackById; let i=index">{{items[i]}}</p>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -341,7 +343,7 @@ let thisArg: any;
expect(finalP.nativeElement).toBe(firstP.nativeElement); expect(finalP.nativeElement).toBe(firstP.nativeElement);
})); }));
it('should update implicit local variable on view', async(() => { it('should update implicit local variable on view', waitForAsync(() => {
const template = const template =
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`; `<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -353,7 +355,7 @@ let thisArg: any;
detectChangesAndExpectText('red'); detectChangesAndExpectText('red');
})); }));
it('should move items around and keep them updated ', async(() => { it('should move items around and keep them updated ', waitForAsync(() => {
const template = const template =
`<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`; `<div *ngFor="let item of items; trackBy: trackById">{{item['color']}}</div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -365,7 +367,8 @@ let thisArg: any;
detectChangesAndExpectText('orangered'); detectChangesAndExpectText('orangered');
})); }));
it('should handle added and removed items properly when tracking by index', async(() => { it('should handle added and removed items properly when tracking by index',
waitForAsync(() => {
const template = `<div *ngFor="let item of items; trackBy: trackByIndex">{{item}}</div>`; const template = `<div *ngFor="let item of items; trackBy: trackByIndex">{{item}}</div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);

View File

@ -8,7 +8,7 @@
import {CommonModule, ɵgetDOM as getDOM} from '@angular/common'; import {CommonModule, ɵgetDOM as getDOM} from '@angular/common';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -31,7 +31,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
}); });
}); });
it('should work in a template attribute', async(() => { it('should work in a template attribute', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition">hello</span>'; const template = '<span *ngIf="booleanCondition">hello</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
fixture.detectChanges(); fixture.detectChanges();
@ -39,14 +39,14 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('hello'); expect(fixture.nativeElement).toHaveText('hello');
})); }));
it('should work on a template element', async(() => { it('should work on a template element', waitForAsync(() => {
const template = '<ng-template [ngIf]="booleanCondition">hello2</ng-template>'; const template = '<ng-template [ngIf]="booleanCondition">hello2</ng-template>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('hello2'); expect(fixture.nativeElement).toHaveText('hello2');
})); }));
it('should toggle node when condition changes', async(() => { it('should toggle node when condition changes', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition">hello</span>'; const template = '<span *ngIf="booleanCondition">hello</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
getComponent().booleanCondition = false; getComponent().booleanCondition = false;
@ -65,7 +65,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
})); }));
it('should handle nested if correctly', async(() => { it('should handle nested if correctly', waitForAsync(() => {
const template = const template =
'<div *ngIf="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></div>'; '<div *ngIf="booleanCondition"><span *ngIf="nestedBooleanCondition">hello</span></div>';
@ -97,7 +97,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
})); }));
it('should update several nodes with if', async(() => { it('should update several nodes with if', waitForAsync(() => {
const template = '<span *ngIf="numberCondition + 1 >= 2">helloNumber</span>' + const template = '<span *ngIf="numberCondition + 1 >= 2">helloNumber</span>' +
'<span *ngIf="stringCondition == \'foo\'">helloString</span>' + '<span *ngIf="stringCondition == \'foo\'">helloString</span>' +
'<span *ngIf="functionCondition(stringCondition, numberCondition)">helloFunction</span>'; '<span *ngIf="functionCondition(stringCondition, numberCondition)">helloFunction</span>';
@ -120,7 +120,8 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('helloNumber'); expect(fixture.nativeElement).toHaveText('helloNumber');
})); }));
it('should not add the element twice if the condition goes from truthy to truthy', async(() => { it('should not add the element twice if the condition goes from truthy to truthy',
waitForAsync(() => {
const template = '<span *ngIf="numberCondition">hello</span>'; const template = '<span *ngIf="numberCondition">hello</span>';
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -141,7 +142,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
})); }));
describe('then/else templates', () => { describe('then/else templates', () => {
it('should support else', async(() => { it('should support else', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition; else elseBlock">TRUE</span>' + const template = '<span *ngIf="booleanCondition; else elseBlock">TRUE</span>' +
'<ng-template #elseBlock>FALSE</ng-template>'; '<ng-template #elseBlock>FALSE</ng-template>';
@ -155,7 +156,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('FALSE'); expect(fixture.nativeElement).toHaveText('FALSE');
})); }));
it('should support then and else', async(() => { it('should support then and else', waitForAsync(() => {
const template = const template =
'<span *ngIf="booleanCondition; then thenBlock; else elseBlock">IGNORE</span>' + '<span *ngIf="booleanCondition; then thenBlock; else elseBlock">IGNORE</span>' +
'<ng-template #thenBlock>THEN</ng-template>' + '<ng-template #thenBlock>THEN</ng-template>' +
@ -202,7 +203,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText(''); expect(fixture.nativeElement).toHaveText('');
}); });
it('should support dynamic else', async(() => { it('should support dynamic else', waitForAsync(() => {
const template = const template =
'<span *ngIf="booleanCondition; else nestedBooleanCondition ? b1 : b2">TRUE</span>' + '<span *ngIf="booleanCondition; else nestedBooleanCondition ? b1 : b2">TRUE</span>' +
'<ng-template #b1>FALSE1</ng-template>' + '<ng-template #b1>FALSE1</ng-template>' +
@ -222,7 +223,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('FALSE2'); expect(fixture.nativeElement).toHaveText('FALSE2');
})); }));
it('should support binding to variable using let', async(() => { it('should support binding to variable using let', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition; else elseBlock; let v">{{v}}</span>' + const template = '<span *ngIf="booleanCondition; else elseBlock; let v">{{v}}</span>' +
'<ng-template #elseBlock let-v>{{v}}</ng-template>'; '<ng-template #elseBlock let-v>{{v}}</ng-template>';
@ -236,7 +237,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('false'); expect(fixture.nativeElement).toHaveText('false');
})); }));
it('should support binding to variable using as', async(() => { it('should support binding to variable using as', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition as v; else elseBlock">{{v}}</span>' + const template = '<span *ngIf="booleanCondition as v; else elseBlock">{{v}}</span>' +
'<ng-template #elseBlock let-v>{{v}}</ng-template>'; '<ng-template #elseBlock let-v>{{v}}</ng-template>';
@ -252,7 +253,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
}); });
describe('Type guarding', () => { describe('Type guarding', () => {
it('should throw when then block is not template', async(() => { it('should throw when then block is not template', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition; then thenBlock">IGNORE</span>' + const template = '<span *ngIf="booleanCondition; then thenBlock">IGNORE</span>' +
'<div #thenBlock>THEN</div>'; '<div #thenBlock>THEN</div>';
@ -262,7 +263,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
.toThrowError(/ngIfThen must be a TemplateRef, but received/); .toThrowError(/ngIfThen must be a TemplateRef, but received/);
})); }));
it('should throw when else block is not template', async(() => { it('should throw when else block is not template', waitForAsync(() => {
const template = '<span *ngIf="booleanCondition; else elseBlock">IGNORE</span>' + const template = '<span *ngIf="booleanCondition; else elseBlock">IGNORE</span>' +
'<div #elseBlock>ELSE</div>'; '<div #elseBlock>ELSE</div>';

View File

@ -8,7 +8,7 @@
import {CommonModule, NgLocalization} from '@angular/common'; import {CommonModule, NgLocalization} from '@angular/common';
import {Component, Injectable} from '@angular/core'; import {Component, Injectable} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
{ {
@ -36,7 +36,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
}); });
}); });
it('should display the template according to the exact value', async(() => { it('should display the template according to the exact value', waitForAsync(() => {
const template = '<ul [ngPlural]="switchValue">' + const template = '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="=0"><li>you have no messages.</li></ng-template>' + '<ng-template ngPluralCase="=0"><li>you have no messages.</li></ng-template>' +
'<ng-template ngPluralCase="=1"><li>you have one message.</li></ng-template>' + '<ng-template ngPluralCase="=1"><li>you have one message.</li></ng-template>' +
@ -51,7 +51,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
detectChangesAndExpectText('you have one message.'); detectChangesAndExpectText('you have one message.');
})); }));
it('should display the template according to the exact numeric value', async(() => { it('should display the template according to the exact numeric value', waitForAsync(() => {
const template = '<div>' + const template = '<div>' +
'<ul [ngPlural]="switchValue">' + '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="0"><li>you have no messages.</li></ng-template>' + '<ng-template ngPluralCase="0"><li>you have no messages.</li></ng-template>' +
@ -69,7 +69,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
// https://github.com/angular/angular/issues/9868 // https://github.com/angular/angular/issues/9868
// https://github.com/angular/angular/issues/9882 // https://github.com/angular/angular/issues/9882
it('should not throw when ngPluralCase contains expressions', async(() => { it('should not throw when ngPluralCase contains expressions', waitForAsync(() => {
const template = '<ul [ngPlural]="switchValue">' + const template = '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="=0"><li>{{ switchValue }}</li></ng-template>' + '<ng-template ngPluralCase="=0"><li>{{ switchValue }}</li></ng-template>' +
'</ul>'; '</ul>';
@ -81,7 +81,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
})); }));
it('should be applicable to <ng-container> elements', async(() => { it('should be applicable to <ng-container> elements', waitForAsync(() => {
const template = '<ng-container [ngPlural]="switchValue">' + const template = '<ng-container [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="=0">you have no messages.</ng-template>' + '<ng-template ngPluralCase="=0">you have no messages.</ng-template>' +
'<ng-template ngPluralCase="=1">you have one message.</ng-template>' + '<ng-template ngPluralCase="=1">you have one message.</ng-template>' +
@ -96,7 +96,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
detectChangesAndExpectText('you have one message.'); detectChangesAndExpectText('you have one message.');
})); }));
it('should display the template according to the category', async(() => { it('should display the template according to the category', waitForAsync(() => {
const template = '<ul [ngPlural]="switchValue">' + const template = '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' + '<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' +
'<ng-template ngPluralCase="many"><li>you have many messages.</li></ng-template>' + '<ng-template ngPluralCase="many"><li>you have many messages.</li></ng-template>' +
@ -111,7 +111,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
detectChangesAndExpectText('you have many messages.'); detectChangesAndExpectText('you have many messages.');
})); }));
it('should default to other when no matches are found', async(() => { it('should default to other when no matches are found', waitForAsync(() => {
const template = '<ul [ngPlural]="switchValue">' + const template = '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' + '<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' +
'<ng-template ngPluralCase="other"><li>default message.</li></ng-template>' + '<ng-template ngPluralCase="other"><li>default message.</li></ng-template>' +
@ -123,7 +123,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
detectChangesAndExpectText('default message.'); detectChangesAndExpectText('default message.');
})); }));
it('should prioritize value matches over category matches', async(() => { it('should prioritize value matches over category matches', waitForAsync(() => {
const template = '<ul [ngPlural]="switchValue">' + const template = '<ul [ngPlural]="switchValue">' +
'<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' + '<ng-template ngPluralCase="few"><li>you have a few messages.</li></ng-template>' +
'<ng-template ngPluralCase="=2">you have two messages.</ng-template>' + '<ng-template ngPluralCase="=2">you have two messages.</ng-template>' +

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
{ {
describe('NgStyle', () => { describe('NgStyle', () => {
@ -30,14 +30,14 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
TestBed.configureTestingModule({declarations: [TestComponent], imports: [CommonModule]}); TestBed.configureTestingModule({declarations: [TestComponent], imports: [CommonModule]});
}); });
it('should add styles specified in an object literal', async(() => { it('should add styles specified in an object literal', waitForAsync(() => {
const template = `<div [ngStyle]="{'max-width': '40px'}"></div>`; const template = `<div [ngStyle]="{'max-width': '40px'}"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
fixture.detectChanges(); fixture.detectChanges();
expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'}); expectNativeEl(fixture).toHaveCssStyle({'max-width': '40px'});
})); }));
it('should add and change styles specified in an object expression', async(() => { it('should add and change styles specified in an object expression', waitForAsync(() => {
const template = `<div [ngStyle]="expr"></div>`; const template = `<div [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -51,7 +51,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
expectNativeEl(fixture).toHaveCssStyle({'max-width': '30%'}); expectNativeEl(fixture).toHaveCssStyle({'max-width': '30%'});
})); }));
it('should add and remove styles specified using style.unit notation', async(() => { it('should add and remove styles specified using style.unit notation', waitForAsync(() => {
const template = `<div [ngStyle]="{'max-width.px': expr}"></div>`; const template = `<div [ngStyle]="{'max-width.px': expr}"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -66,7 +66,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
// https://github.com/angular/angular/issues/21064 // https://github.com/angular/angular/issues/21064
it('should add and remove styles which names are not dash-cased', async(() => { it('should add and remove styles which names are not dash-cased', waitForAsync(() => {
fixture = createTestComponent(`<div [ngStyle]="{'color': expr}"></div>`); fixture = createTestComponent(`<div [ngStyle]="{'color': expr}"></div>`);
getComponent().expr = 'green'; getComponent().expr = 'green';
@ -78,7 +78,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
expectNativeEl(fixture).not.toHaveCssStyle('color'); expectNativeEl(fixture).not.toHaveCssStyle('color');
})); }));
it('should update styles using style.unit notation when unit changes', async(() => { it('should update styles using style.unit notation when unit changes', waitForAsync(() => {
const template = `<div [ngStyle]="expr"></div>`; const template = `<div [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -93,7 +93,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
// keyValueDiffer is sensitive to key order #9115 // keyValueDiffer is sensitive to key order #9115
it('should change styles specified in an object expression', async(() => { it('should change styles specified in an object expression', waitForAsync(() => {
const template = `<div [ngStyle]="expr"></div>`; const template = `<div [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -117,7 +117,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
expectNativeEl(fixture).toHaveCssStyle({'height': '5px', 'width': '5px'}); expectNativeEl(fixture).toHaveCssStyle({'height': '5px', 'width': '5px'});
})); }));
it('should remove styles when deleting a key in an object expression', async(() => { it('should remove styles when deleting a key in an object expression', waitForAsync(() => {
const template = `<div [ngStyle]="expr"></div>`; const template = `<div [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -131,7 +131,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
expectNativeEl(fixture).not.toHaveCssStyle('max-width'); expectNativeEl(fixture).not.toHaveCssStyle('max-width');
})); }));
it('should co-operate with the style attribute', async(() => { it('should co-operate with the style attribute', waitForAsync(() => {
const template = `<div style="font-size: 12px" [ngStyle]="expr"></div>`; const template = `<div style="font-size: 12px" [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -147,7 +147,7 @@ import {async, ComponentFixture, TestBed} from '@angular/core/testing';
})); }));
it('should co-operate with the style.[styleName]="expr" special-case in the compiler', it('should co-operate with the style.[styleName]="expr" special-case in the compiler',
async(() => { waitForAsync(() => {
const template = `<div [style.font-size.px]="12" [ngStyle]="expr"></div>`; const template = `<div [style.font-size.px]="12" [ngStyle]="expr"></div>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {Component, ContentChildren, Directive, Injectable, NO_ERRORS_SCHEMA, OnDestroy, QueryList, TemplateRef} from '@angular/core'; import {Component, ContentChildren, Directive, Injectable, NO_ERRORS_SCHEMA, OnDestroy, QueryList, TemplateRef} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('NgTemplateOutlet', () => { describe('NgTemplateOutlet', () => {
@ -36,7 +36,7 @@ describe('NgTemplateOutlet', () => {
}); });
// https://github.com/angular/angular/issues/14778 // https://github.com/angular/angular/issues/14778
it('should accept the component as the context', async(() => { it('should accept the component as the context', waitForAsync(() => {
const template = `<ng-container *ngTemplateOutlet="tpl; context: this"></ng-container>` + const template = `<ng-container *ngTemplateOutlet="tpl; context: this"></ng-container>` +
`<ng-template #tpl>{{context.foo}}</ng-template>`; `<ng-template #tpl>{{context.foo}}</ng-template>`;
@ -44,20 +44,20 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText('bar'); detectChangesAndExpectText('bar');
})); }));
it('should do nothing if templateRef is `null`', async(() => { it('should do nothing if templateRef is `null`', waitForAsync(() => {
const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`; const template = `<ng-container [ngTemplateOutlet]="null"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
detectChangesAndExpectText(''); detectChangesAndExpectText('');
})); }));
it('should insert content specified by TemplateRef', async(() => { it('should insert content specified by TemplateRef', waitForAsync(() => {
const template = `<ng-template #tpl>foo</ng-template>` + const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container [ngTemplateOutlet]="tpl"></ng-container>`; `<ng-container [ngTemplateOutlet]="tpl"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
detectChangesAndExpectText('foo'); detectChangesAndExpectText('foo');
})); }));
it('should clear content if TemplateRef becomes `null`', async(() => { it('should clear content if TemplateRef becomes `null`', waitForAsync(() => {
const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` + const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`; `<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -71,7 +71,7 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText(''); detectChangesAndExpectText('');
})); }));
it('should swap content if TemplateRef changes', async(() => { it('should swap content if TemplateRef changes', waitForAsync(() => {
const template = const template =
`<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template><ng-template>bar</ng-template></tpl-refs>` + `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template><ng-template>bar</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`; `<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
@ -87,14 +87,14 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText('bar'); detectChangesAndExpectText('bar');
})); }));
it('should display template if context is `null`', async(() => { it('should display template if context is `null`', waitForAsync(() => {
const template = `<ng-template #tpl>foo</ng-template>` + const template = `<ng-template #tpl>foo</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: null"></ng-container>`; `<ng-container *ngTemplateOutlet="tpl; context: null"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
detectChangesAndExpectText('foo'); detectChangesAndExpectText('foo');
})); }));
it('should reflect initial context and changes', async(() => { it('should reflect initial context and changes', waitForAsync(() => {
const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` + const template = `<ng-template let-foo="foo" #tpl>{{foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`; `<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -106,7 +106,7 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText('alter-bar'); detectChangesAndExpectText('alter-bar');
})); }));
it('should reflect user defined `$implicit` property in the context', async(() => { it('should reflect user defined `$implicit` property in the context', waitForAsync(() => {
const template = `<ng-template let-ctx #tpl>{{ctx.foo}}</ng-template>` + const template = `<ng-template let-ctx #tpl>{{ctx.foo}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`; `<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -114,7 +114,7 @@ describe('NgTemplateOutlet', () => {
detectChangesAndExpectText('bra'); detectChangesAndExpectText('bra');
})); }));
it('should reflect context re-binding', async(() => { it('should reflect context re-binding', waitForAsync(() => {
const template = `<ng-template let-shawshank="shawshank" #tpl>{{shawshank}}</ng-template>` + const template = `<ng-template let-shawshank="shawshank" #tpl>{{shawshank}}</ng-template>` +
`<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`; `<ng-container *ngTemplateOutlet="tpl; context: context"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);
@ -222,7 +222,8 @@ describe('NgTemplateOutlet', () => {
}).not.toThrow(); }).not.toThrow();
}); });
it('should not throw when switching from template to null and back to template', async(() => { it('should not throw when switching from template to null and back to template',
waitForAsync(() => {
const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` + const template = `<tpl-refs #refs="tplRefs"><ng-template>foo</ng-template></tpl-refs>` +
`<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`; `<ng-container [ngTemplateOutlet]="currentTplRef"></ng-container>`;
fixture = createTestComponent(template); fixture = createTestComponent(template);

View File

@ -9,7 +9,7 @@
import {ɵgetDOM as getDOM} from '@angular/common'; import {ɵgetDOM as getDOM} from '@angular/common';
import {Component, Directive} from '@angular/core'; import {Component, Directive} from '@angular/core';
import {ElementRef} from '@angular/core/src/linker/element_ref'; import {ElementRef} from '@angular/core/src/linker/element_ref';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {hasClass} from '@angular/platform-browser/testing/src/browser_util'; import {hasClass} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -21,7 +21,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
}); });
}); });
it('should not interpolate children', async(() => { it('should not interpolate children', waitForAsync(() => {
const template = '<div>{{text}}<span ngNonBindable>{{text}}</span></div>'; const template = '<div>{{text}}<span ngNonBindable>{{text}}</span></div>';
const fixture = createTestComponent(template); const fixture = createTestComponent(template);
@ -29,7 +29,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(fixture.nativeElement).toHaveText('foo{{text}}'); expect(fixture.nativeElement).toHaveText('foo{{text}}');
})); }));
it('should ignore directives on child nodes', async(() => { it('should ignore directives on child nodes', waitForAsync(() => {
const template = '<div ngNonBindable><span id=child test-dec>{{text}}</span></div>'; const template = '<div ngNonBindable><span id=child test-dec>{{text}}</span></div>';
const fixture = createTestComponent(template); const fixture = createTestComponent(template);
fixture.detectChanges(); fixture.detectChanges();
@ -40,7 +40,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
expect(hasClass(span, 'compiled')).toBeFalsy(); expect(hasClass(span, 'compiled')).toBeFalsy();
})); }));
it('should trigger directives on the same node', async(() => { it('should trigger directives on the same node', waitForAsync(() => {
const template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>'; const template = '<div><span id=child ngNonBindable test-dec>{{text}}</span></div>';
const fixture = createTestComponent(template); const fixture = createTestComponent(template);
fixture.detectChanges(); fixture.detectChanges();

View File

@ -8,7 +8,7 @@
import {CommonModule, JsonPipe} from '@angular/common'; import {CommonModule, JsonPipe} from '@angular/common';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, TestBed} from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
{ {
@ -64,7 +64,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
TestBed.configureTestingModule({declarations: [TestComp], imports: [CommonModule]}); TestBed.configureTestingModule({declarations: [TestComp], imports: [CommonModule]});
}); });
it('should work with mutable objects', async(() => { it('should work with mutable objects', waitForAsync(() => {
const fixture = TestBed.createComponent(TestComp); const fixture = TestBed.createComponent(TestComp);
const mutable: number[] = [1]; const mutable: number[] = [1];
fixture.componentInstance.data = mutable; fixture.componentInstance.data = mutable;

View File

@ -8,7 +8,7 @@
import {CommonModule, SlicePipe} from '@angular/common'; import {CommonModule, SlicePipe} from '@angular/common';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, TestBed} from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
{ {
@ -105,7 +105,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
TestBed.configureTestingModule({declarations: [TestComp], imports: [CommonModule]}); TestBed.configureTestingModule({declarations: [TestComp], imports: [CommonModule]});
}); });
it('should work with mutable arrays', async(() => { it('should work with mutable arrays', waitForAsync(() => {
const fixture = TestBed.createComponent(TestComp); const fixture = TestBed.createComponent(TestComp);
const mutable: number[] = [1, 2]; const mutable: number[] = [1, 2];
fixture.componentInstance.data = mutable; fixture.componentInstance.data = mutable;

View File

@ -7,15 +7,15 @@
*/ */
import {Xliff2} from '@angular/compiler/src/i18n/serializers/xliff2'; import {Xliff2} from '@angular/compiler/src/i18n/serializers/xliff2';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common'; import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
describe('i18n XLIFF integration spec', () => { describe('i18n XLIFF integration spec', () => {
describe('(with LF line endings)', () => { describe('(with LF line endings)', () => {
beforeEach( beforeEach(waitForAsync(
async(() => configureCompiler(XLIFF2_TOMERGE + LF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2'))); () => configureCompiler(XLIFF2_TOMERGE + LF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2')));
it('should extract from templates', () => { it('should extract from templates', () => {
const serializer = new Xliff2(); const serializer = new Xliff2();
@ -34,8 +34,8 @@ describe('i18n XLIFF integration spec', () => {
}); });
describe('(with CRLF line endings', () => { describe('(with CRLF line endings', () => {
beforeEach( beforeEach(waitForAsync(
async(() => configureCompiler(XLIFF2_TOMERGE + CRLF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2'))); () => configureCompiler(XLIFF2_TOMERGE + CRLF_LINE_ENDING_XLIFF2_TOMERGE, 'xlf2')));
it('should extract from templates (with CRLF line endings)', () => { it('should extract from templates (with CRLF line endings)', () => {
const serializer = new Xliff2(); const serializer = new Xliff2();

View File

@ -7,14 +7,15 @@
*/ */
import {Xliff} from '@angular/compiler/src/i18n/serializers/xliff'; import {Xliff} from '@angular/compiler/src/i18n/serializers/xliff';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common'; import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
describe('i18n XLIFF integration spec', () => { describe('i18n XLIFF integration spec', () => {
describe('(with LF line endings)', () => { describe('(with LF line endings)', () => {
beforeEach(async(() => configureCompiler(XLIFF_TOMERGE + LF_LINE_ENDING_XLIFF_TOMERGE, 'xlf'))); beforeEach(
waitForAsync(() => configureCompiler(XLIFF_TOMERGE + LF_LINE_ENDING_XLIFF_TOMERGE, 'xlf')));
it('should extract from templates', () => { it('should extract from templates', () => {
const serializer = new Xliff(); const serializer = new Xliff();
@ -33,8 +34,8 @@ describe('i18n XLIFF integration spec', () => {
}); });
describe('(with CRLF line endings', () => { describe('(with CRLF line endings', () => {
beforeEach( beforeEach(waitForAsync(
async(() => configureCompiler(XLIFF_TOMERGE + CRLF_LINE_ENDING_XLIFF_TOMERGE, 'xlf'))); () => configureCompiler(XLIFF_TOMERGE + CRLF_LINE_ENDING_XLIFF_TOMERGE, 'xlf')));
it('should extract from templates (with CRLF line endings)', () => { it('should extract from templates (with CRLF line endings)', () => {
const serializer = new Xliff(); const serializer = new Xliff();

View File

@ -7,14 +7,14 @@
*/ */
import {Xmb} from '@angular/compiler/src/i18n/serializers/xmb'; import {Xmb} from '@angular/compiler/src/i18n/serializers/xmb';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common'; import {configureCompiler, createComponent, HTML, serializeTranslations, validateHtml} from './integration_common';
describe('i18n XMB/XTB integration spec', () => { describe('i18n XMB/XTB integration spec', () => {
describe('(with LF line endings)', () => { describe('(with LF line endings)', () => {
beforeEach(async(() => configureCompiler(XTB + LF_LINE_ENDING_XTB, 'xtb'))); beforeEach(waitForAsync(() => configureCompiler(XTB + LF_LINE_ENDING_XTB, 'xtb')));
it('should extract from templates', () => { it('should extract from templates', () => {
const serializer = new Xmb(); const serializer = new Xmb();
@ -33,7 +33,7 @@ describe('i18n XMB/XTB integration spec', () => {
}); });
describe('(with CRLF line endings', () => { describe('(with CRLF line endings', () => {
beforeEach(async(() => configureCompiler(XTB + CRLF_LINE_ENDING_XTB, 'xtb'))); beforeEach(waitForAsync(() => configureCompiler(XTB + CRLF_LINE_ENDING_XTB, 'xtb')));
it('should extract from templates (with CRLF line endings)', () => { it('should extract from templates (with CRLF line endings)', () => {
const serializer = new Xmb(); const serializer = new Xmb();

View File

@ -7,7 +7,7 @@
*/ */
import {Component, Directive, Input} from '@angular/core'; import {Component, Directive, Input} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util'; import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -17,7 +17,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
let fixture: ComponentFixture<TestComponent>; let fixture: ComponentFixture<TestComponent>;
describe('directives', () => { describe('directives', () => {
it('should support dotted selectors', async(() => { it('should support dotted selectors', waitForAsync(() => {
@Directive({selector: '[dot.name]'}) @Directive({selector: '[dot.name]'})
class MyDir { class MyDir {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
@ -41,7 +41,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
describe('ng-container', () => { describe('ng-container', () => {
if (browserDetection.isChromeDesktop) { if (browserDetection.isChromeDesktop) {
it('should work regardless the namespace', async(() => { it('should work regardless the namespace', waitForAsync(() => {
@Component({ @Component({
selector: 'comp', selector: 'comp',
template: template:

View File

@ -8,7 +8,7 @@
import {LIFECYCLE_HOOKS_VALUES, LifecycleHooks} from '@angular/compiler/src/lifecycle_reflector'; import {LIFECYCLE_HOOKS_VALUES, LifecycleHooks} from '@angular/compiler/src/lifecycle_reflector';
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, Component, Directive, DoCheck, Injectable, NgModule, OnChanges, OnDestroy, OnInit, Pipe, SimpleChanges, ViewEncapsulation, ɵstringify as stringify} from '@angular/core'; import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ChangeDetectionStrategy, Component, Directive, DoCheck, Injectable, NgModule, OnChanges, OnDestroy, OnInit, Pipe, SimpleChanges, ViewEncapsulation, ɵstringify as stringify} from '@angular/core';
import {async, inject, TestBed} from '@angular/core/testing'; import {inject, TestBed, waitForAsync} from '@angular/core/testing';
import {CompileDiDependencyMetadata, identifierName} from '../src/compile_metadata'; import {CompileDiDependencyMetadata, identifierName} from '../src/compile_metadata';
import {CompileMetadataResolver} from '../src/metadata_resolver'; import {CompileMetadataResolver} from '../src/metadata_resolver';
@ -77,7 +77,7 @@ import {TEST_COMPILER_PROVIDERS} from './test_bindings';
})); }));
it('should read external metadata when sync=false', it('should read external metadata when sync=false',
async(inject( waitForAsync(inject(
[CompileMetadataResolver, ResourceLoader], [CompileMetadataResolver, ResourceLoader],
(resolver: CompileMetadataResolver, resourceLoader: MockResourceLoader) => { (resolver: CompileMetadataResolver, resourceLoader: MockResourceLoader) => {
@NgModule({declarations: [ComponentWithExternalResources]}) @NgModule({declarations: [ComponentWithExternalResources]})
@ -96,7 +96,7 @@ import {TEST_COMPILER_PROVIDERS} from './test_bindings';
}))); })));
it('should use `./` as base url for templates during runtime compilation if no moduleId is given', it('should use `./` as base url for templates during runtime compilation if no moduleId is given',
async(inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => { waitForAsync(inject([CompileMetadataResolver], (resolver: CompileMetadataResolver) => {
@Component({selector: 'someComponent', templateUrl: 'someUrl'}) @Component({selector: 'someComponent', templateUrl: 'someUrl'})
class ComponentWithoutModuleId { class ComponentWithoutModuleId {
} }

View File

@ -8,7 +8,7 @@
import {DirectiveResolver, ResourceLoader} from '@angular/compiler'; import {DirectiveResolver, ResourceLoader} from '@angular/compiler';
import {Compiler, Component, Injector, NgModule, NgModuleFactory, ɵstringify as stringify} from '@angular/core'; import {Compiler, Component, Injector, NgModule, NgModuleFactory, ɵstringify as stringify} from '@angular/core';
import {async, fakeAsync, inject, TestBed, tick} from '@angular/core/testing'; import {fakeAsync, inject, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {MockDirectiveResolver} from '../testing'; import {MockDirectiveResolver} from '../testing';
@ -42,7 +42,8 @@ class SomeCompWithUrlTemplate {
{providers: [{provide: ResourceLoader, useClass: StubResourceLoader, deps: []}]}); {providers: [{provide: ResourceLoader, useClass: StubResourceLoader, deps: []}]});
}); });
it('should throw when using a templateUrl that has not been compiled before', async(() => { it('should throw when using a templateUrl that has not been compiled before',
waitForAsync(() => {
TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]}); TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]});
TestBed.compileComponents().then(() => { TestBed.compileComponents().then(() => {
expect(() => TestBed.createComponent(SomeCompWithUrlTemplate)) expect(() => TestBed.createComponent(SomeCompWithUrlTemplate))
@ -76,7 +77,8 @@ class SomeCompWithUrlTemplate {
{providers: [{provide: ResourceLoader, useClass: StubResourceLoader, deps: []}]}); {providers: [{provide: ResourceLoader, useClass: StubResourceLoader, deps: []}]});
}); });
it('should allow to use templateUrl components that have been loaded before', async(() => { it('should allow to use templateUrl components that have been loaded before',
waitForAsync(() => {
TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]}); TestBed.configureTestingModule({declarations: [SomeCompWithUrlTemplate]});
TestBed.compileComponents().then(() => { TestBed.compileComponents().then(() => {
const fixture = TestBed.createComponent(SomeCompWithUrlTemplate); const fixture = TestBed.createComponent(SomeCompWithUrlTemplate);

View File

@ -8,7 +8,7 @@
import {CommonModule} from '@angular/common'; import {CommonModule} from '@angular/common';
import {Component, Directive, forwardRef, Inject, Injectable, InjectionToken, Injector, NgModule, Optional} from '@angular/core'; import {Component, Directive, forwardRef, Inject, Injectable, InjectionToken, Injector, NgModule, Optional} from '@angular/core';
import {async, inject, TestBed} from '@angular/core/testing'; import {inject, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser'; import {By} from '@angular/platform-browser';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy, onlyInIvy} from '@angular/private/testing'; import {modifiedInIvy, onlyInIvy} from '@angular/private/testing';
@ -603,7 +603,7 @@ describe('providers', () => {
}); });
it('should support injecting without bootstrapping', it('should support injecting without bootstrapping',
async(inject([MyComp, MyService], (comp: MyComp, service: MyService) => { waitForAsync(inject([MyComp, MyService], (comp: MyComp, service: MyService) => {
expect(comp.svc.value).toEqual('some value'); expect(comp.svc.value).toEqual('some value');
}))); })));
}); });

View File

@ -8,19 +8,19 @@
import {Injector} from '@angular/core'; import {Injector} from '@angular/core';
import {APP_INITIALIZER, ApplicationInitStatus} from '@angular/core/src/application_init'; import {APP_INITIALIZER, ApplicationInitStatus} from '@angular/core/src/application_init';
import {async, inject, TestBed} from '../testing'; import {inject, TestBed, waitForAsync} from '../testing';
{ {
describe('ApplicationInitStatus', () => { describe('ApplicationInitStatus', () => {
describe('no initializers', () => { describe('no initializers', () => {
it('should return true for `done`', it('should return true for `done`',
async(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => { waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
(status as any).runInitializers(); (status as any).runInitializers();
expect(status.done).toBe(true); expect(status.done).toBe(true);
}))); })));
it('should return a promise that resolves immediately for `donePromise`', it('should return a promise that resolves immediately for `donePromise`',
async(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => { waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
(status as any).runInitializers(); (status as any).runInitializers();
status.donePromise.then(() => { status.donePromise.then(() => {
expect(status.done).toBe(true); expect(status.done).toBe(true);
@ -58,7 +58,7 @@ import {async, inject, TestBed} from '../testing';
}); });
it('should update the status once all async initializers are done', it('should update the status once all async initializers are done',
async(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => { waitForAsync(inject([ApplicationInitStatus], (status: ApplicationInitStatus) => {
(status as any).runInitializers(); (status as any).runInitializers();
setTimeout(() => { setTimeout(() => {

View File

@ -19,7 +19,7 @@ import {expect} from '@angular/platform-browser/testing/src/matchers';
import {onlyInIvy} from '@angular/private/testing'; import {onlyInIvy} from '@angular/private/testing';
import {NoopNgZone} from '../src/zone/ng_zone'; import {NoopNgZone} from '../src/zone/ng_zone';
import {async, ComponentFixtureNoNgZone, inject, TestBed, withModule} from '../testing'; import {ComponentFixtureNoNgZone, inject, TestBed, waitForAsync, withModule} from '../testing';
@Component({selector: 'bootstrap-app', template: 'hello'}) @Component({selector: 'bootstrap-app', template: 'hello'})
class SomeComponent { class SomeComponent {
@ -79,62 +79,66 @@ class SomeComponent {
} }
it('should bootstrap a component from a child module', it('should bootstrap a component from a child module',
async(inject([ApplicationRef, Compiler], (app: ApplicationRef, compiler: Compiler) => { waitForAsync(
@Component({ inject([ApplicationRef, Compiler], (app: ApplicationRef, compiler: Compiler) => {
selector: 'bootstrap-app', @Component({
template: '', selector: 'bootstrap-app',
}) template: '',
class SomeComponent { })
} class SomeComponent {
}
const helloToken = new InjectionToken<string>('hello'); const helloToken = new InjectionToken<string>('hello');
@NgModule({ @NgModule({
providers: [{provide: helloToken, useValue: 'component'}], providers: [{provide: helloToken, useValue: 'component'}],
declarations: [SomeComponent], declarations: [SomeComponent],
entryComponents: [SomeComponent], entryComponents: [SomeComponent],
}) })
class SomeModule { class SomeModule {
} }
createRootEl(); createRootEl();
const modFactory = compiler.compileModuleSync(SomeModule); const modFactory = compiler.compileModuleSync(SomeModule);
const module = modFactory.create(TestBed); const module = modFactory.create(TestBed);
const cmpFactory = module.componentFactoryResolver.resolveComponentFactory(SomeComponent)!; const cmpFactory =
const component = app.bootstrap(cmpFactory); module.componentFactoryResolver.resolveComponentFactory(SomeComponent)!;
const component = app.bootstrap(cmpFactory);
// The component should see the child module providers // The component should see the child module providers
expect(component.injector.get(helloToken)).toEqual('component'); expect(component.injector.get(helloToken)).toEqual('component');
}))); })));
it('should bootstrap a component with a custom selector', it('should bootstrap a component with a custom selector',
async(inject([ApplicationRef, Compiler], (app: ApplicationRef, compiler: Compiler) => { waitForAsync(
@Component({ inject([ApplicationRef, Compiler], (app: ApplicationRef, compiler: Compiler) => {
selector: 'bootstrap-app', @Component({
template: '', selector: 'bootstrap-app',
}) template: '',
class SomeComponent { })
} class SomeComponent {
}
const helloToken = new InjectionToken<string>('hello'); const helloToken = new InjectionToken<string>('hello');
@NgModule({ @NgModule({
providers: [{provide: helloToken, useValue: 'component'}], providers: [{provide: helloToken, useValue: 'component'}],
declarations: [SomeComponent], declarations: [SomeComponent],
entryComponents: [SomeComponent], entryComponents: [SomeComponent],
}) })
class SomeModule { class SomeModule {
} }
createRootEl('custom-selector'); createRootEl('custom-selector');
const modFactory = compiler.compileModuleSync(SomeModule); const modFactory = compiler.compileModuleSync(SomeModule);
const module = modFactory.create(TestBed); const module = modFactory.create(TestBed);
const cmpFactory = module.componentFactoryResolver.resolveComponentFactory(SomeComponent)!; const cmpFactory =
const component = app.bootstrap(cmpFactory, 'custom-selector'); module.componentFactoryResolver.resolveComponentFactory(SomeComponent)!;
const component = app.bootstrap(cmpFactory, 'custom-selector');
// The component should see the child module providers // The component should see the child module providers
expect(component.injector.get(helloToken)).toEqual('component'); expect(component.injector.get(helloToken)).toEqual('component');
}))); })));
describe('ApplicationRef', () => { describe('ApplicationRef', () => {
beforeEach(() => { beforeEach(() => {
@ -216,7 +220,7 @@ class SomeComponent {
defaultPlatform = _platform; defaultPlatform = _platform;
})); }));
it('should wait for asynchronous app initializers', async(() => { it('should wait for asynchronous app initializers', waitForAsync(() => {
let resolve: (result: any) => void; let resolve: (result: any) => void;
const promise: Promise<any> = new Promise((res) => { const promise: Promise<any> = new Promise((res) => {
resolve = res; resolve = res;
@ -235,7 +239,8 @@ class SomeComponent {
}); });
})); }));
it('should rethrow sync errors even if the exceptionHandler is not rethrowing', async(() => { it('should rethrow sync errors even if the exceptionHandler is not rethrowing',
waitForAsync(() => {
defaultPlatform defaultPlatform
.bootstrapModule(createModule([{ .bootstrapModule(createModule([{
provide: APP_INITIALIZER, provide: APP_INITIALIZER,
@ -253,7 +258,7 @@ class SomeComponent {
})); }));
it('should rethrow promise errors even if the exceptionHandler is not rethrowing', it('should rethrow promise errors even if the exceptionHandler is not rethrowing',
async(() => { waitForAsync(() => {
defaultPlatform defaultPlatform
.bootstrapModule(createModule([ .bootstrapModule(createModule([
{provide: APP_INITIALIZER, useValue: () => Promise.reject('Test'), multi: true} {provide: APP_INITIALIZER, useValue: () => Promise.reject('Test'), multi: true}
@ -264,7 +269,7 @@ class SomeComponent {
}); });
})); }));
it('should throw useful error when ApplicationRef is not configured', async(() => { it('should throw useful error when ApplicationRef is not configured', waitForAsync(() => {
@NgModule() @NgModule()
class EmptyModule { class EmptyModule {
} }
@ -277,7 +282,7 @@ class SomeComponent {
})); }));
it('should call the `ngDoBootstrap` method with `ApplicationRef` on the main module', it('should call the `ngDoBootstrap` method with `ApplicationRef` on the main module',
async(() => { waitForAsync(() => {
const ngDoBootstrap = jasmine.createSpy('ngDoBootstrap'); const ngDoBootstrap = jasmine.createSpy('ngDoBootstrap');
defaultPlatform.bootstrapModule(createModule({ngDoBootstrap: ngDoBootstrap})) defaultPlatform.bootstrapModule(createModule({ngDoBootstrap: ngDoBootstrap}))
.then((moduleRef) => { .then((moduleRef) => {
@ -286,7 +291,7 @@ class SomeComponent {
}); });
})); }));
it('should auto bootstrap components listed in @NgModule.bootstrap', async(() => { it('should auto bootstrap components listed in @NgModule.bootstrap', waitForAsync(() => {
defaultPlatform.bootstrapModule(createModule({bootstrap: [SomeComponent]})) defaultPlatform.bootstrapModule(createModule({bootstrap: [SomeComponent]}))
.then((moduleRef) => { .then((moduleRef) => {
const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef); const appRef: ApplicationRef = moduleRef.injector.get(ApplicationRef);
@ -295,7 +300,7 @@ class SomeComponent {
})); }));
it('should error if neither `ngDoBootstrap` nor @NgModule.bootstrap was specified', it('should error if neither `ngDoBootstrap` nor @NgModule.bootstrap was specified',
async(() => { waitForAsync(() => {
defaultPlatform.bootstrapModule(createModule({ngDoBootstrap: false})) defaultPlatform.bootstrapModule(createModule({ngDoBootstrap: false}))
.then(() => expect(false).toBe(true), (e) => { .then(() => expect(false).toBe(true), (e) => {
const expectedErrMsg = const expectedErrMsg =
@ -305,12 +310,12 @@ class SomeComponent {
}); });
})); }));
it('should add bootstrapped module into platform modules list', async(() => { it('should add bootstrapped module into platform modules list', waitForAsync(() => {
defaultPlatform.bootstrapModule(createModule({bootstrap: [SomeComponent]})) defaultPlatform.bootstrapModule(createModule({bootstrap: [SomeComponent]}))
.then(module => expect((<any>defaultPlatform)._modules).toContain(module)); .then(module => expect((<any>defaultPlatform)._modules).toContain(module));
})); }));
it('should bootstrap with NoopNgZone', async(() => { it('should bootstrap with NoopNgZone', waitForAsync(() => {
defaultPlatform defaultPlatform
.bootstrapModule(createModule({bootstrap: [SomeComponent]}), {ngZone: 'noop'}) .bootstrapModule(createModule({bootstrap: [SomeComponent]}), {ngZone: 'noop'})
.then((module) => { .then((module) => {
@ -376,7 +381,7 @@ class SomeComponent {
createRootEl(); createRootEl();
defaultPlatform = _platform; defaultPlatform = _platform;
})); }));
it('should wait for asynchronous app initializers', async(() => { it('should wait for asynchronous app initializers', waitForAsync(() => {
let resolve: (result: any) => void; let resolve: (result: any) => void;
const promise: Promise<any> = new Promise((res) => { const promise: Promise<any> = new Promise((res) => {
resolve = res; resolve = res;
@ -396,7 +401,8 @@ class SomeComponent {
}); });
})); }));
it('should rethrow sync errors even if the exceptionHandler is not rethrowing', async(() => { it('should rethrow sync errors even if the exceptionHandler is not rethrowing',
waitForAsync(() => {
const compilerFactory: CompilerFactory = const compilerFactory: CompilerFactory =
defaultPlatform.injector.get(CompilerFactory, null)!; defaultPlatform.injector.get(CompilerFactory, null)!;
const moduleFactory = compilerFactory.createCompiler().compileModuleSync(createModule([{ const moduleFactory = compilerFactory.createCompiler().compileModuleSync(createModule([{
@ -413,7 +419,7 @@ class SomeComponent {
})); }));
it('should rethrow promise errors even if the exceptionHandler is not rethrowing', it('should rethrow promise errors even if the exceptionHandler is not rethrowing',
async(() => { waitForAsync(() => {
const compilerFactory: CompilerFactory = const compilerFactory: CompilerFactory =
defaultPlatform.injector.get(CompilerFactory, null)!; defaultPlatform.injector.get(CompilerFactory, null)!;
const moduleFactory = compilerFactory.createCompiler().compileModuleSync(createModule( const moduleFactory = compilerFactory.createCompiler().compileModuleSync(createModule(
@ -623,25 +629,25 @@ class SomeComponent {
}); });
} }
it('isStable should fire on synchronous component loading', async(() => { it('isStable should fire on synchronous component loading', waitForAsync(() => {
expectStableTexts(SyncComp, ['1']); expectStableTexts(SyncComp, ['1']);
})); }));
it('isStable should fire after a microtask on init is completed', async(() => { it('isStable should fire after a microtask on init is completed', waitForAsync(() => {
expectStableTexts(MicroTaskComp, ['11']); expectStableTexts(MicroTaskComp, ['11']);
})); }));
it('isStable should fire after a macrotask on init is completed', async(() => { it('isStable should fire after a macrotask on init is completed', waitForAsync(() => {
expectStableTexts(MacroTaskComp, ['11']); expectStableTexts(MacroTaskComp, ['11']);
})); }));
it('isStable should fire only after chain of micro and macrotasks on init are completed', it('isStable should fire only after chain of micro and macrotasks on init are completed',
async(() => { waitForAsync(() => {
expectStableTexts(MicroMacroTaskComp, ['111']); expectStableTexts(MicroMacroTaskComp, ['111']);
})); }));
it('isStable should fire only after chain of macro and microtasks on init are completed', it('isStable should fire only after chain of macro and microtasks on init are completed',
async(() => { waitForAsync(() => {
expectStableTexts(MacroMicroTaskComp, ['111']); expectStableTexts(MacroMicroTaskComp, ['111']);
})); }));
@ -665,7 +671,7 @@ class SomeComponent {
}); });
} }
it('should be fired after app becomes unstable', async(() => { it('should be fired after app becomes unstable', waitForAsync(() => {
const fixture = TestBed.createComponent(ClickComp); const fixture = TestBed.createComponent(ClickComp);
const appRef: ApplicationRef = TestBed.inject(ApplicationRef); const appRef: ApplicationRef = TestBed.inject(ApplicationRef);
const zone: NgZone = TestBed.inject(NgZone); const zone: NgZone = TestBed.inject(NgZone);

View File

@ -7,7 +7,7 @@
*/ */
import {Component, Injectable, Input} from '@angular/core'; import {Component, Injectable, Input} from '@angular/core';
import {async, ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBed, withModule} from '@angular/core/testing'; import {ComponentFixtureAutoDetect, ComponentFixtureNoNgZone, TestBed, waitForAsync, withModule} from '@angular/core/testing';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util'; import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -100,7 +100,7 @@ class NestedAsyncTimeoutComp {
{ {
describe('ComponentFixture', () => { describe('ComponentFixture', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ declarations: [
AutoDetectComp, AsyncComp, AsyncTimeoutComp, NestedAsyncTimeoutComp, AsyncChangeComp, AutoDetectComp, AsyncComp, AsyncTimeoutComp, NestedAsyncTimeoutComp, AsyncChangeComp,
@ -134,7 +134,7 @@ class NestedAsyncTimeoutComp {
})); }));
it('should signal through whenStable when the fixture is stable (autoDetectChanges)', it('should signal through whenStable when the fixture is stable (autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncComp); const componentFixture = TestBed.createComponent(AsyncComp);
componentFixture.autoDetectChanges(); componentFixture.autoDetectChanges();
expect(componentFixture.nativeElement).toHaveText('1'); expect(componentFixture.nativeElement).toHaveText('1');
@ -153,7 +153,7 @@ class NestedAsyncTimeoutComp {
})); }));
it('should signal through isStable when the fixture is stable (no autoDetectChanges)', it('should signal through isStable when the fixture is stable (no autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncComp); const componentFixture = TestBed.createComponent(AsyncComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
@ -174,7 +174,7 @@ class NestedAsyncTimeoutComp {
it('should wait for macroTask(setTimeout) while checking for whenStable ' + it('should wait for macroTask(setTimeout) while checking for whenStable ' +
'(autoDetectChanges)', '(autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncTimeoutComp); const componentFixture = TestBed.createComponent(AsyncTimeoutComp);
componentFixture.autoDetectChanges(); componentFixture.autoDetectChanges();
expect(componentFixture.nativeElement).toHaveText('1'); expect(componentFixture.nativeElement).toHaveText('1');
@ -194,7 +194,7 @@ class NestedAsyncTimeoutComp {
it('should wait for macroTask(setTimeout) while checking for whenStable ' + it('should wait for macroTask(setTimeout) while checking for whenStable ' +
'(no autoDetectChanges)', '(no autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncTimeoutComp); const componentFixture = TestBed.createComponent(AsyncTimeoutComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('1'); expect(componentFixture.nativeElement).toHaveText('1');
@ -215,7 +215,7 @@ class NestedAsyncTimeoutComp {
it('should wait for nested macroTasks(setTimeout) while checking for whenStable ' + it('should wait for nested macroTasks(setTimeout) while checking for whenStable ' +
'(autoDetectChanges)', '(autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(NestedAsyncTimeoutComp); const componentFixture = TestBed.createComponent(NestedAsyncTimeoutComp);
componentFixture.autoDetectChanges(); componentFixture.autoDetectChanges();
@ -236,7 +236,7 @@ class NestedAsyncTimeoutComp {
it('should wait for nested macroTasks(setTimeout) while checking for whenStable ' + it('should wait for nested macroTasks(setTimeout) while checking for whenStable ' +
'(no autoDetectChanges)', '(no autoDetectChanges)',
async(() => { waitForAsync(() => {
const componentFixture = TestBed.createComponent(NestedAsyncTimeoutComp); const componentFixture = TestBed.createComponent(NestedAsyncTimeoutComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('1'); expect(componentFixture.nativeElement).toHaveText('1');
@ -255,7 +255,8 @@ class NestedAsyncTimeoutComp {
}); });
})); }));
it('should stabilize after async task in change detection (autoDetectChanges)', async(() => { it('should stabilize after async task in change detection (autoDetectChanges)',
waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncChangeComp); const componentFixture = TestBed.createComponent(AsyncChangeComp);
componentFixture.autoDetectChanges(); componentFixture.autoDetectChanges();
@ -271,7 +272,8 @@ class NestedAsyncTimeoutComp {
}); });
})); }));
it('should stabilize after async task in change detection(no autoDetectChanges)', async(() => { it('should stabilize after async task in change detection(no autoDetectChanges)',
waitForAsync(() => {
const componentFixture = TestBed.createComponent(AsyncChangeComp); const componentFixture = TestBed.createComponent(AsyncChangeComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
componentFixture.whenStable().then((_) => { componentFixture.whenStable().then((_) => {
@ -306,7 +308,7 @@ class NestedAsyncTimeoutComp {
}).toThrowError(/Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set/); }).toThrowError(/Cannot call autoDetectChanges when ComponentFixtureNoNgZone is set/);
}); });
it('should instantiate a component with valid DOM', async(() => { it('should instantiate a component with valid DOM', waitForAsync(() => {
const componentFixture = TestBed.createComponent(SimpleComp); const componentFixture = TestBed.createComponent(SimpleComp);
expect(componentFixture.ngZone).toBeNull(); expect(componentFixture.ngZone).toBeNull();
@ -314,7 +316,7 @@ class NestedAsyncTimeoutComp {
expect(componentFixture.nativeElement).toHaveText('Original Simple'); expect(componentFixture.nativeElement).toHaveText('Original Simple');
})); }));
it('should allow changing members of the component', async(() => { it('should allow changing members of the component', waitForAsync(() => {
const componentFixture = TestBed.createComponent(MyIfComp); const componentFixture = TestBed.createComponent(MyIfComp);
componentFixture.detectChanges(); componentFixture.detectChanges();

View File

@ -10,7 +10,7 @@
import {CommonModule, NgIfContext, ɵgetDOM as getDOM} from '@angular/common'; import {CommonModule, NgIfContext, ɵgetDOM as getDOM} from '@angular/common';
import {Component, DebugElement, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core'; import {Component, DebugElement, DebugNode, Directive, ElementRef, EmbeddedViewRef, EventEmitter, HostBinding, Injectable, Input, NO_ERRORS_SCHEMA, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewContainerRef} from '@angular/core';
import {NgZone} from '@angular/core/src/zone'; import {NgZone} from '@angular/core/src/zone';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {createMouseEvent, hasClass} from '@angular/platform-browser/testing/src/browser_util'; import {createMouseEvent, hasClass} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -264,7 +264,7 @@ class TestCmptWithPropInterpolation {
describe('debug element', () => { describe('debug element', () => {
let fixture: ComponentFixture<any>; let fixture: ComponentFixture<any>;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({ TestBed.configureTestingModule({
declarations: [ declarations: [
ChildComp, ChildComp,

View File

@ -17,7 +17,7 @@ import {TemplateRef} from '@angular/core/src/linker/template_ref';
import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref'; import {ViewContainerRef} from '@angular/core/src/linker/view_container_ref';
import {EmbeddedViewRef} from '@angular/core/src/linker/view_ref'; import {EmbeddedViewRef} from '@angular/core/src/linker/view_ref';
import {Attribute, Component, ContentChildren, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata'; import {Attribute, Component, ContentChildren, Directive, HostBinding, HostListener, Input, Output, Pipe} from '@angular/core/src/metadata';
import {async, fakeAsync, getTestBed, TestBed, tick} from '@angular/core/testing'; import {fakeAsync, getTestBed, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {createMouseEvent, dispatchEvent, el, isCommentNode} from '@angular/platform-browser/testing/src/browser_util'; import {createMouseEvent, dispatchEvent, el, isCommentNode} from '@angular/platform-browser/testing/src/browser_util';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {modifiedInIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing'; import {modifiedInIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing';
@ -757,7 +757,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective); expect(childComponent.myHost).toBeAnInstanceOf(SomeDirective);
}); });
it('should support events via EventEmitter on regular elements', async(() => { it('should support events via EventEmitter on regular elements', waitForAsync(() => {
TestBed.configureTestingModule( TestBed.configureTestingModule(
{declarations: [MyComp, DirectiveEmittingEvent, DirectiveListeningEvent]}); {declarations: [MyComp, DirectiveEmittingEvent, DirectiveListeningEvent]});
const template = '<div emitter listener></div>'; const template = '<div emitter listener></div>';
@ -787,7 +787,7 @@ function declareTests(config?: {useJit: boolean}) {
emitter.fireEvent('fired !'); emitter.fireEvent('fired !');
})); }));
it('should support events via EventEmitter on template elements', async(() => { it('should support events via EventEmitter on template elements', waitForAsync(() => {
const fixture = const fixture =
TestBed TestBed
.configureTestingModule( .configureTestingModule(
@ -819,7 +819,7 @@ function declareTests(config?: {useJit: boolean}) {
emitter.fireEvent('fired !'); emitter.fireEvent('fired !');
})); }));
it('should support [()] syntax', async(() => { it('should support [()] syntax', waitForAsync(() => {
TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithTwoWayBinding]}); TestBed.configureTestingModule({declarations: [MyComp, DirectiveWithTwoWayBinding]});
const template = '<div [(control)]="ctxProp" two-way></div>'; const template = '<div [(control)]="ctxProp" two-way></div>';
TestBed.overrideComponent(MyComp, {set: {template}}); TestBed.overrideComponent(MyComp, {set: {template}});
@ -1072,7 +1072,7 @@ function declareTests(config?: {useJit: boolean}) {
}); });
describe('.createComponent', () => { describe('.createComponent', () => {
it('should allow to create a component at any bound location', async(() => { it('should allow to create a component at any bound location', waitForAsync(() => {
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
.createComponent(MyComp); .createComponent(MyComp);
const tc = fixture.debugElement.children[0].children[0]; const tc = fixture.debugElement.children[0].children[0];
@ -1083,7 +1083,7 @@ function declareTests(config?: {useJit: boolean}) {
.toHaveText('dynamic greet'); .toHaveText('dynamic greet');
})); }));
it('should allow to create multiple components at a location', async(() => { it('should allow to create multiple components at a location', waitForAsync(() => {
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
.createComponent(MyComp); .createComponent(MyComp);
const tc = fixture.debugElement.children[0].children[0]; const tc = fixture.debugElement.children[0].children[0];
@ -1219,7 +1219,7 @@ function declareTests(config?: {useJit: boolean}) {
}); });
describe('.insert', () => { describe('.insert', () => {
it('should throw with destroyed views', async(() => { it('should throw with destroyed views', waitForAsync(() => {
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
.createComponent(MyComp); .createComponent(MyComp);
const tc = fixture.debugElement.children[0].children[0]; const tc = fixture.debugElement.children[0].children[0];
@ -1235,7 +1235,7 @@ function declareTests(config?: {useJit: boolean}) {
}); });
describe('.move', () => { describe('.move', () => {
it('should throw with destroyed views', async(() => { it('should throw with destroyed views', waitForAsync(() => {
const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]}) const fixture = TestBed.configureTestingModule({schemas: [NO_ERRORS_SCHEMA]})
.createComponent(MyComp); .createComponent(MyComp);
const tc = fixture.debugElement.children[0].children[0]; const tc = fixture.debugElement.children[0].children[0];
@ -2001,7 +2001,7 @@ function declareTests(config?: {useJit: boolean}) {
}); });
describe('whitespaces in templates', () => { describe('whitespaces in templates', () => {
it('should not remove whitespaces by default', async(() => { it('should not remove whitespaces by default', waitForAsync(() => {
@Component({ @Component({
selector: 'comp', selector: 'comp',
template: '<span>foo</span> <span>bar</span>', template: '<span>foo</span> <span>bar</span>',
@ -2015,7 +2015,8 @@ function declareTests(config?: {useJit: boolean}) {
expect(f.nativeElement.childNodes.length).toBe(2); expect(f.nativeElement.childNodes.length).toBe(2);
})); }));
it('should not remove whitespaces when explicitly requested not to do so', async(() => { it('should not remove whitespaces when explicitly requested not to do so',
waitForAsync(() => {
@Component({ @Component({
selector: 'comp', selector: 'comp',
template: '<span>foo</span> <span>bar</span>', template: '<span>foo</span> <span>bar</span>',
@ -2030,7 +2031,7 @@ function declareTests(config?: {useJit: boolean}) {
expect(f.nativeElement.childNodes.length).toBe(3); expect(f.nativeElement.childNodes.length).toBe(3);
})); }));
it('should remove whitespaces when explicitly requested to do so', async(() => { it('should remove whitespaces when explicitly requested to do so', waitForAsync(() => {
@Component({ @Component({
selector: 'comp', selector: 'comp',
template: '<span>foo</span> <span>bar</span>', template: '<span>foo</span> <span>bar</span>',

View File

@ -10,7 +10,7 @@ import {ResourceLoader} from '@angular/compiler';
import {CompileMetadataResolver} from '@angular/compiler/src/metadata_resolver'; import {CompileMetadataResolver} from '@angular/compiler/src/metadata_resolver';
import {MockResourceLoader} from '@angular/compiler/testing/src/resource_loader_mock'; import {MockResourceLoader} from '@angular/compiler/testing/src/resource_loader_mock';
import {Component, Directive, Injectable, NgModule, OnDestroy, Pipe} from '@angular/core'; import {Component, Directive, Injectable, NgModule, OnDestroy, Pipe} from '@angular/core';
import {async, getTestBed, TestBed} from '@angular/core/testing'; import {getTestBed, TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {obsoleteInIvy} from '@angular/private/testing'; import {obsoleteInIvy} from '@angular/private/testing';
@ -135,7 +135,7 @@ import {obsoleteInIvy} from '@angular/private/testing';
SomeService.annotations = []; SomeService.annotations = [];
} }
beforeEach(async(() => { beforeEach(waitForAsync(() => {
instances = new Map<any, any>(); instances = new Map<any, any>();
createSummaries().then(s => summaries = s); createSummaries().then(s => summaries = s);
})); }));

View File

@ -8,7 +8,7 @@
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, asNativeElements, Component, ContentChild, ContentChildren, Directive, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core'; import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, asNativeElements, Component, ContentChild, ContentChildren, Directive, QueryList, TemplateRef, Type, ViewChild, ViewChildren, ViewContainerRef} from '@angular/core';
import {ElementRef} from '@angular/core/src/core'; import {ElementRef} from '@angular/core/src/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing'; import {ComponentFixture, TestBed, waitForAsync} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {ivyEnabled, modifiedInIvy, onlyInIvy} from '@angular/private/testing'; import {ivyEnabled, modifiedInIvy, onlyInIvy} from '@angular/private/testing';
import {Subject} from 'rxjs'; import {Subject} from 'rxjs';
@ -414,7 +414,7 @@ describe('Query API', () => {
}); });
describe('changes', () => { describe('changes', () => {
it('should notify query on change', async(() => { it('should notify query on change', waitForAsync(() => {
const template = '<needs-query #q>' + const template = '<needs-query #q>' +
'<div text="1"></div>' + '<div text="1"></div>' +
'<div *ngIf="shouldShow" text="2"></div>' + '<div *ngIf="shouldShow" text="2"></div>' +

View File

@ -8,7 +8,7 @@
import {Compiler, SystemJsNgModuleLoader} from '@angular/core'; import {Compiler, SystemJsNgModuleLoader} from '@angular/core';
import {global} from '@angular/core/src/util/global'; import {global} from '@angular/core/src/util/global';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {afterEach, beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal'; import {afterEach, beforeEach, describe, expect, it} from '@angular/core/testing/src/testing_internal';
import {modifiedInIvy, onlyInIvy} from '@angular/private/testing'; import {modifiedInIvy, onlyInIvy} from '@angular/private/testing';
@ -36,19 +36,19 @@ describe('SystemJsNgModuleLoader', () => {
global['System'] = oldSystem; global['System'] = oldSystem;
}); });
it('loads a default factory by appending the factory suffix', async(() => { it('loads a default factory by appending the factory suffix', waitForAsync(() => {
const loader = new SystemJsNgModuleLoader(new Compiler()); const loader = new SystemJsNgModuleLoader(new Compiler());
loader.load('test').then(contents => { loader.load('test').then(contents => {
expect(contents).toBe('test module factory' as any); expect(contents).toBe('test module factory' as any);
}); });
})); }));
it('loads a named factory by appending the factory suffix', async(() => { it('loads a named factory by appending the factory suffix', waitForAsync(() => {
const loader = new SystemJsNgModuleLoader(new Compiler()); const loader = new SystemJsNgModuleLoader(new Compiler());
loader.load('test#Named').then(contents => { loader.load('test#Named').then(contents => {
expect(contents).toBe('test NamedNgFactory' as any); expect(contents).toBe('test NamedNgFactory' as any);
}); });
})); }));
it('loads a named factory with a configured prefix and suffix', async(() => { it('loads a named factory with a configured prefix and suffix', waitForAsync(() => {
const loader = new SystemJsNgModuleLoader(new Compiler(), { const loader = new SystemJsNgModuleLoader(new Compiler(), {
factoryPathPrefix: 'prefixed/', factoryPathPrefix: 'prefixed/',
factoryPathSuffix: '/suffixed', factoryPathSuffix: '/suffixed',
@ -70,13 +70,13 @@ describe('SystemJsNgModuleLoader', () => {
global['System'] = oldSystem; global['System'] = oldSystem;
}); });
it('loads a default module', async(() => { it('loads a default module', waitForAsync(() => {
const loader = new SystemJsNgModuleLoader(new Compiler()); const loader = new SystemJsNgModuleLoader(new Compiler());
loader.load('test').then(contents => { loader.load('test').then(contents => {
expect(contents.moduleType).toBe('test module' as any); expect(contents.moduleType).toBe('test module' as any);
}); });
})); }));
it('loads a named module', async(() => { it('loads a named module', waitForAsync(() => {
const loader = new SystemJsNgModuleLoader(new Compiler()); const loader = new SystemJsNgModuleLoader(new Compiler());
loader.load('test#NamedModule').then(contents => { loader.load('test#NamedModule').then(contents => {
expect(contents.moduleType).toBe('test NamedModule' as any); expect(contents.moduleType).toBe('test NamedModule' as any);

View File

@ -10,7 +10,7 @@ import {EventEmitter} from '@angular/core';
import {Injectable} from '@angular/core/src/di'; import {Injectable} from '@angular/core/src/di';
import {PendingMacrotask, Testability, TestabilityRegistry} from '@angular/core/src/testability/testability'; import {PendingMacrotask, Testability, TestabilityRegistry} from '@angular/core/src/testability/testability';
import {NgZone} from '@angular/core/src/zone/ng_zone'; import {NgZone} from '@angular/core/src/zone/ng_zone';
import {async, fakeAsync, flush, tick} from '@angular/core/testing'; import {fakeAsync, flush, tick, waitForAsync} from '@angular/core/testing';
import {beforeEach, describe, expect, it, SpyObject} from '@angular/core/testing/src/testing_internal'; import {beforeEach, describe, expect, it, SpyObject} from '@angular/core/testing/src/testing_internal';
import {scheduleMicroTask} from '../../src/util/microtask'; import {scheduleMicroTask} from '../../src/util/microtask';
@ -55,7 +55,7 @@ class MockNgZone extends NgZone {
let updateCallback: any; let updateCallback: any;
let ngZone: MockNgZone; let ngZone: MockNgZone;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
ngZone = new MockNgZone(); ngZone = new MockNgZone();
testability = new Testability(ngZone); testability = new Testability(ngZone);
execute = new SpyObject().spy('execute'); execute = new SpyObject().spy('execute');
@ -68,7 +68,7 @@ class MockNgZone extends NgZone {
expect(testability.getPendingRequestCount()).toEqual(0); expect(testability.getPendingRequestCount()).toEqual(0);
}); });
it('should fire whenstable callbacks if pending count is 0', async(() => { it('should fire whenstable callbacks if pending count is 0', waitForAsync(() => {
testability.whenStable(execute); testability.whenStable(execute);
microTask(() => { microTask(() => {
@ -81,7 +81,7 @@ class MockNgZone extends NgZone {
expect(execute).not.toHaveBeenCalled(); expect(execute).not.toHaveBeenCalled();
}); });
it('should not call whenstable callbacks when there are pending counts', async(() => { it('should not call whenstable callbacks when there are pending counts', waitForAsync(() => {
testability.increasePendingRequestCount(); testability.increasePendingRequestCount();
testability.increasePendingRequestCount(); testability.increasePendingRequestCount();
testability.whenStable(execute); testability.whenStable(execute);
@ -96,7 +96,7 @@ class MockNgZone extends NgZone {
}); });
})); }));
it('should fire whenstable callbacks when pending drops to 0', async(() => { it('should fire whenstable callbacks when pending drops to 0', waitForAsync(() => {
testability.increasePendingRequestCount(); testability.increasePendingRequestCount();
testability.whenStable(execute); testability.whenStable(execute);
@ -110,7 +110,8 @@ class MockNgZone extends NgZone {
}); });
})); }));
it('should not fire whenstable callbacks synchronously when pending drops to 0', async(() => { it('should not fire whenstable callbacks synchronously when pending drops to 0',
waitForAsync(() => {
testability.increasePendingRequestCount(); testability.increasePendingRequestCount();
testability.whenStable(execute); testability.whenStable(execute);
testability.decreasePendingRequestCount(); testability.decreasePendingRequestCount();
@ -118,7 +119,7 @@ class MockNgZone extends NgZone {
expect(execute).not.toHaveBeenCalled(); expect(execute).not.toHaveBeenCalled();
})); }));
it('should fire whenstable callbacks with didWork if pending count is 0', async(() => { it('should fire whenstable callbacks with didWork if pending count is 0', waitForAsync(() => {
microTask(() => { microTask(() => {
testability.whenStable(execute); testability.whenStable(execute);
@ -128,7 +129,8 @@ class MockNgZone extends NgZone {
}); });
})); }));
it('should fire whenstable callbacks with didWork when pending drops to 0', async(() => { it('should fire whenstable callbacks with didWork when pending drops to 0',
waitForAsync(() => {
testability.increasePendingRequestCount(); testability.increasePendingRequestCount();
testability.whenStable(execute); testability.whenStable(execute);
@ -165,7 +167,7 @@ class MockNgZone extends NgZone {
clearTimeout(id); clearTimeout(id);
})); }));
it('should fire if Angular is already stable', async(() => { it('should fire if Angular is already stable', waitForAsync(() => {
testability.whenStable(execute, 200); testability.whenStable(execute, 200);
microTask(() => { microTask(() => {
@ -363,7 +365,7 @@ class MockNgZone extends NgZone {
let registry: TestabilityRegistry; let registry: TestabilityRegistry;
let ngZone: MockNgZone; let ngZone: MockNgZone;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
ngZone = new MockNgZone(); ngZone = new MockNgZone();
testability1 = new Testability(ngZone); testability1 = new Testability(ngZone);
testability2 = new Testability(ngZone); testability2 = new Testability(ngZone);

View File

@ -7,7 +7,7 @@
*/ */
import {EventEmitter, NgZone} from '@angular/core'; import {EventEmitter, NgZone} from '@angular/core';
import {async, fakeAsync, flushMicrotasks} from '@angular/core/testing'; import {fakeAsync, flushMicrotasks, waitForAsync} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, describe, expect, inject, it, Log, xit} from '@angular/core/testing/src/testing_internal'; import {AsyncTestCompleter, beforeEach, describe, expect, inject, it, Log, xit} from '@angular/core/testing/src/testing_internal';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util'; import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';
@ -914,7 +914,7 @@ function commonTests() {
asyncResult = null!; asyncResult = null!;
}); });
it('should async even if the NgZone was created outside.', async(() => { it('should async even if the NgZone was created outside.', waitForAsync(() => {
// try to escape the current async zone by using NgZone which was created outside. // try to escape the current async zone by using NgZone which was created outside.
ngZone.run(() => { ngZone.run(() => {
setTimeout(() => { setTimeout(() => {

View File

@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license * found in the LICENSE file at https://angular.io/license
*/ */
import {async, fakeAsync, tick} from '@angular/core/testing'; import {fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import {AsyncTestCompleter, beforeEach, describe, inject, it} from '@angular/core/testing/src/testing_internal'; import {AsyncTestCompleter, beforeEach, describe, inject, it} from '@angular/core/testing/src/testing_internal';
import {AbstractControl, FormArray, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms'; import {AbstractControl, FormArray, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms';
import {of} from 'rxjs'; import {of} from 'rxjs';
@ -726,7 +726,7 @@ describe('FormGroup', () => {
let control: FormControl; let control: FormControl;
let group: FormGroup; let group: FormGroup;
beforeEach(async(() => { beforeEach(waitForAsync(() => {
control = new FormControl('', asyncValidatorReturningObservable); control = new FormControl('', asyncValidatorReturningObservable);
group = new FormGroup({'one': control}); group = new FormGroup({'one': control});
})); }));

View File

@ -8,7 +8,7 @@
import {ɵgetDOM as getDOM} from '@angular/common'; import {ɵgetDOM as getDOM} from '@angular/common';
import {Component, Directive, forwardRef, Type} from '@angular/core'; import {Component, Directive, forwardRef, Type} from '@angular/core';
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {AbstractControl, AsyncValidator, COMPOSITION_BUFFER_MODE, FormControl, FormsModule, NG_ASYNC_VALIDATORS, NgForm, NgModel} from '@angular/forms'; import {AbstractControl, AsyncValidator, COMPOSITION_BUFFER_MODE, FormControl, FormsModule, NG_ASYNC_VALIDATORS, NgForm, NgModel} from '@angular/forms';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {dispatchEvent, sortedClassList} from '@angular/platform-browser/testing/src/browser_util'; import {dispatchEvent, sortedClassList} from '@angular/platform-browser/testing/src/browser_util';
@ -168,7 +168,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
expect(form.value).toEqual({}); expect(form.value).toEqual({});
})); }));
it('should set status classes with ngModel', async(() => { it('should set status classes with ngModel', waitForAsync(() => {
const fixture = initTest(NgModelForm); const fixture = initTest(NgModelForm);
fixture.componentInstance.name = 'aa'; fixture.componentInstance.name = 'aa';
fixture.detectChanges(); fixture.detectChanges();
@ -212,7 +212,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
}); });
})); }));
it('should set status classes with ngModelGroup and ngForm', async(() => { it('should set status classes with ngModelGroup and ngForm', waitForAsync(() => {
const fixture = initTest(NgModelGroupForm); const fixture = initTest(NgModelGroupForm);
fixture.componentInstance.first = ''; fixture.componentInstance.first = '';
fixture.detectChanges(); fixture.detectChanges();
@ -1179,7 +1179,7 @@ import {NgModelCustomComp, NgModelCustomWrapper} from './value_accessor_integrat
expect(input.nativeElement.disabled).toBe(true); expect(input.nativeElement.disabled).toBe(true);
})); }));
it('should disable a custom control if disabled attr is added', async(() => { it('should disable a custom control if disabled attr is added', waitForAsync(() => {
const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp); const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp);
fixture.componentInstance.name = 'Nancy'; fixture.componentInstance.name = 'Nancy';
fixture.componentInstance.isDisabled = true; fixture.componentInstance.isDisabled = true;

View File

@ -7,7 +7,7 @@
*/ */
import {Component, Directive, EventEmitter, Input, Output, Type, ViewChild} from '@angular/core'; import {Component, Directive, EventEmitter, Input, Output, Type, ViewChild} from '@angular/core';
import {async, ComponentFixture, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {ComponentFixture, fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {AbstractControl, ControlValueAccessor, FormControl, FormGroup, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, NgForm, NgModel, ReactiveFormsModule, Validators} from '@angular/forms'; import {AbstractControl, ControlValueAccessor, FormControl, FormGroup, FormsModule, NG_VALIDATORS, NG_VALUE_ACCESSOR, NgControl, NgForm, NgModel, ReactiveFormsModule, Validators} from '@angular/forms';
import {By} from '@angular/platform-browser/src/dom/debug/by'; import {By} from '@angular/platform-browser/src/dom/debug/by';
import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util'; import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util';
@ -1078,7 +1078,7 @@ import {dispatchEvent} from '@angular/platform-browser/testing/src/browser_util'
}); });
describe('in template-driven forms', () => { describe('in template-driven forms', () => {
it('should support standard writing to view and model', async(() => { it('should support standard writing to view and model', waitForAsync(() => {
const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp); const fixture = initTest(NgModelCustomWrapper, NgModelCustomComp);
fixture.componentInstance.name = 'Nancy'; fixture.componentInstance.name = 'Nancy';
fixture.detectChanges(); fixture.detectChanges();

View File

@ -10,7 +10,7 @@
import {HTTP_INTERCEPTORS, HttpBackend, HttpClient, HttpClientModule, HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http'; import {HTTP_INTERCEPTORS, HttpBackend, HttpClient, HttpClientModule, HttpEvent, HttpEventType, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse} from '@angular/common/http';
import {Injectable} from '@angular/core'; import {Injectable} from '@angular/core';
import {async, TestBed} from '@angular/core/testing'; import {TestBed, waitForAsync} from '@angular/core/testing';
import {HttpClientBackendService, HttpClientInMemoryWebApiModule} from 'angular-in-memory-web-api'; import {HttpClientBackendService, HttpClientInMemoryWebApiModule} from 'angular-in-memory-web-api';
import {Observable, zip} from 'rxjs'; import {Observable, zip} from 'rxjs';
import {concatMap, map, tap} from 'rxjs/operators'; import {concatMap, map, tap} from 'rxjs/operators';
@ -37,14 +37,14 @@ describe('HttpClient Backend Service', () => {
http = TestBed.get(HttpClient); http = TestBed.get(HttpClient);
}); });
it('can get heroes', async(() => { it('can get heroes', waitForAsync(() => {
http.get<Hero[]>('api/heroes') http.get<Hero[]>('api/heroes')
.subscribe( .subscribe(
heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'), heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'),
failRequest); failRequest);
})); }));
it('GET should be a "cold" observable', async(() => { it('GET should be a "cold" observable', waitForAsync(() => {
const httpBackend = TestBed.get(HttpBackend); const httpBackend = TestBed.get(HttpBackend);
const spy = spyOn(httpBackend, 'collectionHandler').and.callThrough(); const spy = spyOn(httpBackend, 'collectionHandler').and.callThrough();
const get$ = http.get<Hero[]>('api/heroes'); const get$ = http.get<Hero[]>('api/heroes');
@ -58,7 +58,7 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('GET should wait until after delay to respond', async(() => { it('GET should wait until after delay to respond', waitForAsync(() => {
// to make test fail, set `delay=0` above // to make test fail, set `delay=0` above
let gotResponse = false; let gotResponse = false;
@ -70,7 +70,7 @@ describe('HttpClient Backend Service', () => {
expect(gotResponse).toBe(false, 'should delay before response'); expect(gotResponse).toBe(false, 'should delay before response');
})); }));
it('Should only initialize the db once', async(() => { it('Should only initialize the db once', waitForAsync(() => {
const httpBackend = TestBed.get(HttpBackend); const httpBackend = TestBed.get(HttpBackend);
const spy = spyOn(httpBackend, 'resetDb').and.callThrough(); const spy = spyOn(httpBackend, 'resetDb').and.callThrough();
@ -86,13 +86,13 @@ describe('HttpClient Backend Service', () => {
expect(spy.calls.count()).toBe(1); expect(spy.calls.count()).toBe(1);
})); }));
it('can get heroes (w/ a different base path)', async(() => { it('can get heroes (w/ a different base path)', waitForAsync(() => {
http.get<Hero[]>('some-base-path/heroes').subscribe(heroes => { http.get<Hero[]>('some-base-path/heroes').subscribe(heroes => {
expect(heroes.length).toBeGreaterThan(0, 'should have heroes'); expect(heroes.length).toBeGreaterThan(0, 'should have heroes');
}, failRequest); }, failRequest);
})); }));
it('should 404 when GET unknown collection (after delay)', async(() => { it('should 404 when GET unknown collection (after delay)', waitForAsync(() => {
let gotError = false; let gotError = false;
const url = 'api/unknown-collection'; const url = 'api/unknown-collection';
http.get<Hero[]>(url).subscribe( http.get<Hero[]>(url).subscribe(
@ -104,46 +104,46 @@ describe('HttpClient Backend Service', () => {
expect(gotError).toBe(false, 'should not get error until after delay'); expect(gotError).toBe(false, 'should not get error until after delay');
})); }));
it('should return the hero w/id=1 for GET app/heroes/1', async(() => { it('should return the hero w/id=1 for GET app/heroes/1', waitForAsync(() => {
http.get<Hero>('api/heroes/1') http.get<Hero>('api/heroes/1')
.subscribe( .subscribe(
hero => expect(hero).toBeDefined('should find hero with id=1'), failRequest); hero => expect(hero).toBeDefined('should find hero with id=1'), failRequest);
})); }));
// test where id is string that looks like a number // test where id is string that looks like a number
it('should return the stringer w/id="10" for GET app/stringers/10', async(() => { it('should return the stringer w/id="10" for GET app/stringers/10', waitForAsync(() => {
http.get<Hero>('api/stringers/10') http.get<Hero>('api/stringers/10')
.subscribe( .subscribe(
hero => expect(hero).toBeDefined('should find string with id="10"'), failRequest); hero => expect(hero).toBeDefined('should find string with id="10"'), failRequest);
})); }));
it('should return 1-item array for GET app/heroes/?id=1', async(() => { it('should return 1-item array for GET app/heroes/?id=1', waitForAsync(() => {
http.get<Hero[]>('api/heroes/?id=1') http.get<Hero[]>('api/heroes/?id=1')
.subscribe( .subscribe(
heroes => expect(heroes.length).toBe(1, 'should find one hero w/id=1'), heroes => expect(heroes.length).toBe(1, 'should find one hero w/id=1'),
failRequest); failRequest);
})); }));
it('should return 1-item array for GET app/heroes?id=1', async(() => { it('should return 1-item array for GET app/heroes?id=1', waitForAsync(() => {
http.get<Hero[]>('api/heroes?id=1') http.get<Hero[]>('api/heroes?id=1')
.subscribe( .subscribe(
heroes => expect(heroes.length).toBe(1, 'should find one hero w/id=1'), heroes => expect(heroes.length).toBe(1, 'should find one hero w/id=1'),
failRequest); failRequest);
})); }));
it('should return undefined for GET app/heroes?id=not-found-id', async(() => { it('should return undefined for GET app/heroes?id=not-found-id', waitForAsync(() => {
http.get<Hero[]>('api/heroes?id=123456') http.get<Hero[]>('api/heroes?id=123456')
.subscribe(heroes => expect(heroes.length).toBe(0), failRequest); .subscribe(heroes => expect(heroes.length).toBe(0), failRequest);
})); }));
it('should return 404 for GET app/heroes/not-found-id', async(() => { it('should return 404 for GET app/heroes/not-found-id', waitForAsync(() => {
const url = 'api/heroes/123456'; const url = 'api/heroes/123456';
http.get<Hero[]>(url).subscribe( http.get<Hero[]>(url).subscribe(
() => fail(`should not have found data for '${url}'`), () => fail(`should not have found data for '${url}'`),
err => expect(err.status).toBe(404, 'should have 404 status')); err => expect(err.status).toBe(404, 'should have 404 status'));
})); }));
it('can generate the id when add a hero with no id', async(() => { it('can generate the id when add a hero with no id', waitForAsync(() => {
const hero = new Hero(undefined, 'SuperDooper'); const hero = new Hero(undefined, 'SuperDooper');
http.post<Hero>('api/heroes', hero).subscribe(replyHero => { http.post<Hero>('api/heroes', hero).subscribe(replyHero => {
expect(replyHero.id).toBeDefined('added hero should have an id'); expect(replyHero.id).toBeDefined('added hero should have an id');
@ -151,13 +151,13 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('can get nobodies (empty collection)', async(() => { it('can get nobodies (empty collection)', waitForAsync(() => {
http.get<Hero[]>('api/nobodies').subscribe(nobodies => { http.get<Hero[]>('api/nobodies').subscribe(nobodies => {
expect(nobodies.length).toBe(0, 'should have no nobodies'); expect(nobodies.length).toBe(0, 'should have no nobodies');
}, failRequest); }, failRequest);
})); }));
it('can add a nobody with an id to empty nobodies collection', async(() => { it('can add a nobody with an id to empty nobodies collection', waitForAsync(() => {
const id = 'g-u-i-d'; const id = 'g-u-i-d';
http.post('api/nobodies', {id, name: 'Noman'}) http.post('api/nobodies', {id, name: 'Noman'})
@ -169,7 +169,8 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('should fail when add a nobody without an id to empty nobodies collection', async(() => { it('should fail when add a nobody without an id to empty nobodies collection',
waitForAsync(() => {
http.post('api/nobodies', {name: 'Noman'}) http.post('api/nobodies', {name: 'Noman'})
.subscribe( .subscribe(
() => fail(`should not have been able to add 'Norman' to 'nobodies'`), err => { () => fail(`should not have been able to add 'Norman' to 'nobodies'`), err => {
@ -179,11 +180,11 @@ describe('HttpClient Backend Service', () => {
})); }));
describe('can reset the database', () => { describe('can reset the database', () => {
it('to empty (object db)', async(() => resetDatabaseTest('object'))); it('to empty (object db)', waitForAsync(() => resetDatabaseTest('object')));
it('to empty (observable db)', async(() => resetDatabaseTest('observable'))); it('to empty (observable db)', waitForAsync(() => resetDatabaseTest('observable')));
it('to empty (promise db)', async(() => resetDatabaseTest('promise'))); it('to empty (promise db)', waitForAsync(() => resetDatabaseTest('promise')));
function resetDatabaseTest(returnType: string) { function resetDatabaseTest(returnType: string) {
// Observable of the number of heroes and nobodies // Observable of the number of heroes and nobodies
@ -223,28 +224,29 @@ describe('HttpClient Backend Service', () => {
http = TestBed.get(HttpClient); http = TestBed.get(HttpClient);
}); });
it('can get heroes', async(() => { it('can get heroes', waitForAsync(() => {
http.get<Hero[]>('api/heroes') http.get<Hero[]>('api/heroes')
.subscribe( .subscribe(
heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'), heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'),
failRequest); failRequest);
})); }));
it('can translate `foo/heroes` to `heroes` via `parsedRequestUrl` override', async(() => { it('can translate `foo/heroes` to `heroes` via `parsedRequestUrl` override',
waitForAsync(() => {
http.get<Hero[]>('api/foo/heroes') http.get<Hero[]>('api/foo/heroes')
.subscribe( .subscribe(
heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'), heroes => expect(heroes.length).toBeGreaterThan(0, 'should have heroes'),
failRequest); failRequest);
})); }));
it('can get villains', async(() => { it('can get villains', waitForAsync(() => {
http.get<Hero[]>('api/villains') http.get<Hero[]>('api/villains')
.subscribe( .subscribe(
villains => expect(villains.length).toBeGreaterThan(0, 'should have villains'), villains => expect(villains.length).toBeGreaterThan(0, 'should have villains'),
failRequest); failRequest);
})); }));
it('should 404 when POST to villains', async(() => { it('should 404 when POST to villains', waitForAsync(() => {
const url = 'api/villains'; const url = 'api/villains';
http.post<Hero[]>(url, {id: 42, name: 'Dr. Evil'}) http.post<Hero[]>(url, {id: 42, name: 'Dr. Evil'})
.subscribe( .subscribe(
@ -252,14 +254,14 @@ describe('HttpClient Backend Service', () => {
err => expect(err.status).toBe(404, 'should have 404 status')); err => expect(err.status).toBe(404, 'should have 404 status'));
})); }));
it('should 404 when GET unknown collection', async(() => { it('should 404 when GET unknown collection', waitForAsync(() => {
const url = 'api/unknown-collection'; const url = 'api/unknown-collection';
http.get<Hero[]>(url).subscribe( http.get<Hero[]>(url).subscribe(
() => fail(`should not have found data for '${url}'`), () => fail(`should not have found data for '${url}'`),
err => expect(err.status).toBe(404, 'should have 404 status')); err => expect(err.status).toBe(404, 'should have 404 status'));
})); }));
it('should use genId override to add new hero, "Maxinius"', async(() => { it('should use genId override to add new hero, "Maxinius"', waitForAsync(() => {
http.post('api/heroes', {name: 'Maxinius'}) http.post('api/heroes', {name: 'Maxinius'})
.pipe(concatMap(() => http.get<Hero[]>('api/heroes?name=Maxi'))) .pipe(concatMap(() => http.get<Hero[]>('api/heroes?name=Maxi')))
.subscribe(heroes => { .subscribe(heroes => {
@ -269,7 +271,8 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('should use genId override guid generator for a new nobody without an id', async(() => { it('should use genId override guid generator for a new nobody without an id',
waitForAsync(() => {
http.post('api/nobodies', {name: 'Noman'}) http.post('api/nobodies', {name: 'Noman'})
.pipe(concatMap(() => http.get<{id: string; name: string}[]>('api/nobodies'))) .pipe(concatMap(() => http.get<{id: string; name: string}[]>('api/nobodies')))
.subscribe(nobodies => { .subscribe(nobodies => {
@ -280,11 +283,11 @@ describe('HttpClient Backend Service', () => {
})); }));
describe('can reset the database', () => { describe('can reset the database', () => {
it('to empty (object db)', async(() => resetDatabaseTest('object'))); it('to empty (object db)', waitForAsync(() => resetDatabaseTest('object')));
it('to empty (observable db)', async(() => resetDatabaseTest('observable'))); it('to empty (observable db)', waitForAsync(() => resetDatabaseTest('observable')));
it('to empty (promise db)', async(() => resetDatabaseTest('promise'))); it('to empty (promise db)', waitForAsync(() => resetDatabaseTest('promise')));
function resetDatabaseTest(returnType: string) { function resetDatabaseTest(returnType: string) {
// Observable of the number of heroes, nobodies and villains // Observable of the number of heroes, nobodies and villains
@ -331,19 +334,19 @@ describe('HttpClient Backend Service', () => {
heroService = TestBed.get(HeroService); heroService = TestBed.get(HeroService);
}); });
it('can get heroes', async(() => { it('can get heroes', waitForAsync(() => {
heroService.getHeroes().subscribe(heroes => { heroService.getHeroes().subscribe(heroes => {
expect(heroes.length).toBeGreaterThan(0, 'should have heroes'); expect(heroes.length).toBeGreaterThan(0, 'should have heroes');
}, failRequest); }, failRequest);
})); }));
it('can get hero w/ id=1', async(() => { it('can get hero w/ id=1', waitForAsync(() => {
heroService.getHero(1).subscribe(hero => { heroService.getHero(1).subscribe(hero => {
expect(hero.name).toBe('Windstorm'); expect(hero.name).toBe('Windstorm');
}, () => fail('getHero failed')); }, () => fail('getHero failed'));
})); }));
it('should 404 when hero id not found', async(() => { it('should 404 when hero id not found', waitForAsync(() => {
const id = 123456; const id = 123456;
heroService.getHero(id).subscribe( heroService.getHero(id).subscribe(
() => fail(`should not have found hero for id='${id}'`), err => { () => fail(`should not have found hero for id='${id}'`), err => {
@ -351,7 +354,7 @@ describe('HttpClient Backend Service', () => {
}); });
})); }));
it('can add a hero', async(() => { it('can add a hero', waitForAsync(() => {
heroService.addHero('FunkyBob') heroService.addHero('FunkyBob')
.pipe( .pipe(
tap(hero => expect(hero.name).toBe('FunkyBob')), tap(hero => expect(hero.name).toBe('FunkyBob')),
@ -363,23 +366,23 @@ describe('HttpClient Backend Service', () => {
}), }),
10000); 10000);
it('can delete a hero', async(() => { it('can delete a hero', waitForAsync(() => {
const id = 1; const id = 1;
heroService.deleteHero(id).subscribe((_: {}) => expect(_).toBeDefined(), failRequest); heroService.deleteHero(id).subscribe((_: {}) => expect(_).toBeDefined(), failRequest);
})); }));
it('should allow delete of non-existent hero', async(() => { it('should allow delete of non-existent hero', waitForAsync(() => {
const id = 123456; const id = 123456;
heroService.deleteHero(id).subscribe((_: {}) => expect(_).toBeDefined(), failRequest); heroService.deleteHero(id).subscribe((_: {}) => expect(_).toBeDefined(), failRequest);
})); }));
it('can search for heroes by name containing "a"', async(() => { it('can search for heroes by name containing "a"', waitForAsync(() => {
heroService.searchHeroes('a').subscribe((heroes: Hero[]) => { heroService.searchHeroes('a').subscribe((heroes: Hero[]) => {
expect(heroes.length).toBe(3, 'should find 3 heroes with letter "a"'); expect(heroes.length).toBe(3, 'should find 3 heroes with letter "a"');
}, failRequest); }, failRequest);
})); }));
it('can update existing hero', async(() => { it('can update existing hero', waitForAsync(() => {
const id = 1; const id = 1;
heroService.getHero(id) heroService.getHero(id)
.pipe( .pipe(
@ -394,7 +397,7 @@ describe('HttpClient Backend Service', () => {
}), }),
10000); 10000);
it('should create new hero when try to update non-existent hero', async(() => { it('should create new hero when try to update non-existent hero', waitForAsync(() => {
const falseHero = new Hero(12321, 'DryMan'); const falseHero = new Hero(12321, 'DryMan');
heroService.updateHero(falseHero).subscribe( heroService.updateHero(falseHero).subscribe(
hero => expect(hero.name).toBe(falseHero.name), failRequest); hero => expect(hero.name).toBe(falseHero.name), failRequest);
@ -446,7 +449,7 @@ describe('HttpClient Backend Service', () => {
expect(ti).toBeDefined(); expect(ti).toBeDefined();
}); });
it('should have GET request header from test interceptor', async(() => { it('should have GET request header from test interceptor', waitForAsync(() => {
const handle = spyOn(httpBackend, 'handle').and.callThrough(); const handle = spyOn(httpBackend, 'handle').and.callThrough();
http.get<Hero[]>('api/heroes').subscribe(heroes => { http.get<Hero[]>('api/heroes').subscribe(heroes => {
@ -459,7 +462,7 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('should have GET response header from test interceptor', async(() => { it('should have GET response header from test interceptor', waitForAsync(() => {
let gotResponse = false; let gotResponse = false;
const req = new HttpRequest<any>('GET', 'api/heroes'); const req = new HttpRequest<any>('GET', 'api/heroes');
http.request<Hero[]>(req).subscribe(event => { http.request<Hero[]>(req).subscribe(event => {
@ -503,7 +506,7 @@ describe('HttpClient Backend Service', () => {
jasmine.Ajax.uninstall(); jasmine.Ajax.uninstall();
}); });
it('can get heroes (no passthru)', async(() => { it('can get heroes (no passthru)', waitForAsync(() => {
http.get<Hero[]>('api/heroes').subscribe(heroes => { http.get<Hero[]>('api/heroes').subscribe(heroes => {
expect(createPassThruBackend).not.toHaveBeenCalled(); expect(createPassThruBackend).not.toHaveBeenCalled();
expect(heroes.length).toBeGreaterThan(0, 'should have heroes'); expect(heroes.length).toBeGreaterThan(0, 'should have heroes');
@ -513,7 +516,7 @@ describe('HttpClient Backend Service', () => {
// `passthru` is NOT a collection in the data store // `passthru` is NOT a collection in the data store
// so requests for it should pass thru to the "real" server // so requests for it should pass thru to the "real" server
it('can GET passthru', async(() => { it('can GET passthru', waitForAsync(() => {
jasmine.Ajax.stubRequest('api/passthru').andReturn({ jasmine.Ajax.stubRequest('api/passthru').andReturn({
'status': 200, 'status': 200,
'contentType': 'application/json', 'contentType': 'application/json',
@ -525,7 +528,7 @@ describe('HttpClient Backend Service', () => {
}, failRequest); }, failRequest);
})); }));
it('can ADD to passthru', async(() => { it('can ADD to passthru', waitForAsync(() => {
jasmine.Ajax.stubRequest('api/passthru').andReturn({ jasmine.Ajax.stubRequest('api/passthru').andReturn({
'status': 200, 'status': 200,
'contentType': 'application/json', 'contentType': 'application/json',
@ -554,7 +557,7 @@ describe('HttpClient Backend Service', () => {
http = TestBed.get(HttpClient); http = TestBed.get(HttpClient);
}); });
it('can get heroes (encapsulated)', async(() => { it('can get heroes (encapsulated)', waitForAsync(() => {
http.get<{data: any}>('api/heroes') http.get<{data: any}>('api/heroes')
.pipe(map(data => data.data as Hero[])) .pipe(map(data => data.data as Hero[]))
.subscribe( .subscribe(

View File

@ -8,7 +8,7 @@
import {ResourceLoader, UrlResolver} from '@angular/compiler'; import {ResourceLoader, UrlResolver} from '@angular/compiler';
import {Component} from '@angular/core'; import {Component} from '@angular/core';
import {async, fakeAsync, TestBed, tick} from '@angular/core/testing'; import {fakeAsync, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {CachedResourceLoader} from '@angular/platform-browser-dynamic/src/resource_loader/resource_loader_cache'; import {CachedResourceLoader} from '@angular/platform-browser-dynamic/src/resource_loader/resource_loader_cache';
import {setTemplateCache} from '@angular/platform-browser-dynamic/test/resource_loader/resource_loader_cache_setter'; import {setTemplateCache} from '@angular/platform-browser-dynamic/test/resource_loader/resource_loader_cache_setter';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
@ -29,14 +29,14 @@ if (isBrowser) {
}).toThrowError('CachedResourceLoader: Template cache was not found in $templateCache.'); }).toThrowError('CachedResourceLoader: Template cache was not found in $templateCache.');
}); });
it('should resolve the Promise with the cached file content on success', async(() => { it('should resolve the Promise with the cached file content on success', waitForAsync(() => {
resourceLoader = createCachedResourceLoader(); resourceLoader = createCachedResourceLoader();
resourceLoader.get('test.html').then((text) => { resourceLoader.get('test.html').then((text) => {
expect(text).toBe('<div>Hello</div>'); expect(text).toBe('<div>Hello</div>');
}); });
})); }));
it('should reject the Promise on failure', async(() => { it('should reject the Promise on failure', waitForAsync(() => {
resourceLoader = createCachedResourceLoader(); resourceLoader = createCachedResourceLoader();
resourceLoader.get('unknown.html').then(() => { resourceLoader.get('unknown.html').then(() => {
throw new Error('Not expected to succeed.'); throw new Error('Not expected to succeed.');

View File

@ -8,7 +8,7 @@
import {ResourceLoader} from '@angular/compiler'; import {ResourceLoader} from '@angular/compiler';
import {Compiler, Component, NgModule} from '@angular/core'; import {Compiler, Component, NgModule} from '@angular/core';
import {async, fakeAsync, inject, TestBed, tick} from '@angular/core/testing'; import {fakeAsync, inject, TestBed, tick, waitForAsync} from '@angular/core/testing';
import {ResourceLoaderImpl} from '@angular/platform-browser-dynamic/src/resource_loader/resource_loader_impl'; import {ResourceLoaderImpl} from '@angular/platform-browser-dynamic/src/resource_loader/resource_loader_impl';
@ -54,7 +54,7 @@ if (isBrowser) {
expect(actuallyDone).toEqual(true); expect(actuallyDone).toEqual(true);
}); });
it('should run async tests with ResourceLoaders', async(() => { it('should run async tests with ResourceLoaders', waitForAsync(() => {
const resourceLoader = new ResourceLoaderImpl(); const resourceLoader = new ResourceLoaderImpl();
resourceLoader resourceLoader
.get('/base/angular/packages/platform-browser/test/static_assets/test.html') .get('/base/angular/packages/platform-browser/test/static_assets/test.html')
@ -132,7 +132,7 @@ if (isBrowser) {
it('should fail when an ResourceLoader fails', done => { it('should fail when an ResourceLoader fails', done => {
const itPromise = patchJasmineIt(); const itPromise = patchJasmineIt();
it('should fail with an error from a promise', async(() => { it('should fail with an error from a promise', waitForAsync(() => {
TestBed.configureTestingModule({declarations: [BadTemplateUrl]}); TestBed.configureTestingModule({declarations: [BadTemplateUrl]});
TestBed.compileComponents(); TestBed.compileComponents();
})); }));
@ -151,7 +151,7 @@ if (isBrowser) {
}); });
describe('TestBed createComponent', function() { describe('TestBed createComponent', function() {
it('should allow an external templateUrl', async(() => { it('should allow an external templateUrl', waitForAsync(() => {
TestBed.configureTestingModule({declarations: [ExternalTemplateComp]}); TestBed.configureTestingModule({declarations: [ExternalTemplateComp]});
TestBed.compileComponents().then(() => { TestBed.compileComponents().then(() => {
const componentFixture = TestBed.createComponent(ExternalTemplateComp); const componentFixture = TestBed.createComponent(ExternalTemplateComp);

View File

@ -8,7 +8,7 @@
import {CompilerConfig, ResourceLoader} from '@angular/compiler'; import {CompilerConfig, ResourceLoader} from '@angular/compiler';
import {Compiler, Component, ComponentFactoryResolver, CUSTOM_ELEMENTS_SCHEMA, Directive, Inject, Injectable, InjectionToken, Injector, Input, NgModule, Optional, Pipe, SkipSelf, ɵstringify as stringify} from '@angular/core'; import {Compiler, Component, ComponentFactoryResolver, CUSTOM_ELEMENTS_SCHEMA, Directive, Inject, Injectable, InjectionToken, Injector, Input, NgModule, Optional, Pipe, SkipSelf, ɵstringify as stringify} from '@angular/core';
import {async, fakeAsync, getTestBed, inject, TestBed, tick, withModule} from '@angular/core/testing'; import {fakeAsync, getTestBed, inject, TestBed, tick, waitForAsync, withModule} from '@angular/core/testing';
import {expect} from '@angular/platform-browser/testing/src/matchers'; import {expect} from '@angular/platform-browser/testing/src/matchers';
import {ivyEnabled, modifiedInIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing'; import {ivyEnabled, modifiedInIvy, obsoleteInIvy, onlyInIvy} from '@angular/private/testing';
@ -146,11 +146,11 @@ const bTok = new InjectionToken<string>('b');
}, 0); }, 0);
}); });
it('should run async tests with tasks', async(function(this: TestContext) { it('should run async tests with tasks', waitForAsync(function(this: TestContext) {
setTimeout(() => this.actuallyDone = true, 0); setTimeout(() => this.actuallyDone = true, 0);
})); }));
it('should run async tests with promises', async(function(this: TestContext) { it('should run async tests with promises', waitForAsync(function(this: TestContext) {
const p = new Promise((resolve, reject) => setTimeout(resolve, 10)); const p = new Promise((resolve, reject) => setTimeout(resolve, 10));
p.then(() => this.actuallyDone = true); p.then(() => this.actuallyDone = true);
})); }));
@ -192,7 +192,7 @@ const bTok = new InjectionToken<string>('b');
})); }));
it('should preserve context when async and inject helpers are combined', it('should preserve context when async and inject helpers are combined',
async(inject([], function(this: TestContext) { waitForAsync(inject([], function(this: TestContext) {
setTimeout(() => this.contextModified = true, 0); setTimeout(() => this.contextModified = true, 0);
}))); })));
@ -214,7 +214,7 @@ const bTok = new InjectionToken<string>('b');
})); }));
it('should wait until returned promises', it('should wait until returned promises',
async(inject([FancyService], (service: FancyService) => { waitForAsync(inject([FancyService], (service: FancyService) => {
service.getAsyncValue().then((value) => expect(value).toEqual('async value')); service.getAsyncValue().then((value) => expect(value).toEqual('async value'));
service.getTimeoutValue().then((value) => expect(value).toEqual('timeout value')); service.getTimeoutValue().then((value) => expect(value).toEqual('timeout value'));
}))); })));
@ -251,7 +251,7 @@ const bTok = new InjectionToken<string>('b');
}); });
describe('using async beforeEach', () => { describe('using async beforeEach', () => {
beforeEach(async(inject([FancyService], (service: FancyService) => { beforeEach(waitForAsync(inject([FancyService], (service: FancyService) => {
service.getAsyncValue().then((value) => service.value = value); service.getAsyncValue().then((value) => service.value = value);
}))); })));
@ -335,7 +335,7 @@ const bTok = new InjectionToken<string>('b');
}); });
describe('components with template url', () => { describe('components with template url', () => {
beforeEach(async(() => { beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]}); TestBed.configureTestingModule({declarations: [CompWithUrlTemplate]});
TestBed.compileComponents(); TestBed.compileComponents();
})); }));
@ -892,9 +892,9 @@ const bTok = new InjectionToken<string>('b');
const itPromise = patchJasmineIt(); const itPromise = patchJasmineIt();
const barError = new Error('bar'); const barError = new Error('bar');
it('throws an async error', async(inject([], () => setTimeout(() => { it('throws an async error', waitForAsync(inject([], () => setTimeout(() => {
throw barError; throw barError;
}, 0)))); }, 0))));
itPromise.then(() => done.fail('Expected test to fail, but it did not'), (err) => { itPromise.then(() => done.fail('Expected test to fail, but it did not'), (err) => {
expect(err).toEqual(barError); expect(err).toEqual(barError);
@ -906,7 +906,7 @@ const bTok = new InjectionToken<string>('b');
it('should fail when a returned promise is rejected', (done) => { it('should fail when a returned promise is rejected', (done) => {
const itPromise = patchJasmineIt(); const itPromise = patchJasmineIt();
it('should fail with an error from a promise', async(inject([], () => { it('should fail with an error from a promise', waitForAsync(inject([], () => {
let reject: (error: any) => void = undefined!; let reject: (error: any) => void = undefined!;
const promise = new Promise((_, rej) => reject = rej); const promise = new Promise((_, rej) => reject = rej);
const p = promise.then(() => expect(1).toEqual(2)); const p = promise.then(() => expect(1).toEqual(2));
@ -1011,14 +1011,14 @@ Did you run and wait for 'resolveComponentResources()'?` :
}); });
}); });
it('should instantiate a component with valid DOM', async(() => { it('should instantiate a component with valid DOM', waitForAsync(() => {
const fixture = TestBed.createComponent(ChildComp); const fixture = TestBed.createComponent(ChildComp);
fixture.detectChanges(); fixture.detectChanges();
expect(fixture.nativeElement).toHaveText('Original Child'); expect(fixture.nativeElement).toHaveText('Original Child');
})); }));
it('should allow changing members of the component', async(() => { it('should allow changing members of the component', waitForAsync(() => {
const componentFixture = TestBed.createComponent(MyIfComp); const componentFixture = TestBed.createComponent(MyIfComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('MyIf()'); expect(componentFixture.nativeElement).toHaveText('MyIf()');
@ -1028,14 +1028,14 @@ Did you run and wait for 'resolveComponentResources()'?` :
expect(componentFixture.nativeElement).toHaveText('MyIf(More)'); expect(componentFixture.nativeElement).toHaveText('MyIf(More)');
})); }));
it('should override a template', async(() => { it('should override a template', waitForAsync(() => {
TestBed.overrideComponent(ChildComp, {set: {template: '<span>Mock</span>'}}); TestBed.overrideComponent(ChildComp, {set: {template: '<span>Mock</span>'}});
const componentFixture = TestBed.createComponent(ChildComp); const componentFixture = TestBed.createComponent(ChildComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('Mock'); expect(componentFixture.nativeElement).toHaveText('Mock');
})); }));
it('should override a provider', async(() => { it('should override a provider', waitForAsync(() => {
TestBed.overrideComponent( TestBed.overrideComponent(
TestProvidersComp, TestProvidersComp,
{set: {providers: [{provide: FancyService, useClass: MockFancyService}]}}); {set: {providers: [{provide: FancyService, useClass: MockFancyService}]}});
@ -1045,7 +1045,7 @@ Did you run and wait for 'resolveComponentResources()'?` :
})); }));
it('should override a viewProvider', async(() => { it('should override a viewProvider', waitForAsync(() => {
TestBed.overrideComponent( TestBed.overrideComponent(
TestViewProvidersComp, TestViewProvidersComp,
{set: {viewProviders: [{provide: FancyService, useClass: MockFancyService}]}}); {set: {viewProviders: [{provide: FancyService, useClass: MockFancyService}]}});
@ -1065,7 +1065,7 @@ Did you run and wait for 'resolveComponentResources()'?` :
}); });
}); });
it('should override component dependencies', async(() => { it('should override component dependencies', waitForAsync(() => {
const componentFixture = TestBed.createComponent(ParentComp); const componentFixture = TestBed.createComponent(ParentComp);
componentFixture.detectChanges(); componentFixture.detectChanges();
expect(componentFixture.nativeElement).toHaveText('Parent(Mock)'); expect(componentFixture.nativeElement).toHaveText('Parent(Mock)');

View File

@ -11,7 +11,7 @@ import {DOCUMENT, isPlatformServer, PlatformLocation, ɵgetDOM as getDOM} from '
import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http'; import {HTTP_INTERCEPTORS, HttpClient, HttpClientModule, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'; import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {ApplicationRef, CompilerFactory, Component, destroyPlatform, getPlatform, HostListener, Inject, Injectable, Input, NgModule, NgZone, PLATFORM_ID, PlatformRef, ViewEncapsulation} from '@angular/core'; import {ApplicationRef, CompilerFactory, Component, destroyPlatform, getPlatform, HostListener, Inject, Injectable, Input, NgModule, NgZone, PLATFORM_ID, PlatformRef, ViewEncapsulation} from '@angular/core';
import {async, inject} from '@angular/core/testing'; import {inject, waitForAsync} from '@angular/core/testing';
import {BrowserModule, makeStateKey, Title, TransferState} from '@angular/platform-browser'; import {BrowserModule, makeStateKey, Title, TransferState} from '@angular/platform-browser';
import {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, platformDynamicServer, PlatformState, renderModule, renderModuleFactory, ServerModule, ServerTransferStateModule} from '@angular/platform-server'; import {BEFORE_APP_SERIALIZED, INITIAL_CONFIG, platformDynamicServer, PlatformState, renderModule, renderModuleFactory, ServerModule, ServerTransferStateModule} from '@angular/platform-server';
import {ivyEnabled, modifiedInIvy} from '@angular/private/testing'; import {ivyEnabled, modifiedInIvy} from '@angular/private/testing';
@ -409,7 +409,7 @@ describe('platform-server integration', () => {
if (getPlatform()) destroyPlatform(); if (getPlatform()) destroyPlatform();
}); });
it('should bootstrap', async(() => { it('should bootstrap', waitForAsync(() => {
const platform = const platform =
platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
@ -426,7 +426,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should allow multiple platform instances', async(() => { it('should allow multiple platform instances', waitForAsync(() => {
const platform = const platform =
platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
@ -447,7 +447,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('adds title to the document using Title service', async(() => { it('adds title to the document using Title service', waitForAsync(() => {
const platform = platformDynamicServer([{ const platform = platformDynamicServer([{
provide: INITIAL_CONFIG, provide: INITIAL_CONFIG,
useValue: {document: '<html><head><title></title></head><body><app></app></body></html>'} useValue: {document: '<html><head><title></title></head><body><app></app></body></html>'}
@ -461,7 +461,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should get base href from document', async(() => { it('should get base href from document', waitForAsync(() => {
const platform = platformDynamicServer([{ const platform = platformDynamicServer([{
provide: INITIAL_CONFIG, provide: INITIAL_CONFIG,
useValue: {document: '<html><head><base href="/"></head><body><app></app></body></html>'} useValue: {document: '<html><head><base href="/"></head><body><app></app></body></html>'}
@ -473,7 +473,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('adds styles with ng-transition attribute', async(() => { it('adds styles with ng-transition attribute', waitForAsync(() => {
const platform = platformDynamicServer([{ const platform = platformDynamicServer([{
provide: INITIAL_CONFIG, provide: INITIAL_CONFIG,
useValue: {document: '<html><head></head><body><app></app></body></html>'} useValue: {document: '<html><head></head><body><app></app></body></html>'}
@ -488,7 +488,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('copies known properties to attributes', async(() => { it('copies known properties to attributes', waitForAsync(() => {
const platform = const platform =
platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(ImageExampleModule).then(ref => { platform.bootstrapModule(ImageExampleModule).then(ref => {
@ -500,7 +500,7 @@ describe('platform-server integration', () => {
})); }));
describe('PlatformLocation', () => { describe('PlatformLocation', () => {
it('is injectable', async(() => { it('is injectable', waitForAsync(() => {
const platform = platformDynamicServer( const platform = platformDynamicServer(
[{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); [{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(ExampleModule).then(appRef => { platform.bootstrapModule(ExampleModule).then(appRef => {
@ -551,7 +551,7 @@ describe('platform-server integration', () => {
expect(location.hash).toBe(''); expect(location.hash).toBe('');
}); });
}); });
it('pushState causes the URL to update', async(() => { it('pushState causes the URL to update', waitForAsync(() => {
const platform = platformDynamicServer( const platform = platformDynamicServer(
[{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); [{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(ExampleModule).then(appRef => { platform.bootstrapModule(ExampleModule).then(appRef => {
@ -601,7 +601,7 @@ describe('platform-server integration', () => {
expect(called).toBe(true); expect(called).toBe(true);
}); });
it('using long form should work', async(() => { it('using long form should work', waitForAsync(() => {
const platform = const platform =
platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: doc}}]); platformDynamicServer([{provide: INITIAL_CONFIG, useValue: {document: doc}}]);
@ -618,7 +618,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('using renderModule should work', async(() => { it('using renderModule should work', waitForAsync(() => {
renderModule(AsyncServerModule, {document: doc}).then(output => { renderModule(AsyncServerModule, {document: doc}).then(output => {
expect(output).toBe(expectedOutput); expect(output).toBe(expectedOutput);
called = true; called = true;
@ -626,7 +626,7 @@ describe('platform-server integration', () => {
})); }));
modifiedInIvy('Will not support binding to innerText in Ivy since domino does not') modifiedInIvy('Will not support binding to innerText in Ivy since domino does not')
.it('should support binding to innerText', async(() => { .it('should support binding to innerText', waitForAsync(() => {
renderModule(InnerTextModule, {document: doc}).then(output => { renderModule(InnerTextModule, {document: doc}).then(output => {
expect(output).toBe( expect(output).toBe(
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER"><div innertext="Some text">Some text</div></app></body></html>'); '<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER"><div innertext="Some text">Some text</div></app></body></html>');
@ -635,7 +635,7 @@ describe('platform-server integration', () => {
})); }));
it('using renderModuleFactory should work', it('using renderModuleFactory should work',
async(inject([PlatformRef], (defaultPlatform: PlatformRef) => { waitForAsync(inject([PlatformRef], (defaultPlatform: PlatformRef) => {
const compilerFactory: CompilerFactory = const compilerFactory: CompilerFactory =
defaultPlatform.injector.get(CompilerFactory, null)!; defaultPlatform.injector.get(CompilerFactory, null)!;
const moduleFactory = const moduleFactory =
@ -646,7 +646,7 @@ describe('platform-server integration', () => {
}); });
}))); })));
it('works with SVG elements', async(() => { it('works with SVG elements', waitForAsync(() => {
renderModule(SVGServerModule, {document: doc}).then(output => { renderModule(SVGServerModule, {document: doc}).then(output => {
expect(output).toBe( expect(output).toBe(
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' + '<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
@ -655,7 +655,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('works with animation', async(() => { it('works with animation', waitForAsync(() => {
renderModule(AnimationServerModule, {document: doc}).then(output => { renderModule(AnimationServerModule, {document: doc}).then(output => {
expect(output).toContain('Works!'); expect(output).toContain('Works!');
expect(output).toContain('ng-trigger-myAnimation'); expect(output).toContain('ng-trigger-myAnimation');
@ -666,7 +666,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should handle ViewEncapsulation.Native', async(() => { it('should handle ViewEncapsulation.Native', waitForAsync(() => {
renderModule(NativeExampleModule, {document: doc}).then(output => { renderModule(NativeExampleModule, {document: doc}).then(output => {
expect(output).not.toBe(''); expect(output).not.toBe('');
expect(output).toContain('color: red'); expect(output).toContain('color: red');
@ -675,7 +675,7 @@ describe('platform-server integration', () => {
})); }));
it('sets a prefix for the _nghost and _ngcontent attributes', async(() => { it('sets a prefix for the _nghost and _ngcontent attributes', waitForAsync(() => {
renderModule(ExampleStylesModule, {document: doc}).then(output => { renderModule(ExampleStylesModule, {document: doc}).then(output => {
expect(output).toMatch( expect(output).toMatch(
/<html><head><style ng-transition="example-styles">div\[_ngcontent-sc\d+\] {color: blue; } \[_nghost-sc\d+\] { color: red; }<\/style><\/head><body><app _nghost-sc\d+="" ng-version="0.0.0-PLACEHOLDER"><div _ngcontent-sc\d+="">Works!<\/div><\/app><\/body><\/html>/); /<html><head><style ng-transition="example-styles">div\[_ngcontent-sc\d+\] {color: blue; } \[_nghost-sc\d+\] { color: red; }<\/style><\/head><body><app _nghost-sc\d+="" ng-version="0.0.0-PLACEHOLDER"><div _ngcontent-sc\d+="">Works!<\/div><\/app><\/body><\/html>/);
@ -683,7 +683,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should handle false values on attributes', async(() => { it('should handle false values on attributes', waitForAsync(() => {
renderModule(FalseAttributesModule, {document: doc}).then(output => { renderModule(FalseAttributesModule, {document: doc}).then(output => {
expect(output).toBe( expect(output).toBe(
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' + '<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
@ -692,7 +692,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should handle element property "name"', async(() => { it('should handle element property "name"', waitForAsync(() => {
renderModule(NameModule, {document: doc}).then(output => { renderModule(NameModule, {document: doc}).then(output => {
expect(output).toBe( expect(output).toBe(
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' + '<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
@ -701,7 +701,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should work with sanitizer to handle "innerHTML"', async(() => { it('should work with sanitizer to handle "innerHTML"', waitForAsync(() => {
// Clear out any global states. These should be set when platform-server // Clear out any global states. These should be set when platform-server
// is initialized. // is initialized.
(global as any).Node = undefined; (global as any).Node = undefined;
@ -714,7 +714,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should handle element property "hidden"', async(() => { it('should handle element property "hidden"', waitForAsync(() => {
renderModule(HiddenModule, {document: doc}).then(output => { renderModule(HiddenModule, {document: doc}).then(output => {
expect(output).toBe( expect(output).toBe(
'<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' + '<html><head></head><body><app ng-version="0.0.0-PLACEHOLDER">' +
@ -723,7 +723,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should call render hook', async(() => { it('should call render hook', waitForAsync(() => {
renderModule(RenderHookModule, {document: doc}).then(output => { renderModule(RenderHookModule, {document: doc}).then(output => {
// title should be added by the render hook. // title should be added by the render hook.
expect(output).toBe( expect(output).toBe(
@ -733,7 +733,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should call multiple render hooks', async(() => { it('should call multiple render hooks', waitForAsync(() => {
const consoleSpy = spyOn(console, 'warn'); const consoleSpy = spyOn(console, 'warn');
renderModule(MultiRenderHookModule, {document: doc}).then(output => { renderModule(MultiRenderHookModule, {document: doc}).then(output => {
// title should be added by the render hook. // title should be added by the render hook.
@ -745,7 +745,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should call async render hooks', async(() => { it('should call async render hooks', waitForAsync(() => {
renderModule(AsyncRenderHookModule, {document: doc}).then(output => { renderModule(AsyncRenderHookModule, {document: doc}).then(output => {
// title should be added by the render hook. // title should be added by the render hook.
expect(output).toBe( expect(output).toBe(
@ -755,7 +755,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('should call multiple async and sync render hooks', async(() => { it('should call multiple async and sync render hooks', waitForAsync(() => {
const consoleSpy = spyOn(console, 'warn'); const consoleSpy = spyOn(console, 'warn');
renderModule(AsyncMultiRenderHookModule, {document: doc}).then(output => { renderModule(AsyncMultiRenderHookModule, {document: doc}).then(output => {
// title should be added by the render hook. // title should be added by the render hook.
@ -769,7 +769,7 @@ describe('platform-server integration', () => {
}); });
describe('HttpClient', () => { describe('HttpClient', () => {
it('can inject HttpClient', async(() => { it('can inject HttpClient', waitForAsync(() => {
const platform = platformDynamicServer( const platform = platformDynamicServer(
[{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); [{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(HttpClientExampleModule).then(ref => { platform.bootstrapModule(HttpClientExampleModule).then(ref => {
@ -777,7 +777,7 @@ describe('platform-server integration', () => {
}); });
})); }));
it('can make HttpClient requests', async(() => { it('can make HttpClient requests', waitForAsync(() => {
const platform = platformDynamicServer( const platform = platformDynamicServer(
[{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); [{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(HttpClientExampleModule).then(ref => { platform.bootstrapModule(HttpClientExampleModule).then(ref => {
@ -938,7 +938,7 @@ describe('platform-server integration', () => {
}); });
}); });
it('requests are macrotasks', async(() => { it('requests are macrotasks', waitForAsync(() => {
const platform = platformDynamicServer( const platform = platformDynamicServer(
[{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]); [{provide: INITIAL_CONFIG, useValue: {document: '<app></app>'}}]);
platform.bootstrapModule(HttpClientExampleModule).then(ref => { platform.bootstrapModule(HttpClientExampleModule).then(ref => {
@ -984,7 +984,7 @@ describe('platform-server integration', () => {
expect(called).toBe(true); expect(called).toBe(true);
}); });
it('adds transfer script tag when using renderModule', async(() => { it('adds transfer script tag when using renderModule', waitForAsync(() => {
renderModule(TransferStoreModule, {document: '<app></app>'}).then(output => { renderModule(TransferStoreModule, {document: '<app></app>'}).then(output => {
expect(output).toBe(defaultExpectedOutput); expect(output).toBe(defaultExpectedOutput);
called = true; called = true;
@ -992,7 +992,7 @@ describe('platform-server integration', () => {
})); }));
it('adds transfer script tag when using renderModuleFactory', it('adds transfer script tag when using renderModuleFactory',
async(inject([PlatformRef], (defaultPlatform: PlatformRef) => { waitForAsync(inject([PlatformRef], (defaultPlatform: PlatformRef) => {
const compilerFactory: CompilerFactory = const compilerFactory: CompilerFactory =
defaultPlatform.injector.get(CompilerFactory, null)!; defaultPlatform.injector.get(CompilerFactory, null)!;
const moduleFactory = const moduleFactory =
@ -1003,7 +1003,7 @@ describe('platform-server integration', () => {
}); });
}))); })));
it('cannot break out of <script> tag in serialized output', async(() => { it('cannot break out of <script> tag in serialized output', waitForAsync(() => {
renderModule(EscapedTransferStoreModule, { renderModule(EscapedTransferStoreModule, {
document: '<esc-app></esc-app>' document: '<esc-app></esc-app>'
}).then(output => { }).then(output => {

View File

@ -7,7 +7,7 @@
*/ */
import {ChangeDetectorRef, Component, destroyPlatform, EventEmitter, forwardRef, Input, NgModule, NgModuleFactory, NgZone, NO_ERRORS_SCHEMA, OnChanges, OnDestroy, Output, SimpleChange, SimpleChanges, Testability} from '@angular/core'; import {ChangeDetectorRef, Component, destroyPlatform, EventEmitter, forwardRef, Input, NgModule, NgModuleFactory, NgZone, NO_ERRORS_SCHEMA, OnChanges, OnDestroy, Output, SimpleChange, SimpleChanges, Testability} from '@angular/core';
import {async, fakeAsync, flushMicrotasks, tick} from '@angular/core/testing'; import {fakeAsync, flushMicrotasks, tick, waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -30,7 +30,7 @@ withEachNg1Version(() => {
it('should have AngularJS loaded', it('should have AngularJS loaded',
() => expect(angular.getAngularJSGlobal().version.major).toBe(1)); () => expect(angular.getAngularJSGlobal().version.major).toBe(1));
it('should instantiate ng2 in ng1 template and project content', async(() => { it('should instantiate ng2 in ng1 template and project content', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@Component({ @Component({
@ -55,7 +55,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should instantiate ng1 in ng2 template and project content', async(() => { it('should instantiate ng1 in ng2 template and project content', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -86,7 +86,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('supports the compilerOptions argument', async(() => { it('supports the compilerOptions argument', waitForAsync(() => {
const platformRef = platformBrowserDynamic(); const platformRef = platformBrowserDynamic();
spyOn(platformRef, 'bootstrapModule').and.callThrough(); spyOn(platformRef, 'bootstrapModule').and.callThrough();
spyOn(platformRef, 'bootstrapModuleFactory').and.callThrough(); spyOn(platformRef, 'bootstrapModuleFactory').and.callThrough();
@ -170,7 +170,7 @@ withEachNg1Version(() => {
}); });
describe('change-detection', () => { describe('change-detection', () => {
it('should not break if a $digest is already in progress', async(() => { it('should not break if a $digest is already in progress', waitForAsync(() => {
@Component({selector: 'my-app', template: ''}) @Component({selector: 'my-app', template: ''})
class AppComponent { class AppComponent {
} }
@ -209,7 +209,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should interleave scope and component expressions', async(() => { it('should interleave scope and component expressions', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
const log: string[] = []; const log: string[] = [];
@ -256,7 +256,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should propagate changes to a downgraded component inside the ngZone', async(() => { it('should propagate changes to a downgraded component inside the ngZone',
waitForAsync(() => {
let appComponent: AppComponent; let appComponent: AppComponent;
let upgradeRef: UpgradeAdapterRef; let upgradeRef: UpgradeAdapterRef;
@ -342,7 +343,7 @@ withEachNg1Version(() => {
}); });
describe('downgrade ng2 component', () => { describe('downgrade ng2 component', () => {
it('should allow non-element selectors for downgraded components', async(() => { it('should allow non-element selectors for downgraded components', waitForAsync(() => {
@Component({selector: '[itWorks]', template: 'It works'}) @Component({selector: '[itWorks]', template: 'It works'})
class WorksComponent { class WorksComponent {
} }
@ -361,7 +362,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind properties, events', async(() => { it('should bind properties, events', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []).value($EXCEPTION_HANDLER, (err: any) => { const ng1Module = angular.module_('ng1', []).value($EXCEPTION_HANDLER, (err: any) => {
throw err; throw err;
@ -483,7 +484,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support two-way binding and event listener', async(() => { it('should support two-way binding and event listener', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const listenerSpy = jasmine.createSpy('$rootScope.listener'); const listenerSpy = jasmine.createSpy('$rootScope.listener');
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => { const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
@ -532,7 +533,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should initialize inputs in time for `ngOnChanges`', async(() => { it('should initialize inputs in time for `ngOnChanges`', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
@Component({ @Component({
@ -591,7 +592,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind to ng-model', async(() => { it('should bind to ng-model', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -661,7 +662,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should properly run cleanup when ng1 directive is destroyed', async(() => { it('should properly run cleanup when ng1 directive is destroyed', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
const onDestroyed: EventEmitter<string> = new EventEmitter<string>(); const onDestroyed: EventEmitter<string> = new EventEmitter<string>();
@ -700,7 +701,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should properly run cleanup with multiple levels of nesting', async(() => { it('should properly run cleanup with multiple levels of nesting', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let destroyed = false; let destroyed = false;
@ -745,7 +746,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should fallback to the root ng2.injector when compiled outside the dom', async(() => { it('should fallback to the root ng2.injector when compiled outside the dom',
waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -781,7 +783,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support multi-slot projection', async(() => { it('should support multi-slot projection', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@Component({ @Component({
@ -810,7 +812,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should correctly project structural directives', async(() => { it('should correctly project structural directives', waitForAsync(() => {
@Component({selector: 'ng2', template: 'ng2-{{ itemId }}(<ng-content></ng-content>)'}) @Component({selector: 'ng2', template: 'ng2-{{ itemId }}(<ng-content></ng-content>)'})
class Ng2Component { class Ng2Component {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
@ -844,7 +846,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should allow attribute selectors for components in ng2', async(() => { it('should allow attribute selectors for components in ng2', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => MyNg2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => MyNg2Module));
const ng1Module = angular.module_('myExample', []); const ng1Module = angular.module_('myExample', []);
@ -1123,7 +1125,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind properties, events', async(() => { it('should bind properties, events', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1181,7 +1183,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind optional properties', async(() => { it('should bind optional properties', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1226,7 +1228,7 @@ withEachNg1Version(() => {
})); }));
it('should bind properties, events in controller when bindToController is not used', it('should bind properties, events in controller when bindToController is not used',
async(() => { waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1272,7 +1274,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind properties, events in link function', async(() => { it('should bind properties, events in link function', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1318,7 +1320,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support templateUrl fetched from $httpBackend', async(() => { it('should support templateUrl fetched from $httpBackend', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
ng1Module.value( ng1Module.value(
@ -1349,7 +1351,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support templateUrl as a function', async(() => { it('should support templateUrl as a function', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
ng1Module.value( ng1Module.value(
@ -1384,7 +1386,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support empty template', async(() => { it('should support empty template', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1412,7 +1414,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support template as a function', async(() => { it('should support template as a function', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1444,7 +1446,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support templateUrl fetched from $templateCache', async(() => { it('should support templateUrl fetched from $templateCache', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
ng1Module.run(($templateCache: any) => $templateCache.put('url.html', 'WORKS')); ng1Module.run(($templateCache: any) => $templateCache.put('url.html', 'WORKS'));
@ -1473,7 +1475,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support controller with controllerAs', async(() => { it('should support controller with controllerAs', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1524,7 +1526,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support bindToController', async(() => { it('should support bindToController', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1558,7 +1560,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support bindToController with bindings', async(() => { it('should support bindToController with bindings', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1592,7 +1594,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support single require in linking fn', async(() => { it('should support single require in linking fn', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1635,7 +1637,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support array require in linking fn', async(() => { it('should support array require in linking fn', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -1688,7 +1690,7 @@ withEachNg1Version(() => {
})); }));
describe('with life-cycle hooks', () => { describe('with life-cycle hooks', () => {
it('should call `$onInit()` on controller', async(() => { it('should call `$onInit()` on controller', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onInitSpyA = jasmine.createSpy('$onInitA'); const $onInitSpyA = jasmine.createSpy('$onInitA');
const $onInitSpyB = jasmine.createSpy('$onInitB'); const $onInitSpyB = jasmine.createSpy('$onInitB');
@ -1739,7 +1741,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$onInit()` on scope', async(() => { it('should not call `$onInit()` on scope', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $onInitSpy = jasmine.createSpy('$onInit'); const $onInitSpy = jasmine.createSpy('$onInit');
@ -1785,7 +1787,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should call `$doCheck()` on controller', async(() => { it('should call `$doCheck()` on controller', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $doCheckSpyA = jasmine.createSpy('$doCheckA'); const $doCheckSpyA = jasmine.createSpy('$doCheckA');
const $doCheckSpyB = jasmine.createSpy('$doCheckB'); const $doCheckSpyB = jasmine.createSpy('$doCheckB');
@ -1847,7 +1849,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$doCheck()` on scope', async(() => { it('should not call `$doCheck()` on scope', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $doCheckSpyA = jasmine.createSpy('$doCheckA'); const $doCheckSpyA = jasmine.createSpy('$doCheckA');
const $doCheckSpyB = jasmine.createSpy('$doCheckB'); const $doCheckSpyB = jasmine.createSpy('$doCheckB');
@ -1904,7 +1906,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should call `$postLink()` on controller', async(() => { it('should call `$postLink()` on controller', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $postLinkSpyA = jasmine.createSpy('$postLinkA'); const $postLinkSpyA = jasmine.createSpy('$postLinkA');
const $postLinkSpyB = jasmine.createSpy('$postLinkB'); const $postLinkSpyB = jasmine.createSpy('$postLinkB');
@ -1955,7 +1957,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$postLink()` on scope', async(() => { it('should not call `$postLink()` on scope', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const $postLinkSpy = jasmine.createSpy('$postLink'); const $postLinkSpy = jasmine.createSpy('$postLink');
@ -2520,7 +2522,7 @@ withEachNg1Version(() => {
}); });
describe('linking', () => { describe('linking', () => {
it('should run the pre-linking after instantiating the controller', async(() => { it('should run the pre-linking after instantiating the controller', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = []; const log: string[] = [];
@ -2561,7 +2563,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the pre-linking function before linking', async(() => { it('should run the pre-linking function before linking', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = []; const log: string[] = [];
@ -2601,7 +2603,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function after linking (link: object)', async(() => { it('should run the post-linking function after linking (link: object)', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = []; const log: string[] = [];
@ -2641,7 +2643,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function after linking (link: function)', async(() => { it('should run the post-linking function after linking (link: function)',
waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = []; const log: string[] = [];
@ -2681,7 +2684,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function before `$postLink`', async(() => { it('should run the post-linking function before `$postLink`', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const log: string[] = []; const log: string[] = [];
@ -2724,7 +2727,7 @@ withEachNg1Version(() => {
}); });
describe('transclusion', () => { describe('transclusion', () => {
it('should support single-slot transclusion', async(() => { it('should support single-slot transclusion', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng2ComponentAInstance: Ng2ComponentA; let ng2ComponentAInstance: Ng2ComponentA;
let ng2ComponentBInstance: Ng2ComponentB; let ng2ComponentBInstance: Ng2ComponentB;
@ -2788,7 +2791,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support single-slot transclusion with fallback content', async(() => { it('should support single-slot transclusion with fallback content', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2854,7 +2857,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support multi-slot transclusion', async(() => { it('should support multi-slot transclusion', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2916,7 +2919,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support default slot (with fallback content)', async(() => { it('should support default slot (with fallback content)', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2999,7 +3002,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support optional transclusion slots (with fallback content)', async(() => { it('should support optional transclusion slots (with fallback content)',
waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -3072,7 +3076,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should throw if a non-optional slot is not filled', async(() => { it('should throw if a non-optional slot is not filled', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let errorMessage: string; let errorMessage: string;
@ -3111,7 +3115,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support structural directives in transcluded content', async(() => { it('should support structural directives in transcluded content', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -3179,7 +3183,7 @@ withEachNg1Version(() => {
})); }));
}); });
it('should bind input properties (<) of components', async(() => { it('should bind input properties (<) of components', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -3211,7 +3215,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support ng2 > ng1 > ng2', async(() => { it('should support ng2 > ng1 > ng2', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@ -3247,7 +3251,7 @@ withEachNg1Version(() => {
describe('injection', () => { describe('injection', () => {
function SomeToken() {} function SomeToken() {}
it('should export ng2 instance to ng1', async(() => { it('should export ng2 instance to ng1', waitForAsync(() => {
@NgModule({ @NgModule({
providers: [{provide: SomeToken, useValue: 'correct_value'}], providers: [{provide: SomeToken, useValue: 'correct_value'}],
imports: [BrowserModule], imports: [BrowserModule],
@ -3264,7 +3268,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should export ng1 instance to ng2', async(() => { it('should export ng1 instance to ng2', waitForAsync(() => {
@NgModule({imports: [BrowserModule]}) @NgModule({imports: [BrowserModule]})
class MyNg2Module { class MyNg2Module {
} }
@ -3283,7 +3287,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should respect hierarchical dependency injection for ng2', async(() => { it('should respect hierarchical dependency injection for ng2', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []); const ng1Module = angular.module_('ng1', []);
@Component({selector: 'ng2-parent', template: `ng2-parent(<ng-content></ng-content>)`}) @Component({selector: 'ng2-parent', template: `ng2-parent(<ng-content></ng-content>)`})
@ -3311,7 +3315,7 @@ withEachNg1Version(() => {
}); });
describe('testability', () => { describe('testability', () => {
it('should handle deferred bootstrap', async(() => { it('should handle deferred bootstrap', waitForAsync(() => {
@NgModule({imports: [BrowserModule]}) @NgModule({imports: [BrowserModule]})
class MyNg2Module { class MyNg2Module {
} }
@ -3362,7 +3366,7 @@ withEachNg1Version(() => {
expect(value).toBe(a1Injector); expect(value).toBe(a1Injector);
})); }));
it('should wait for ng2 testability', async(() => { it('should wait for ng2 testability', waitForAsync(() => {
@NgModule({imports: [BrowserModule]}) @NgModule({imports: [BrowserModule]})
class MyNg2Module { class MyNg2Module {
} }
@ -3389,7 +3393,7 @@ withEachNg1Version(() => {
}); });
describe('examples', () => { describe('examples', () => {
it('should verify UpgradeAdapter example', async(() => { it('should verify UpgradeAdapter example', waitForAsync(() => {
const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module)); const adapter: UpgradeAdapter = new UpgradeAdapter(forwardRef(() => Ng2Module));
const module = angular.module_('myExample', []); const module = angular.module_('myExample', []);
@ -3461,7 +3465,7 @@ withEachNg1Version(() => {
}); });
}); });
it('should be able to test ng1 components that use ng2 components', async(() => { it('should be able to test ng1 components that use ng2 components', waitForAsync(() => {
upgradeAdapterRef.ready(() => { upgradeAdapterRef.ready(() => {
const element = $compile('<ng2></ng2>')($rootScope); const element = $compile('<ng2></ng2>')($rootScope);
$rootScope.$digest(); $rootScope.$digest();

View File

@ -7,7 +7,7 @@
*/ */
import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule, NgZone, SimpleChanges} from '@angular/core'; import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule, NgZone, SimpleChanges} from '@angular/core';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static'; import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static';
@ -22,7 +22,7 @@ withEachNg1Version(() => {
beforeEach(() => destroyPlatform()); beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
it('should not break if a $digest is already in progress', async(() => { it('should not break if a $digest is already in progress', waitForAsync(() => {
const element = html('<my-app></my-app>'); const element = html('<my-app></my-app>');
@Component({selector: 'my-app', template: ''}) @Component({selector: 'my-app', template: ''})
@ -77,7 +77,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should interleave scope and component expressions', async(() => { it('should interleave scope and component expressions', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
const l = (value: string) => { const l = (value: string) => {
log.push(value); log.push(value);
@ -132,7 +132,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should propagate changes to a downgraded component inside the ngZone', async(() => { it('should propagate changes to a downgraded component inside the ngZone', waitForAsync(() => {
const element = html('<my-app></my-app>'); const element = html('<my-app></my-app>');
let appComponent: AppComponent; let appComponent: AppComponent;

View File

@ -7,7 +7,7 @@
*/ */
import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule} from '@angular/core'; import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule} from '@angular/core';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static'; import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static';
@ -22,7 +22,7 @@ withEachNg1Version(() => {
beforeEach(() => destroyPlatform()); beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
it('should instantiate ng2 in ng1 template and project content', async(() => { it('should instantiate ng2 in ng1 template and project content', waitForAsync(() => {
// the ng2 component that will be used in ng1 (downgraded) // the ng2 component that will be used in ng1 (downgraded)
@Component({selector: 'ng2', template: `{{ prop }}(<ng-content></ng-content>)`}) @Component({selector: 'ng2', template: `{{ prop }}(<ng-content></ng-content>)`})
class Ng2Component { class Ng2Component {
@ -57,7 +57,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should correctly project structural directives', async(() => { it('should correctly project structural directives', waitForAsync(() => {
@Component({selector: 'ng2', template: 'ng2-{{ itemId }}(<ng-content></ng-content>)'}) @Component({selector: 'ng2', template: 'ng2-{{ itemId }}(<ng-content></ng-content>)'})
class Ng2Component { class Ng2Component {
// TODO(issue/24571): remove '!'. // TODO(issue/24571): remove '!'.
@ -94,7 +94,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should instantiate ng1 in ng2 template and project content', async(() => { it('should instantiate ng1 in ng2 template and project content', waitForAsync(() => {
@Component({ @Component({
selector: 'ng2', selector: 'ng2',
template: `{{ 'ng2(' }}<ng1>{{ transclude }}</ng1>{{ ')' }}`, template: `{{ 'ng2(' }}<ng1>{{ transclude }}</ng1>{{ ')' }}`,
@ -139,7 +139,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support multi-slot projection', async(() => { it('should support multi-slot projection', waitForAsync(() => {
@Component({ @Component({
selector: 'ng2', selector: 'ng2',
template: '2a(<ng-content select=".ng1a"></ng-content>)' + template: '2a(<ng-content select=".ng1a"></ng-content>)' +

View File

@ -7,7 +7,7 @@
*/ */
import {ChangeDetectionStrategy, Compiler, Component, destroyPlatform, Directive, ElementRef, EventEmitter, Injector, Input, NgModule, NgModuleRef, OnChanges, OnDestroy, Output, SimpleChanges} from '@angular/core'; import {ChangeDetectionStrategy, Compiler, Component, destroyPlatform, Directive, ElementRef, EventEmitter, Injector, Input, NgModule, NgModuleRef, OnChanges, OnDestroy, Output, SimpleChanges} from '@angular/core';
import {async, fakeAsync, tick} from '@angular/core/testing'; import {fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static'; import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static';
@ -22,7 +22,7 @@ withEachNg1Version(() => {
beforeEach(() => destroyPlatform()); beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
it('should bind properties, events', async(() => { it('should bind properties, events', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => { const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['name'] = 'world'; $rootScope['name'] = 'world';
$rootScope['dataA'] = 'A'; $rootScope['dataA'] = 'A';
@ -146,7 +146,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind properties to onpush components', async(() => { it('should bind properties to onpush components', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => { const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['dataB'] = 'B'; $rootScope['dataB'] = 'B';
}); });
@ -188,7 +188,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support two-way binding and event listener', async(() => { it('should support two-way binding and event listener', waitForAsync(() => {
const listenerSpy = jasmine.createSpy('$rootScope.listener'); const listenerSpy = jasmine.createSpy('$rootScope.listener');
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => { const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['value'] = 'world'; $rootScope['value'] = 'world';
@ -240,7 +240,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run change-detection on every digest (by default)', async(() => { it('should run change-detection on every digest (by default)', waitForAsync(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;
@Component({selector: 'ng2', template: '{{ value1 }} | {{ value2 }}'}) @Component({selector: 'ng2', template: '{{ value1 }} | {{ value2 }}'})
@ -305,7 +305,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not run change-detection on every digest when opted out', async(() => { it('should not run change-detection on every digest when opted out', waitForAsync(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;
@Component({selector: 'ng2', template: '{{ value1 }} | {{ value2 }}'}) @Component({selector: 'ng2', template: '{{ value1 }} | {{ value2 }}'})
@ -408,7 +408,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should initialize inputs in time for `ngOnChanges`', async(() => { it('should initialize inputs in time for `ngOnChanges`', waitForAsync(() => {
@Component({ @Component({
selector: 'ng2', selector: 'ng2',
template: ` template: `
@ -468,7 +468,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should bind to ng-model', async(() => { it('should bind to ng-model', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => { const ng1Module = angular.module_('ng1', []).run(($rootScope: angular.IScope) => {
$rootScope['modelA'] = 'A'; $rootScope['modelA'] = 'A';
}); });
@ -534,7 +534,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should properly run cleanup when ng1 directive is destroyed', async(() => { it('should properly run cleanup when ng1 directive is destroyed', waitForAsync(() => {
let destroyed = false; let destroyed = false;
@Component({selector: 'ng2', template: 'test'}) @Component({selector: 'ng2', template: 'test'})
class Ng2Component implements OnDestroy { class Ng2Component implements OnDestroy {
@ -574,7 +574,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should properly run cleanup with multiple levels of nesting', async(() => { it('should properly run cleanup with multiple levels of nesting', waitForAsync(() => {
let destroyed = false; let destroyed = false;
@Component({ @Component({
@ -628,7 +628,7 @@ withEachNg1Version(() => {
})); }));
it('should work when compiled outside the dom (by fallback to the root ng2.injector)', it('should work when compiled outside the dom (by fallback to the root ng2.injector)',
async(() => { waitForAsync(() => {
@Component({selector: 'ng2', template: 'test'}) @Component({selector: 'ng2', template: 'test'})
class Ng2Component { class Ng2Component {
} }
@ -674,7 +674,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should allow attribute selectors for downgraded components', async(() => { it('should allow attribute selectors for downgraded components', waitForAsync(() => {
@Component({selector: '[itWorks]', template: 'It works'}) @Component({selector: '[itWorks]', template: 'It works'})
class WorksComponent { class WorksComponent {
} }
@ -698,7 +698,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should allow attribute selectors for components in ng2', async(() => { it('should allow attribute selectors for components in ng2', waitForAsync(() => {
@Component({selector: '[itWorks]', template: 'It works'}) @Component({selector: '[itWorks]', template: 'It works'})
class WorksComponent { class WorksComponent {
} }
@ -726,7 +726,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should respect hierarchical dependency injection for ng2', async(() => { it('should respect hierarchical dependency injection for ng2', waitForAsync(() => {
@Component({selector: 'parent', template: 'parent(<ng-content></ng-content>)'}) @Component({selector: 'parent', template: 'parent(<ng-content></ng-content>)'})
class ParentComponent { class ParentComponent {
} }
@ -757,7 +757,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should be compiled synchronously, if possible', async(() => { it('should be compiled synchronously, if possible', waitForAsync(() => {
@Component({selector: 'ng2A', template: '<ng-content></ng-content>'}) @Component({selector: 'ng2A', template: '<ng-content></ng-content>'})
class Ng2ComponentA { class Ng2ComponentA {
} }
@ -786,7 +786,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should work with ng2 lazy loaded components', async(() => { it('should work with ng2 lazy loaded components', waitForAsync(() => {
let componentInjector: Injector; let componentInjector: Injector;
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
@ -836,7 +836,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should throw if `downgradedModule` is specified', async(() => { it('should throw if `downgradedModule` is specified', waitForAsync(() => {
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
class Ng2Component { class Ng2Component {
} }

View File

@ -7,7 +7,7 @@
*/ */
import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ApplicationRef, Compiler, Component, destroyPlatform, Directive, DoCheck, ElementRef, getPlatform, Inject, Injectable, Injector, Input, NgModule, NgZone, OnChanges, OnDestroy, OnInit, StaticProvider, Type, ViewRef} from '@angular/core'; import {AfterContentChecked, AfterContentInit, AfterViewChecked, AfterViewInit, ApplicationRef, Compiler, Component, destroyPlatform, Directive, DoCheck, ElementRef, getPlatform, Inject, Injectable, Injector, Input, NgModule, NgZone, OnChanges, OnDestroy, OnInit, StaticProvider, Type, ViewRef} from '@angular/core';
import {async, fakeAsync, tick} from '@angular/core/testing'; import {fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {browserDetection} from '@angular/platform-browser/testing/src/browser_util'; import {browserDetection} from '@angular/platform-browser/testing/src/browser_util';
@ -26,7 +26,7 @@ withEachNg1Version(() => {
beforeEach(() => destroyPlatform()); beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
it('should support multiple downgraded modules', async(() => { it('should support multiple downgraded modules', waitForAsync(() => {
@Component({selector: 'ng2A', template: 'a'}) @Component({selector: 'ng2A', template: 'a'})
class Ng2ComponentA { class Ng2ComponentA {
} }
@ -80,7 +80,7 @@ withEachNg1Version(() => {
setTimeout(() => expect(element.textContent).toBe('a | b')); setTimeout(() => expect(element.textContent).toBe('a | b'));
})); }));
it('should support nesting components from different downgraded modules', async(() => { it('should support nesting components from different downgraded modules', waitForAsync(() => {
@Directive({selector: 'ng1A'}) @Directive({selector: 'ng1A'})
class Ng1ComponentA extends UpgradeComponent { class Ng1ComponentA extends UpgradeComponent {
constructor(elementRef: ElementRef, injector: Injector) { constructor(elementRef: ElementRef, injector: Injector) {
@ -163,7 +163,7 @@ withEachNg1Version(() => {
})); }));
it('should support nesting components from different downgraded modules (via projection)', it('should support nesting components from different downgraded modules (via projection)',
async(() => { waitForAsync(() => {
@Component({ @Component({
selector: 'ng2A', selector: 'ng2A',
template: 'ng2A(<ng-content></ng-content>)', template: 'ng2A(<ng-content></ng-content>)',
@ -336,7 +336,8 @@ withEachNg1Version(() => {
expect(multiTrim(element.children[1].textContent)).toBe('Counter:1'); expect(multiTrim(element.children[1].textContent)).toBe('Counter:1');
})); }));
it('should correctly traverse the injector tree of downgraded components', async(() => { it('should correctly traverse the injector tree of downgraded components',
waitForAsync(() => {
@Component({ @Component({
selector: 'ng2A', selector: 'ng2A',
template: 'ng2A(<ng-content></ng-content>)', template: 'ng2A(<ng-content></ng-content>)',
@ -423,7 +424,7 @@ withEachNg1Version(() => {
})); }));
it('should correctly traverse the injector tree of downgraded components (from different modules)', it('should correctly traverse the injector tree of downgraded components (from different modules)',
async(() => { waitForAsync(() => {
@Component({ @Component({
selector: 'ng2A', selector: 'ng2A',
template: 'ng2A(<ng-content></ng-content>)', template: 'ng2A(<ng-content></ng-content>)',
@ -544,7 +545,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support downgrading a component and propagate inputs', async(() => { it('should support downgrading a component and propagate inputs', waitForAsync(() => {
@Component( @Component(
{selector: 'ng2A', template: 'a({{ value }}) | <ng2B [value]="value"></ng2B>'}) {selector: 'ng2A', template: 'a({{ value }}) | <ng2B [value]="value"></ng2B>'})
class Ng2AComponent { class Ng2AComponent {
@ -598,7 +599,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support using an upgraded service', async(() => { it('should support using an upgraded service', waitForAsync(() => {
@Injectable() @Injectable()
class Ng2Service { class Ng2Service {
constructor(@Inject('ng1Value') private ng1Value: string) {} constructor(@Inject('ng1Value') private ng1Value: string) {}
@ -658,7 +659,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should create components inside the Angular zone', async(() => { it('should create components inside the Angular zone', waitForAsync(() => {
@Component({selector: 'ng2', template: 'In the zone: {{ inTheZone }}'}) @Component({selector: 'ng2', template: 'In the zone: {{ inTheZone }}'})
class Ng2Component { class Ng2Component {
private inTheZone = false; private inTheZone = false;
@ -694,7 +695,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should destroy components inside the Angular zone', async(() => { it('should destroy components inside the Angular zone', waitForAsync(() => {
let destroyedInTheZone = false; let destroyedInTheZone = false;
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
@ -732,7 +733,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should propagate input changes inside the Angular zone', async(() => { it('should propagate input changes inside the Angular zone', waitForAsync(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
@ -793,7 +794,7 @@ withEachNg1Version(() => {
})); }));
it('should create and destroy nested, asynchronously instantiated components inside the Angular zone', it('should create and destroy nested, asynchronously instantiated components inside the Angular zone',
async(() => { waitForAsync(() => {
let createdInTheZone = false; let createdInTheZone = false;
let destroyedInTheZone = false; let destroyedInTheZone = false;
@ -858,7 +859,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should wire up the component for change detection', async(() => { it('should wire up the component for change detection', waitForAsync(() => {
@Component( @Component(
{selector: 'ng2', template: '{{ count }}<button (click)="increment()"></button>'}) {selector: 'ng2', template: '{{ count }}<button (click)="increment()"></button>'})
class Ng2Component { class Ng2Component {
@ -903,7 +904,7 @@ withEachNg1Version(() => {
})); }));
it('should wire up nested, asynchronously instantiated components for change detection', it('should wire up nested, asynchronously instantiated components for change detection',
async(() => { waitForAsync(() => {
@Component( @Component(
{selector: 'test', template: '{{ count }}<button (click)="increment()"></button>'}) {selector: 'test', template: '{{ count }}<button (click)="increment()"></button>'})
class TestComponent { class TestComponent {
@ -961,7 +962,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the lifecycle hooks in the correct order', async(() => { it('should run the lifecycle hooks in the correct order', waitForAsync(() => {
const logs: string[] = []; const logs: string[] = [];
let rootScope: angular.IRootScopeService; let rootScope: angular.IRootScopeService;
@ -1138,7 +1139,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should detach hostViews from the ApplicationRef once destroyed', async(() => { it('should detach hostViews from the ApplicationRef once destroyed', waitForAsync(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
@ -1253,7 +1254,8 @@ withEachNg1Version(() => {
$rootScope.$destroy(); $rootScope.$destroy();
})); }));
it('should give access to both injectors in the Angular module\'s constructor', async(() => { it('should give access to both injectors in the Angular module\'s constructor',
waitForAsync(() => {
let $injectorFromNg2: angular.IInjectorService|null = null; let $injectorFromNg2: angular.IInjectorService|null = null;
@Component({selector: 'ng2', template: ''}) @Component({selector: 'ng2', template: ''})
@ -1341,7 +1343,7 @@ withEachNg1Version(() => {
// Explicitly clean up after each test to prevent that. // Explicitly clean up after each test to prevent that.
afterEach(() => setTempInjectorRef(null!)); afterEach(() => setTempInjectorRef(null!));
it('should throw if no downgraded module is included', async(() => { it('should throw if no downgraded module is included', waitForAsync(() => {
const ng1Module = angular.module_('ng1', []) const ng1Module = angular.module_('ng1', [])
.value($EXCEPTION_HANDLER, errorSpy) .value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({ .directive('ng2A', downgradeComponent({
@ -1374,7 +1376,8 @@ withEachNg1Version(() => {
'<ng2-b>'); '<ng2-b>');
})); }));
it('should throw if the corresponding downgraded module is not included', async(() => { it('should throw if the corresponding downgraded module is not included',
waitForAsync(() => {
const ng1Module = angular.module_('ng1', [downModA]) const ng1Module = angular.module_('ng1', [downModA])
.value($EXCEPTION_HANDLER, errorSpy) .value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({ .directive('ng2A', downgradeComponent({
@ -1402,7 +1405,7 @@ withEachNg1Version(() => {
})); }));
it('should throw if `downgradedModule` is not specified and there are multiple downgraded modules', it('should throw if `downgradedModule` is not specified and there are multiple downgraded modules',
async(() => { waitForAsync(() => {
const ng1Module = angular.module_('ng1', [downModA, downModB]) const ng1Module = angular.module_('ng1', [downModA, downModB])
.value($EXCEPTION_HANDLER, errorSpy) .value($EXCEPTION_HANDLER, errorSpy)
.directive('ng2A', downgradeComponent({ .directive('ng2A', downgradeComponent({

View File

@ -7,7 +7,7 @@
*/ */
import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule} from '@angular/core'; import {Component, destroyPlatform, Directive, ElementRef, Injector, Input, NgModule} from '@angular/core';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static'; import {downgradeComponent, UpgradeComponent, UpgradeModule} from '@angular/upgrade/static';
@ -25,7 +25,7 @@ withEachNg1Version(() => {
it('should have AngularJS loaded', it('should have AngularJS loaded',
() => expect(angular.getAngularJSGlobal().version.major).toBe(1)); () => expect(angular.getAngularJSGlobal().version.major).toBe(1));
it('should verify UpgradeAdapter example', async(() => { it('should verify UpgradeAdapter example', waitForAsync(() => {
// This is wrapping (upgrading) an AngularJS component to be used in an Angular // This is wrapping (upgrading) an AngularJS component to be used in an Angular
// component // component
@Directive({selector: 'ng1'}) @Directive({selector: 'ng1'})

View File

@ -7,7 +7,7 @@
*/ */
import {destroyPlatform, InjectionToken, Injector, NgModule} from '@angular/core'; import {destroyPlatform, InjectionToken, Injector, NgModule} from '@angular/core';
import {async} from '@angular/core/testing'; import {waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -23,7 +23,7 @@ withEachNg1Version(() => {
beforeEach(() => destroyPlatform()); beforeEach(() => destroyPlatform());
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
it('should downgrade ng2 service to ng1', async(() => { it('should downgrade ng2 service to ng1', waitForAsync(() => {
// Tokens used in ng2 to identify services // Tokens used in ng2 to identify services
const Ng2Service = new InjectionToken('ng2-service'); const Ng2Service = new InjectionToken('ng2-service');
@ -49,7 +49,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should upgrade ng1 service to ng2', async(() => { it('should upgrade ng1 service to ng2', waitForAsync(() => {
// Tokens used in ng2 to identify services // Tokens used in ng2 to identify services
const Ng1Service = new InjectionToken('ng1-service'); const Ng1Service = new InjectionToken('ng1-service');
@ -81,7 +81,7 @@ withEachNg1Version(() => {
})); }));
it('should initialize the upgraded injector before application run blocks are executed', it('should initialize the upgraded injector before application run blocks are executed',
async(() => { waitForAsync(() => {
let runBlockTriggered = false; let runBlockTriggered = false;
const ng1Module = angular.module_('ng1Module', []).run([ const ng1Module = angular.module_('ng1Module', []).run([
@ -102,7 +102,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should allow resetting angular at runtime', async(() => { it('should allow resetting angular at runtime', waitForAsync(() => {
let wrappedBootstrapCalled = false; let wrappedBootstrapCalled = false;
const n: any = getAngularJSGlobal(); const n: any = getAngularJSGlobal();

View File

@ -7,7 +7,7 @@
*/ */
import {Component, destroyPlatform, Directive, ElementRef, EventEmitter, Inject, Injector, Input, NgModule, NO_ERRORS_SCHEMA, Output, SimpleChanges} from '@angular/core'; import {Component, destroyPlatform, Directive, ElementRef, EventEmitter, Inject, Injector, Input, NgModule, NO_ERRORS_SCHEMA, Output, SimpleChanges} from '@angular/core';
import {async, fakeAsync, tick} from '@angular/core/testing'; import {fakeAsync, tick, waitForAsync} from '@angular/core/testing';
import {BrowserModule} from '@angular/platform-browser'; import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic'; import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
@ -25,7 +25,7 @@ withEachNg1Version(() => {
afterEach(() => destroyPlatform()); afterEach(() => destroyPlatform());
describe('template/templateUrl', () => { describe('template/templateUrl', () => {
it('should support `template` (string)', async(() => { it('should support `template` (string)', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = {template: 'Hello, Angular!'}; const ng1Component: angular.IComponent = {template: 'Hello, Angular!'};
@ -65,7 +65,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `template` (function)', async(() => { it('should support `template` (function)', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = {template: () => 'Hello, Angular!'}; const ng1Component: angular.IComponent = {template: () => 'Hello, Angular!'};
@ -105,7 +105,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should pass $element to `template` function and not $attrs', async(() => { it('should pass $element to `template` function and not $attrs', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = { const ng1Component: angular.IComponent = {
template: ($attrs: angular.IAttributes, $element: angular.IAugmentedJQuery) => { template: ($attrs: angular.IAttributes, $element: angular.IAugmentedJQuery) => {
@ -152,7 +152,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `templateUrl` (string) fetched from `$templateCache`', async(() => { it('should support `templateUrl` (string) fetched from `$templateCache`', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = {templateUrl: 'ng1.component.html'}; const ng1Component: angular.IComponent = {templateUrl: 'ng1.component.html'};
@ -196,7 +196,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `templateUrl` (function) fetched from `$templateCache`', async(() => { it('should support `templateUrl` (function) fetched from `$templateCache`',
waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = {templateUrl: () => 'ng1.component.html'}; const ng1Component: angular.IComponent = {templateUrl: () => 'ng1.component.html'};
@ -240,7 +241,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should pass $element to `templateUrl` function and not $attrs', async(() => { it('should pass $element to `templateUrl` function and not $attrs', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = { const ng1Component: angular.IComponent = {
templateUrl: ($attrs: angular.IAttributes, $element: angular.IAugmentedJQuery) => { templateUrl: ($attrs: angular.IAttributes, $element: angular.IAugmentedJQuery) => {
@ -393,7 +394,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support empty templates', async(() => { it('should support empty templates', waitForAsync(() => {
// Define `ng1Component`s // Define `ng1Component`s
const ng1ComponentA: angular.IComponent = {template: ''}; const ng1ComponentA: angular.IComponent = {template: ''};
const ng1ComponentB: angular.IComponent = {template: () => ''}; const ng1ComponentB: angular.IComponent = {template: () => ''};
@ -1063,7 +1064,7 @@ withEachNg1Version(() => {
}); });
describe('compiling', () => { describe('compiling', () => {
it('should compile the ng1 template in the correct DOM context', async(() => { it('should compile the ng1 template in the correct DOM context', waitForAsync(() => {
let grandParentNodeName: string; let grandParentNodeName: string;
// Define `ng1Component` // Define `ng1Component`
@ -1114,7 +1115,7 @@ withEachNg1Version(() => {
}); });
describe('linking', () => { describe('linking', () => {
it('should run the pre-linking after instantiating the controller', async(() => { it('should run the pre-linking after instantiating the controller', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
// Define `ng1Directive` // Define `ng1Directive`
@ -1164,7 +1165,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the pre-linking function before linking', async(() => { it('should run the pre-linking function before linking', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
// Define `ng1Directive` // Define `ng1Directive`
@ -1212,7 +1213,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function after linking (link: object)', async(() => { it('should run the post-linking function after linking (link: object)', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
// Define `ng1Directive` // Define `ng1Directive`
@ -1260,7 +1261,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function after linking (link: function)', async(() => { it('should run the post-linking function after linking (link: function)', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
// Define `ng1Directive` // Define `ng1Directive`
@ -1308,7 +1309,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should run the post-linking function before `$postLink`', async(() => { it('should run the post-linking function before `$postLink`', waitForAsync(() => {
const log: string[] = []; const log: string[] = [];
// Define `ng1Directive` // Define `ng1Directive`
@ -1360,7 +1361,7 @@ withEachNg1Version(() => {
}); });
describe('controller', () => { describe('controller', () => {
it('should support `controllerAs`', async(() => { it('should support `controllerAs`', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1Directive: angular.IDirective = { const ng1Directive: angular.IDirective = {
template: template:
@ -1425,7 +1426,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `bindToController` (boolean)', async(() => { it('should support `bindToController` (boolean)', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1DirectiveA: angular.IDirective = { const ng1DirectiveA: angular.IDirective = {
template: 'Scope: {{ title }}; Controller: {{ $ctrl.title }}', template: 'Scope: {{ title }}; Controller: {{ $ctrl.title }}',
@ -1501,7 +1502,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `bindToController` (object)', async(() => { it('should support `bindToController` (object)', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1Directive: angular.IDirective = { const ng1Directive: angular.IDirective = {
template: '{{ $ctrl.title }}', template: '{{ $ctrl.title }}',
@ -1552,7 +1553,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support `controller` as string', async(() => { it('should support `controller` as string', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1Directive: angular.IDirective = { const ng1Directive: angular.IDirective = {
template: '{{ $ctrl.title }} {{ $ctrl.text }}', template: '{{ $ctrl.title }} {{ $ctrl.text }}',
@ -1605,7 +1606,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should insert the compiled content before instantiating the controller', async(() => { it('should insert the compiled content before instantiating the controller',
waitForAsync(() => {
let compiledContent: string; let compiledContent: string;
let getCurrentContent: () => string; let getCurrentContent: () => string;
@ -1663,7 +1665,7 @@ withEachNg1Version(() => {
describe('require', () => { describe('require', () => {
// NOT YET SUPPORTED // NOT YET SUPPORTED
xdescribe('in pre-/post-link', () => { xdescribe('in pre-/post-link', () => {
it('should resolve to its own controller if falsy', async(() => { it('should resolve to its own controller if falsy', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1Directive: angular.IDirective = { const ng1Directive: angular.IDirective = {
template: 'Pre: {{ pre }} | Post: {{ post }}', template: 'Pre: {{ pre }} | Post: {{ post }}',
@ -1720,7 +1722,7 @@ withEachNg1Version(() => {
}); });
describe('in controller', () => { describe('in controller', () => {
it('should be available to children', async(() => { it('should be available to children', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: '<ng1-b></ng1-b>', template: '<ng1-b></ng1-b>',
@ -1771,7 +1773,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should throw if required controller cannot be found', async(() => { it('should throw if required controller cannot be found', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = {require: {foo: 'iDoNotExist'}}; const ng1ComponentA: angular.IComponent = {require: {foo: 'iDoNotExist'}};
const ng1ComponentB: angular.IComponent = {require: {foo: '^iDoNotExist'}}; const ng1ComponentB: angular.IComponent = {require: {foo: '^iDoNotExist'}};
@ -1861,7 +1863,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not throw if missing required controller is optional', async(() => { it('should not throw if missing required controller is optional', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = { const ng1Component: angular.IComponent = {
require: { require: {
@ -1910,7 +1912,7 @@ withEachNg1Version(() => {
})); }));
it('should assign resolved values to the controller instance (if `require` is not object)', it('should assign resolved values to the controller instance (if `require` is not object)',
async(() => { waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: 'ng1A(<div><ng2></ng2></div>)', template: 'ng1A(<div><ng2></ng2></div>)',
@ -1988,7 +1990,7 @@ withEachNg1Version(() => {
})); }));
it('should assign resolved values to the controller instance (if `require` is object)', it('should assign resolved values to the controller instance (if `require` is object)',
async(() => { waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: 'ng1A(<div><ng2></ng2></div>)', template: 'ng1A(<div><ng2></ng2></div>)',
@ -2058,7 +2060,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should assign to controller before calling `$onInit()`', async(() => { it('should assign to controller before calling `$onInit()`', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: '<ng2></ng2>', template: '<ng2></ng2>',
@ -2115,7 +2117,8 @@ withEachNg1Version(() => {
}); });
})); }));
it('should use the key as name if the required controller name is omitted', async(() => { it('should use the key as name if the required controller name is omitted',
waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: '<ng1-b></ng1-b>', template: '<ng1-b></ng1-b>',
@ -2185,7 +2188,7 @@ withEachNg1Version(() => {
}); });
describe('transclusion', () => { describe('transclusion', () => {
it('should support single-slot transclusion', async(() => { it('should support single-slot transclusion', waitForAsync(() => {
let ng2ComponentAInstance: Ng2ComponentA; let ng2ComponentAInstance: Ng2ComponentA;
let ng2ComponentBInstance: Ng2ComponentB; let ng2ComponentBInstance: Ng2ComponentB;
@ -2256,7 +2259,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support single-slot transclusion with fallback content', async(() => { it('should support single-slot transclusion with fallback content', waitForAsync(() => {
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2318,7 +2321,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support multi-slot transclusion', async(() => { it('should support multi-slot transclusion', waitForAsync(() => {
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
// Define `ng1Component` // Define `ng1Component`
@ -2387,7 +2390,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support default slot (with fallback content)', async(() => { it('should support default slot (with fallback content)', waitForAsync(() => {
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2471,7 +2474,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support optional transclusion slots (with fallback content)', async(() => { it('should support optional transclusion slots (with fallback content)', waitForAsync(() => {
let ng1ControllerInstances: any[] = []; let ng1ControllerInstances: any[] = [];
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
@ -2553,7 +2556,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should throw if a non-optional slot is not filled', async(() => { it('should throw if a non-optional slot is not filled', waitForAsync(() => {
let errorMessage: string; let errorMessage: string;
// Define `ng1Component` // Define `ng1Component`
@ -2601,7 +2604,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support structural directives in transcluded content', async(() => { it('should support structural directives in transcluded content', waitForAsync(() => {
let ng2ComponentInstance: Ng2Component; let ng2ComponentInstance: Ng2Component;
// Define `ng1Component` // Define `ng1Component`
@ -2984,7 +2987,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should call `$onInit()` on controller', async(() => { it('should call `$onInit()` on controller', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1DirectiveA: angular.IDirective = { const ng1DirectiveA: angular.IDirective = {
template: 'Called: {{ called }}', template: 'Called: {{ called }}',
@ -3055,7 +3058,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$onInit()` on scope', async(() => { it('should not call `$onInit()` on scope', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1DirectiveA: angular.IDirective = { const ng1DirectiveA: angular.IDirective = {
template: 'Called: {{ called }}', template: 'Called: {{ called }}',
@ -3125,7 +3128,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should call `$postLink()` on controller', async(() => { it('should call `$postLink()` on controller', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1DirectiveA: angular.IDirective = { const ng1DirectiveA: angular.IDirective = {
template: 'Called: {{ called }}', template: 'Called: {{ called }}',
@ -3196,7 +3199,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$postLink()` on scope', async(() => { it('should not call `$postLink()` on scope', waitForAsync(() => {
// Define `ng1Directive` // Define `ng1Directive`
const ng1DirectiveA: angular.IDirective = { const ng1DirectiveA: angular.IDirective = {
template: 'Called: {{ called }}', template: 'Called: {{ called }}',
@ -3267,7 +3270,7 @@ withEachNg1Version(() => {
})); }));
it('should call `$doCheck()` on controller', async(() => { it('should call `$doCheck()` on controller', waitForAsync(() => {
const controllerDoCheckA = jasmine.createSpy('controllerDoCheckA'); const controllerDoCheckA = jasmine.createSpy('controllerDoCheckA');
const controllerDoCheckB = jasmine.createSpy('controllerDoCheckB'); const controllerDoCheckB = jasmine.createSpy('controllerDoCheckB');
@ -3354,7 +3357,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$doCheck()` on scope', async(() => { it('should not call `$doCheck()` on scope', waitForAsync(() => {
const scopeDoCheck = jasmine.createSpy('scopeDoCheck'); const scopeDoCheck = jasmine.createSpy('scopeDoCheck');
// Define `ng1Directive` // Define `ng1Directive`
@ -3432,7 +3435,7 @@ withEachNg1Version(() => {
})); }));
it('should call `$onDestroy()` on controller', async(() => { it('should call `$onDestroy()` on controller', waitForAsync(() => {
const controllerOnDestroyA = jasmine.createSpy('controllerOnDestroyA'); const controllerOnDestroyA = jasmine.createSpy('controllerOnDestroyA');
const controllerOnDestroyB = jasmine.createSpy('controllerOnDestroyB'); const controllerOnDestroyB = jasmine.createSpy('controllerOnDestroyB');
@ -3532,7 +3535,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should not call `$onDestroy()` on scope', async(() => { it('should not call `$onDestroy()` on scope', waitForAsync(() => {
const scopeOnDestroy = jasmine.createSpy('scopeOnDestroy'); const scopeOnDestroy = jasmine.createSpy('scopeOnDestroy');
// Define `ng1Directive` // Define `ng1Directive`
@ -3628,7 +3631,7 @@ withEachNg1Version(() => {
})); }));
it('should be called in order `$onChanges()` > `$onInit()` > `$doCheck()` > `$postLink()`', it('should be called in order `$onChanges()` > `$onInit()` > `$doCheck()` > `$postLink()`',
async(() => { waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = { const ng1Component: angular.IComponent = {
// `$doCheck()` will keep getting called as long as the interpolated value keeps // `$doCheck()` will keep getting called as long as the interpolated value keeps
@ -3697,7 +3700,7 @@ withEachNg1Version(() => {
}); });
describe('destroying the upgraded component', () => { describe('destroying the upgraded component', () => {
it('should destroy `$componentScope`', async(() => { it('should destroy `$componentScope`', waitForAsync(() => {
const scopeDestroyListener = jasmine.createSpy('scopeDestroyListener'); const scopeDestroyListener = jasmine.createSpy('scopeDestroyListener');
let ng2ComponentAInstance: Ng2ComponentA; let ng2ComponentAInstance: Ng2ComponentA;
@ -3760,7 +3763,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should emit `$destroy` on `$element` and descendants', async(() => { it('should emit `$destroy` on `$element` and descendants', waitForAsync(() => {
const elementDestroyListener = jasmine.createSpy('elementDestroyListener'); const elementDestroyListener = jasmine.createSpy('elementDestroyListener');
const descendantDestroyListener = jasmine.createSpy('descendantDestroyListener'); const descendantDestroyListener = jasmine.createSpy('descendantDestroyListener');
let ng2ComponentAInstance: Ng2ComponentA; let ng2ComponentAInstance: Ng2ComponentA;
@ -3828,7 +3831,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should clear data on `$element` and descendants`', async(() => { it('should clear data on `$element` and descendants`', waitForAsync(() => {
let ng1ComponentElement: angular.IAugmentedJQuery; let ng1ComponentElement: angular.IAugmentedJQuery;
let ng2ComponentAInstance: Ng2ComponentA; let ng2ComponentAInstance: Ng2ComponentA;
@ -3897,7 +3900,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should clear dom listeners on `$element` and descendants`', async(() => { it('should clear dom listeners on `$element` and descendants`', waitForAsync(() => {
const elementClickListener = jasmine.createSpy('elementClickListener'); const elementClickListener = jasmine.createSpy('elementClickListener');
const descendantClickListener = jasmine.createSpy('descendantClickListener'); const descendantClickListener = jasmine.createSpy('descendantClickListener');
let ng1DescendantElement: angular.IAugmentedJQuery; let ng1DescendantElement: angular.IAugmentedJQuery;
@ -3970,7 +3973,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should clean up `$doCheck()` watchers from the parent scope', async(() => { it('should clean up `$doCheck()` watchers from the parent scope', waitForAsync(() => {
let ng2Component: Ng2Component; let ng2Component: Ng2Component;
// Define `ng1Component` // Define `ng1Component`
@ -4041,7 +4044,7 @@ withEachNg1Version(() => {
})); }));
}); });
it('should support ng2 > ng1 > ng2 (no inputs/outputs)', async(() => { it('should support ng2 > ng1 > ng2 (no inputs/outputs)', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1Component: angular.IComponent = {template: 'ng1X(<ng2-b></ng2-b>)'}; const ng1Component: angular.IComponent = {template: 'ng1X(<ng2-b></ng2-b>)'};
@ -4283,7 +4286,7 @@ withEachNg1Version(() => {
}); });
})); }));
it('should support ng2 > ng1 > ng2 > ng1 (with `require`)', async(() => { it('should support ng2 > ng1 > ng2 > ng1 (with `require`)', waitForAsync(() => {
// Define `ng1Component` // Define `ng1Component`
const ng1ComponentA: angular.IComponent = { const ng1ComponentA: angular.IComponent = {
template: 'ng1A(<ng2-b></ng2-b>)', template: 'ng1A(<ng2-b></ng2-b>)',