kt-template-online-api/test/modules/admin/environment-dashboard/environment-event-stream.service.spec.ts

60 lines
2.2 KiB
TypeScript

import { take, toArray } from 'rxjs';
import { EnvironmentEventMaterializer } from '../../../../src/modules/admin/platform-config/environment-dashboard/application/environment-event.materializer';
import { EnvironmentEventStreamService } from '../../../../src/modules/admin/platform-config/environment-dashboard/application/environment-event-stream.service';
import { EnvironmentEventBusService } from '../../../../src/modules/admin/platform-config/environment-dashboard/infrastructure/event/environment-event-bus.service';
describe('EnvironmentEventStreamService', () => {
it('emits materialized bus events to SSE subscribers', async () => {
const bus = new EnvironmentEventBusService({ mode: 'local' });
const materializer = new EnvironmentEventMaterializer(undefined, 5);
const stream = new EnvironmentEventStreamService(bus, materializer, {
heartbeatMs: 60_000,
replayLimit: 5,
});
const received = stream.stream().pipe(take(1), toArray()).toPromise();
await bus.publish({
eventId: 'evt-1',
observedAt: '2026-06-18T08:00:00.000Z',
severity: 'degraded',
siteId: 'nas-prod',
sourceKind: 'mqtt',
summary: 'NapCat degraded',
topic: 'kt/env/nas-prod/napcat/runtime/event',
});
await expect(received).resolves.toEqual([
expect.objectContaining({
data: expect.objectContaining({ summary: 'NapCat degraded' }),
id: 'evt-1',
type: 'environment-event',
}),
]);
});
it('emits snapshot-required when Last-Event-ID is outside replay window', async () => {
const bus = new EnvironmentEventBusService({ mode: 'local' });
const materializer = new EnvironmentEventMaterializer(undefined, 1);
const stream = new EnvironmentEventStreamService(bus, materializer, {
heartbeatMs: 60_000,
replayLimit: 1,
});
await bus.publish({
eventId: 'evt-current',
observedAt: '2026-06-18T08:00:00.000Z',
severity: 'ok',
siteId: 'local-dev',
sourceKind: 'local',
summary: 'current event',
topic: 'kt/env/local-dev/api/event',
});
const first = await stream.stream('evt-missing').pipe(take(1)).toPromise();
expect(first).toMatchObject({
type: 'snapshot-required',
});
});
});