bend_puzzle/test/realtime-lease-unit-test.js

33 lines
2.4 KiB
JavaScript
Raw Normal View History

2026-07-30 15:13:53 +09:00
'use strict';
const http=require('http');
const assert=require('assert/strict');
const {createRealtimeHub}=require('../realtime-server');
const {connectRealtime}=require('./helpers/realtime-client');
(async()=>{
const server=http.createServer((_req,res)=>{res.writeHead(404);res.end()});
const identities=new Map([
['alice',{playerId:'alice',token:'a',name:'Alice'}],
['bob',{playerId:'bob',token:'b',name:'Bob'}]
]);
const hub=createRealtimeHub({
server,claimTtlMs:120,
authenticate:async({playerId,token})=>{const identity=identities.get(playerId);if(!identity||identity.token!==token)throw new Error('bad auth');return identity},
getBoardInfo:async boardId=>boardId==='B0'?{solved:false,bounds:{minX:0,minY:0,maxX:1,maxY:1}}:null
});
await new Promise(resolve=>server.listen(0,'127.0.0.1',resolve));
const base=`http://127.0.0.1:${server.address().port}`;
let alice=null,bob=null;
try{
alice=await connectRealtime(base,{playerId:'alice',token:'a'});bob=await connectRealtime(base,{playerId:'bob',token:'b'});
alice.send({type:'viewport',minX:-2,minY:-2,maxX:2,maxY:2});bob.send({type:'viewport',minX:-2,minY:-2,maxX:2,maxY:2});await alice.waitFor('snapshot');await bob.waitFor('snapshot');
alice.send({type:'claim',requestId:'lease-a',boardId:'B0'});assert.equal((await alice.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-a')).ok,true);await bob.waitFor(message=>message.type==='claim'&&message.claim?.boardId==='B0');
alice.close();alice=null;
bob.send({type:'claim',requestId:'lease-b-early',boardId:'B0'});const early=await bob.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-b-early');assert.equal(early.ok,false);assert.equal(early.reason,'occupied');
await new Promise(resolve=>setTimeout(resolve,170));bob.send({type:'snapshot-request'});await bob.waitFor(message=>message.type==='claim-release'&&message.boardId==='B0'&&message.reason==='expired');
bob.send({type:'claim',requestId:'lease-b-late',boardId:'B0'});const late=await bob.waitFor(message=>message.type==='claim-result'&&message.requestId==='lease-b-late');assert.equal(late.ok,true);
console.log('Realtime lease expiry and disconnect semantics passed');
}finally{
alice?.close();bob?.close();hub.close();await new Promise(resolve=>server.close(resolve));
}
})().catch(error=>{console.error(error);process.exitCode=1});