144 lines
4.6 KiB
Plaintext
144 lines
4.6 KiB
Plaintext
///// Boiler Plate ////
|
|
import {bind, Component, Directive, EventEmitter, FORM_DIRECTIVES, View} from 'angular2/angular2';
|
|
|
|
// Angular 2 Test Bed
|
|
import {
|
|
beforeEachProviders, By, DebugElement, RootTestComponent as RTC,
|
|
beforeEach, ddescribe, xdescribe, describe, expect, iit, it, xit // Jasmine wrappers
|
|
} from 'angular2/testing';
|
|
|
|
import {injectAsync, injectTcb} from '../test-helpers/test-helpers';
|
|
|
|
///// Testing this component ////
|
|
import {HeroDetailComponent} from './hero-detail.component';
|
|
import {Hero} from './hero';
|
|
|
|
describe('HeroDetailComponent', () => {
|
|
|
|
it('can be created', () => {
|
|
let hc = new HeroDetailComponent()
|
|
expect(hc instanceof HeroDetailComponent).toEqual(true); // proof of life
|
|
});
|
|
|
|
it('parent "currentHero" flows down to HeroDetailComponent', injectTcb( tcb => {
|
|
return tcb
|
|
.createAsync(TestWrapper)
|
|
.then((rootTC:RTC) => {
|
|
let hc:HeroDetailComponent = rootTC.componentViewChildren[0].componentInstance;
|
|
let hw:TestWrapper = rootTC.componentInstance;
|
|
|
|
rootTC.detectChanges(); // trigger view binding
|
|
|
|
expect(hw.currentHero).toBe(hc.hero);
|
|
});
|
|
}));
|
|
|
|
it('delete button should raise delete event for parent component', injectTcb( tcb => {
|
|
|
|
return tcb
|
|
//.overrideTemplate(HeroDetailComponent, '<button (click)="onDelete()" [disabled]="!hero">Delete</button>')
|
|
.overrideDirective(TestWrapper, HeroDetailComponent, mockHDC)
|
|
.createAsync(TestWrapper)
|
|
.then((rootTC:RTC) => {
|
|
|
|
let hw:TestWrapper = rootTC.componentInstance;
|
|
let hdcElement = rootTC.componentViewChildren[0];
|
|
let hdc:HeroDetailComponent = hdcElement.componentInstance;
|
|
|
|
rootTC.detectChanges(); // trigger view binding
|
|
|
|
// We can watch the HeroComponent.delete EventEmitter's event
|
|
let subscription = hdc.delete.toRx().subscribe(() => {
|
|
console.log('HeroComponent.delete event raised');
|
|
subscription.dispose();
|
|
});
|
|
|
|
// We can EITHER invoke HeroComponent delete button handler OR
|
|
// trigger the 'click' event on the delete HeroComponent button
|
|
// BUT DON'T DO BOTH
|
|
|
|
// Trigger event
|
|
// FRAGILE because assumes precise knowledge of HeroComponent template
|
|
hdcElement
|
|
.query(By.css('#delete'))
|
|
.triggerEventHandler('click', {});
|
|
|
|
hw.testCallback = () => {
|
|
// if wrapper.onDelete is called, HeroComponent.delete event must have been raised
|
|
//console.log('HeroWrapper.onDelete called');
|
|
expect(true).toEqual(true);
|
|
}
|
|
// hc.onDelete();
|
|
});
|
|
}), 500); // needs some time for event to complete; 100ms is not long enough
|
|
|
|
it('update button should modify hero', injectTcb( tcb => {
|
|
|
|
return tcb
|
|
.createAsync(TestWrapper)
|
|
.then((rootTC:RTC) => {
|
|
|
|
let hc:HeroDetailComponent = rootTC.componentViewChildren[0].componentInstance;
|
|
let hw:TestWrapper = rootTC.componentInstance;
|
|
let origNameLength = hw.currentHero.name.length;
|
|
|
|
rootTC.detectChanges(); // trigger view binding
|
|
|
|
// We can EITHER invoke HeroComponent update button handler OR
|
|
// trigger the 'click' event on the HeroComponent update button
|
|
// BUT DON'T DO BOTH
|
|
|
|
// Trigger event
|
|
// FRAGILE because assumes precise knowledge of HeroComponent template
|
|
rootTC.componentViewChildren[0]
|
|
.componentViewChildren[2]
|
|
.triggerEventHandler('click', {});
|
|
|
|
// hc.onUpdate(); // Invoke button handler
|
|
expect(hw.currentHero.name.length).toBeGreaterThan(origNameLength);
|
|
});
|
|
}));
|
|
|
|
});
|
|
|
|
///// Test Components ////////
|
|
|
|
// TestWrapper is a convenient way to communicate w/ HeroDetailComponent in a test
|
|
@Component({selector: 'hero-wrapper'})
|
|
@View({
|
|
template: `<my-hero-detail [hero]="currentHero" [user-name]="userName" (delete)="onDelete()"></my-hero-detail>`,
|
|
directives: [HeroDetailComponent]
|
|
})
|
|
class TestWrapper {
|
|
currentHero = new Hero(42, 'Cat Woman');
|
|
userName = 'Sally';
|
|
testCallback() {} // monkey-punched in a test
|
|
onDelete() { this.testCallback(); }
|
|
}
|
|
|
|
@View({
|
|
template: `
|
|
<div>
|
|
<h2>{{hero.name}} | {{userName}}</h2>
|
|
<button id="delete" (click)="onDelete()" [disabled]="!hero">Delete</button>
|
|
<button id="update" (click)="onUpdate()" [disabled]="!hero">Update</button>
|
|
<div id="id">{{hero.id}}</div>
|
|
<input [(ngModel)]="hero.name"/>
|
|
</div>`,
|
|
directives: [FORM_DIRECTIVES]
|
|
})
|
|
class mockHDC //extends HeroDetailComponent { }
|
|
{
|
|
hero: Hero;
|
|
|
|
delete = new EventEmitter();
|
|
|
|
onDelete() { this.delete.next(this.hero) }
|
|
|
|
onUpdate() {
|
|
if (this.hero) {
|
|
this.hero.name += 'x';
|
|
}
|
|
}
|
|
userName: string;
|
|
} |