Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 3c3c416

Browse files
committed
docs(testing): more scenarios
1 parent 84b5297 commit 3c3c416

10 files changed

+306
-126
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { NgModule } from '@angular/core';
2+
import { RouterModule } from '@angular/router';
3+
4+
import { AboutComponent } from './about.component';
5+
6+
@NgModule({
7+
imports: [
8+
RouterModule.forRoot([
9+
{ path: '', redirectTo: 'dashboard', pathMatch: 'full'},
10+
{ path: 'about', component: AboutComponent },
11+
{ path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule'}
12+
])
13+
],
14+
exports: [ RouterModule ] // re-export the module declarations
15+
})
16+
export class AppRoutingModule { };

public/docs/_examples/testing/ts/app/app.component.html

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
<!-- #docregion -->
12
<app-banner></app-banner>
23
<app-welcome></app-welcome>
34

Original file line numberDiff line numberDiff line change
@@ -1,108 +1,94 @@
1+
// #docplaster
12
import { async, ComponentFixture, TestBed
23
} from '@angular/core/testing';
34

4-
import { NO_ERRORS_SCHEMA } from '@angular/core';
5+
import { DebugElement } from '@angular/core';
56
import { By } from '@angular/platform-browser';
67

7-
import { AppComponent } from './app.component';
8-
import { BannerComponent } from './banner.component';
9-
import { SharedModule } from './shared/shared.module';
10-
11-
import { Router, RouterStub, RouterLinkDirectiveStub, RouterOutletStubComponent
12-
} from '../testing';
13-
8+
// #docregion setup-schemas
9+
import { NO_ERRORS_SCHEMA } from '@angular/core';
10+
// #enddocregion setup-schemas
11+
// #docregion setup-stubs-w-imports
12+
import { Component } from '@angular/core';
13+
// #docregion setup-schemas
14+
import { AppComponent } from './app.component';
15+
// #enddocregion setup-schemas
16+
import { BannerComponent } from './banner.component';
17+
import { RouterLinkStubDirective } from '../testing';
18+
// #docregion setup-schemas
19+
import { RouterOutletStubComponent } from '../testing';
20+
21+
// #enddocregion setup-schemas
22+
@Component({selector: 'app-welcome', template: ''})
23+
class WelcomeStubComponent {}
24+
25+
// #enddocregion setup-stubs-w-imports
1426

1527
let comp: AppComponent;
1628
let fixture: ComponentFixture<AppComponent>;
1729

1830
describe('AppComponent & TestModule', () => {
31+
// #docregion setup-stubs, setup-stubs-w-imports
1932
beforeEach( async(() => {
2033
TestBed.configureTestingModule({
2134
declarations: [
22-
AppComponent, BannerComponent,
23-
RouterLinkDirectiveStub, RouterOutletStubComponent
24-
],
25-
providers: [{ provide: Router, useClass: RouterStub }],
26-
schemas: [NO_ERRORS_SCHEMA]
35+
AppComponent,
36+
BannerComponent, WelcomeStubComponent,
37+
RouterLinkStubDirective, RouterOutletStubComponent
38+
]
2739
})
2840

2941
.compileComponents()
30-
3142
.then(() => {
3243
fixture = TestBed.createComponent(AppComponent);
3344
comp = fixture.componentInstance;
3445
});
35-
3646
}));
37-
47+
// #enddocregion setup-stubs, setup-stubs-w-imports
3848
tests();
3949
});
4050

