Skip to content

mock.timers ignores AbortSignal.timeout #60509

@DerGernTod

Description

@DerGernTod

Version

v24.10.0, v25.1.0

Platform

Microsoft Windows NT 10.0.26100.0
x64

Subsystem

No response

What steps will reproduce the bug?

Execute this test:

import {
    beforeEach,
    describe,
    it,
    mock
} from "node:test";
import assert from "node:assert";

describe("test", () => {
    beforeEach(() => {
        mock.timers.enable({ apis: ["Date", "setTimeout"] });
    });

    it("should test abort", { timeout: 5000 }, async () => {
        const timeout = AbortSignal.timeout(10000);
        const catchSpy = mock.fn();
        const abortablePromise = new Promise((_, reject) => {
            timeout.addEventListener("abort", () => {
                reject(new Error("promise rejected due to abort signal"));
            });
        }).catch(catchSpy);
        assert.equal(catchSpy.mock.calls.length, 0);
        await Promise.resolve();
        mock.timers.tick(10000);
        await abortablePromise;
        assert.equal(catchSpy.mock.calls.length, 1);
    });
});

It times out.

How often does it reproduce? Is there a required condition?

Every time.

What is the expected behavior? Why is that the expected behavior?

The timer tick also ticks the timeout AbortSignal and triggers listeners if applicable, or the mock.timers.enable option supports a new "AbortSignal.timeout" API.

What do you see instead?

The test times out before the abort signal is triggered.

Additional information

In node versions <24, this results in a failing test after a few milliseconds with
"Promise resolution is still pending but the event loop has already resolved".

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions