import { test, expect } from 'bun:test'; import { createDirectRelay } from './direct-relay.js'; test('room membership, receiver acceptance and one-use invitation bind signalling', () => { let clock = 0; const relay = createDirectRelay({ now: () => clock }); const peers = new Map([['host', 'hostSocket'], ['guest', 'guestSocket'], ['other', 'otherSocket']]); const out = []; const send = (ws, m) => out.push({ ws, m }); const invite = { type: 'direct', action: 'invite', to: 'guest', file: { id: 'song', title: 'Song', cid: 'a'.repeat(64), size: 123 } }; expect(relay.handle('outsider', invite, peers, send)).toBe(false); expect(relay.handle('host', { ...invite, to: 'outsider' }, peers, send)).toBe(false); expect(relay.handle('host', invite, peers, send)).toBe(true); const token = out[0].m.token; const signal = { type: 'direct', action: 'signal', token, data: { kind: 'offer', sdp: 'valid' } }; expect(relay.handle('host', signal, peers, send)).toBe(false); expect(relay.handle('other', { type: 'direct', action: 'accept', token }, peers, send)).toBe(false); expect(relay.handle('guest', { type: 'direct', action: 'accept', token }, peers, send)).toBe(true); expect(relay.handle('guest', { type: 'direct', action: 'accept', token }, peers, send)).toBe(false); expect(relay.handle('other', signal, peers, send)).toBe(false); expect(relay.handle('host', signal, peers, send)).toBe(true); relay.handle('guest', { type: 'direct', action: 'complete', token }, peers, send); expect(relay.handle('host', signal, peers, send)).toBe(false); relay.handle('host', invite, peers, send); clock = 61000; expect(relay.handle('guest', { type: 'direct', action: 'accept', token: out.at(-1).m.token }, peers, send)).toBe(false); });