fix(platform): apply room action battle flags
This commit is contained in:
@@ -120,6 +120,106 @@ test('playerJoin atomically adds one canonical entity and its seat id', () => {
|
||||
assert.equal(Object.isFrozen(state.players.entities[77]), true);
|
||||
});
|
||||
|
||||
test('playerJoin applies deskwar battle start in the same root commit', () => {
|
||||
const store = new PlatformStore();
|
||||
const loginData = fixture('player-login-room.json').data;
|
||||
loginData.isbattle = 0;
|
||||
store.applyLoginSuccess(parseLoginResponse(loginData));
|
||||
const before = store.getState();
|
||||
assert.equal(before.room.kind, 'inside');
|
||||
if (before.room.kind !== 'inside') return;
|
||||
assert.equal(before.room.stage, 0);
|
||||
const transitions: PlatformState[] = [];
|
||||
store.subscribe((state) => { transitions.push(state); });
|
||||
|
||||
store.playerJoin(parseOtherJoinRoomPayload({
|
||||
seat: 2,
|
||||
playerid: 77,
|
||||
nickname: '对家',
|
||||
avatar: 'http://b',
|
||||
sex: 1,
|
||||
ip: '127.0.0.2',
|
||||
onstate: 0,
|
||||
bean: 90,
|
||||
isprepare: 0,
|
||||
deskwar: 1,
|
||||
}));
|
||||
|
||||
const after = store.getState();
|
||||
assert.equal(transitions.length, 1);
|
||||
assert.equal(transitions[0], after);
|
||||
assert.equal(after.room.kind, 'inside');
|
||||
if (after.room.kind !== 'inside') return;
|
||||
assert.equal(after.room.stage, 1);
|
||||
assert.equal(after.room.seatPlayerIds[2], 77);
|
||||
assert.equal(after.players.entities[77]?.playerid, 77);
|
||||
});
|
||||
|
||||
test('playerJoin preserves the current stage when deskwar is absent or zero', () => {
|
||||
for (const initialStage of [0, 1] as const) {
|
||||
for (const deskwar of [undefined, 0] as const) {
|
||||
const store = new PlatformStore();
|
||||
const loginData = fixture('player-login-room.json').data;
|
||||
loginData.isbattle = initialStage;
|
||||
store.applyLoginSuccess(parseLoginResponse(loginData));
|
||||
const joinData: Record<string, unknown> = {
|
||||
seat: 2,
|
||||
playerid: 77,
|
||||
nickname: '对家',
|
||||
avatar: 'http://b',
|
||||
sex: 1,
|
||||
ip: '127.0.0.2',
|
||||
onstate: 0,
|
||||
bean: 90,
|
||||
isprepare: 0,
|
||||
};
|
||||
if (deskwar !== undefined) joinData.deskwar = deskwar;
|
||||
|
||||
store.playerJoin(parseOtherJoinRoomPayload(joinData));
|
||||
|
||||
const state = store.getState();
|
||||
assert.equal(state.room.kind, 'inside');
|
||||
if (state.room.kind !== 'inside') continue;
|
||||
assert.equal(
|
||||
state.room.stage,
|
||||
initialStage,
|
||||
`initial stage ${initialStage}, deskwar ${String(deskwar)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('playerJoin rejects an invalid own deskwar atomically without changing input', () => {
|
||||
for (const deskwar of [2, -1, true, '1', null, undefined]) {
|
||||
const store = new PlatformStore();
|
||||
store.applyLoginSuccess(parseLoginResponse(fixture('player-login-room.json').data));
|
||||
const joinData: Record<string, unknown> = {
|
||||
seat: 2,
|
||||
playerid: 77,
|
||||
nickname: '对家',
|
||||
avatar: 'http://b',
|
||||
sex: 1,
|
||||
ip: '127.0.0.2',
|
||||
onstate: 0,
|
||||
bean: 90,
|
||||
isprepare: 0,
|
||||
deskwar,
|
||||
};
|
||||
const originalInput = { ...joinData };
|
||||
const parsed = parseOtherJoinRoomPayload(joinData);
|
||||
const before = store.getState();
|
||||
let notifications = 0;
|
||||
store.subscribe(() => { notifications += 1; });
|
||||
|
||||
assert.throws(() => store.playerJoin(parsed), /deskwar/i);
|
||||
assert.equal(store.getState(), before);
|
||||
assert.equal(notifications, 0);
|
||||
assert.deepEqual(joinData, originalInput);
|
||||
assert.equal(Object.prototype.hasOwnProperty.call(joinData, 'deskwar'), true);
|
||||
assert.equal(Object.isFrozen(joinData), false);
|
||||
}
|
||||
});
|
||||
|
||||
test('playerReady replaces the affected player and room subtrees without prior mutation', () => {
|
||||
const store = new PlatformStore();
|
||||
store.applyLoginSuccess(parseLoginResponse(fixture('player-login-room.json').data));
|
||||
@@ -147,6 +247,86 @@ test('playerReady replaces the affected player and room subtrees without prior m
|
||||
assert.equal(Object.isFrozen(after.room.readySeats), true);
|
||||
});
|
||||
|
||||
test('playerReady applies deskwar battle start in the same root commit', () => {
|
||||
const store = new PlatformStore();
|
||||
const loginData = fixture('player-login-room.json').data;
|
||||
loginData.isbattle = 0;
|
||||
store.applyLoginSuccess(parseLoginResponse(loginData));
|
||||
store.playerJoin(parseOtherJoinRoomPayload({
|
||||
seat: 2, playerid: 77, nickname: '对家', avatar: 'http://b',
|
||||
sex: 1, bean: 90, ip: '127.0.0.2', onstate: 0, isprepare: 0,
|
||||
}));
|
||||
const before = store.getState();
|
||||
assert.equal(before.room.kind, 'inside');
|
||||
if (before.room.kind !== 'inside') return;
|
||||
assert.equal(before.room.stage, 0);
|
||||
const transitions: PlatformState[] = [];
|
||||
store.subscribe((state) => { transitions.push(state); });
|
||||
|
||||
store.playerReady(parsePlayerPreparePayload({ seat: 2, deskwar: 1 }));
|
||||
|
||||
const after = store.getState();
|
||||
assert.equal(transitions.length, 1);
|
||||
assert.equal(transitions[0], after);
|
||||
assert.equal(after.room.kind, 'inside');
|
||||
if (after.room.kind !== 'inside') return;
|
||||
assert.equal(after.room.stage, 1);
|
||||
assert.deepEqual(after.room.readySeats, [1, 2]);
|
||||
assert.equal(after.players.entities[77]?.isprepare, 1);
|
||||
});
|
||||
|
||||
test('playerReady preserves the current stage when deskwar is absent or zero', () => {
|
||||
for (const initialStage of [0, 1] as const) {
|
||||
for (const deskwar of [undefined, 0] as const) {
|
||||
const store = new PlatformStore();
|
||||
const loginData = fixture('player-login-room.json').data;
|
||||
loginData.isbattle = initialStage;
|
||||
store.applyLoginSuccess(parseLoginResponse(loginData));
|
||||
store.playerJoin(parseOtherJoinRoomPayload({
|
||||
seat: 2, playerid: 77, nickname: '对家', avatar: 'http://b',
|
||||
sex: 1, bean: 90, ip: '127.0.0.2', onstate: 0, isprepare: 0,
|
||||
}));
|
||||
const prepareData: Record<string, unknown> = { seat: 2 };
|
||||
if (deskwar !== undefined) prepareData.deskwar = deskwar;
|
||||
|
||||
store.playerReady(parsePlayerPreparePayload(prepareData));
|
||||
|
||||
const state = store.getState();
|
||||
assert.equal(state.room.kind, 'inside');
|
||||
if (state.room.kind !== 'inside') continue;
|
||||
assert.equal(
|
||||
state.room.stage,
|
||||
initialStage,
|
||||
`initial stage ${initialStage}, deskwar ${String(deskwar)}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
test('playerReady rejects an invalid own deskwar atomically without changing input', () => {
|
||||
for (const deskwar of [2, -1, true, '1', null, undefined]) {
|
||||
const store = new PlatformStore();
|
||||
store.applyLoginSuccess(parseLoginResponse(fixture('player-login-room.json').data));
|
||||
store.playerJoin(parseOtherJoinRoomPayload({
|
||||
seat: 2, playerid: 77, nickname: '对家', avatar: 'http://b',
|
||||
sex: 1, bean: 90, ip: '127.0.0.2', onstate: 0, isprepare: 0,
|
||||
}));
|
||||
const prepareData: Record<string, unknown> = { seat: 2, deskwar };
|
||||
const originalInput = { ...prepareData };
|
||||
const parsed = parsePlayerPreparePayload(prepareData);
|
||||
const before = store.getState();
|
||||
let notifications = 0;
|
||||
store.subscribe(() => { notifications += 1; });
|
||||
|
||||
assert.throws(() => store.playerReady(parsed), /deskwar/i);
|
||||
assert.equal(store.getState(), before);
|
||||
assert.equal(notifications, 0);
|
||||
assert.deepEqual(prepareData, originalInput);
|
||||
assert.equal(Object.prototype.hasOwnProperty.call(prepareData, 'deskwar'), true);
|
||||
assert.equal(Object.isFrozen(prepareData), false);
|
||||
}
|
||||
});
|
||||
|
||||
test('playerOffline records protocol and room status with one atomic commit', () => {
|
||||
const store = new PlatformStore();
|
||||
store.applyLoginSuccess(parseLoginResponse(fixture('player-login-room.json').data));
|
||||
|
||||
Reference in New Issue
Block a user