kt-template-online-api/test/admin/network-management/network-management-event-stream.service.spec.ts

93 lines
2.7 KiB
TypeScript

import { filter, firstValueFrom, take } from 'rxjs';
import { NetworkManagementEventStreamService } from '../../../src/modules/admin/platform-config/network-management/network-management-event-stream.service';
describe('NetworkManagementEventStreamService', () => {
it('fans out committed MQTT changes and replays only events after the cursor', async () => {
const service = new NetworkManagementEventStreamService({
heartbeatMs: 60_000,
replayLimit: 5,
});
const liveEvent = firstValueFrom(
service.stream().pipe(
filter((event) => event.type === 'network-state-changed'),
take(1),
),
);
const first = service.publishCommitted('reported');
await expect(liveEvent).resolves.toEqual(first);
const second = service.publishCommitted('status');
await expect(
firstValueFrom(service.stream(first.id).pipe(take(1))),
).resolves.toEqual(second);
});
it('requests one snapshot for an unknown replay cursor', async () => {
const service = new NetworkManagementEventStreamService({
heartbeatMs: 60_000,
replayLimit: 1,
});
const latest = service.publishCommitted('events');
const event = await firstValueFrom(
service.stream('missing-event').pipe(take(1)),
);
expect(event).toMatchObject({ type: 'snapshot-required' });
expect(event.id).toBe(latest.id);
});
it('keeps heartbeat on the latest committed replay cursor', async () => {
jest.useFakeTimers();
try {
const service = new NetworkManagementEventStreamService({
heartbeatMs: 1_000,
replayLimit: 1,
});
const latest = service.publishCommitted('status');
const heartbeat = firstValueFrom(
service.stream(latest.id).pipe(
filter((event) => event.type === 'heartbeat'),
take(1),
),
);
jest.advanceTimersByTime(1_000);
await Promise.resolve();
const event = await heartbeat;
expect(event).toMatchObject({ type: 'heartbeat' });
expect(event.id).toBe(latest.id);
} finally {
jest.useRealTimers();
}
});
it('uses an explicit empty heartbeat cursor before any state event', async () => {
jest.useFakeTimers();
try {
const service = new NetworkManagementEventStreamService({
heartbeatMs: 1_000,
replayLimit: 1,
});
const heartbeat = firstValueFrom(
service.stream().pipe(
filter((event) => event.type === 'heartbeat'),
take(1),
),
);
jest.advanceTimersByTime(1_000);
await Promise.resolve();
await expect(heartbeat).resolves.toMatchObject({
id: '',
type: 'heartbeat',
});
} finally {
jest.useRealTimers();
}
});
});