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

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

Merged
merged 1 commit into from
Sep 23, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 22 additions & 19 deletions public/docs/_examples/testing/ts/app/banner.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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(() => {
Expand All @@ -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

Expand All @@ -59,36 +62,36 @@ describe('BannerComponent with AutoChangeDetect', () => {
fixture = TestBed.configureTestingModule({
declarations: [ BannerComponent ],
providers: [
{ provide: ComponentFixtureAutoDetect,
useValue: true }
{ provide: ComponentFixtureAutoDetect, useValue: true }
]
})
// #enddocregion auto-detect
.createComponent(BannerComponent);

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
});
Expand All @@ -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
});
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand All @@ -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
26 changes: 13 additions & 13 deletions public/docs/_examples/testing/ts/app/shared/twain.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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();
});
});
Expand Down
68 changes: 42 additions & 26 deletions public/docs/_examples/testing/ts/app/welcome.component.spec.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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;
Expand All @@ -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 } ]
});
Expand All @@ -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', () => {
// #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
});
2 changes: 1 addition & 1 deletion public/docs/dart/latest/cookbook/_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},

Expand Down
14 changes: 7 additions & 7 deletions public/docs/dart/latest/guide/_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down Expand Up @@ -59,7 +59,7 @@

"style-guide": {
"title": "Style Guide",
"intro": "Write Angular 2 with style.",
"intro": "Write Angular with style.",
"basics": true
},

Expand Down Expand Up @@ -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
},

Expand Down Expand Up @@ -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": {
Expand All @@ -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
},

Expand All @@ -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
}
}
Loading