41-
function tests() {
42-
43-
it('can instantiate it', () => {
44-
expect(comp).not.toBeNull();
45-
});
46-
47-
it('can get RouterLinks from template', () => {
48-
fixture.detectChanges();
49-
50-
const links = fixture.debugElement
51-
// find all elements with an attached FakeRouterLink directive
52-
.queryAll(By.directive(RouterLinkDirectiveStub))
53-
// use injector to get the RouterLink directive instance attached to each element
54-
.map(de => de.injector.get(RouterLinkDirectiveStub) as RouterLinkDirectiveStub);
55-
56-
expect(links.length).toBe(3, 'should have 3 links');
57-
expect(links[0].linkParams).toBe('/dashboard', '1st link should go to Dashboard');
58-
expect(links[1].linkParams).toBe('/heroes', '1st link should go to Heroes');
59-
});
60-
61-
it('can click Heroes link in template', () => {
62-
fixture.detectChanges();
63-
64-
// Heroes RouterLink DebugElement
65-
const heroesLinkDe = fixture.debugElement
66-
.queryAll(By.directive(RouterLinkDirectiveStub))[1];
67-
68-
expect(heroesLinkDe).toBeDefined('should have a 2nd RouterLink');
69-
70-
const link = heroesLinkDe.injector.get(RouterLinkDirectiveStub) as RouterLinkDirectiveStub;
71-
72-
expect(link.navigatedTo).toBeNull('link should not have navigate yet');
73-
74-
heroesLinkDe.triggerEventHandler('click', null);
51+
//////// Testing w/ NO_ERRORS_SCHEMA //////
52+
describe('AppComponent & NO_ERRORS_SCHEMA', () => {
53+
// #docregion setup-schemas
54+
beforeEach( async(() => {
55+
TestBed.configureTestingModule({
56+
declarations: [ AppComponent, RouterLinkStubDirective ],
57+
schemas: [ NO_ERRORS_SCHEMA ]
58+
})
7559

76-
fixture.detectChanges();
77-
expect(link.navigatedTo).toBe('/heroes');
78-
});
79-
}
60+
.compileComponents()
61+
.then(() => {
62+
fixture = TestBed.createComponent(AppComponent);
63+
comp = fixture.componentInstance;
64+
});
65+
}));
66+
// #enddocregion setup-schemas
67+
tests();
68+
});
8069

8170
//////// Testing w/ real root module //////
82-
// Best to avoid
8371
// Tricky because we are disabling the router and its configuration
72+
// Better to use RouterTestingModule
8473
import { AppModule } from './app.module';
74+
import { AppRoutingModule } from './app-routing.module';
8575

