From 3a2e908fdd1ba98bafa378c1994faa5936f41c86 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 11 May 2026 01:13:25 +0100 Subject: [PATCH] test: tighten whatsapp reconnect assertions --- ...o-reply.connection-and-logging.e2e.test.ts | 62 ++++++++++++------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/extensions/whatsapp/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts b/extensions/whatsapp/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts index fb836674ecda..057e7a5a6dc3 100644 --- a/extensions/whatsapp/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts +++ b/extensions/whatsapp/src/auto-reply.web-auto-reply.connection-and-logging.e2e.test.ts @@ -78,6 +78,29 @@ async function startWatchdogScenario(params: { return { scripted, sleep, spies, ...started }; } +function expectErrorContaining(errorFn: unknown, text: string): void { + const messages = ((errorFn as { mock?: { calls?: unknown[][] } }).mock?.calls ?? []).map((call) => + typeof call[0] === "string" ? call[0] : call[0] instanceof Error ? call[0].message : "", + ); + expect(messages.some((message) => message.includes(text))).toBe(true); +} + +function mockCallArg(mocked: unknown, callIndex: number, argIndex: number): unknown { + const calls = (mocked as { mock?: { calls?: unknown[][] } }).mock?.calls; + expect(calls?.[callIndex]).toBeDefined(); + return calls?.[callIndex]?.[argIndex]; +} + +async function expectPathMissing(targetPath: string): Promise { + try { + await fs.stat(targetPath); + } catch (error) { + expect((error as { code?: unknown }).code).toBe("ENOENT"); + return; + } + throw new Error(`Expected path to be missing: ${targetPath}`); +} + describe("web auto-reply connection", () => { installWebAutoReplyUnitTestHooks(); @@ -140,7 +163,7 @@ describe("web auto-reply connection", () => { await run; } - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining(scenario.expectedError)); + expectErrorContaining(runtime.error, scenario.expectedError); } }); @@ -186,9 +209,9 @@ describe("web auto-reply connection", () => { expect(completedQuickly).toBe(true); expect(scripted.getListenerCount()).toBe(1); expect(sleep).not.toHaveBeenCalled(); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("status 440")); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("session conflict")); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Stopping web monitoring")); + expectErrorContaining(runtime.error, "status 440"); + expectErrorContaining(runtime.error, "session conflict"); + expectErrorContaining(runtime.error, "Stopping web monitoring"); }); it.each([ @@ -260,20 +283,14 @@ describe("web auto-reply connection", () => { expect(scripted.getListenerCount()).toBe(1); expect(sleep).not.toHaveBeenCalled(); expect(getActiveWebListener(accountId)).toBeNull(); - await expect(fs.stat(authDir)).rejects.toMatchObject({ code: "ENOENT" }); - expect(statuses).toContainEqual( - expect.objectContaining({ - connected: false, - healthState, - }), - ); - expect(statuses.at(-1)).toEqual( - expect.objectContaining({ - running: false, - connected: false, - healthState, - }), - ); + await expectPathMissing(authDir); + expect( + statuses.some((entry) => entry.connected === false && entry.healthState === healthState), + ).toBe(true); + const finalStatus = statuses.at(-1); + expect(finalStatus?.running).toBe(false); + expect(finalStatus?.connected).toBe(false); + expect(finalStatus?.healthState).toBe(healthState); }, ); @@ -304,8 +321,9 @@ describe("web auto-reply connection", () => { controller.abort(); await run; - expect(sleep).toHaveBeenCalledWith(expect.any(Number), expect.any(AbortSignal)); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("inbox attach")); + expect(typeof mockCallArg(sleep, 0, 0)).toBe("number"); + expect(mockCallArg(sleep, 0, 1)).toBeInstanceOf(AbortSignal); + expectErrorContaining(runtime.error, "inbox attach"); }); it("stops retrying inbox attach when auth stays unstable past max attempts", async () => { @@ -326,8 +344,8 @@ describe("web auto-reply connection", () => { expect(listenerFactory).toHaveBeenCalledTimes(2); expect(sleep).toHaveBeenCalledTimes(1); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Retry 1/2")); - expect(runtime.error).toHaveBeenCalledWith(expect.stringContaining("Stopping web monitoring")); + expectErrorContaining(runtime.error, "Retry 1/2"); + expectErrorContaining(runtime.error, "Stopping web monitoring"); }); it("forces reconnect when watchdog closes without onClose", async () => {