Initial Commit
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import {
|
||||
afterAll,
|
||||
beforeAll,
|
||||
describe,
|
||||
expect,
|
||||
it,
|
||||
} from "@suaveplan/testing/runner";
|
||||
import { WebSocket as WsClient } from "ws";
|
||||
import { WebSocketGateway } from "../src/gateway/gateway.js";
|
||||
import { makeRealWsServerFactory } from "./setup/real-ws-adapter.js";
|
||||
|
||||
function baseUrl(address: string, port: number): string {
|
||||
const host =
|
||||
address === "::" || address === "0.0.0.0" ? "127.0.0.1" : address;
|
||||
return `http://${host}:${port}`;
|
||||
}
|
||||
|
||||
function wsUrl(address: string, port: number): string {
|
||||
const host =
|
||||
address === "::" || address === "0.0.0.0" ? "127.0.0.1" : address;
|
||||
return `ws://${host}:${port}`;
|
||||
}
|
||||
|
||||
let gateway: WebSocketGateway;
|
||||
let address = "";
|
||||
let port = 0;
|
||||
|
||||
beforeAll(async () => {
|
||||
let snap: () => ReturnType<WebSocketGateway["snapshot"]> = () => ({
|
||||
running: false,
|
||||
disposed: false,
|
||||
clientCount: 0,
|
||||
roomCount: 0,
|
||||
startedAt: undefined,
|
||||
});
|
||||
const factory = makeRealWsServerFactory(() => snap());
|
||||
gateway = new WebSocketGateway({
|
||||
port: 0,
|
||||
host: "127.0.0.1",
|
||||
wsServerFactory: factory,
|
||||
heartbeatIntervalMs: 60_000,
|
||||
});
|
||||
snap = () => gateway.snapshot();
|
||||
const result = await gateway.start();
|
||||
address = result.address;
|
||||
port = result.port;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await gateway?.stop();
|
||||
});
|
||||
|
||||
describe("integration: real ws server boot + health probes", () => {
|
||||
it("/health returns 200 ok while running", {
|
||||
timeout: 10_000,
|
||||
}, async () => {
|
||||
const res = await fetch(`${baseUrl(address, port)}/health`);
|
||||
expect(res.status).toBe(200);
|
||||
const body = (await res.json()) as { status: string; running: boolean };
|
||||
expect(body.status).toBe("ok");
|
||||
expect(body.running).toBe(true);
|
||||
});
|
||||
|
||||
it("/ready returns 200 once started", { timeout: 10_000 }, async () => {
|
||||
const res = await fetch(`${baseUrl(address, port)}/ready`);
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
|
||||
it("/live returns 200", { timeout: 10_000 }, async () => {
|
||||
const res = await fetch(`${baseUrl(address, port)}/live`);
|
||||
expect(res.status).toBe(200);
|
||||
});
|
||||
});
|
||||
|
||||
describe("integration: 3 real ws clients connect, join a room, broadcast", () => {
|
||||
it("all 3 clients receive broadcasts to a shared room", {
|
||||
timeout: 15_000,
|
||||
}, async () => {
|
||||
// Open 3 real WebSocket connections to the gateway.
|
||||
const c1 = new WsClient(wsUrl(address, port));
|
||||
const c2 = new WsClient(wsUrl(address, port));
|
||||
const c3 = new WsClient(wsUrl(address, port));
|
||||
const all = [c1, c2, c3];
|
||||
await Promise.all(
|
||||
all.map(
|
||||
(c) =>
|
||||
new Promise<void>((resolve, reject) => {
|
||||
c.once("open", () => resolve());
|
||||
c.once("error", reject);
|
||||
})
|
||||
)
|
||||
);
|
||||
// Wait a tick for the daemon to register all three sockets.
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
const ids = Array.from(
|
||||
{ length: 3 },
|
||||
(_, i) => `wsc-${i + 1}` as const
|
||||
);
|
||||
expect(gateway.clientCount).toBe(3);
|
||||
// Create the room and join all three clients to it.
|
||||
gateway.createRoom({ id: "shared", maxClients: 10 });
|
||||
for (const id of ids) {
|
||||
const joined = await gateway.joinRoom("shared", id);
|
||||
expect(joined).toBe(true);
|
||||
}
|
||||
expect(gateway.getRoom("shared")?.size).toBe(3);
|
||||
// Broadcast from id-1; the room returns ids of (id-2, id-3).
|
||||
const result = await gateway.broadcastToRoom("shared", ids[0]!, {
|
||||
text: "hello",
|
||||
});
|
||||
expect(result?.recipients.sort()).toEqual([ids[1]!, ids[2]!]);
|
||||
expect(result?.message.payload).toEqual({ text: "hello" });
|
||||
for (const c of all) c.close();
|
||||
await new Promise((r) => setTimeout(r, 50));
|
||||
expect(gateway.clientCount).toBe(0);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user