8676
describe('AppComponent & AppModule', () => {
8777

8878
beforeEach( async(() => {
8979

9080
TestBed.configureTestingModule({
91-
imports: [ AppModule ],
92-
})
93-
94-
.overrideModule(AppModule, {
95-
// Must get rid of `RouterModule.forRoot` to prevent attempt to configure a router
96-
// Can't remove it because it doesn't have a known type (`forRoot` returns an object)
97-
// therefore, must reset the entire `imports` with just the necessary stuff
98-
set: { imports: [ SharedModule ]}
81+
imports: [ AppModule ]
9982
})
10083

101-
// Separate override because cannot both `set` and `add/remove` in same override
84+
// Get rid of app's Router configuration otherwise many failures.
85+
// Doing so removes Router declarations; add the Router stubs
10286
.overrideModule(AppModule, {
87+
remove: {
88+
imports: [ AppRoutingModule ]
89+
},
10390
add: {
104-
declarations: [ RouterLinkDirectiveStub, RouterOutletStubComponent ],
105-
providers: [{ provide: Router, useClass: RouterStub }]
91+
declarations: [ RouterLinkStubDirective, RouterOutletStubComponent ]
10692
}
10793
})
10894

@@ -117,3 +103,46 @@ describe('AppComponent & AppModule', () => {
117103
tests();
118104
});
119105

106+
function tests() {
107+
let links: RouterLinkStubDirective[];
108+
let linkDes: DebugElement[];
109+
110+
// #docregion test-setup
111+
beforeEach(() => {
112+
// trigger initial data binding
113+
fixture.detectChanges();
114+
115+
// find DebugElements with an attached RouterLinkStubDirective
116+
linkDes = fixture.debugElement
117+
.queryAll(By.directive(RouterLinkStubDirective));
118+
119+
// get the attached link directive instances using the DebugElement injectors
120+
links = linkDes
121+
.map(de => de.injector.get(RouterLinkStubDirective) as RouterLinkStubDirective);
122+
});
123+
// #enddocregion test-setup
124+
125+
it('can instantiate it', () => {
126+
expect(comp).not.toBeNull();
127+
});
128+
129+
// #docregion tests
130+
it('can get RouterLinks from template', () => {
131+
expect(links.length).toBe(3, 'should have 3 links');
132+
expect(links[0].linkParams).toBe('/dashboard', '1st link should go to Dashboard');
133+
expect(links[1].linkParams).toBe('/heroes', '1st link should go to Heroes');
134+
});
135+
136+
it('can click Heroes link in template', () => {
137+
const heroesLinkDe = linkDes[1];
138+
const heroesLink = links[1];
139+
140+
expect(heroesLink.navigatedTo).toBeNull('link should not have navigated yet');
141+
142+
heroesLinkDe.triggerEventHandler('click', null);
143+
fixture.detectChanges();
144+
145+
expect(heroesLink.navigatedTo).toBe('/heroes');
146+
});
147+
// #docregion tests
148+
}

public/docs/_examples/testing/ts/app/app.component.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// #docregion
2-
import { Component } from '@angular/core';
3-
2+
import { Component } from '@angular/core';
43
@Component({
54
selector: 'my-app',
65
templateUrl: 'app/app.component.html'

public/docs/_examples/testing/ts/app/app.module.ts

+3-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { NgModule } from '@angular/core';
22
import { BrowserModule } from '@angular/platform-browser';
3-
import { RouterModule } from '@angular/router';
4-
53

64
import { AppComponent } from './app.component';
5+
import { AppRoutingModule } from './app-routing.module';
6+
77
import { AboutComponent } from './about.component';
88
import { BannerComponent } from './banner.component';
99
import { HeroService,
@@ -19,11 +19,7 @@ import { SharedModule } from './shared/shared.module';
1919
imports: [
2020
BrowserModule,
2121
DashboardModule,
22-
RouterModule.forRoot([
23-
{ path: '', redirectTo: 'dashboard', pathMatch: 'full'},
24-
{ path: 'about', component: AboutComponent },
25-
{ path: 'heroes', loadChildren: 'app/hero/hero.module#HeroModule'}
26-
]),
22+
AppRoutingModule,
2723
SharedModule
2824
],
2925
providers: [ HeroService, TwainService, UserService ],

public/docs/_examples/testing/ts/app/dashboard/dashboard.component.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { DashboardModule } from './dashboard.module';
1414

1515
// #docregion router-stub
1616
class RouterStub {
17-
navigateByUrl(url: string) { return url; }
17+
navigateByUrl(url: string) { return url; }
1818
}
1919
// #enddocregion router-stub
2020

public/docs/_examples/testing/ts/app/hero/hero-detail.component.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ class Page {
187187
const router = compInjector.get(Router);
188188
this.gotoSpy = spyOn(comp, 'gotoList').and.callThrough();
189189
this.saveSpy = spyOn(hds, 'saveHero').and.callThrough();
190-
this.navSpy = spyOn(router, 'navigate').and.callThrough();
190+
this.navSpy = spyOn(router, 'navigate');
191191
}
192192

193193
/** Add page elements after hero arrives */

public/docs/_examples/testing/ts/app/hero/hero-list.component.spec.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ class Page {
132132

133133
// Get the component's injected router and spy on it
134134
const router = fixture.debugElement.injector.get(Router);
135-
this.navSpy = spyOn(router, 'navigate').and.callThrough();
135+
this.navSpy = spyOn(router, 'navigate');
136136
};
137137
}
138138

public/docs/_examples/testing/ts/testing/router-stubs.ts

+5-13
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,29 @@ export { ActivatedRoute, Router, RouterLink, RouterOutlet} from '@angular/router
44
import { Component, Directive, Injectable, Input } from '@angular/core';
55
import { NavigationExtras } from '@angular/router';
66

7+
// #docregion router-link
78
@Directive({
89
selector: '[routerLink]',
910
host: {
10-
'(click)': 'onClick()',
11-
'[attr.href]': 'href',
12-
'[class.router-link-active]': 'isRouteActive'
11+
'(click)': 'onClick()'
1312
}
1413
})
15-
export class RouterLinkDirectiveStub {
16-
17-
isRouteActive = false;
18-
href: string; // the url displayed on the anchor element.
19-
14+
export class RouterLinkStubDirective {
2015
@Input('routerLink') linkParams: any;
2116
navigatedTo: any = null;
2217

2318
onClick() {
2419
this.navigatedTo = this.linkParams;
2520
}
2621
}
22+
// #enddocregion router-link
2723

2824
@Component({selector: 'router-outlet', template: ''})
2925
export class RouterOutletStubComponent { }
3026

3127
@Injectable()
3228
export class RouterStub {
33-
lastCommand: any[];
34-
navigate(commands: any[], extras?: NavigationExtras) {
35-
this.lastCommand = commands;
36-
return commands;
37-
}
29+
navigate(commands: any[], extras?: NavigationExtras) { }
3830
}
3931

4032

0 commit comments

Comments
 (0)