import fs from 'node:fs'; import { afterAll, describe, expect, test } from 'vitest'; import { WebSocket } from 'ws'; import { createApp, type GibbzApp } from '../src/server/index.ts'; import { IceConfigProvider } from '../src/server/ice.ts'; let app: GibbzApp | undefined; let port = 0; async function startTestApp(): Promise { if (!app) { app = createApp(); await app.http.start(0, '127.0.0.1'); port = app.http.address()!.port; } return port; } afterAll(async () => { await app?.stop(); }); describe('server', () => { test('static client files exist', () => { expect(fs.existsSync('src/client/index.html'), 'index.html exists').toBe(true); expect(fs.existsSync('src/client/main.ts'), 'main.ts exists').toBe(true); expect(fs.existsSync('src/client/style.css'), 'style.css exists').toBe(true); }); test('/healthz answers ok', async () => { const p = await startTestApp(); const res = await fetch(`http://127.0.0.1:${p}/healthz`); expect(res.status).toBe(200); expect(await res.text()).toBe('ok'); }); test('/api/ice returns cluster stun/turn', async () => { const p = await startTestApp(); const res = await fetch(`http://127.0.0.1:${p}/api/ice`); expect(res.status).toBe(200); const ice = await res.json(); expect(Array.isArray(ice.iceServers)).toBe(true); const stunUrls = ice.iceServers.flatMap((s: { urls: string | string[] }) => Array.isArray(s.urls) ? s.urls : [s.urls], ); expect(stunUrls.some((u: string) => u.includes('turn.k6n.net'))).toBe(true); }); test('/api/rooms starts empty and reflects a connected peer', async () => { const p = await startTestApp(); const empty = await (await fetch(`http://127.0.0.1:${p}/api/rooms`)).json(); expect(empty).toEqual({}); const ws = new WebSocket(`ws://127.0.0.1:${p}/ws?room=testroom&name=tester`); const hello = await new Promise<{ id: string; room: string; type: string }>((resolve, reject) => { ws.on('message', (raw) => { const msg = JSON.parse(raw.toString()); if (msg.type === 'hello') resolve(msg); }); ws.on('error', reject); }); expect(hello.type).toBe('hello'); expect(hello.room).toBe('testroom'); expect(hello.id).toBeTruthy(); const res = await fetch(`http://127.0.0.1:${p}/api/rooms`); const rooms = await res.json(); expect(rooms.testroom).toBeTruthy(); expect(rooms.testroom).toHaveLength(1); expect(rooms.testroom[0].name).toBe('tester'); ws.close(); }); test('TURN secret generates ephemeral HMAC credentials', () => { const provider = new IceConfigProvider({ TURN_SECRET: 'secret123' }); const config = provider.get(); const turnServer = config.iceServers.find((s) => (Array.isArray(s.urls) ? s.urls : [s.urls]).some((u) => u.startsWith('turn')), ); expect(turnServer).toBeTruthy(); expect(turnServer!.username!.endsWith(':gibbz')).toBe(true); expect(turnServer!.credential!.length).toBeGreaterThan(0); }); test('ICE transport policy is passed through', () => { const provider = new IceConfigProvider({ ICE_TRANSPORT_POLICY: 'relay' }); expect(provider.get().iceTransportPolicy).toBe('relay'); }); });