more integration tests

This commit is contained in:
seavor 2026-04-16 12:40:47 -05:00
parent 4b5f66d497
commit decebc25c7
192 changed files with 3090 additions and 1657 deletions

View file

@ -1,11 +1,12 @@
// Room scenarios — Event_ListRooms handling, auto-join, Response_JoinRoom,
// room chat, and in-room game list updates.
// room chat (inbound + outbound), game list updates, and leaveRoom.
import { create } from '@bufbuild/protobuf';
import { describe, expect, it } from 'vitest';
import { Data } from '@app/types';
import { store } from '@app/store';
import { RoomCommands } from '@app/websocket';
import { connectAndHandshake } from './helpers/setup';
import {
@ -15,7 +16,8 @@ import {
buildSessionEventMessage,
deliverMessage,
} from './helpers/protobuf-builders';
import { findLastSessionCommand } from './helpers/command-capture';
import { findLastSessionCommand, findLastRoomCommand, captureAllOutbound } from './helpers/command-capture';
import { fromBinary, hasExtension, getExtension } from '@bufbuild/protobuf';
function makeRoom(overrides: Partial<{
roomId: number;
@ -35,6 +37,21 @@ function makeRoom(overrides: Partial<{
});
}
/** Deliver Event_ListRooms then join a single auto-join room, returning the roomId. */
function setupJoinedRoom(roomId = 1): void {
deliverMessage(buildSessionEventMessage(
Data.Event_ListRooms_ext,
create(Data.Event_ListRoomsSchema, { roomList: [makeRoom({ roomId, autoJoin: true })] })
));
const join = findLastSessionCommand(Data.Command_JoinRoom_ext);
deliverMessage(buildResponseMessage(buildResponse({
cmdId: join.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
ext: Data.Response_JoinRoom_ext,
value: create(Data.Response_JoinRoomSchema, { roomInfo: makeRoom({ roomId }) }),
})));
}
describe('rooms', () => {
it('populates rooms state from Event_ListRooms', () => {
connectAndHandshake();
@ -81,18 +98,7 @@ describe('rooms', () => {
it('appends a room chat message on Event_RoomSay', () => {
connectAndHandshake();
deliverMessage(buildSessionEventMessage(
Data.Event_ListRooms_ext,
create(Data.Event_ListRoomsSchema, { roomList: [makeRoom({ roomId: 1, autoJoin: true })] })
));
const join = findLastSessionCommand(Data.Command_JoinRoom_ext);
deliverMessage(buildResponseMessage(buildResponse({
cmdId: join.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
ext: Data.Response_JoinRoom_ext,
value: create(Data.Response_JoinRoomSchema, { roomInfo: makeRoom({ roomId: 1 }) }),
})));
setupJoinedRoom(1);
const say = create(Data.Event_RoomSaySchema, {
name: 'bob',
@ -109,18 +115,7 @@ describe('rooms', () => {
it('updates the game list on Event_ListGames', () => {
connectAndHandshake();
deliverMessage(buildSessionEventMessage(
Data.Event_ListRooms_ext,
create(Data.Event_ListRoomsSchema, { roomList: [makeRoom({ roomId: 1, autoJoin: true })] })
));
const join = findLastSessionCommand(Data.Command_JoinRoom_ext);
deliverMessage(buildResponseMessage(buildResponse({
cmdId: join.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
ext: Data.Response_JoinRoom_ext,
value: create(Data.Response_JoinRoomSchema, { roomInfo: makeRoom({ roomId: 1 }) }),
})));
setupJoinedRoom(1);
const game = create(Data.ServerInfo_GameSchema, {
gameId: 42,
@ -137,4 +132,102 @@ describe('rooms', () => {
expect(roomGames?.[42]?.info?.description).toBe('Test Game');
expect(roomGames?.[42]?.info?.gameId).toBe(42);
});
});
it('auto-join filters correctly across multiple rooms', () => {
connectAndHandshake();
deliverMessage(buildSessionEventMessage(
Data.Event_ListRooms_ext,
create(Data.Event_ListRoomsSchema, {
roomList: [
makeRoom({ roomId: 1, name: 'Lobby', autoJoin: true }),
makeRoom({ roomId: 2, name: 'Legacy', autoJoin: false }),
makeRoom({ roomId: 3, name: 'Modern', autoJoin: true }),
],
})
));
// Count outbound JoinRoom commands
const containers = captureAllOutbound();
const joinCommands: number[] = [];
for (const container of containers) {
for (const cmd of container.sessionCommand ?? []) {
if (hasExtension(cmd, Data.Command_JoinRoom_ext)) {
joinCommands.push(getExtension(cmd, Data.Command_JoinRoom_ext).roomId);
}
}
}
expect(joinCommands).toHaveLength(2);
expect(joinCommands).toContain(1);
expect(joinCommands).toContain(3);
expect(joinCommands).not.toContain(2);
});
it('sends outbound Command_RoomSay with trimmed message', () => {
connectAndHandshake();
setupJoinedRoom(1);
RoomCommands.roomSay(1, ' hello ');
const { value } = findLastRoomCommand(Data.Command_RoomSay_ext);
expect(value.message).toBe('hello');
});
it('removes room from joinedRoomIds on leaveRoom round-trip', () => {
connectAndHandshake();
setupJoinedRoom(1);
expect(store.getState().rooms.joinedRoomIds[1]).toBe(true);
RoomCommands.leaveRoom(1);
const leave = findLastRoomCommand(Data.Command_LeaveRoom_ext);
deliverMessage(buildResponseMessage(buildResponse({
cmdId: leave.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
})));
expect(store.getState().rooms.joinedRoomIds[1]).toBeUndefined();
});
it('tracks user join and leave within a room', () => {
connectAndHandshake();
setupJoinedRoom(1);
deliverMessage(buildRoomEventMessage(1, Data.Event_JoinRoom_ext, create(Data.Event_JoinRoomSchema, {
userInfo: create(Data.ServerInfo_UserSchema, { name: 'bob' }),
})));
expect(store.getState().rooms.rooms[1]?.users?.bob).toBeDefined();
deliverMessage(buildRoomEventMessage(1, Data.Event_LeaveRoom_ext, create(Data.Event_LeaveRoomSchema, {
name: 'bob',
})));
expect(store.getState().rooms.rooms[1]?.users?.bob).toBeUndefined();
});
it('tracks game creation and join within a room', () => {
connectAndHandshake();
setupJoinedRoom(1);
RoomCommands.createGame(1, { description: 'Casual', maxPlayers: 2 });
const create_ = findLastRoomCommand(Data.Command_CreateGame_ext);
expect(create_.value.description).toBe('Casual');
deliverMessage(buildResponseMessage(buildResponse({
cmdId: create_.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
})));
RoomCommands.joinGame(1, { gameId: 99 });
const join = findLastRoomCommand(Data.Command_JoinGame_ext);
deliverMessage(buildResponseMessage(buildResponse({
cmdId: join.cmdId,
responseCode: Data.Response_ResponseCode.RespOk,
})));
expect(store.getState().rooms.joinedGameIds[1]?.[99]).toBe(true);
});
});