/// import { assertEquals } from "jsr:@std/assert"; const url = "ws://0.0.0.0:6969"; function connect(url: string): Promise { return new Promise((resolve, reject) => { const socket = new WebSocket(url); socket.onopen = () => resolve(socket); socket.onerror = (e) => reject(e); }); } function nextMessage(socket: WebSocket): Promise { return new Promise((resolve, reject) => { const onMessage = (e: MessageEvent) => { socket.removeEventListener("message", onMessage); try { resolve(JSON.parse(e.data)); } catch { resolve(e.data); } }; socket.addEventListener("message", onMessage); socket.addEventListener("error", reject, { once: true }); }); } function close(socket: WebSocket): Promise { return new Promise((resolve) => { if (socket.readyState === WebSocket.CLOSED) { return resolve(); } socket.onclose = () => resolve(); socket.close(); }); } Deno.test("broadcasts a message on connect to all clients", async () => { const s1 = await connect(url); const s2 = await connect(url); assertEquals(await nextMessage(s1), "2 has joined!"); const s3 = connect(url); Promise.all([nextMessage(s1), nextMessage(s2)]).then((messages) => { messages.forEach((message) => { assertEquals(message, "3 has joined!"); }); }); await close(s1); await close(s2); await close(await s3); }); Deno.test("removes a client from broadcast after it disconnects", async () => { const s4 = await connect(url); const s5 = await connect(url); const s6 = await connect(url); await close(s5); Promise.all([nextMessage(s4), nextMessage(s6)]).then((messages) => { messages.forEach((message) => { assertEquals(message, "5 has left!"); }); }); await close(s4); await close(s6); });