docs(testing): fix hero-detail impl and use done for observable tests (#3270)

This commit is contained in:
Ward Bell 2017-02-17 18:19:44 -08:00 committed by GitHub
parent bdac5ca6b0
commit acfd22c96b
5 changed files with 46 additions and 32 deletions

View File

@ -174,7 +174,7 @@ class Page {
} }
constructor() { constructor() {
router.events.forEach(e => this.recordedEvents.push(e)); router.events.subscribe(e => this.recordedEvents.push(e));
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];

View File

@ -1,3 +1,4 @@
// tslint:disable-next-line:no-unused-variable
import { async, fakeAsync, tick } from '@angular/core/testing'; import { async, fakeAsync, tick } from '@angular/core/testing';
import { Observable } from 'rxjs/Observable'; import { Observable } from 'rxjs/Observable';
@ -31,26 +32,37 @@ describe('Angular async helper', () => {
p.catch(() => { actuallyDone = true; }); p.catch(() => { actuallyDone = true; });
})); }));
// Fail message: Cannot use setInterval from within an async zone test // Use done. Cannot use setInterval with async or fakeAsync
// See https://github.com/angular/angular/issues/10127 // See https://github.com/angular/angular/issues/10127
xit('should run async test with successful delayed Observable', async(() => { it('should run async test with successful delayed Observable', done => {
const source = Observable.of(true).delay(10); const source = Observable.of(true).delay(10);
source.subscribe( source.subscribe(
val => actuallyDone = true, val => actuallyDone = true,
err => fail(err) err => fail(err),
done
); );
})); });
// Fail message: Error: 1 periodic timer(s) still in the queue // Cannot use setInterval from within an async zone test
// See https://github.com/angular/angular/issues/10127 // See https://github.com/angular/angular/issues/10127
xit('should run async test with successful delayed Observable', fakeAsync(() => { // xit('should run async test with successful delayed Observable', async(() => {
const source = Observable.of(true).delay(10); // const source = Observable.of(true).delay(10);
source.subscribe( // source.subscribe(
val => actuallyDone = true, // val => actuallyDone = true,
err => fail(err) // err => fail(err)
); // );
// }));
tick(); // // Fail message: Error: 1 periodic timer(s) still in the queue
})); // // See https://github.com/angular/angular/issues/10127
// xit('should run async test with successful delayed Observable', fakeAsync(() => {
// const source = Observable.of(true).delay(10);
// source.subscribe(
// val => actuallyDone = true,
// err => fail(err)
// );
// tick();
// }));
}); });

View File

@ -72,14 +72,14 @@ describe('use inject helper in beforeEach', () => {
); );
})); }));
// #enddocregion FancyService // Must use done. See https://github.com/angular/angular/issues/10127
// See https://github.com/angular/angular/issues/10127 it('test should wait for FancyService.getObservableDelayValue', done => {
xit('test should wait for FancyService.getObservableDelayValue', async(() => { service.getObservableDelayValue().subscribe(value => {
service.getObservableDelayValue().subscribe( expect(value).toBe('observable delay value');
value => expect(value).toBe('observable delay value') done();
); });
})); });
// #docregion FancyService
it('should allow the use of fakeAsync', fakeAsync(() => { it('should allow the use of fakeAsync', fakeAsync(() => {
let value: any; let value: any;
service.getAsyncValue().then((val: any) => value = val); service.getAsyncValue().then((val: any) => value = val);

View File

@ -30,13 +30,17 @@ export class HeroDetailComponent implements OnInit {
// #docregion ng-on-init // #docregion ng-on-init
ngOnInit(): void { ngOnInit(): void {
// get hero when `id` param changes // get hero when `id` param changes
this.route.params.map(p => p['id']) this.route.params.subscribe(p => this.getHero(p && p['id']));
.forEach(id => this.getHero(id))
.catch(() => this.hero = new Hero()); // no id; should edit new hero
} }
// #enddocregion ng-on-init // #enddocregion ng-on-init
private getHero(id: string): void { private getHero(id: string): void {
// when no id or id===0, create new hero
if (!id) {
this.hero = new Hero();
return;
}
this.heroDetailService.getHero(id).then(hero => { this.heroDetailService.getHero(id).then(hero => {
if (hero) { if (hero) {
this.hero = hero; this.hero = hero;

View File

@ -1105,17 +1105,15 @@ a#routed-component-w-param
Here's the `HeroDetailComponent` constructor: Here's the `HeroDetailComponent` constructor:
+makeExample('testing/ts/src/app/hero/hero-detail.component.ts', 'ctor', 'src/app/hero/hero-detail.component.ts (constructor)')(format='.') +makeExample('testing/ts/src/app/hero/hero-detail.component.ts', 'ctor', 'src/app/hero/hero-detail.component.ts (constructor)')(format='.')
:marked :marked
`HeroDetailComponent` listens for changes to the `ActivatedRoute.params` in its `ngOnInit` method. `HeroDetailComponent` subscribes to `ActivatedRoute.params` changes in its `ngOnInit` method.
+makeExample('testing/ts/src/app/hero/hero-detail.component.ts', 'ng-on-init', 'src/app/hero/hero-detail.component.ts (ngOnInit)')(format='.') +makeExample('testing/ts/src/app/hero/hero-detail.component.ts', 'ng-on-init', 'src/app/hero/hero-detail.component.ts (ngOnInit)')(format='.')
.l-sub-section .l-sub-section
:marked :marked
The expression after `route.params` chains an _Observable_ operator that _plucks_ the `id` from the `params` The subscription confirms that there are `params` and, if there are,
and then chains a `forEach` operator to subscribes to `id`-changing events. plucks the `id` from those `params`.
The `id` changes every time the user navigates to a different hero. It passes the `id` to the component's `getHero` method (not shown)
The `forEach` passes the new `id` value to the component's `getHero` method (not shown)
which fetches a hero and sets the component's `hero` property. which fetches a hero and sets the component's `hero` property.
If the`id` parameter is missing, the `pluck` operator fails and the `catch` treats failure as a request to edit a new hero. The `getHero` method treats an undefined `id` or `id===0` as a request to edit a new hero.
The [Router](router.html#route-parameters) guide covers `ActivatedRoute.params` in more detail. The [Router](router.html#route-parameters) guide covers `ActivatedRoute.params` in more detail.
:marked :marked