import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";import { getWsConnectionStatus, getWsReconnectDelayMsForRetry, getWsConnectionUiState, recordWsConnectionAttempt, recordWsConnectionClosed, recordWsConnectionErrored, recordWsConnectionOpened, resetWsConnectionStateForTests, setBrowserOnlineStatus, WS_RECONNECT_MAX_ATTEMPTS,} from "./wsConnectionState";describe("wsConnectionState", () => { beforeEach(() => { vi.useFakeTimers(); vi.setSystemTime(new Date("2026-04-03T20:30:00.000Z")); resetWsConnectionStateForTests(); }); afterEach(() => { vi.useRealTimers(); }); it("treats a disconnected browser as offline once the websocket drops", () => { recordWsConnectionAttempt("ws://localhost:3020/ws"); recordWsConnectionOpened(); recordWsConnectionClosed({ code: 1006, reason: "offline" }); setBrowserOnlineStatus(false); expect(getWsConnectionUiState(getWsConnectionStatus())).toBe("offline"); }); it("stays in the initial connecting state until the first disconnect", () => { recordWsConnectionAttempt("ws://localhost:3020/ws"); expect(getWsConnectionStatus()).toMatchObject({ attemptCount: 1, hasConnected: false, phase: "connecting", }); expect(getWsConnectionUiState(getWsConnectionStatus())).toBe("connecting"); }); it("schedules the next retry after a failed websocket attempt", () => { recordWsConnectionAttempt("ws://localhost:3020/ws"); recordWsConnectionErrored("Unable to connect to the T3 server WebSocket."); const firstRetryDelayMs = getWsReconnectDelayMsForRetry(0); if (firstRetryDelayMs === null) { throw new Error("Expected an initial retry delay."); } expect(getWsConnectionStatus()).toMatchObject({ nextRetryAt: new Date(Date.now() + firstRetryDelayMs).toISOString(), reconnectAttemptCount: 1, reconnectPhase: "waiting", }); }); it("marks the reconnect cycle as exhausted after the final attempt fails", () => { for (let attempt = 0; attempt < WS_RECONNECT_MAX_ATTEMPTS; attempt += 1) { recordWsConnectionAttempt("ws://localhost:3020/ws"); recordWsConnectionErrored("Unable to connect to the T3 server WebSocket."); } expect(getWsConnectionStatus()).toMatchObject({ nextRetryAt: null, reconnectAttemptCount: WS_RECONNECT_MAX_ATTEMPTS, reconnectPhase: "exhausted", }); });});
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import {
getWsConnectionStatus,
getWsReconnectDelayMsForRetry,
getWsConnectionUiState,
recordWsConnectionAttempt,
recordWsConnectionClosed,
recordWsConnectionErrored,
recordWsConnectionOpened,
resetWsConnectionStateForTests,
setBrowserOnlineStatus,
WS_RECONNECT_MAX_ATTEMPTS,
} from "./wsConnectionState";
describe("wsConnectionState", () => {
beforeEach(() => {
vi.useFakeTimers();
vi.setSystemTime(new Date("2026-04-03T20:30:00.000Z"));
resetWsConnectionStateForTests();
});
afterEach(() => {
vi.useRealTimers();
});
it("treats a disconnected browser as offline once the websocket drops", () => {
recordWsConnectionAttempt("ws://localhost:3020/ws");
recordWsConnectionOpened();
recordWsConnectionClosed({ code: 1006, reason: "offline" });
setBrowserOnlineStatus(false);
expect(getWsConnectionUiState(getWsConnectionStatus())).toBe("offline");
});
it("stays in the initial connecting state until the first disconnect", () => {
recordWsConnectionAttempt("ws://localhost:3020/ws");
expect(getWsConnectionStatus()).toMatchObject({
attemptCount: 1,
hasConnected: false,
phase: "connecting",
});
expect(getWsConnectionUiState(getWsConnectionStatus())).toBe("connecting");
});
it("schedules the next retry after a failed websocket attempt", () => {
recordWsConnectionAttempt("ws://localhost:3020/ws");
recordWsConnectionErrored("Unable to connect to the T3 server WebSocket.");
const firstRetryDelayMs = getWsReconnectDelayMsForRetry(0);
if (firstRetryDelayMs === null) {
throw new Error("Expected an initial retry delay.");
}
expect(getWsConnectionStatus()).toMatchObject({
nextRetryAt: new Date(Date.now() + firstRetryDelayMs).toISOString(),
reconnectAttemptCount: 1,
reconnectPhase: "waiting",
});
});
it("marks the reconnect cycle as exhausted after the final attempt fails", () => {
for (let attempt = 0; attempt < WS_RECONNECT_MAX_ATTEMPTS; attempt += 1) {
recordWsConnectionAttempt("ws://localhost:3020/ws");
recordWsConnectionErrored("Unable to connect to the T3 server WebSocket.");
}
expect(getWsConnectionStatus()).toMatchObject({
nextRetryAt: null,
reconnectAttemptCount: WS_RECONNECT_MAX_ATTEMPTS,
reconnectPhase: "exhausted",
});
});
});