Files
joywayer 35216f75e7 feat: integrate room framework and isolated subgame bundles
Complete room UI and protocol integration, move game definitions and resources behind bundle entries, publish authoritative version XML, and document single-game builds. Include all current resource changes and experiment artifacts.
2026-09-09 03:13:18 +08:00

21 lines
2.0 KiB
TypeScript

import assert from 'node:assert/strict';
import {test} from 'node:test';
import {createGameRoomProjection} from '../../YouleNexus/assets/framework/sdk/game-room-projection.ts';
import {gameAllowsRoomAction} from '../../YouleNexus/assets/framework/presentation/game-room-presentation.ts';
test('game owns atomic complete projections and exposes no consumer setter',()=>{
const initial={roundPhase:'waiting',selfParticipation:'waiting' as const,scoresBySeat:{0:10},restrictions:{}};
const owner=createGameRoomProjection(initial);const source=owner.source;const versions:any[]=[];
source.subscribe(value=>versions.push(value));owner.commit({roundPhase:'playing',selfParticipation:'playing',scoresBySeat:{0:20},restrictions:{prepare:false}});
assert.deepEqual(versions.map(v=>[v.revision,v.roundPhase,v.scoresBySeat[0]]),[[0,'waiting',10],[1,'playing',20]]);
initial.scoresBySeat[0]=999;assert.equal(versions[0].scoresBySeat[0],10);
assert.equal('commit' in source,false);assert.ok(Object.isFrozen(source.getSnapshot().scoresBySeat));
assert.equal(gameAllowsRoomAction(false,source.getSnapshot(),'exit'),false);assert.equal(gameAllowsRoomAction(true,source.getSnapshot(),'prepare'),false);
assert.throws(()=>owner.commit({...initial,restrictions:{exit:true} as any}),/disable/);assert.equal(source.getSnapshot().revision,1);
owner.dispose();assert.throws(()=>owner.commit(initial),/disposed/);assert.throws(()=>source.subscribe(()=>{}),/disposed/);
});
test('reentrant projection commits notify complete versions in order and isolate listener failure',()=>{
const initial={roundPhase:'waiting',selfParticipation:'waiting' as const,scoresBySeat:{},restrictions:{}};const owner=createGameRoomProjection(initial);const seen:number[]=[];
owner.source.subscribe(p=>{if(p.revision===1){owner.commit({...initial,roundPhase:'finished'});throw Error('listener failed');}});
owner.source.subscribe(p=>seen.push(p.revision));assert.throws(()=>owner.commit({...initial,roundPhase:'playing'}),/notification/);assert.deepEqual(seen,[0,1,2]);
});