import { expect, it } from "bun:test"; import { Type } from "@sinclair/typebox"; import type { ConnectionOptions, WebSocketConnection, } from "@noya-app/noya-multiplayer-react"; import { jwt } from "../../jwt"; import type { ClientToServerMessage } from "../../multiplayer"; import { NoyaManager } from "../../NoyaManager"; import { webSocketSync } from "../webSocketSync"; type TestState = { count: number; }; class MockWebSocketConnection { public sent: ClientToServerMessage[] = []; constructor( public url: URL, private options?: ConnectionOptions ) {} connect() { this.options?.onConnectionEvent?.({ type: "stateChange", state: "OPEN", }); } send(message: ClientToServerMessage) { this.sent.push(message); this.options?.onConnectionEvent?.({ type: "send", message, }); } close() { this.options?.onConnectionEvent?.({ type: "stateChange", state: "CLOSED", }); } } function createToken(payload: Record) { return jwt.encode({ payload, secret: "test-secret", }); } it("sends enqueueInput messages through the websocket adapter", async () => { const schema = Type.Object({ count: Type.Number({ default: 0 }), }); const noyaManager = new NoyaManager(() => ({ count: 0 }), { schema, }); const tokenPayload = { connectionId: "connection-test", fileId: "file-id", access: "write" as const, baseUrl: "https://api.example.com", }; const token = await createToken(tokenPayload); const connections: MockWebSocketConnection[] = []; const adapter = webSocketSync( async () => { const url = new URL("https://sync.example.com"); url.searchParams.set("token", token); return url; }, { createWebSocketConnection: (url, options) => { const connection = new MockWebSocketConnection( url, options ); connections.push(connection); return connection as unknown as WebSocketConnection; }, } ); const destroy = adapter({ noyaManager }); const waitForConnection = async () => { for (let i = 0; i < 10; i += 1) { if (connections[0]) return; await new Promise((resolve) => setTimeout(resolve, 0)); } throw new Error("Connection was never created"); }; await waitForConnection(); const connection = connections[0]; connection.connect(); noyaManager.enqueueInput("controller", { delta: 2 }); await Promise.resolve(); expect(connection.sent.at(-1)).toEqual({ type: "enqueueInput", connectionId: tokenPayload.connectionId, queue: "controller", payload: { delta: 2 }, }); destroy(); });