mancala/apps/backend/tests/game/FakeRtmt.ts
Halit Aksoy 85e3fb60f6 feat(backend): add game history API and live game previews
- GET /games/me/active and /games/me (Bearer token), /games/popular (live
  games, or the most spectated finished ones), and /game/:id now also
  returns saved records of finished games
- Lists are cached in Valkey for 10 seconds, cleared when a game is saved,
  and empty instead of failing while the database is down
- Live game previews over WebSocket: subscribers get the top 5 on
  subscribe and on change, at most once per second, without counting as
  spectators; ids are public ids
- RTMT supports several connection listeners
2026-10-16 00:21:09 +03:00

54 lines
2.0 KiB
TypeScript

import { AuthUser } from "../../src/auth";
import { OnClientConnectionChange, OnMessage, RTMT } from "../../src/rtmt/rtmt";
export type SentMessage = { clientID: string, channel: string, message: any };
// In-memory RTMT: tests connect users, send messages as them and inspect what the server sent back.
export class FakeRtmt implements RTMT {
readonly sent: SentMessage[] = [];
private readonly listeners = new Map<string, OnMessage>();
private readonly online = new Map<string, AuthUser>();
private readonly connectionListeners: OnClientConnectionChange[] = [];
connect(user: AuthUser) {
this.online.set(user.id, user);
this.connectionListeners.forEach((listener) => listener(user.id, true));
}
disconnect(userId: string) {
this.online.delete(userId);
this.connectionListeners.forEach((listener) => listener(userId, false));
}
receive(userId: string, channel: string, message: Object = {}) {
const listener = this.listeners.get(channel);
if (!listener) throw new Error(`No listener for ${channel}`);
listener(userId, message);
}
messagesTo(userId: string, channel: string): any[] {
return this.sent.filter((m) => m.clientID === userId && m.channel === channel).map((m) => m.message);
}
sendMessage(clientID: string, channel: string, message: Object) {
// Copy, like serialising over the wire would.
this.sent.push({ clientID, channel, message: JSON.parse(JSON.stringify(message)) });
}
listenMessage(channel: string, callback: OnMessage) {
this.listeners.set(channel, callback);
}
isClientOnline(clientID: string): boolean {
return this.online.has(clientID);
}
getUser(clientID: string): AuthUser | undefined {
return this.online.get(clientID);
}
listenOnClientConnectionChange(onUserConnectionChange: OnClientConnectionChange): void {
this.connectionListeners.push(onUserConnectionChange);
}
}