From 4bdccddc08047f6c54907ba7a1a10dc9a1b2b510 Mon Sep 17 00:00:00 2001 From: Owen McGirr Date: Sat, 3 Oct 2026 08:51:40 +0100 Subject: [PATCH 1/2] Make the cancelled pairing request test independent of timing The setup guide is revealed in the same render that removes the pairing dialog, so wait for both in one assertion with a longer timeout instead of a separate default one-second wait that could expire on slow CI. Closes #947 Co-Authored-By: Claude Opus 5.5 (1M context) --- src/App.test.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/App.test.tsx b/src/App.test.tsx index 4fb9b1c9..b42fc36c 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -499,8 +499,11 @@ describe("Switchify PC shell", () => { lastActivity: { kind: "info", message: "Pairing request cancelled." }, })); - await waitFor(() => expect(screen.queryByLabelText("Verification code for Galaxy")).not.toBeInTheDocument()); - expect(await screen.findByRole("dialog", { name: "Input access" })).toBeInTheDocument(); + // The setup guide is revealed in the same render that removes the pairing dialog; allow slow CI runners to reach it. + await waitFor(() => { + expect(screen.queryByLabelText("Verification code for Galaxy")).not.toBeInTheDocument(); + expect(screen.getByRole("dialog", { name: "Input access" })).toBeInTheDocument(); + }, { timeout: 4000 }); }); it("creates a profile and records a desired key", async () => { From 6b3c0d811a61c609ff31fc663c6ad678468aad4d Mon Sep 17 00:00:00 2001 From: Owen McGirr Date: Sat, 3 Oct 2026 08:55:18 +0100 Subject: [PATCH 2/2] Settle the setup-shown response before cancelling the pairing The flake came from the auto-open markSetupShown response, which still carried the pending pairing, landing after the cancellation event and restoring the pairing dialog. Wait for that response first and keep the fallback state consistent with the cancellation event. Co-Authored-By: Claude Opus 5.5 (1M context) --- src/App.test.tsx | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/App.test.tsx b/src/App.test.tsx index b42fc36c..56152c8a 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -487,23 +487,22 @@ describe("Switchify PC shell", () => { stateHandler = handler; return () => undefined; }); + const markShown = vi.spyOn(api, "markSetupShown"); render(); await screen.findByRole("dialog", { name: "Pairing requests" }); expect(screen.queryByRole("dialog", { name: "Input access" })).not.toBeInTheDocument(); expect(screen.getByLabelText("Verification code for Galaxy")).toHaveTextContent("063781"); + // Let the auto-open state response settle first, so it cannot land after the cancellation and restore the pairing. + await waitFor(() => expect(markShown).toHaveBeenCalled()); + await act(() => markShown.mock.results[0].value); - act(() => stateHandler?.({ - ...structuredClone(browserState), - pendingPairings: [], - lastActivity: { kind: "info", message: "Pairing request cancelled." }, - })); + browserState.pendingPairings = []; + browserState.lastActivity = { kind: "info", message: "Pairing request cancelled." }; + act(() => stateHandler?.(structuredClone(browserState))); - // The setup guide is revealed in the same render that removes the pairing dialog; allow slow CI runners to reach it. - await waitFor(() => { - expect(screen.queryByLabelText("Verification code for Galaxy")).not.toBeInTheDocument(); - expect(screen.getByRole("dialog", { name: "Input access" })).toBeInTheDocument(); - }, { timeout: 4000 }); + expect(await screen.findByRole("dialog", { name: "Input access" })).toBeInTheDocument(); + expect(screen.queryByLabelText("Verification code for Galaxy")).not.toBeInTheDocument(); }); it("creates a profile and records a desired key", async () => {