Files
2026-07-18 20:41:22 -05:00

70 lines
3.1 KiB
JavaScript

// Test 2: hints, timer ticks, quick_join, mid-game joiner snapshot
const WebSocket = require('ws');
const URL = 'ws://localhost:3000';
class Client {
constructor(name) {
this.name = name; this.msgs = [];
this.ws = new WebSocket(URL);
this.ws.on('open', () => this.send({ t: 'hello', name, avatar: { color: 2, eyes: 2, mouth: 2, extra: 2 } }));
this.ws.on('message', (raw) => { const m = JSON.parse(raw.toString()); this.msgs.push(m); });
}
send(m) { this.ws.send(JSON.stringify(m)); }
last(t) { return [...this.msgs].reverse().find(m => m.t === t); }
all(t) { return this.msgs.filter(m => m.t === t); }
close() { this.ws.close(); }
}
const wait = (ms) => new Promise(r => setTimeout(r, ms));
async function waitFor(fn, what, timeout = 20000) {
const t0 = Date.now();
while (Date.now() - t0 < timeout) { const v = fn(); if (v) return v; await wait(50); }
throw new Error('timeout: ' + what);
}
(async () => {
const a = new Client('P1');
await waitFor(() => a.last('welcome'), 'welcome');
a.send({ t: 'quick_join' });
const ja = await waitFor(() => a.last('joined'), 'joined a');
console.log('✔ quick_join created/joined public room:', ja.room.code, '| public:', ja.room.settings.isPublic);
const b = new Client('P2');
await waitFor(() => b.last('welcome'), 'welcome b');
b.send({ t: 'quick_join' });
const jb = await waitFor(() => b.last('joined'), 'joined b');
console.log('✔ second quick_join landed in same room:', jb.room.code === ja.room.code);
// public list shows it
b.send({ t: 'list_rooms' });
await waitFor(() => b.last('room_list'), 'room_list');
const listed = b.last('room_list').rooms.find(r => r.code === ja.room.code);
console.log('✔ public room listed:', !!listed, `(${listed.players}/${listed.maxPlayers})`);
a.send({ t: 'set_settings', settings: { drawTime: 30, rounds: 2 } });
await wait(200);
a.send({ t: 'start_game' });
const cw = await waitFor(() => a.last('choose_words'), 'choose_words');
a.send({ t: 'pick_word', word: cw.words[0] });
const ds = await waitFor(() => b.last('draw_start'), 'draw_start');
console.log('✔ word:', cw.words[0], '| initial mask:', ds.mask);
// mid-game joiner gets snapshot with ops + mask
const c = new Client('P3');
await waitFor(() => c.last('welcome'), 'welcome c');
c.send({ t: 'join_room', code: ja.room.code });
const jc = await waitFor(() => c.last('joined'), 'joined c');
console.log('✔ mid-game join snapshot: phase:', jc.room.phase, '| mask:', jc.room.mask === ds.mask, '| timeLeft>0:', jc.room.timeLeft > 0);
// timer broadcasts
await waitFor(() => c.all('timer').length >= 3, 'timer ticks', 6000);
console.log('✔ timer broadcasts ticking:', c.all('timer').slice(-1)[0].timeLeft <= 30);
// hint at ~45% of 30s = ~13.5s
const hint = await waitFor(() => b.last('hint'), 'hint', 20000);
console.log('✔ hint revealed:', hint.mask, '| differs from start:', hint.mask !== ds.mask);
a.close(); b.close(); c.close();
console.log('\nTEST 2 DONE');
process.exit(0);
})().catch(e => { console.error('TEST 2 FAILED:', e.message); process.exit(1); });