69 lines
2.9 KiB
JavaScript
69 lines
2.9 KiB
JavaScript
/* Дымовой тест M1: сервер должен быть запущен с DEV_HTTP=1, SQLITE_PATH=:memory:.
|
|
`pnpm --filter @idle/server smoke` */
|
|
import WebSocket from 'ws';
|
|
|
|
const BASE = 'http://localhost:3000';
|
|
const WS = 'ws://localhost:3000/ws';
|
|
|
|
function connect(onMsg) {
|
|
const ws = new WebSocket(WS);
|
|
ws.on('open', () => ws.send(JSON.stringify({ t: 'hello', v: 2 })));
|
|
ws.on('message', (d) => onMsg(JSON.parse(String(d))));
|
|
return ws;
|
|
}
|
|
|
|
// 1. welcome + полный снапшот
|
|
const first = [];
|
|
await new Promise((resolve, reject) => {
|
|
const ws = connect((m) => {
|
|
first.push(m);
|
|
if (first.length >= 2) {
|
|
ws.close();
|
|
resolve();
|
|
}
|
|
});
|
|
ws.on('error', reject);
|
|
setTimeout(() => reject(new Error('timeout waiting welcome+snapshot')), 5000);
|
|
});
|
|
const [welcome, snap] = first;
|
|
console.log('welcome:', JSON.stringify({ t: welcome.t, v: welcome.v, tickMs: welcome.tickMs }));
|
|
if (welcome.t !== 'welcome' || welcome.v !== 2) throw new Error(`bad welcome: ${JSON.stringify(welcome)}`);
|
|
if (snap.t !== 'snapshot' || snap.nodes.length !== 7) throw new Error(`bad snapshot: ${snap.t}, nodes=${snap.nodes?.length}`);
|
|
console.log(`snapshot: деревьев=${snap.nodes.length}, зрителей=${snap.avatars.length}`);
|
|
|
|
// 2. команда через dev-эндпоинт
|
|
const res = await fetch(`${BASE}/dev/command`, {
|
|
method: 'POST',
|
|
headers: { 'content-type': 'application/json' },
|
|
body: JSON.stringify({ name: 'Тестер', text: '!рубить' }),
|
|
});
|
|
if (!res.ok) throw new Error(`dev command failed: ${res.status} ${await res.text()}`);
|
|
console.log('dev command: accepted');
|
|
|
|
// 3. ждём дельту: аватар «Тестер» должен заспавниться и пойти к дереву
|
|
const delta = await new Promise((resolve, reject) => {
|
|
const ws = connect((m) => {
|
|
if (m.t === 'delta' && m.avatars?.some((a) => a.name === 'Тестер')) {
|
|
ws.close();
|
|
resolve(m);
|
|
}
|
|
});
|
|
ws.on('error', reject);
|
|
setTimeout(() => reject(new Error('no delta with Тестер')), 8000);
|
|
});
|
|
const tester = delta.avatars.find((a) => a.name === 'Тестер');
|
|
console.log(`delta: ${tester.name} moving=${tester.moving} action=${tester.action} target=(${tester.tx},${tester.ty})`);
|
|
console.log(`events: ${(delta.events ?? []).map((e) => e.k).join(',') || '—'}`);
|
|
if (!tester.moving || tester.action !== 'idle') throw new Error('Тестер должен идти к дереву (idle + moving)');
|
|
|
|
// 4. неверная версия протокола — close 4001
|
|
const closeCode = await new Promise((resolve) => {
|
|
const ws = new WebSocket(WS);
|
|
ws.on('open', () => ws.send(JSON.stringify({ t: 'hello', v: 999 })));
|
|
ws.on('close', (code) => resolve(code));
|
|
setTimeout(() => resolve('no-close'), 3000);
|
|
});
|
|
if (closeCode !== 4001) throw new Error(`expected close 4001, got ${closeCode}`);
|
|
|
|
console.log('WS smoke: OK');
|