docs: testing guide for CLI (#20697)
- updates tests - heavy prose revisions - uses HttpClient (with angular-in-memory-web-api) - test HeroService using `HttpClientTestingModule` - scrub away most By.CSS - fake async observable with `asyncData()` - extensive Twain work - different take on retryWhen - remove app barrels (& systemjs.extras) which troubled plunker/systemjs - add dummy export const to hero.ts (plunkr/systemjs fails w/o it) - shrink and re-organize TOC - add marble testing package and tests - demonstrate the "no beforeEach()" test coding style - add section on Http service testing - prepare for stackblitz - confirm works in plunker except excluded marble test - add tests for avoidFile class feature of CodeExampleComponent PR Close #20697
This commit is contained in:
@ -1,7 +1,9 @@
|
||||
|
||||
// #docplaster
|
||||
import { async, ComponentFixture, TestBed
|
||||
} from '@angular/core/testing';
|
||||
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
import { addMatchers, click } from '../../testing';
|
||||
@ -11,64 +13,96 @@ import { DashboardHeroComponent } from './dashboard-hero.component';
|
||||
|
||||
beforeEach( addMatchers );
|
||||
|
||||
describe('DashboardHeroComponent class only', () => {
|
||||
// #docregion class-only
|
||||
it('raises the selected event when clicked', () => {
|
||||
const comp = new DashboardHeroComponent();
|
||||
const hero: Hero = { id: 42, name: 'Test' };
|
||||
comp.hero = hero;
|
||||
|
||||
comp.selected.subscribe(selectedHero => expect(selectedHero).toBe(hero));
|
||||
comp.click();
|
||||
});
|
||||
// #enddocregion class-only
|
||||
});
|
||||
|
||||
describe('DashboardHeroComponent when tested directly', () => {
|
||||
|
||||
let comp: DashboardHeroComponent;
|
||||
let expectedHero: Hero;
|
||||
let fixture: ComponentFixture<DashboardHeroComponent>;
|
||||
let heroEl: DebugElement;
|
||||
let heroDe: DebugElement;
|
||||
let heroEl: HTMLElement;
|
||||
|
||||
// #docregion setup, compile-components
|
||||
// async beforeEach
|
||||
beforeEach( async(() => {
|
||||
beforeEach(async(() => {
|
||||
// #docregion setup, config-testbed
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardHeroComponent ],
|
||||
declarations: [ DashboardHeroComponent ]
|
||||
})
|
||||
.compileComponents(); // compile template and css
|
||||
// #enddocregion setup, config-testbed
|
||||
.compileComponents();
|
||||
}));
|
||||
// #enddocregion compile-components
|
||||
|
||||
// synchronous beforeEach
|
||||
beforeEach(() => {
|
||||
// #docregion setup
|
||||
fixture = TestBed.createComponent(DashboardHeroComponent);
|
||||
comp = fixture.componentInstance;
|
||||
heroEl = fixture.debugElement.query(By.css('.hero')); // find hero element
|
||||
|
||||
// pretend that it was wired to something that supplied a hero
|
||||
expectedHero = new Hero(42, 'Test Name');
|
||||
// find the hero's DebugElement and element
|
||||
heroDe = fixture.debugElement.query(By.css('.hero'));
|
||||
heroEl = heroDe.nativeElement;
|
||||
|
||||
// mock the hero supplied by the parent component
|
||||
expectedHero = { id: 42, name: 'Test Name' };
|
||||
|
||||
// simulate the parent setting the input property with that hero
|
||||
comp.hero = expectedHero;
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
|
||||
// trigger initial data binding
|
||||
fixture.detectChanges();
|
||||
// #enddocregion setup
|
||||
});
|
||||
// #enddocregion setup
|
||||
|
||||
// #docregion name-test
|
||||
it('should display hero name', () => {
|
||||
it('should display hero name in uppercase', () => {
|
||||
const expectedPipedName = expectedHero.name.toUpperCase();
|
||||
expect(heroEl.nativeElement.textContent).toContain(expectedPipedName);
|
||||
expect(heroEl.textContent).toContain(expectedPipedName);
|
||||
});
|
||||
// #enddocregion name-test
|
||||
|
||||
// #docregion click-test
|
||||
it('should raise selected event when clicked', () => {
|
||||
it('should raise selected event when clicked (triggerEventHandler)', () => {
|
||||
let selectedHero: Hero;
|
||||
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
||||
|
||||
// #docregion trigger-event-handler
|
||||
heroEl.triggerEventHandler('click', null);
|
||||
heroDe.triggerEventHandler('click', null);
|
||||
// #enddocregion trigger-event-handler
|
||||
expect(selectedHero).toBe(expectedHero);
|
||||
});
|
||||
// #enddocregion click-test
|
||||
|
||||
// #docregion click-test-2
|
||||
it('should raise selected event when clicked', () => {
|
||||
let selectedHero: Hero;
|
||||
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
||||
// #docregion click-test-2
|
||||
it('should raise selected event when clicked (element.click)', () => {
|
||||
let selectedHero: Hero;
|
||||
comp.selected.subscribe((hero: Hero) => selectedHero = hero);
|
||||
|
||||
heroEl.click();
|
||||
expect(selectedHero).toBe(expectedHero);
|
||||
});
|
||||
// #enddocregion click-test-2
|
||||
|
||||
// #docregion click-test-3
|
||||
it('should raise selected event when clicked (click helper)', () => {
|
||||
let selectedHero: Hero;
|
||||
comp.selected.subscribe(hero => selectedHero = hero);
|
||||
|
||||
click(heroDe); // click helper with DebugElement
|
||||
click(heroEl); // click helper with native element
|
||||
|
||||
click(heroEl); // triggerEventHandler helper
|
||||
expect(selectedHero).toBe(expectedHero);
|
||||
});
|
||||
// #enddocregion click-test-2
|
||||
// #enddocregion click-test-3
|
||||
});
|
||||
|
||||
//////////////////
|
||||
@ -76,28 +110,31 @@ describe('DashboardHeroComponent when tested directly', () => {
|
||||
describe('DashboardHeroComponent when inside a test host', () => {
|
||||
let testHost: TestHostComponent;
|
||||
let fixture: ComponentFixture<TestHostComponent>;
|
||||
let heroEl: DebugElement;
|
||||
let heroEl: HTMLElement;
|
||||
|
||||
// #docregion test-host-setup
|
||||
beforeEach( async(() => {
|
||||
beforeEach(async(() => {
|
||||
// #docregion test-host-setup
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ DashboardHeroComponent, TestHostComponent ], // declare both
|
||||
}).compileComponents();
|
||||
declarations: [ DashboardHeroComponent, TestHostComponent ]
|
||||
})
|
||||
// #enddocregion test-host-setup
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
// #docregion test-host-setup
|
||||
// create TestHostComponent instead of DashboardHeroComponent
|
||||
fixture = TestBed.createComponent(TestHostComponent);
|
||||
testHost = fixture.componentInstance;
|
||||
heroEl = fixture.debugElement.query(By.css('.hero')); // find hero
|
||||
heroEl = fixture.nativeElement.querySelector('.hero');
|
||||
fixture.detectChanges(); // trigger initial data binding
|
||||
// #enddocregion test-host-setup
|
||||
});
|
||||
// #enddocregion test-host-setup
|
||||
|
||||
// #docregion test-host-tests
|
||||
it('should display hero name', () => {
|
||||
const expectedPipedName = testHost.hero.name.toUpperCase();
|
||||
expect(heroEl.nativeElement.textContent).toContain(expectedPipedName);
|
||||
expect(heroEl.textContent).toContain(expectedPipedName);
|
||||
});
|
||||
|
||||
it('should raise selected event when clicked', () => {
|
||||
@ -114,10 +151,12 @@ import { Component } from '@angular/core';
|
||||
// #docregion test-host
|
||||
@Component({
|
||||
template: `
|
||||
<dashboard-hero [hero]="hero" (selected)="onSelected($event)"></dashboard-hero>`
|
||||
<dashboard-hero
|
||||
[hero]="hero" (selected)="onSelected($event)">
|
||||
</dashboard-hero>`
|
||||
})
|
||||
class TestHostComponent {
|
||||
hero = new Hero(42, 'Test Name');
|
||||
hero: Hero = {id: 42, name: 'Test Name' };
|
||||
selectedHero: Hero;
|
||||
onSelected(hero: Hero) { this.selectedHero = hero; }
|
||||
}
|
||||
|
Reference in New Issue
Block a user