docs(testing): from Igor Minar feedback (Part 1) (#2450)

This commit is contained in:
Ward Bell
2016-09-23 02:03:20 -07:00
committed by GitHub
parent 37cebe9746
commit b478aaf7a2
11 changed files with 296 additions and 277 deletions
@@ -11,7 +11,8 @@ import { BannerComponent } from './banner.component';
// #docregion setup
let comp: BannerComponent;
let fixture: ComponentFixture<BannerComponent>;
let el: DebugElement;
let de: DebugElement;
let el: HTMLElement;
describe('BannerComponent', () => {
beforeEach(() => {
@@ -23,25 +24,27 @@ describe('BannerComponent', () => {
comp = fixture.componentInstance; // BannerComponent test instance
// get title DebugElement by element name
el = fixture.debugElement.query(By.css('h1'));
// query for the title <h1> by CSS element selector
de = fixture.debugElement.query(By.css('h1'));
el = de.nativeElement;
});
// #enddocregion setup
// #docregion tests
it('should display original title', () => {
fixture.detectChanges(); // trigger data binding
expect(el.nativeElement.textContent).toContain(comp.title);
fixture.detectChanges();
expect(el.textContent).toContain(comp.title);
});
it('should display a different test title', () => {
comp.title = 'Test Title';
fixture.detectChanges(); // trigger data binding
expect(el.nativeElement.textContent).toContain('Test Title');
fixture.detectChanges();
expect(el.textContent).toContain('Test Title');
});
// #enddocregion tests
// #docregion test-w-o-detect-changes
it('no title in the DOM until manually call `detectChanges`', () => {
expect(el.nativeElement.textContent).toEqual('');
expect(el.textContent).toEqual('');
});
// #enddocregion test-w-o-detect-changes
@@ -59,8 +62,7 @@ describe('BannerComponent with AutoChangeDetect', () => {
fixture = TestBed.configureTestingModule({
declarations: [ BannerComponent ],
providers: [
{ provide: ComponentFixtureAutoDetect,
useValue: true }
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
})
// #enddocregion auto-detect
@@ -68,27 +70,28 @@ describe('BannerComponent with AutoChangeDetect', () => {
comp = fixture.componentInstance; // BannerComponent test instance
// find title DebugElement by element name
el = fixture.debugElement.query(By.css('h1'));
// query for the title <h1> by CSS element selector
de = fixture.debugElement.query(By.css('h1'));
el = de.nativeElement;
});
// #docregion auto-detect-tests
it('should display original title', () => {
// Hooray! No `fixture.detectChanges()` needed
expect(el.nativeElement.textContent).toContain(comp.title);
expect(el.textContent).toContain(comp.title);
});
it('should still see original title after comp.title change', () => {
const oldTitle = comp.title;
comp.title = 'Test Title';
// Displayed title is old because Angular didn't hear the change :(
expect(el.nativeElement.textContent).toContain(oldTitle);
expect(el.textContent).toContain(oldTitle);
});
it('should display updated title after detectChanges', () => {
comp.title = 'Test Title';
fixture.detectChanges(); // detect changes explicitly
expect(el.nativeElement.textContent).toContain(comp.title);
expect(el.textContent).toContain(comp.title);
});
// #enddocregion auto-detect-tests
});
@@ -114,14 +117,14 @@ describe('BannerComponent (simpified)', () => {
// #docregion simple-example-it
it('should display original title', () => {
// trigger data binding to update the view
// trigger change detection to update the view
fixture.detectChanges();
// find the title element in the DOM using a CSS selector
el = fixture.debugElement.query(By.css('h1'));
// query for the title <h1> by CSS element selector
de = fixture.debugElement.query(By.css('h1'));
// confirm the element's content
expect(el.nativeElement.textContent).toContain(comp.title);
expect(de.nativeElement.textContent).toContain(comp.title);
});
// #enddocregion simple-example-it
});
@@ -2,14 +2,15 @@
// #docregion
import { TitleCasePipe } from './title-case.pipe';
// #docregion excerpt
// #docregion excerpt, mini-excerpt
describe('TitleCasePipe', () => {
// This pipe is a pure function so no need for BeforeEach
// This pipe is a pure, stateless function so no need for BeforeEach
let pipe = new TitleCasePipe();
it('transforms "abc" to "Abc"', () => {
expect(pipe.transform('abc')).toBe('Abc');
});
// #enddocregion mini-excerpt
it('transforms "abc def" to "Abc Def"', () => {
expect(pipe.transform('abc def')).toBe('Abc Def');
@@ -28,6 +29,6 @@ describe('TitleCasePipe', () => {
it('transforms " abc def" to " Abc Def" (preserves spaces) ', () => {
expect(pipe.transform(' abc def')).toBe(' Abc Def');
});
// #docregion excerpt
// #docregion excerpt, mini-excerpt
});
// #enddocregion excerpt
// #enddocregion excerpt, mini-excerpt
@@ -12,7 +12,8 @@ describe('TwainComponent', () => {
let fixture: ComponentFixture<TwainComponent>;
let spy: jasmine.Spy;
let twainEl: DebugElement; // the element with the Twain quote
let de: DebugElement;
let el: HTMLElement;
let twainService: TwainService; // the actually injected service
const testQuote = 'Test Quote';
@@ -37,54 +38,53 @@ describe('TwainComponent', () => {
// #enddocregion spy
// Get the Twain quote element by CSS selector (e.g., by class name)
twainEl = fixture.debugElement.query(By.css('.twain'));
de = fixture.debugElement.query(By.css('.twain'));
el = de.nativeElement;
});
// #enddocregion setup
// #docregion tests
function getQuote() { return twainEl.nativeElement.textContent; }
it('should not show quote before OnInit', () => {
expect(getQuote()).toBe('', 'nothing displayed');
expect(el.textContent).toBe('', 'nothing displayed');
expect(spy.calls.any()).toBe(false, 'getQuote not yet called');
});
it('should still not show quote after component initialized', () => {
fixture.detectChanges(); // trigger data binding
fixture.detectChanges();
// getQuote service is async => still has not returned with quote
expect(getQuote()).toBe('...', 'no quote yet');
expect(el.textContent).toBe('...', 'no quote yet');
expect(spy.calls.any()).toBe(true, 'getQuote called');
});
// #docregion async-test
it('should show quote after getQuote promise (async)', async(() => {
fixture.detectChanges(); // trigger data binding
fixture.detectChanges();
fixture.whenStable().then(() => { // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(getQuote()).toBe(testQuote);
expect(el.textContent).toBe(testQuote);
});
}));
// #enddocregion async-test
// #docregion fake-async-test
it('should show quote after getQuote promise (fakeAsync)', fakeAsync(() => {
fixture.detectChanges(); // trigger data binding
fixture.detectChanges();
tick(); // wait for async getQuote
fixture.detectChanges(); // update view with quote
expect(getQuote()).toBe(testQuote);
expect(el.textContent).toBe(testQuote);
}));
// #enddocregion fake-async-test
// #enddocregion tests
// #docregion done-test
it('should show quote after getQuote promise (done)', done => {
fixture.detectChanges(); // trigger data binding
fixture.detectChanges();
// get the spy promise and wait for it to resolve
spy.calls.mostRecent().returnValue.then(() => {
fixture.detectChanges(); // update view with quote
expect(getQuote()).toBe(testQuote);
expect(el.textContent).toBe(testQuote);
done();
});
});
@@ -1,7 +1,7 @@
// #docplaster
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { ComponentFixture, inject, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { DebugElement } from '@angular/core';
import { UserService } from './model';
import { WelcomeComponent } from './welcome.component';
@@ -10,8 +10,10 @@ describe('WelcomeComponent', () => {
let comp: WelcomeComponent;
let fixture: ComponentFixture<WelcomeComponent>;
let userService: UserService; // the actually injected service
let welcomeEl: DebugElement; // the element with the welcome message
let componentUserService: UserService; // the actually injected service
let userService: UserService; // the TestBed injected service
let de: DebugElement; // the DebugElement with the welcome message
let el: HTMLElement; // the DOM element with the welcome message
let userServiceStub: {
isLoggedIn: boolean;
@@ -32,7 +34,8 @@ describe('WelcomeComponent', () => {
TestBed.configureTestingModule({
declarations: [ WelcomeComponent ],
// #enddocregion setup
// providers: [ UserService ] // a real service would be a problem!
// providers: [ UserService ] // NO! Don't provide the real service!
// Provide a test-double instead
// #docregion setup
providers: [ {provide: UserService, useValue: userServiceStub } ]
});
@@ -42,51 +45,64 @@ describe('WelcomeComponent', () => {
comp = fixture.componentInstance;
// #enddocregion setup
// #docregion inject-from-testbed
// UserService provided to the TestBed
userService = TestBed.get(UserService);
// #enddocregion inject-from-testbed
// #docregion setup
// #docregion injected-service
// #docregion injected-service
// UserService actually injected into the component
userService = fixture.debugElement.injector.get(UserService);
// #enddocregion injected-service
componentUserService = userService;
// #docregion setup
// #docregion inject-from-testbed
// UserService from the root injector
userService = TestBed.get(UserService);
// #enddocregion inject-from-testbed
// get the "welcome" element by CSS selector (e.g., by class name)
welcomeEl = fixture.debugElement.query(By.css('.welcome'));
de = fixture.debugElement.query(By.css('.welcome'));
el = de.nativeElement;
});
// #enddocregion setup
// #docregion tests
it('should welcome the user', () => {
fixture.detectChanges(); // trigger data binding
let content = welcomeEl.nativeElement.textContent;
fixture.detectChanges();
const content = el.textContent;
expect(content).toContain('Welcome', '"Welcome ..."');
expect(content).toContain('Test User', 'expected name');
});
it('should welcome "Bubba"', () => {
userService.user.name = 'Bubba'; // welcome message hasn't been shown yet
fixture.detectChanges(); // trigger data binding
let content = welcomeEl.nativeElement.textContent;
expect(content).toContain('Bubba');
fixture.detectChanges();
expect(el.textContent).toContain('Bubba');
});
it('should request login if not logged in', () => {
userService.isLoggedIn = false; // welcome message hasn't been shown yet
fixture.detectChanges(); // trigger data binding
let content = welcomeEl.nativeElement.textContent;
fixture.detectChanges();
const content = el.textContent;
expect(content).not.toContain('Welcome', 'not welcomed');
expect(content).toMatch(/log in/i, '"log in"');
});
// #enddocregion tests
it('orig stub and injected UserService are not the same object', () => {
expect(userServiceStub === userService).toBe(false);
// #docregion inject-it
it('should inject the component\'s UserService instance',
inject([UserService], (service: UserService) => {
expect(service).toBe(componentUserService);
}));
// #enddocregion inject-it
it('TestBed and Component UserService should be the same', () => {
expect(userService === componentUserService).toBe(true);
});
// #docregion stub-not-injected
it('stub object and injected UserService should not be the same', () => {
expect(userServiceStub === userService).toBe(false);
// Changing the stub object has no effect on the injected service
userServiceStub.isLoggedIn = false;
expect(userService.isLoggedIn).toBe(true);
});
// #enddocregion stub-not-injected
});
+1 -1
View File
@@ -60,7 +60,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript",
"intro": "Convert Angular TypeScript examples into ES5 JavaScript",
"hide": true
},
+7 -7
View File
@@ -10,7 +10,7 @@
"architecture": {
"title": "Architecture Overview",
"navTitle": "Architecture",
"intro": "The basic building blocks of Angular 2 applications",
"intro": "The basic building blocks of Angular applications",
"nextable": true,
"basics": true
},
@@ -59,7 +59,7 @@
"style-guide": {
"title": "Style Guide",
"intro": "Write Angular 2 with style.",
"intro": "Write Angular with style.",
"basics": true
},
@@ -92,7 +92,7 @@
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"intro": "Brief definitions of the most important words in the Angular vocabulary",
"basics": true
},
@@ -125,7 +125,7 @@
"router": {
"title": "Routing & Navigation",
"intro": "Discover the basics of screen navigation with the Angular 2 Component Router."
"intro": "Discover the basics of screen navigation with the Angular Component Router."
},
"security": {
@@ -140,13 +140,13 @@
"testing": {
"title": "Testing",
"intro": "Techniques and practices for testing an Angular 2 app",
"intro": "Techniques and practices for testing an Angular app",
"hide": true
},
"typescript-configuration": {
"title": "TypeScript Configuration",
"intro": "TypeScript configuration for Angular 2 developers",
"intro": "TypeScript configuration for Angular developers",
"hide": true
},
@@ -158,7 +158,7 @@
"webpack": {
"title": "Webpack: an introduction",
"intro": "Create your Angular 2 applications with a Webpack based tooling",
"intro": "Create your Angular applications with a Webpack based tooling",
"hide": true
}
}
+1 -1
View File
@@ -55,7 +55,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript"
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
},
"visual-studio-2015": {
+7 -7
View File
@@ -10,7 +10,7 @@
"architecture": {
"title": "Architecture Overview",
"navTitle": "Architecture",
"intro": "The basic building blocks of Angular 2 applications",
"intro": "The basic building blocks of Angular applications",
"nextable": true,
"basics": true
},
@@ -59,7 +59,7 @@
"style-guide": {
"title": "Style Guide",
"intro": "Write Angular 2 with style.",
"intro": "Write Angular with style.",
"basics": true
},
@@ -86,7 +86,7 @@
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"intro": "Brief definitions of the most important words in the Angular vocabulary",
"basics": true
},
@@ -118,7 +118,7 @@
"router": {
"title": "Routing & Navigation",
"intro": "Discover the basics of screen navigation with the Angular 2 router."
"intro": "Discover the basics of screen navigation with the Angular router."
},
"security": {
@@ -133,13 +133,13 @@
"testing": {
"title": "Testing",
"intro": "Techniques and practices for testing an Angular 2 app",
"intro": "Techniques and practices for testing an Angular app",
"hide": true
},
"typescript-configuration": {
"title": "TypeScript Configuration",
"intro": "TypeScript configuration for Angular 2 developers",
"intro": "TypeScript configuration for Angular developers",
"hide": true
},
@@ -150,7 +150,7 @@
"webpack": {
"title": "Webpack: an introduction",
"intro": "Create your Angular 2 applications with a Webpack based tooling",
"intro": "Create your Angular applications with a Webpack based tooling",
"hide": true
}
}
+1 -1
View File
@@ -65,7 +65,7 @@
"ts-to-js": {
"title": "TypeScript to JavaScript",
"intro": "Convert Angular 2 TypeScript examples into ES5 JavaScript"
"intro": "Convert Angular TypeScript examples into ES5 JavaScript"
},
"visual-studio-2015": {
+7 -7
View File
@@ -10,7 +10,7 @@
"architecture": {
"title": "Architecture Overview",
"navTitle": "Architecture",
"intro": "The basic building blocks of Angular 2 applications",
"intro": "The basic building blocks of Angular applications",
"nextable": true,
"basics": true
},
@@ -59,7 +59,7 @@
"style-guide": {
"title": "Style Guide",
"intro": "Write Angular 2 with style.",
"intro": "Write Angular with style.",
"basics": true
},
@@ -90,7 +90,7 @@
"glossary": {
"title": "Glossary",
"intro": "Brief definitions of the most important words in the Angular 2 vocabulary",
"intro": "Brief definitions of the most important words in the Angular vocabulary",
"basics": true
},
@@ -122,7 +122,7 @@
"router": {
"title": "Routing & Navigation",
"intro": "Discover the basics of screen navigation with the Angular 2 Router."
"intro": "Discover the basics of screen navigation with the Angular Router."
},
"security": {
@@ -137,12 +137,12 @@
"testing": {
"title": "Testing",
"intro": "Techniques and practices for testing an Angular 2 app"
"intro": "Techniques and practices for testing an Angular app"
},
"typescript-configuration": {
"title": "TypeScript Configuration",
"intro": "TypeScript configuration for Angular 2 developers"
"intro": "TypeScript configuration for Angular developers"
},
"upgrade": {
@@ -152,6 +152,6 @@
"webpack": {
"title": "Webpack: an introduction",
"intro": "Create your Angular 2 applications with a Webpack based tooling"
"intro": "Create your Angular applications with a Webpack based tooling"
}
}
File diff suppressed because it is too large Load Diff