Как сделать так, чтобы обнаружение изменений в модульных тестах работало правильно? Из исходников changeDetection следует запускать после того, как микрозадачи опустеют (включая событийные задачи?).
this._onMicrotaskEmptySubscription = ngZone.onMicrotaskEmpty.subscribe({
next: () => {
if (this._autoDetect) {
// Do a change detection run with checkNoChanges set to true to check
// there are no changes on the second run.
this.detectChanges(true);
}
}
});
В этом коротком примере обнаружение изменений запускается после setTimeout, но не после нажатия на элемент вручную. Есть ли правильный способ инициировать обнаружение изменений после отправки события (внутри зоны fakeAsync, без приспособления.detectChanges, потому что в этом случае обнаружение изменений не будет таким же, как в реальной жизни)?
import {
fakeAsync, tick, ComponentFixture, TestBed, ComponentFixtureAutoDetect
} from '@angular/core/testing';
import {
Component, QueryList, ViewChildren
} from '@angular/core';
import { By } from '@angular/platform-browser';
import { CommonModule } from '@angular/common';
describe('bug', () => {
let host: Host;
let fixture: ComponentFixture<Host>;
@Component({
selector: 'child',
template: ``,
})
class Child {}
@Component({
template: `
<ng-container *ngFor="let show of shows">
<child *ngIf="show"></child>
</ng-container>
<button (click)="shows[1] = true">show</button>`
})
class Host {
shows = [false, false];
@ViewChildren(Child) children: QueryList<Child>;
constructor() {
setTimeout(() => this.shows[0] = true, 50);
}
}
fit('test', fakeAsync(() => {
TestBed.configureTestingModule({
imports: [
CommonModule,
],
declarations: [
Host, Child,
],
providers: [{
provide: ComponentFixtureAutoDetect,
useValue: true,
}]
});
fixture = TestBed.createComponent(Host);
host = fixture.componentInstance;
tick(10);
expect(host.children.length).toEqual(0);
tick(50);
expect(host.children.length).toEqual(1);
const button = fixture.debugElement.query(By.css('button'));
button.triggerEventHandler('click', new Event('click'));
tick(50);
// fixture.detectChanges();
expect(host.children.length).toEqual(2); // fails here
}));
});