Reputation: 651
I am testing a component which dinamically inserts a checkbox in its template when ngAfterViewInit lifecycle hook is called.
export class MyComponent {
ngAfterViewInit() {
// checkbox insertion in the template here
...
}
...
}
This is my test:
it('should inject the checkbox', () => {
fixture = TestBed.createComponent(AutogeneratedTableComponent);
fixture.detectChanges();
rows = fixture.debugElement.queryAll(By.css('tr'));
console.log(Object.assign({}, rows[1].nativeElement)); // *referenceLog
console.log(rows[1].nativeElement)); // *cloneLog
expect(rows[1].query(By.css('input')).not.toBeNull(); // FAILS
}
*refereceLog (prints the tr without the inserted td)
<tr ng-reflect-id="22" id="22">
<td>Single Room</td>
<td>My single room.</td>
</tr>
*cloneLog (shows that at time of testing the template is not ready)
Object{__zone_symbol__eventTasks: [ZoneTask{zone: ..., runCount: ..., _zoneDelegates: ..., _state: ..., type: ..., source: ..., data: ..., scheduleFn: ..., cancelFn: ..., callback: ..., invoke: ...}]}
I tried manually calling ngAfterViewInit()
it('should inject the checkbox', () => {
fixture = TestBed.createComponent(AutogeneratedTableComponent);
fixture.detectChanges();
fixture.debugElement.componentInstance.ngAfterViewInit();
fixture.detectChanges();
rows = fixture.debugElement.queryAll(By.css('tr'));
console.log(Object.assign({}, rows[1].nativeElement)); // *referenceLog
console.log(rows[1].nativeElement)); // *cloneLog
expect(rows[1].query(By.css('input')).not.toBeNull(); // FAILS
}
*refereceLog (prints the expected tr)
<tr ng-reflect-id="22" id="22">
<td><input id="22" type="checkbox"></td>
<td>Single Room</td>
<td>My single room.</td>
</tr>
No changes in *cloneLog
Then I tried
Adding spyOn(component,
'ngAfterViewInit').andReturnValue(Promise.resolve(true)).and.callThrough();
and then spyOn().calls.mostRecent.returnValue.then(() =>
{fixture.detectChanges() ... })
with the done()
at the bottom of
the block
Adding async()
to the individual test declaration and doing the
evaluation inside a fixture.whenStable.then( () => {
fixture.detectChanges()... } )
Adding fakeAsync()
to the individual test declaration and a tick()
calling before the evaluation
All the attempts with the same previous result. The template element is being updated after the evaluation is done.
I should find a way to stop the test execution until the nativeElement that I am testing is updated.
Upvotes: 1
Views: 2074
Reputation: 51
I had a similar problem and this solution worked for me:
I called fixture.autoDetectChanges(true);
instead of (or additionally to) fixture.detectChanges()
.
Upvotes: 4