1+ // #docplaster
12import {
23 async , ComponentFixture , fakeAsync , inject , TestBed , tick
34} from '@angular/core/testing' ;
@@ -7,7 +8,7 @@ import { DebugElement } from '@angular/core';
78
89import {
910 addMatchers , newEvent ,
10- ActivatedRoute , FakeActivatedRoute , Router , FakeRouter
11+ ActivatedRoute , ActivatedRouteStub , Router , RouterStub
1112} from '../../testing' ;
1213
1314import { HEROES , FakeHeroService } from '../model/testing' ;
@@ -18,7 +19,7 @@ import { HeroDetailService } from './hero-detail.service';
1819import { Hero , HeroService } from '../model' ;
1920
2021////// Testing Vars //////
21- let activatedRoute : FakeActivatedRoute ;
22+ let activatedRoute : ActivatedRouteStub ;
2223let comp : HeroDetailComponent ;
2324let fixture : ComponentFixture < HeroDetailComponent > ;
2425let page : Page ;
@@ -29,7 +30,7 @@ describe('HeroDetailComponent', () => {
2930
3031 beforeEach ( async ( ( ) => {
3132 addMatchers ( ) ;
32- activatedRoute = new FakeActivatedRoute ( ) ;
33+ activatedRoute = new ActivatedRouteStub ( ) ;
3334
3435 TestBed . configureTestingModule ( {
3536 imports : [ HeroModule ] ,
@@ -40,12 +41,13 @@ describe('HeroDetailComponent', () => {
4041 providers : [
4142 { provide : ActivatedRoute , useValue : activatedRoute } ,
4243 { provide : HeroService , useClass : FakeHeroService } ,
43- { provide : Router , useClass : FakeRouter } ,
44+ { provide : Router , useClass : RouterStub } ,
4445 ]
4546 } )
4647 . compileComponents ( ) ;
4748 } ) ) ;
4849
50+ // #docregion route-good-id
4951 describe ( 'when navigate to hero id=' + HEROES [ 0 ] . id , ( ) => {
5052 let expectedHero : Hero ;
5153
@@ -55,51 +57,53 @@ describe('HeroDetailComponent', () => {
5557 createComponent ( ) ;
5658 } ) ) ;
5759
60+ // #docregion selected-tests
5861 it ( 'should display that hero\'s name' , ( ) => {
5962 expect ( page . nameDisplay . textContent ) . toBe ( expectedHero . name ) ;
6063 } ) ;
64+ // #enddocregion route-good-id
6165
6266 it ( 'should navigate when click cancel' , ( ) => {
6367 page . cancelBtn . triggerEventHandler ( 'click' , null ) ;
6468 expect ( page . navSpy . calls . any ( ) ) . toBe ( true , 'router.navigate called' ) ;
6569 } ) ;
6670
67- it ( 'should save when click save' , ( ) => {
71+ it ( 'should save when click save but not navigate immediately ' , ( ) => {
6872 page . saveBtn . triggerEventHandler ( 'click' , null ) ;
6973 expect ( page . saveSpy . calls . any ( ) ) . toBe ( true , 'HeroDetailService.save called' ) ;
74+ expect ( page . navSpy . calls . any ( ) ) . toBe ( false , 'router.navigate not called' ) ;
7075 } ) ;
7176
72- it ( 'should navigate when click click save resolves' , fakeAsync ( ( ) => {
77+ it ( 'should navigate when click save and save resolves' , fakeAsync ( ( ) => {
7378 page . saveBtn . triggerEventHandler ( 'click' , null ) ;
74- tick ( ) ; // waits for async save to "complete" before navigating
79+ tick ( ) ; // wait for async save to "complete" before navigating
7580 expect ( page . navSpy . calls . any ( ) ) . toBe ( true , 'router.navigate called' ) ;
7681 } ) ) ;
7782
78-
7983 // #docregion title-case-pipe
80- it ( 'should convert original hero name to Title Case' , ( ) => {
81- expect ( page . nameDisplay . textContent ) . toBe ( comp . hero . name ) ;
82- } ) ;
83- // #enddocregion title-case-pipe
84-
8584 it ( 'should convert hero name to Title Case' , fakeAsync ( ( ) => {
8685 const inputName = 'quick BROWN fox' ;
87- const expectedName = 'Quick Brown Fox' ;
86+ const titleCaseName = 'Quick Brown Fox' ;
8887
89- // simulate user entering new name in input
88+ // simulate user entering new name into the input box
9089 page . nameInput . value = inputName ;
9190
9291 // dispatch a DOM event so that Angular learns of input value change.
93- // detectChanges() makes ngModel push input value to component property
94- // and Angular updates the output span
9592 page . nameInput . dispatchEvent ( newEvent ( 'input' ) ) ;
93+
94+ // detectChanges() makes [(ngModel)] push input value to component property
95+ // and Angular updates the output span through the title pipe
9696 fixture . detectChanges ( ) ;
97- expect ( page . nameDisplay . textContent ) . toBe ( expectedName , 'hero name display' ) ;
98- expect ( comp . hero . name ) . toBe ( inputName , 'comp.hero.name' ) ;
99- } ) ) ;
10097
98+ expect ( page . nameDisplay . textContent ) . toBe ( titleCaseName ) ;
99+ } ) ) ;
100+ // #enddocregion title-case-pipe
101+ // #enddocregion selected-tests
102+ // #docregion route-good-id
101103 } ) ;
104+ // #enddocregion route-good-id
102105
106+ // #docregion route-no-id
103107 describe ( 'when navigate with no hero id' , ( ) => {
104108 beforeEach ( async ( createComponent ) ) ;
105109
@@ -111,7 +115,9 @@ describe('HeroDetailComponent', () => {
111115 expect ( page . nameDisplay . textContent ) . toBe ( '' ) ;
112116 } ) ;
113117 } ) ;
118+ // #enddocregion route-no-id
114119
120+ // #docregion route-bad-id
115121 describe ( 'when navigate to non-existant hero id' , ( ) => {
116122 beforeEach ( async ( ( ) => {
117123 activatedRoute . testParams = { id : 99999 } ;
@@ -123,6 +129,7 @@ describe('HeroDetailComponent', () => {
123129 expect ( page . navSpy . calls . any ( ) ) . toBe ( true , 'router.navigate called' ) ;
124130 } ) ;
125131 } ) ;
132+ // #enddocregion route-bad-id
126133
127134 ///////////////////////////
128135
@@ -145,22 +152,24 @@ describe('HeroDetailComponent', () => {
145152
146153/////////// Helpers /////
147154
155+ // #docregion create-component
148156/** Create the HeroDetailComponent, initialize it, set test variables */
149157function createComponent ( ) {
150158 fixture = TestBed . createComponent ( HeroDetailComponent ) ;
151159 comp = fixture . componentInstance ;
152160 page = new Page ( ) ;
153161
154- // change detection triggers ngOnInit which gets a hero
162+ // 1st change detection triggers ngOnInit which gets a hero
155163 fixture . detectChanges ( ) ;
156164 return fixture . whenStable ( ) . then ( ( ) => {
157- // got the hero and updated component
158- // change detection updates the view
165+ // 2nd change detection displays the async-fetched hero
159166 fixture . detectChanges ( ) ;
160167 page . addPageElements ( ) ;
161168 } ) ;
162169}
170+ // #enddocregion create-component
163171
172+ // #docregion page
164173class Page {
165174 gotoSpy : jasmine . Spy ;
166175 navSpy : jasmine . Spy ;
@@ -173,24 +182,24 @@ class Page {
173182
174183 constructor ( ) {
175184 // Use component's injector to see the services it injected.
176- let compInjector = fixture . debugElement . injector ;
177- let hds = compInjector . get ( HeroDetailService ) ;
178- let router = compInjector . get ( Router ) ;
179- this . gotoSpy = spyOn ( comp , 'gotoList' ) . and . callThrough ( ) ;
180- this . saveSpy = spyOn ( hds , 'saveHero' ) . and . callThrough ( ) ;
181- this . navSpy = spyOn ( router , 'navigate' ) . and . callThrough ( ) ;
185+ const compInjector = fixture . debugElement . injector ;
186+ const hds = compInjector . get ( HeroDetailService ) ;
187+ const router = compInjector . get ( Router ) ;
188+ this . gotoSpy = spyOn ( comp , 'gotoList' ) . and . callThrough ( ) ;
189+ this . saveSpy = spyOn ( hds , 'saveHero' ) . and . callThrough ( ) ;
190+ this . navSpy = spyOn ( router , 'navigate' ) . and . callThrough ( ) ;
182191 }
183192
184- /** Add page elements after page initializes */
193+ /** Add page elements after hero arrives */
185194 addPageElements ( ) {
186195 if ( comp . hero ) {
187- // have a hero so these DOM elements can be reached
188- let buttons = fixture . debugElement . queryAll ( By . css ( 'button' ) ) ;
196+ // have a hero so these elements are now in the DOM
197+ const buttons = fixture . debugElement . queryAll ( By . css ( 'button' ) ) ;
189198 this . saveBtn = buttons [ 0 ] ;
190199 this . cancelBtn = buttons [ 1 ] ;
191200 this . nameDisplay = fixture . debugElement . query ( By . css ( 'span' ) ) . nativeElement ;
192201 this . nameInput = fixture . debugElement . query ( By . css ( 'input' ) ) . nativeElement ;
193202 }
194203 }
195204}
196-
205+ // #enddocregion page
0 commit comments