feat(framework): RoomStore + RoomState.players 类型精确化
RoomState.players: unknown[] → Array<PlayerState | null> - 座位未占用显式为 null(不是 undefined、不是空对象) - 长度由 maxPlayerCount 决定,RoomStore.applyRecovery 校验填充 deskinfo 字段注释强调"C 规范 §5 边界判据 2:平台层不持有、不解析", 新测试覆盖引用相等透传(不深拷贝)。 新增 RoomStore: applyRecovery/clear,响应式 + 类型化入参 RoomRecoveryData。 97/97 tests pass, typecheck exit 0。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { RoomStore } from '../../YouleNexus/assets/framework/platform/stores/room-store.ts';
|
||||
|
||||
test('初始: inRoom=false, seat=-1, players=[]', () => {
|
||||
const v = new RoomStore().state.value;
|
||||
assert.equal(v.inRoom, false);
|
||||
assert.equal(v.seat, -1);
|
||||
assert.deepEqual(v.players, []);
|
||||
});
|
||||
|
||||
test('applyRecovery: 填充 B 组并置 inRoom=true', () => {
|
||||
const store = new RoomStore();
|
||||
store.applyRecovery({
|
||||
roomcode: 'ROOM1', isbattle: 1, roommode: 1,
|
||||
seat: 2, isowner: 1,
|
||||
players: [
|
||||
null,
|
||||
{ playerid: 100, nickname: '甲', bean: 0, roomcard: 0 } as any,
|
||||
null,
|
||||
],
|
||||
});
|
||||
const v = store.state.value;
|
||||
assert.equal(v.inRoom, true);
|
||||
assert.equal(v.roomcode, 'ROOM1');
|
||||
assert.equal(v.isbattle, 1);
|
||||
assert.equal(v.seat, 2);
|
||||
assert.equal(v.players.length, 3);
|
||||
assert.equal(v.players[0], null);
|
||||
assert.equal(v.players[1]?.playerid, 100);
|
||||
assert.equal(v.players[2], null);
|
||||
});
|
||||
|
||||
test('applyRecovery: 未传 players 字段 → 空数组(非 null,非 undefined)', () => {
|
||||
const store = new RoomStore();
|
||||
store.applyRecovery({ roomcode: 'R' } as any);
|
||||
assert.deepEqual(store.state.value.players, []);
|
||||
});
|
||||
|
||||
test('applyRecovery: deskinfo 透传原值不解析(第二准则:平台层不解析对局态)', () => {
|
||||
const store = new RoomStore();
|
||||
const deskinfo = { round: 3, cards: ['A', 'B'] };
|
||||
store.applyRecovery({ roomcode: 'R', deskinfo } as any);
|
||||
assert.equal(store.state.value.deskinfo, deskinfo, 'deskinfo 必须是引用相等(不深拷贝、不解析)');
|
||||
});
|
||||
|
||||
test('applyRecovery: deskinfo 缺省 → null', () => {
|
||||
const store = new RoomStore();
|
||||
store.applyRecovery({ roomcode: 'R' } as any);
|
||||
assert.equal(store.state.value.deskinfo, null);
|
||||
});
|
||||
|
||||
test('clear: 复位 inRoom 与字段, players 也清空', () => {
|
||||
const store = new RoomStore();
|
||||
store.applyRecovery({
|
||||
roomcode: 'R', seat: 1,
|
||||
players: [{ playerid: 1 } as any, null],
|
||||
});
|
||||
store.clear();
|
||||
const v = store.state.value;
|
||||
assert.equal(v.inRoom, false);
|
||||
assert.equal(v.roomcode, null);
|
||||
assert.equal(v.seat, -1);
|
||||
assert.deepEqual(v.players, []);
|
||||
});
|
||||
|
||||
test('subscribe: inRoom 由 false → true 触发一次', () => {
|
||||
const store = new RoomStore();
|
||||
let n = 0;
|
||||
store.state.subscribe(() => { n++;
|
||||
});
|
||||
store.applyRecovery({ roomcode: 'R' } as any);
|
||||
store.clear();
|
||||
assert.equal(n, 2);
|
||||
});
|
||||
Reference in New Issue
Block a user