import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { WSClient } from "./ws-client"; // Capture URL passed to WebSocket so we can assert the connect-time // query string. We don't simulate the full WS lifecycle here — only the // upgrade URL construction, which is what carries client identity. class FakeWebSocket { static lastUrl: string | null = null; // Fields read by WSClient.connect()/disconnect(), all no-op here. onopen: (() => void) | null = null; onmessage: ((ev: { data: string }) => void) | null = null; onclose: (() => void) | null = null; onerror: (() => void) | null = null; readyState = 0; constructor(url: string) { FakeWebSocket.lastUrl = url; } close() {} send() {} } describe("WSClient", () => { beforeEach(() => { FakeWebSocket.lastUrl = null; vi.stubGlobal("WebSocket", FakeWebSocket as unknown as typeof WebSocket); }); afterEach(() => { vi.unstubAllGlobals(); }); it("includes client identity in the upgrade URL when configured", () => { const ws = new WSClient("ws://example.test/ws", { identity: { platform: "desktop", version: "1.2.3", os: "macos" }, }); ws.setAuth("tok", "acme"); ws.connect(); const url = new URL(FakeWebSocket.lastUrl!); expect(url.searchParams.get("workspace_slug")).toBe("acme"); expect(url.searchParams.get("client_platform")).toBe("desktop"); expect(url.searchParams.get("client_version")).toBe("1.2.3"); expect(url.searchParams.get("client_os")).toBe("macos"); // Token must never appear in the URL — it is delivered as the first // WS message in token mode. expect(url.searchParams.has("token")).toBe(false); }); it("omits client_* params when identity is not configured", () => { const ws = new WSClient("ws://example.test/ws"); ws.setAuth("tok", "acme"); ws.connect(); const url = new URL(FakeWebSocket.lastUrl!); expect(url.searchParams.has("client_platform")).toBe(false); expect(url.searchParams.has("client_version")).toBe(false); expect(url.searchParams.has("client_os")).toBe(false); }); it("only includes the identity fields that are set", () => { const ws = new WSClient("ws://example.test/ws", { identity: { platform: "cli" }, }); ws.setAuth("tok", "acme"); ws.connect(); const url = new URL(FakeWebSocket.lastUrl!); expect(url.searchParams.get("client_platform")).toBe("cli"); expect(url.searchParams.has("client_version")).toBe(false); expect(url.searchParams.has("client_os")).toBe(false); }); });