curltastic/e2e/e2e_end_score.cjs
Jason Dekarske b06a78227f test(e2e): multi-client throws and collision multi-path QA
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-07-10 23:16:07 -07:00

68 lines
2.2 KiB
JavaScript

const WebSocket = require('ws')
const base = (room) => `ws://127.0.0.1:3000/ws?room=${room}`
function connect(name, room) {
return new Promise((resolve, reject) => {
const ws = new WebSocket(base(room))
const messages = []
ws.on('message', (data) => {
const msg = JSON.parse(data.toString())
messages.push(msg)
if (msg.type === 'joined') resolve({ ws, messages })
})
ws.on('error', reject)
})
}
function waitFor(messages, pred, timeout = 30000) {
const start = Date.now()
return new Promise((resolve, reject) => {
const check = () => {
if (pred()) return resolve(undefined)
if (Date.now() - start > timeout) return reject(new Error('timeout'))
setTimeout(check, 50)
}
check()
})
}
;(async () => {
const room = 'ENDQA' + Math.floor(Math.random() * 1000)
const p1 = await connect('p1', room)
const p2 = await connect('p2', room)
await waitFor(p1.messages, () => p1.messages.some(m => m.type === 'game_state'), 5000)
const getTurn = () => {
const st = p1.messages.slice(-1)[0]
return st && st.type === 'game_state' ? st.turn_team : null
}
let stateCount = p1.messages.filter(m => m.type === 'game_state').length
for (let i = 0; i < 16; i++) {
await waitFor(p1.messages, () => {
const last = p1.messages.slice(-1)[0]
return last && last.type === 'game_state' && last.phase === 'playing'
}, 5000)
const turn = getTurn()
if (!turn) throw new Error('no turn')
const broomX = (Math.random() - 0.5) * 0.6
p1.ws.send(JSON.stringify({ type: 'throw', team: turn, broom_x: broomX, broom_y: 38.7, weight: 9, curl: 1, friction: 1.0 }))
const prevStateCount = p1.messages.filter(m => m.type === 'game_state').length
await waitFor(p1.messages, () => p1.messages.filter(m => m.type === 'game_state').length > prevStateCount, 15000)
}
await waitFor(p1.messages, () => p1.messages.some(m => m.type === 'end_scored'), 20000)
const final = p1.messages.slice(-1)[0]
console.log('Final game_state:', final)
if (final.end <= 1) throw new Error('end did not advance')
console.log('End scored event received; end advanced to', final.end)
p1.ws.close()
p2.ws.close()
process.exit(0)
})().catch((e) => {
console.error(e)
process.exit(1)
})