Angular 17 fakeAsync tasks not running until test is cleaned up with 'resetFakeAsyncZone()'

Discussão em 'Angular' iniciado por IMeyers20, Novembro 11, 2024.

  1. IMeyers20

    IMeyers20 Guest

    Overview


    I am in the progress of migrating my Angular project from v14 to v17, and also migrating my Jest from v27 to v29 at the same time. I have my project running, with no console errors / warnings, but I am struggling to get Jest to work.

    I am running my tests using the fakeAsync wrapper, but am getting an issue where some of the async tasks within aren't ran until after any of my expect(...) checks fail and Angular's resetFakeAsyncZone() runs, despite having all the necessary flush / tick calls (this test passed before and breakpoints can show that it is still getting the same data but just not until after the expect call)

    One of my failing tests


    it('should call Update on submit if shouldUpdate is true', fakeAsync(() => {
    // arrange
    comp.shouldUpdate = true;
    comp.CanAlter = true;
    jest.spyOn(connectionResource, 'Update').mockImplementation((c) => {
    return Promise.resolve({ ...c, Id: connection.Id, Children: [] } as ApiConnection);
    });
    let onSubSpy = jest.spyOn(comp.onSubmit, 'emit');

    // act
    comp.ngOnChanges();
    flush();
    fixture.detectChanges();

    let result = { ...comp.form.getRawValue(), ParentId: probe.Id };
    let submitButton = fixture.debugElement.query(By.css('button[type="submit"]'));
    submitButton.nativeElement.click();
    flush();

    // assert
    expect(connectionResource.Update).toHaveBeenCalledWith(result, connection.Id);
    let cached = coreCache.SearchMonitorableTree(coreCache.PayloadCache.Monitorables[0], 'Id', connection.Id)[0];
    expect(onSubSpy).toHaveBeenCalledWith(cached); // This expect fails, and the the spied function is hit directly after
    }));

    What I have tried so far


    • I have tried changing the expect to toHaveBeenCalled() to double check that there wasn't some small change to the model somewhere, it insisted that it wasn't called, then called it right after (same problem)


    • I tried using jest.useFakeTimers() (there were many changes to fakeTimers in the last couple Jest updates), this did not fix.


    • I tried adding tick() and flushMicrotasks() to see if those would have any affect, they did not.


    • I tried calling resetFakeAsyncZone() to see if that had any affect as that is what seems to cause it to work at the end, that did not work.
    Helpful Resources


    Continue reading...

Compartilhe esta Página