2f6a221f09
770's HTTP→read-RPC migration replaced fetch-based agent calls with rpcCall over WebSocket. setupTests.ts only mocks fetch though, so the real jsdom WebSocket runs — and jsdom's WebSocket implementation asynchronously fires its connection-failure error after ~9 seconds (via internal Timeout._onTimeout). Tests that await component-mount state (like App.test.tsx > calls getCurrentProject() on mount) hang on that pending promise and time out at 10s. This silently broke 1 test on master (App.test.tsx getCurrentProject on mount) and cascaded into 16 failures in any worktree where the test file count changed and timing shifted (804, 806). Fix: replace the global WebSocket constructor with a stub that immediately fires onerror + onclose on the next microtask. rpcCall sees the error and rejects synchronously; components catch and continue rendering with empty state. Tests pass without flake. Verified locally: vitest run → 349/349 pass.
46 lines
1.7 KiB
TypeScript
46 lines
1.7 KiB
TypeScript
import "@testing-library/jest-dom";
|
|
import { beforeEach, vi } from "vitest";
|
|
|
|
// Default WebSocket stub: every `new WebSocket(...)` immediately fires
|
|
// `onerror` + `onclose` on the next microtask. Without this, `rpcCall` from
|
|
// `./api/rpc` (added by 770's HTTP→read-RPC migration) opens a real jsdom
|
|
// WebSocket that hangs ~9s before firing its connection-failure error,
|
|
// making any test that mounts a component calling `listAgents()` time out.
|
|
// Tests that need real WS responses should override per-test with
|
|
// `vi.stubGlobal("WebSocket", ...)`.
|
|
class FailingWebSocket {
|
|
onopen: ((ev: Event) => void) | null = null;
|
|
onmessage: ((ev: MessageEvent) => void) | null = null;
|
|
onerror: ((ev: Event) => void) | null = null;
|
|
onclose: ((ev: CloseEvent) => void) | null = null;
|
|
readyState = 0;
|
|
constructor(_url: string) {
|
|
queueMicrotask(() => {
|
|
this.readyState = 3;
|
|
this.onerror?.(new Event("error"));
|
|
this.onclose?.(new CloseEvent("close"));
|
|
});
|
|
}
|
|
send(_data: string) {}
|
|
close() {}
|
|
}
|
|
vi.stubGlobal("WebSocket", FailingWebSocket);
|
|
|
|
// Provide a default fetch mock so components that call API endpoints on mount
|
|
// don't throw URL-parse errors in the jsdom test environment. Tests that need
|
|
// specific responses should mock the relevant `api.*` method as usual.
|
|
beforeEach(() => {
|
|
vi.stubGlobal(
|
|
"fetch",
|
|
vi.fn((input: string | URL | Request) => {
|
|
const url = typeof input === "string" ? input : input.toString();
|
|
// Endpoints that return arrays need [] not {} to avoid "not iterable" errors.
|
|
const arrayEndpoints = ["/agents/config"];
|
|
const body = arrayEndpoints.some((ep) => url.endsWith(ep))
|
|
? JSON.stringify([])
|
|
: JSON.stringify({});
|
|
return Promise.resolve(new Response(body, { status: 200 }));
|
|
}),
|
|
);
|
|
});
|