import { describe, it, expect } from "vitest"; import { createSocketIntentMessage, createSocketEchoMessage, isValidSocketMessage, SOCKET_EVENTS, MAX_PAYLOAD_BYTES, } from "../../../src/contracts/socket-message.js"; import { SOCKET_PAYLOADS } from "../../fixtures/socket-payloads.js"; describe("socket-message contract", () => { describe("createSocketIntentMessage()", () => { it("creates a valid intent message", () => { const msg = createSocketIntentMessage("op-1", "user-1", "hidden"); expect(msg.event).toBe(SOCKET_EVENTS.VISIBILITY_SET); const p = /** @type {any} */ (msg.payload); expect(p.opId).toBe("op-1"); expect(p.userId).toBe("user-1"); expect(p.targetState).toBe("hidden"); }); }); describe("createSocketEchoMessage()", () => { it("creates a valid echo message", () => { const msg = createSocketEchoMessage("op-1", "user-1", "hidden", 1); expect(msg.event).toBe(SOCKET_EVENTS.VISIBILITY_UPDATED); const p = /** @type {any} */ (msg.payload); expect(p.opId).toBe("op-1"); expect(p.state).toBe("hidden"); expect(p.revision).toBe(1); }); }); describe("isValidSocketMessage()", () => { it("accepts a valid intent from fixture", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.validIntent)).not.toThrow(); }); it("accepts a valid echo from fixture", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.validEcho)).not.toThrow(); }); it("throws on missing opId", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.missingOpId)).toThrow(TypeError); }); it("throws on unknown event", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.unknownEvent)).toThrow(TypeError); }); it("throws on extra payload keys (intent)", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.extraKeys)).toThrow(TypeError); }); it("throws if not an object", () => { expect(() => isValidSocketMessage(null)).toThrow(TypeError); expect(() => isValidSocketMessage("string")).toThrow(TypeError); }); it("throws on unknown top-level keys", () => { expect(() => isValidSocketMessage({ event: SOCKET_EVENTS.VISIBILITY_SET, payload: { opId: "x", userId: "y", targetState: "active" }, extra: true }) ).toThrow(TypeError); }); it("throws on empty event string", () => { expect(() => isValidSocketMessage({ event: "", payload: {} }) ).toThrow(TypeError); }); it("throws on non-finite revision in echo", () => { expect(() => isValidSocketMessage({ event: SOCKET_EVENTS.VISIBILITY_UPDATED, payload: { opId: "op-1", userId: "u-1", state: "active", revision: NaN }, }) ).toThrow(TypeError); }); it("throws on negative revision in echo", () => { expect(() => isValidSocketMessage({ event: SOCKET_EVENTS.VISIBILITY_UPDATED, payload: { opId: "op-1", userId: "u-1", state: "active", revision: -1 }, }) ).toThrow(TypeError); }); it("throws on missing revision in echo", () => { expect(() => isValidSocketMessage(SOCKET_PAYLOADS.missingRevision) ).toThrow(TypeError); }); }); describe("SOCKET_EVENTS", () => { it("is frozen", () => { expect(Object.isFrozen(SOCKET_EVENTS)).toBe(true); }); it("uses scrying-pool. prefix for all events", () => { for (const event of Object.values(SOCKET_EVENTS)) { expect(event.startsWith("scrying-pool.")).toBe(true); } }); }); describe("MAX_PAYLOAD_BYTES", () => { it("is 4096", () => { expect(MAX_PAYLOAD_BYTES).toBe(4096); }); }); });