Scope live chat to the current match and save match history
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { mkdir, utimes, writeFile } from 'node:fs/promises';
|
||||
import { mkdir, rm, utimes, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { newFixture, type Fixture } from '../helpers/fixture.js';
|
||||
import { gameEvent } from '../helpers/telemetry.js';
|
||||
@@ -137,8 +137,70 @@ describe('server chat API', () => {
|
||||
await log(['60:50 say;abc;0;Player;previous server', '61:40 say;abc;0;Player;current server'], 100);
|
||||
const body = await (await get()).json();
|
||||
const messages = body.entries.filter((entry: { type: string }) => entry.type === 'message');
|
||||
expect(messages).toHaveLength(2);
|
||||
expect(messages[0].context).toEqual({ realTime: at(50), matchElapsedMs: null, round: null });
|
||||
expect(messages[1].context).toEqual({ realTime: at(100), matchElapsedMs: 20_000, round: 2 });
|
||||
expect(messages).toHaveLength(1);
|
||||
expect(messages[0].message.message).toBe('current server');
|
||||
expect(messages[0].context).toEqual({ realTime: at(100), matchElapsedMs: 20_000, round: 2 });
|
||||
});
|
||||
|
||||
it('clears at a new match before it writes to the log and keeps the old chat with its match', async () => {
|
||||
await report('game_start', 0);
|
||||
await report('round_change', 20, 4);
|
||||
await log(['60:30 say;abc;0;Player;old match'], 30);
|
||||
expect((await (await get()).json()).entries[0].message.message).toBe('old match');
|
||||
await report('game_end', 60, 4);
|
||||
await report('game_start', 80);
|
||||
expect((await (await get()).json()).entries).toEqual([]);
|
||||
await report('heartbeat', 90, 2);
|
||||
await log(['60:30 say;abc;0;Player;old match', '61:40 say;abc;0;Player;new match'], 100);
|
||||
const body = await (await get()).json();
|
||||
expect(body.entries.map((entry: any) => entry.message.message)).toEqual(['new match']);
|
||||
const { getMatchDetail } = await import('../../src/lib/server/fleet/match-history.js');
|
||||
expect(getMatchDetail(1)!.chat.map(entry => entry.type === 'message' && entry.message.message)).toEqual(['old match']);
|
||||
});
|
||||
|
||||
it('clears on log boundaries and clock resets before the next telemetry report', async () => {
|
||||
for (const boundary of ['61:00 InitGame:', '0:00 InitGame:', '0:00 J;abc;0;Player', 'InitGame:']) {
|
||||
await report('game_start', 0);
|
||||
await report('heartbeat', 20, 4);
|
||||
await log(['60:30 say;abc;0;Player;old match'], 30);
|
||||
expect((await (await get()).json()).entries).toHaveLength(1);
|
||||
await log(['60:30 say;abc;0;Player;old match', boundary], 60);
|
||||
expect((await (await get()).json()).entries, boundary).toEqual([]);
|
||||
}
|
||||
});
|
||||
|
||||
it('shows only the latest log session without telemetry', async () => {
|
||||
await log(['80:00 say;abc;0;Player;old match', '0:00 InitGame:', '0:30 say;abc;0;Player;new match'], 60);
|
||||
const entries = (await (await get()).json()).entries;
|
||||
expect(entries.filter((entry: any) => entry.type === 'message').map((entry: any) => entry.message.message))
|
||||
.toEqual(['new match']);
|
||||
await log(['80:00 say;abc;0;Player;old match', '0:00 InitGame:'], 60);
|
||||
expect((await (await get()).json()).entries.some((entry: any) => entry.type === 'message')).toBe(false);
|
||||
});
|
||||
|
||||
it('collects without a viewer and retains repeated messages after log rotation, restart and server deletion', async () => {
|
||||
await report('game_start', 0);
|
||||
await report('heartbeat', 20, 4);
|
||||
const lines = ['60:30 say;abc;0;Player;hello', '60:30 say;abc;0;Player;hello'];
|
||||
await log(lines, 30);
|
||||
const { collectFleetChat } = await import('../../src/lib/server/fleet/chat.js');
|
||||
await collectFleetChat();
|
||||
await collectFleetChat();
|
||||
await report('game_end', 60, 4);
|
||||
await log([...lines, '61:00 ExitLevel:'], 60);
|
||||
await collectFleetChat();
|
||||
const { closeDb, db } = await import('../../src/lib/server/db/index.js');
|
||||
const { getMatchDetail } = await import('../../src/lib/server/fleet/match-history.js');
|
||||
const saved = getMatchDetail(1)!.chat;
|
||||
expect(saved).toHaveLength(2);
|
||||
expect(saved[0]).toMatchObject({ message: { message: 'hello' }, context: { realTime: at(30), round: 4 } });
|
||||
await rm(join(fixture.t5, SERVER, 'logs'), { recursive: true });
|
||||
closeDb();
|
||||
expect((await (await get()).json()).entries).toEqual(saved);
|
||||
db().prepare('DELETE FROM servers WHERE name = ?').run(SERVER);
|
||||
expect(getMatchDetail(1)!.chat).toEqual(saved);
|
||||
// Match retention also removes its chat, with no orphaned history.
|
||||
db().prepare('DELETE FROM leaderboard_matches WHERE id = 1').run();
|
||||
expect(db().prepare('SELECT * FROM match_chat').all()).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user