fix(platform): serialize runtime session transitions

This commit is contained in:
2026-09-05 06:17:04 +08:00
parent 1c124cf216
commit 7e5a950cc7
13 changed files with 1297 additions and 157 deletions
@@ -15,6 +15,7 @@ import {
parseOtherOfflinePayload,
parseOtherOnlinePayload,
parsePlayerPreparePayload,
parseSelfExitRoomPayload,
parseSelfJoinRoomResponse,
} from '../../YouleNexus/assets/framework/protocol/contracts/index.ts';
@@ -214,6 +215,38 @@ test('parseSelfJoinRoomResponse 接受金样,不深验 roomtype/deskinfo 并
assert.equal(parsed.reconnect.present && parsed.reconnect.value, opaqueDeskinfo);
});
test('parseSelfJoinRoomResponse defines the optional deskwar default once and deskinfo wins stage', () => {
const cases = [
{ deskwar: 'missing', deskinfo: false, expectedStage: 0 },
{ deskwar: 0, deskinfo: false, expectedStage: 0 },
{ deskwar: 1, deskinfo: false, expectedStage: 1 },
{ deskwar: 'missing', deskinfo: true, expectedStage: 1 },
{ deskwar: 0, deskinfo: true, expectedStage: 1 },
{ deskwar: 1, deskinfo: true, expectedStage: 1 },
] as const;
for (const row of cases) {
const data = fixture('self-join-room.json').data;
if (row.deskwar === 'missing') delete data.deskwar;
else data.deskwar = row.deskwar;
if (row.deskinfo) data.deskinfo = { round: 7 };
else delete data.deskinfo;
data.isbattle = 1;
const parsed = parseSelfJoinRoomResponse(data);
assert.equal(parsed.stage, row.expectedStage, JSON.stringify(row));
assert.equal(parsed.reconnect.present, row.deskinfo, JSON.stringify(row));
}
for (const deskwar of [-1, 2, 1.5, '1', undefined]) {
assert.throws(
() => parseSelfJoinRoomResponse({ ...fixture('self-join-room.json').data, deskwar }),
/\$\.data\.deskwar/,
);
}
});
test('房间请求 builder 使用唯一 route,并仅发协议定义字段', () => {
const room = { playerid: 430511, roomcode: '100001' };
assert.deepEqual(buildPrepareRequest(runtimeConfig, room), {
@@ -311,6 +344,23 @@ test('座位事件 parser 校验实际消费字段并保留 raw', () => {
assert.throws(() => parseOtherOnlinePayload({ seat: 1 }), /\$\.data\.ip.*undefined/);
});
test('self_exit_room parser accepts an omitted seat but strictly validates it when present', () => {
const withoutSeat = { isowner: 1, roomcode: '100001', extension: 'kept' };
const parsedWithoutSeat = parseSelfExitRoomPayload(withoutSeat);
assert.equal(parsedWithoutSeat.raw, withoutSeat);
assert.equal(Object.prototype.hasOwnProperty.call(parsedWithoutSeat, 'seat'), false);
const withSeat = { seat: 1, extension: 'kept' };
const parsedWithSeat = parseSelfExitRoomPayload(withSeat);
assert.equal(parsedWithSeat.raw, withSeat);
assert.equal(parsedWithSeat.seat, 1);
for (const seat of [-1, 1.2, '1', undefined]) {
assert.throws(() => parseSelfExitRoomPayload({ seat }), /\$\.data\.seat/);
}
assert.throws(() => parseOtherExitRoomPayload({}), /\$\.data\.seat/);
});
test('切服与踢出 parser 拒绝畸形载荷并保留未知扩展', () => {
const roomSwitch = { roomserver: '127.0.0.1:9001', epoch: 7 };
assert.deepEqual(parseConnectRoomserverPayload(roomSwitch), {