import assert from 'node:assert/strict'; import { test } from 'node:test'; import type { GameEntry, GameHost, GameModule, PlatformGameSnapshot, } from '../../YouleNexus/assets/framework/sdk/contracts/index.ts'; import { assertGameContract, type GameContractHost, } from '../../YouleNexus/assets/framework/sdk/testing/game-contract-harness.ts'; test('assertGameContract runs the reusable isolated session conformance suite', () => { let invalidations = 0; let nextModuleId = 0; const entry: GameEntry = { key: 'fixture', gameId: 41, route: 'fixture-route', resolveSeatCount: (roomtype) => { const seats = roomtype[0]; if (seats === 2 || seats === 4 || seats === 10) return seats; return 4; }, createModule: () => makeModule(++nextModuleId), }; assert.doesNotThrow(() => assertGameContract(entry, makeConformanceHost(() => { invalidations++; }))); assert.equal(invalidations, 2); assert.ok(nextModuleId >= 2); }); function makeModule(id: number): GameModule { let host: GameHost | undefined; let restored: unknown; let eventCount = 0; let messageCycle: number | undefined; return { attach(value) { host = value; }, handlePlatformEvent(event) { eventCount++; if (event.type === 'room.entered') { assert.equal(event.roomtype[0], 4); } }, handleGameMessage(message) { assert.equal(message.rpc, 'conformance.message'); const data = message.data as { cycle: number }; assert.equal(typeof data.cycle, 'number'); messageCycle = data.cycle; }, restore(deskinfo) { restored = deskinfo; }, dispose() { assert.ok(host); assert.equal(eventCount, 1); assert.deepEqual(restored, deskinfoFor(messageCycle!)); }, }; } function deskinfoFor(cycle: number): { readonly cycle: number } { return { cycle }; } function makeConformanceHost(onInvalidate: () => void): () => GameContractHost { return () => { const snapshot: PlatformGameSnapshot = { connection: { phase: 'connected' }, self: { playerId: 1, seat: 0 }, room: { roomcode: 'fixture', roomtype: [], stage: 0, needprepare: 0, infinite: 0 }, seats: [], }; return { host: { seat: { toView: (seat) => seat, toServer: (seat) => seat }, getSnapshot: () => snapshot, subscribe: () => () => {}, sendGameMessage: () => {}, execute: () => {}, }, invalidate: onInvalidate, }; }; }