Last active
May 17, 2019 12:41
-
-
Save IlCallo/a003f4f0a12b4e0276d461d5ff8c2562 to your computer and use it in GitHub Desktop.
Testing code inside ngOnChanges (and in components using OnPush) using Spectator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, Directive, Host, Input, OnChanges, SimpleChanges } from '@angular/core'; | |
import { createHostComponentFactory, SpectatorWithHost } from '@netbasal/spectator/jest'; | |
@Component({ | |
selector: 'simple-component', | |
template: '{{ name }}' | |
}) | |
class SimpleComponent implements OnChanges { | |
@Input() name!: string; | |
ngOnChanges(changes: SimpleChanges) { | |
console.log('ngOnChanges from Component, name: ', changes['name']); | |
} | |
} | |
@Directive({ | |
selector: '[simpleDirective]' | |
}) | |
class SimpleDirective implements OnChanges { | |
@Input() nameButStronger!: string; | |
constructor(@Host() private host: SimpleComponent) {} | |
ngOnChanges(changes: SimpleChanges) { | |
console.log('ngOnChanges from Directive, name: ', changes['nameButStronger']); | |
this.host.name = changes['nameButStronger'].currentValue + ', stronger!'; | |
} | |
} | |
@Component({ | |
selector: 'host', | |
template: '' | |
}) | |
class HostComponent { | |
nameMirror!: string; | |
nameButStrongerMirror!: string; | |
} | |
// During a Change Detection cycle (automatic or triggered with detectChanges()). | |
// ngOnChanges hook it's called only when at least a change is registered on @Input properties. | |
// Programmatic manipulation of properties on the component effectively prevents the @Input mechanism to notice the change. | |
// These methods are or perform programmatic manipulations and as such won't cause ngOnChanges hook to be called. | |
// * directive.nameButStronger = 'Luca'; | |
// * host.setInput('nameButStronger', 'Paolo'); | |
// * createHost(`<simple-component simpleDirective></simple-component>`, undefined, { nameButStronger: 'Simone' } ); | |
// | |
// The only working way, aside manually calling ngOnChanges hook, is to create a custom host component with properties bound | |
// via template to the tested component/directive @Input properties, update host component mirror properties | |
// and then force a Change Detection cycle (using detectChanges()). | |
describe('SimpleComponent and SimpleDirective', () => { | |
let host: SpectatorWithHost<SimpleDirective, HostComponent>; | |
const createHost = createHostComponentFactory({ | |
component: SimpleDirective, | |
declarations: [SimpleComponent], | |
host: HostComponent | |
}); | |
it('should correctly call ngOnChanges hook and detectChanges on SimpleComponent', () => { | |
host = createHost(`<simple-component [name]="nameMirror"></simple-component>`); | |
const component = host.queryHost<SimpleComponent>(SimpleComponent); | |
const componentElement = host.queryHost('simple-component'); | |
host.hostComponent.nameMirror = 'Paolo'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Paolo'); | |
host.hostComponent.nameMirror = 'Luca'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Luca'); | |
host.hostComponent.nameMirror = 'Simone'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Simone'); | |
}); | |
it('should correctly call ngOnChanges hook and detectChanges on SimpleDirective', () => { | |
host = createHost( | |
`<simple-component [nameButStronger]="nameButStrongerMirror" simpleDirective></simple-component>` | |
); | |
const component = host.queryHost<SimpleComponent>(SimpleComponent); | |
const componentElement = host.queryHost('simple-component'); | |
const directive = host.getDirectiveInstance<SimpleDirective>(SimpleDirective); | |
host.hostComponent.nameButStrongerMirror = 'Paolo'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Directive property: ', directive.nameButStronger); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Paolo, stronger!'); | |
host.hostComponent.nameButStrongerMirror = 'Luca'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Directive property: ', directive.nameButStronger); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Luca, stronger!'); | |
host.hostComponent.nameButStrongerMirror = 'Simone'; | |
host.detectChanges(); | |
console.log('Current host content: ', host.hostElement.innerHTML); | |
console.log('Directive property: ', directive.nameButStronger); | |
console.log('Component property: ', component.name); | |
expect(componentElement).toHaveText('Simone, stronger!'); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment