From 0d25b6a31761394ef7b9296e15855014eb6fed94 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Wed, 18 Feb 2026 17:20:35 +0000 Subject: [PATCH] perf(test): remove fixed sleeps in async test flows --- src/auto-reply/reply/reply-flow.test.ts | 4 +- src/browser/routes/dispatcher.abort.test.ts | 5 +- src/infra/bonjour.test.ts | 55 +++++++-------------- 3 files changed, 24 insertions(+), 40 deletions(-) diff --git a/src/auto-reply/reply/reply-flow.test.ts b/src/auto-reply/reply/reply-flow.test.ts index 73c16fa0a8e..6df2037ae27 100644 --- a/src/auto-reply/reply/reply-flow.test.ts +++ b/src/auto-reply/reply/reply-flow.test.ts @@ -1146,7 +1146,7 @@ describe("createReplyDispatcher", () => { const deliver = vi.fn(async (_payload, info) => { delivered.push(info.kind); if (info.kind === "tool") { - await new Promise((resolve) => setTimeout(resolve, 5)); + await Promise.resolve(); } }); const dispatcher = createReplyDispatcher({ deliver }); @@ -1161,7 +1161,7 @@ describe("createReplyDispatcher", () => { it("fires onIdle when the queue drains", async () => { const deliver: Parameters[0]["deliver"] = async () => - await new Promise((resolve) => setTimeout(resolve, 5)); + await Promise.resolve(); const onIdle = vi.fn(); const dispatcher = createReplyDispatcher({ deliver, onIdle }); diff --git a/src/browser/routes/dispatcher.abort.test.ts b/src/browser/routes/dispatcher.abort.test.ts index 42859bb26e7..642953ae55c 100644 --- a/src/browser/routes/dispatcher.abort.test.ts +++ b/src/browser/routes/dispatcher.abort.test.ts @@ -15,7 +15,10 @@ vi.mock("./index.js", () => { } const onAbort = () => reject(signal?.reason ?? new Error("aborted")); signal?.addEventListener("abort", onAbort, { once: true }); - setTimeout(resolve, 50); + queueMicrotask(() => { + signal?.removeEventListener("abort", onAbort); + resolve(); + }); }); res.json({ ok: true }); }, diff --git a/src/infra/bonjour.test.ts b/src/infra/bonjour.test.ts index 2e2b6d81d2d..382c6ed37ba 100644 --- a/src/infra/bonjour.test.ts +++ b/src/infra/bonjour.test.ts @@ -15,6 +15,14 @@ const getLoggerInfo = vi.fn(); const asString = (value: unknown, fallback: string) => typeof value === "string" && value.trim() ? value : fallback; +function enableAdvertiserUnitMode(hostname = "test-host") { + // Allow advertiser to run in unit tests. + delete process.env.VITEST; + process.env.NODE_ENV = "development"; + vi.spyOn(os, "hostname").mockReturnValue(hostname); + process.env.OPENCLAW_MDNS_HOSTNAME = hostname; +} + function mockCiaoService(params?: { advertise?: ReturnType; destroy?: ReturnType; @@ -105,19 +113,14 @@ describe("gateway bonjour advertiser", () => { }); it("does not block on advertise and publishes expected txt keys", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - - vi.spyOn(os, "hostname").mockReturnValue("test-host"); - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; + enableAdvertiserUnitMode(); const destroy = vi.fn().mockResolvedValue(undefined); + let resolveAdvertise = () => {}; const advertise = vi.fn().mockImplementation( async () => await new Promise((resolve) => { - setTimeout(resolve, 250); + resolveAdvertise = resolve; }), ); mockCiaoService({ advertise, destroy }); @@ -147,6 +150,8 @@ describe("gateway bonjour advertiser", () => { // We don't await `advertise()`, but it should still be called for each service. expect(advertise).toHaveBeenCalledTimes(1); + resolveAdvertise(); + await Promise.resolve(); await started.stop(); expect(destroy).toHaveBeenCalledTimes(1); @@ -154,11 +159,7 @@ describe("gateway bonjour advertiser", () => { }); it("omits cliPath and sshPort in minimal mode", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - - vi.spyOn(os, "hostname").mockReturnValue("test-host"); + enableAdvertiserUnitMode(); const destroy = vi.fn().mockResolvedValue(undefined); const advertise = vi.fn().mockResolvedValue(undefined); @@ -179,12 +180,7 @@ describe("gateway bonjour advertiser", () => { }); it("attaches conflict listeners for services", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - - vi.spyOn(os, "hostname").mockReturnValue("test-host"); - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; + enableAdvertiserUnitMode(); const destroy = vi.fn().mockResolvedValue(undefined); const advertise = vi.fn().mockResolvedValue(undefined); @@ -207,12 +203,7 @@ describe("gateway bonjour advertiser", () => { }); it("cleans up unhandled rejection handler after shutdown", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - - vi.spyOn(os, "hostname").mockReturnValue("test-host"); - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; + enableAdvertiserUnitMode(); const destroy = vi.fn().mockResolvedValue(undefined); const advertise = vi.fn().mockResolvedValue(undefined); @@ -240,13 +231,8 @@ describe("gateway bonjour advertiser", () => { }); it("logs advertise failures and retries via watchdog", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - + enableAdvertiserUnitMode(); vi.useFakeTimers(); - vi.spyOn(os, "hostname").mockReturnValue("test-host"); - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; const destroy = vi.fn().mockResolvedValue(undefined); const advertise = vi @@ -278,12 +264,7 @@ describe("gateway bonjour advertiser", () => { }); it("handles advertise throwing synchronously", async () => { - // Allow advertiser to run in unit tests. - delete process.env.VITEST; - process.env.NODE_ENV = "development"; - - vi.spyOn(os, "hostname").mockReturnValue("test-host"); - process.env.OPENCLAW_MDNS_HOSTNAME = "test-host"; + enableAdvertiserUnitMode(); const destroy = vi.fn().mockResolvedValue(undefined); const advertise = vi.fn(() => {