Files
RedditBot/tests/log-broadcaster.test.ts
T

71 lines
2.5 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { RealtimeEventHub, type RealtimeEvent } from '../src/web/events/index.js';
import { LogBroadcaster } from '../src/web/log-broadcaster.js';
describe('LogBroadcaster realtime bridge', () => {
it('publishes each log through the typed event hub', () => {
const occurredAt = new Date('2026-08-08T15:00:00.000Z');
const hub = new RealtimeEventHub({
capacity: 10,
clock: { now: () => occurredAt },
});
const received: RealtimeEvent[] = [];
let recent: unknown;
hub.subscribe((event) => received.push(event));
const broadcaster = new LogBroadcaster(hub);
broadcaster.push('warn', 'Connection is stale', { attempts: 2 });
broadcaster.recent(
{ query: {} } as never,
{ json: (value: unknown) => { recent = value; } } as never,
);
expect(received).toEqual([
expect.objectContaining({
type: 'log.created',
payload: {
level: 'warn',
message: 'Connection is stale',
data: { attempts: 2 },
},
}),
]);
expect(recent).toEqual([
expect.objectContaining({ timestamp: occurredAt.getTime() }),
]);
});
it('sanitizes circular network errors before buffering or publishing them', () => {
const hub = new RealtimeEventHub({ capacity: 10 });
const received: RealtimeEvent[] = [];
hub.subscribe((event) => received.push(event));
const broadcaster = new LogBroadcaster(hub);
const socket: Record<string, unknown> = { constructorName: 'TLSSocket' };
const parser: Record<string, unknown> = { socket };
socket.parser = parser;
const networkError = Object.assign(new Error('upstream request failed'), {
code: 'ECONNRESET',
request: socket,
});
let serializedRecent = '';
broadcaster.push('error', 'Matrix request failed', {
error: networkError,
socket,
authorization: 'Bearer must-not-leak',
});
broadcaster.recent(
{ query: {} } as never,
{ json: (value: unknown) => { serializedRecent = JSON.stringify(value); } } as never,
);
expect(() => JSON.stringify(received)).not.toThrow();
expect(() => JSON.parse(serializedRecent)).not.toThrow();
expect(serializedRecent).toContain('ECONNRESET');
expect(serializedRecent).toContain('[Circular]');
expect(serializedRecent).toContain('[Redacted]');
expect(serializedRecent).not.toContain('must-not-leak');
expect(serializedRecent).not.toContain('"request"');
});
});