69 lines
2.7 KiB
TypeScript
69 lines
2.7 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import {
|
|
groupChatTimeline,
|
|
type ChatBoundaryEntry,
|
|
type ChatMessageEntry
|
|
} from '../../src/lib/ui/chat-timeline.js';
|
|
|
|
const boundary = (event: ChatBoundaryEntry['event'], time: string | null): ChatBoundaryEntry => ({
|
|
type: 'boundary',
|
|
event,
|
|
time,
|
|
context: { realTime: null, matchElapsedMs: null, round: null }
|
|
});
|
|
|
|
const message = (text: string, round: number | null = 7): ChatMessageEntry => ({
|
|
type: 'message',
|
|
message: { time: '12:08', guid: 'abc', slot: 0, player: 'Player', message: text },
|
|
context: { realTime: '2026-10-02T12:16:04Z', matchElapsedMs: 728000, round }
|
|
});
|
|
|
|
describe('chat timeline display groups', () => {
|
|
it('retains every lifecycle event in log order, including repeated starts, resets and unknown times', () => {
|
|
const entries = Object.freeze([
|
|
boundary('end', '80:00'),
|
|
boundary('start', null),
|
|
boundary('start', '0:00'),
|
|
boundary('reset', '0:00'),
|
|
boundary('end', null)
|
|
]);
|
|
const timeline = groupChatTimeline(entries);
|
|
|
|
expect(timeline).toEqual([{ type: 'boundaries', entries }]);
|
|
if (timeline[0].type !== 'boundaries') throw new Error('Expected lifecycle group');
|
|
timeline[0].entries.forEach((entry, index) => expect(entry).toBe(entries[index]));
|
|
});
|
|
|
|
it('never combines lifecycle runs separated by messages, including leading and trailing runs', () => {
|
|
const first = [boundary('start', null), boundary('reset', '0:00')];
|
|
const middle = [boundary('end', '12:08'), boundary('start', '0:00')];
|
|
const last = [boundary('end', null)];
|
|
const hello = message('hello');
|
|
const goodbye = message('goodbye');
|
|
|
|
expect(groupChatTimeline([...first, hello, ...middle, goodbye, ...last])).toEqual([
|
|
{ type: 'boundaries', entries: first },
|
|
{ type: 'message', entry: hello },
|
|
{ type: 'boundaries', entries: middle },
|
|
{ type: 'message', entry: goodbye },
|
|
{ type: 'boundaries', entries: last }
|
|
]);
|
|
});
|
|
|
|
it('preserves consecutive and repeated messages with their individual contexts', () => {
|
|
const entries = Object.freeze([
|
|
message('hello', 7),
|
|
message('hello', 8),
|
|
message('later', null)
|
|
]);
|
|
const timeline = groupChatTimeline(entries);
|
|
|
|
expect(timeline).toEqual(entries.map((entry) => ({ type: 'message', entry })));
|
|
timeline.forEach((item, index) => {
|
|
if (item.type !== 'message') throw new Error('Expected message');
|
|
expect(item.entry).toBe(entries[index]);
|
|
expect(item.entry.context).toBe(entries[index].context);
|
|
});
|
|
});
|
|
});
|