mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-04-27 07:48:01 -07:00
112 lines
3.9 KiB
TypeScript
112 lines
3.9 KiB
TypeScript
// Helpers for inspecting outbound commands. WebSocketService calls
|
|
// `this.socket.send(bytes)` with the encoded CommandContainer; the mock
|
|
// WebSocket records those calls on its `send` vi.fn. These helpers decode
|
|
// the bytes back into a CommandContainer so tests can assert on what was
|
|
// sent and extract the `cmdId` needed to build a correlated response.
|
|
|
|
import { fromBinary, getExtension, hasExtension } from '@bufbuild/protobuf';
|
|
import type { GenExtension } from '@bufbuild/protobuf/codegenv2';
|
|
|
|
import { Data } from '@app/types';
|
|
|
|
import { getMockWebSocket } from './setup';
|
|
|
|
/** The three command scopes a CommandContainer can carry in practice. */
|
|
type SessionCmd = Data.SessionCommand;
|
|
type RoomCmd = Data.RoomCommand;
|
|
type GameCmd = Data.GameCommand;
|
|
|
|
/** Decode every CommandContainer sent through the mock socket so far. */
|
|
export function captureAllOutbound(): Data.CommandContainer[] {
|
|
const mock = getMockWebSocket();
|
|
return mock.send.mock.calls.map(([bytes]: [Uint8Array]) =>
|
|
fromBinary(Data.CommandContainerSchema, bytes)
|
|
);
|
|
}
|
|
|
|
/** Decode the most recent CommandContainer. Throws if none has been sent. */
|
|
export function captureLastOutbound(): Data.CommandContainer {
|
|
const all = captureAllOutbound();
|
|
if (all.length === 0) {
|
|
throw new Error('No outbound command has been sent through the mock WebSocket.');
|
|
}
|
|
return all[all.length - 1];
|
|
}
|
|
|
|
/** Numeric cmdId of the most recently sent command (the BigInt cast back to number). */
|
|
export function lastCmdId(): number {
|
|
return Number(captureLastOutbound().cmdId);
|
|
}
|
|
|
|
/**
|
|
* Find the most recently sent CommandContainer whose session-scope command
|
|
* carries the given extension, and return both the container and the
|
|
* unwrapped extension value. Handy for "the login() call fired — grab its
|
|
* cmdId and the Command_Login payload it sent".
|
|
*/
|
|
export function findLastSessionCommand<V>(
|
|
ext: GenExtension<SessionCmd, V>
|
|
): { container: Data.CommandContainer; value: V; cmdId: number } {
|
|
const containers = captureAllOutbound();
|
|
for (let i = containers.length - 1; i >= 0; i--) {
|
|
const container = containers[i];
|
|
for (const sessionCmd of container.sessionCommand ?? []) {
|
|
if (hasExtension(sessionCmd, ext)) {
|
|
return {
|
|
container,
|
|
value: getExtension(sessionCmd, ext),
|
|
cmdId: Number(container.cmdId),
|
|
};
|
|
}
|
|
}
|
|
}
|
|
throw new Error(
|
|
`No outbound session command with extension ${ext.typeName} has been sent.`
|
|
);
|
|
}
|
|
|
|
/** Room-scoped equivalent of {@link findLastSessionCommand}. */
|
|
export function findLastRoomCommand<V>(
|
|
ext: GenExtension<RoomCmd, V>
|
|
): { container: Data.CommandContainer; value: V; cmdId: number; roomId: number } {
|
|
const containers = captureAllOutbound();
|
|
for (let i = containers.length - 1; i >= 0; i--) {
|
|
const container = containers[i];
|
|
for (const roomCmd of container.roomCommand ?? []) {
|
|
if (hasExtension(roomCmd, ext)) {
|
|
return {
|
|
container,
|
|
value: getExtension(roomCmd, ext),
|
|
cmdId: Number(container.cmdId),
|
|
roomId: container.roomId ?? 0,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
throw new Error(
|
|
`No outbound room command with extension ${ext.typeName} has been sent.`
|
|
);
|
|
}
|
|
|
|
/** Game-scoped equivalent of {@link findLastSessionCommand}. */
|
|
export function findLastGameCommand<V>(
|
|
ext: GenExtension<GameCmd, V>
|
|
): { container: Data.CommandContainer; value: V; cmdId: number; gameId: number } {
|
|
const containers = captureAllOutbound();
|
|
for (let i = containers.length - 1; i >= 0; i--) {
|
|
const container = containers[i];
|
|
for (const gameCmd of container.gameCommand ?? []) {
|
|
if (hasExtension(gameCmd, ext)) {
|
|
return {
|
|
container,
|
|
value: getExtension(gameCmd, ext),
|
|
cmdId: Number(container.cmdId),
|
|
gameId: container.gameId ?? 0,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
throw new Error(
|
|
`No outbound game command with extension ${ext.typeName} has been sent.`
|
|
);
|
|
}
|