angular-docs-cn/public/docs/_examples/testing/ts/app/old-specs/hero-detail.component.spec....

219 lines
7.3 KiB
Plaintext

///// Boiler Plate ////
import {bind, By, Component, Directive, EventEmitter, FORM_DIRECTIVES} from 'angular2/angular2';
// Angular 2 Test Bed
import {
beforeEachProviders, inject, injectAsync, RootTestComponent as RTC,
beforeEach, ddescribe, xdescribe, describe, expect, iit, it, xit // Jasmine wrappers
} from 'angular2/testing';
import {dispatchEvent, DoneFn, injectTcb, tick} from '../test-helpers/test-helpers';
///// Testing this component ////
import {HeroDetailComponent} from './hero-detail.component';
import {Hero} from './hero';
describe('HeroDetailComponent', () => {
/////////// Component Tests without DOM interaction /////////////
describe('(No DOM)', () => {
it('can be created', () => {
let hdc = new HeroDetailComponent();
expect(hdc instanceof HeroDetailComponent).toEqual(true); // proof of life
});
it('onDelete method should raise delete event', (done: DoneFn) => {
let hdc = new HeroDetailComponent();
// Listen for the HeroComponent.delete EventEmitter's event
hdc.delete.toRx().subscribe(() => {
console.log('HeroComponent.delete event raised');
done(); // it must have worked
}, (error: any) => { fail(error); done() });
hdc.onDelete();
});
// Disable until toPromise() works again
xit('onDelete method should raise delete event (w/ promise)', (done: DoneFn) => {
let hdc = new HeroDetailComponent();
// Listen for the HeroComponent.delete EventEmitter's event
let p = hdc.delete.toRx()
.toPromise()
.then(() => {
console.log('HeroComponent.delete event raised in promise');
})
.then(done, done.fail);
hdc.delete.toRx()
.subscribe(() => {
console.log('HeroComponent.delete event raised in subscription')
});
hdc.onDelete();
// toPromise() does not fulfill until emitter is completed by `return()`
hdc.delete.return();
});
it('onUpdate method should modify hero', () => {
let hdc = new HeroDetailComponent();
hdc.hero = new Hero(42, 'Cat Woman');
let origNameLength = hdc.hero.name.length;
hdc.onUpdate();
expect(hdc.hero.name.length).toBeGreaterThan(origNameLength);
});
});
/////////// Component tests that check the DOM /////////////
describe('(DOM)', () => {
// Disable until toPromise() works again
xit('Delete button should raise delete event', injectTcb(tcb => {
// We only care about the button
let template = '<button (click)="onDelete()">Delete</button>';
return tcb
.overrideTemplate(HeroDetailComponent, template)
.createAsync(HeroDetailComponent)
.then((rootTC: RTC) => {
let hdc: HeroDetailComponent = rootTC.debugElement.componentInstance;
// // USE PROMISE WRAPPING AN OBSERVABLE UNTIL can get `toPromise` working again
// let p = new Promise<Hero>((resolve) => {
// // Listen for the HeroComponent.delete EventEmitter's event with observable
// hdc.delete.toRx().subscribe((hero: Hero) => {
// console.log('Observable heard HeroComponent.delete event raised');
// resolve(hero);
// });
// })
//Listen for the HeroComponent.delete EventEmitter's event with promise
let p = <Promise<Hero>> hdc.delete.toRx().toPromise()
.then((hero:Hero) => {
console.log('Promise heard HeroComponent.delete event raised');
});
// trigger the 'click' event on the HeroDetailComponent delete button
let el = rootTC.debugElement.query(By.css('button'));
el.triggerEventHandler('click', null);
// toPromise() does not fulfill until emitter is completed by `return()`
hdc.delete.return();
return p;
});
}));
it('Update button should modify hero', injectTcb(tcb => {
let template =
`<div>
<button id="update" (click)="onUpdate()" [disabled]="!hero">Update</button>
<input [(ngModel)]="hero.name"/>
</div>`
return tcb
.overrideTemplate(HeroDetailComponent, template)
.createAsync(HeroDetailComponent)
.then((rootTC: RTC) => {
let hdc: HeroDetailComponent = rootTC.debugElement.componentInstance;
hdc.hero = new Hero(42, 'Cat Woman');
let origNameLength = hdc.hero.name.length;
// trigger the 'click' event on the HeroDetailComponent update button
rootTC.debugElement.query(By.css('#update'))
.triggerEventHandler('click', null);
expect(hdc.hero.name.length).toBeGreaterThan(origNameLength);
});
}));
it('Entering hero name in textbox changes hero', injectTcb(tcb => {
let hdc: HeroDetailComponent
let template = `<input [(ngModel)]="hero.name"/>`
return tcb
.overrideTemplate(HeroDetailComponent, template)
.createAsync(HeroDetailComponent)
.then((rootTC: RTC) => {
hdc = rootTC.debugElement.componentInstance;
hdc.hero = new Hero(42, 'Cat Woman');
rootTC.detectChanges();
// get the HTML element and change its value in the DOM
var input = rootTC.debugElement.query(By.css('input')).nativeElement;
input.value = "Dog Man"
dispatchEvent(input, 'change'); // event triggers Ng to update model
rootTC.detectChanges();
// model update hasn't happened yet, despite `detectChanges`
expect(hdc.hero.name).toEqual('Cat Woman');
})
.then(tick) // must wait a tick for the model update
.then(() => {
expect(hdc.hero.name).toEqual('Dog Man');
});
}));
// Simulates ...
// 1. change a hero
// 2. select a different hero
// 3 re-select the first hero
// 4. confirm that the change is preserved in HTML
// Reveals 2-way binding bug in alpha-36, fixed in pull #3715 for alpha-37
it('toggling heroes after modifying name preserves the change on screen', injectTcb(tcb => {
let hdc: HeroDetailComponent;
let hero1 = new Hero(1, 'Cat Woman');
let hero2 = new Hero(2, 'Goat Boy');
let input: HTMLInputElement;
let rootTC: RTC;
let template = `{{hero.id}} - <input [(ngModel)]="hero.name"/>`
return tcb
.overrideTemplate(HeroDetailComponent, template)
.createAsync(HeroDetailComponent)
.then((rtc: RTC) => {
rootTC = rtc;
hdc = rootTC.debugElement.componentInstance;
hdc.hero = hero1; // start with hero1
rootTC.detectChanges();
// get the HTML element and change its value in the DOM
input = rootTC.debugElement.query(By.css('input')).nativeElement;
input.value = "Dog Man"
dispatchEvent(input, 'change'); // event triggers Ng to update model
})
.then(tick) // must wait a tick for the model update
.then(() => {
expect(hdc.hero.name).toEqual('Dog Man');
hdc.hero = hero2 // switch to hero2
rootTC.detectChanges();
hdc.hero = hero1 // switch back to hero1
rootTC.detectChanges();
// model value will be the same changed value (of course)
expect(hdc.hero.name).toEqual('Dog Man');
// the view should reflect the same changed value
expect(input.value).toEqual('Dog Man');
});
}));
});
});