Repository navigation
eventCoalescing breaks things in a fakeAsync test #56767
Description
Which @angular/* package(s) are the source of the bug?
core
Is this a regression?
No
Description
When using eventCoalescing: true in combination with fakeAsync, any event triggered will then block NgZone.onMicrotaskEmpty and .onStable for the rest of the test. Coalescing schedules change detection to be run in a way that the fake async zone cannot see, I think because of the Zone.root.run() used here. This causes the NgZone to be marked as having a microtask pending here, which never gets cleared. So as long as the zone thinks a microtask is pending it will never emit onMicrotaskEmpty nor onStable (see the check here).
Users do not need to use onMicrotaskEmpty or onStable directly to be affected. I noticed this when using an afterRender hook, which is internally triggered by onMicrotaskEmpty. Here is a repro showing that situation:
it('runs coalesced change detection', fakeAsync(() => {
let ranAfterRenderHook = false;
@Component({ standalone: true, selector: 'app-inner' })
class InnerComponent {
constructor() {
// this is an inner component so that we can register this hook _after_
// dispatching an event
afterRender(() => {
ranAfterRenderHook = true;
});
}
}
@Component({
standalone: true,
imports: [InnerComponent],
template: `
<div class="clickable" (click)="noop()"></div>
@if (showInner) {
<app-inner />
}
`,
})
class OuterComponent {
showInner = false;
noop = () => {};
}
TestBed.configureTestingModule({
// change this to `false` and the test passes
providers: [provideZoneChangeDetection({ eventCoalescing: true })],
});
const fixture = TestBed.createComponent(OuterComponent);
document.querySelector('.clickable')!.dispatchEvent(new MouseEvent('click'));
tick(); // you'd think this would flush the pending CD task, but it doesn't
fixture.componentInstance.showInner = true;
fixture.detectChanges();
tick(); // If afterRender is delayed, surely this should trigger it? Alas, no!
expect(ranAfterRenderHook).toBe(true);
}));Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
No response
Please provide the environment you discovered this bug in (run ng version)
Angular CLI: 18.0.5
Node: 20.9.0
Package Manager: npm 10.1.0
OS: win32 x64
Angular: 18.0.4
... animations, cdk, common, compiler, compiler-cli, core, forms
... material, platform-browser, platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1800.5
@angular-devkit/build-angular 18.0.5
@angular-devkit/core 18.0.5
@angular-devkit/schematics 18.0.5
@angular/cli 18.0.5
@schematics/angular 18.0.5
ng-packagr 18.0.0
rxjs 7.8.1
typescript 5.4.5
zone.js 0.14.7
Anything else?
No response
Activity
7 remaining items
fix(core): Allow zoneless scheduler to run inside `fakeAsync` (#56932)
fix(core): Allow zoneless scheduler to run inside `fakeAsync` (#56932)
fix(core): Schedulers run in zone above Angular rather than root
fix(core): Schedulers run in zone above Angular rather than root (ang…
angular-automatic-lock-bot commentedon Sep 27, 2024
This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.
Read more about our automatic conversation locking policy.
This action has been performed automatically by a bot.