Files

82 lines
3.1 KiB
JavaScript
Raw Permalink Normal View History

// Test logEvent normalizer — canonical shape for UI/download/replay/analyze.
// New design: legacy logs (no type) DROPPED. Not in pipeline. Kept only for
// human scroll in LogsView (raw). download/copy/replay/analyze = typed only.
const { normalizeEvent, serializeEvents } = require('../logEvent.js');
describe('logEvent normalizer', () => {
test('new schema passes through', () => {
const raw = {
id: 'l1', ts: 1000, type: 'next_turn', message: 'Bob turn',
encounterId: 'e1', encounterName: 'Enc', encounterPath: 'encounters/e1',
participantId: 'p1', participantName: 'Bob',
delta: { wrapped: true, prevRound: 1 },
undo: { currentTurnParticipantId: 'p0', round: 1, turnOrderIds: ['p0','p1'] },
undone: false, snapshot: { round: 2, currentTurnParticipantId: 'p1', turnOrderIds: ['p1'], activeIds: ['p1'] },
};
const e = normalizeEvent(raw);
expect(e.id).toBe('l1');
expect(e.type).toBe('next_turn');
expect(e.snapshot.round).toBe(2);
expect(e.delta.wrapped).toBe(true);
expect(e.undo.round).toBe(1);
expect(e.participantName).toBe('Bob');
});
test('old bloated schema (payload/undo_payload) lifts undo, drops payload', () => {
const raw = {
id: 'l1b', ts: 1100, type: 'damage', message: 'dmg',
encounterPath: 'encounters/e1',
payload: { participants: [{ id: 'p1', currentHp: 30 }] },
undo_payload: { encounterPath: 'encounters/e1', updates: { round: 1 }, redo: { round: 2 } },
snapshot: { round: 2, currentTurnParticipantId: 'p1', turnOrderIds: ['p1'], activeIds: ['p1'] },
};
const e = normalizeEvent(raw);
expect(e.type).toBe('damage');
expect(e.undo).toBeTruthy();
expect(e.delta).toBeNull();
});
test('legacy (no type) dropped → null', () => {
const raw = { id: 'l2', timestamp: 500, message: 'old', encounterName: 'Enc', undo: { encounterPath: 'enc/e1', updates: {} } };
expect(normalizeEvent(raw)).toBeNull();
});
test('explicit unknown type dropped → null', () => {
expect(normalizeEvent({ id: 'l3', type: 'unknown' })).toBeNull();
});
test('no type at all dropped → null', () => {
expect(normalizeEvent({ id: 'l4' })).toBeNull();
expect(normalizeEvent({ path: 'logs/abc' })).toBeNull();
});
test('null in null out', () => {
expect(normalizeEvent(null)).toBeNull();
});
test('serialize drops all-legacy input → empty', () => {
const raw = [
{ id: 'c', timestamp: 300 },
{ id: 'a', timestamp: 100 },
{ id: 'b', timestamp: 200 },
];
expect(JSON.parse(serializeEvents(raw))).toEqual([]);
});
test('serialize sorts typed events ascending by ts', () => {
const raw = [
{ id: 'c', type: 'next_turn', ts: 300 },
{ id: 'a', type: 'start_encounter', ts: 100 },
{ id: 'b', type: 'damage', ts: 200 },
];
const arr = JSON.parse(serializeEvents(raw));
expect(arr.map(e => e.id)).toEqual(['a', 'b', 'c']);
});
test('serialize filters nulls + legacy, keeps typed', () => {
const arr = JSON.parse(serializeEvents([null, { id: 'x', type: 'damage' }, { id: 'legacy' }, null]));
expect(arr).toHaveLength(1);
expect(arr[0].id).toBe('x');
});
});