25 lines
1.7 KiB
TypeScript
25 lines
1.7 KiB
TypeScript
import assert from 'node:assert/strict';
|
|
import { once } from 'node:events';
|
|
import { createServer } from 'node:http';
|
|
import test from 'node:test';
|
|
import { WebSocketServer } from 'ws';
|
|
import { subscribeNotificationEvents } from '../src/agent-push-events.js';
|
|
|
|
test('notification observer authenticates, reconnects and stops without leaking missed invalidations', async t => {
|
|
const server = createServer(); const sockets = new WebSocketServer({ server });
|
|
server.listen(0, '127.0.0.1'); await once(server, 'listening');
|
|
let connections = 0, wakes = 0;
|
|
sockets.on('connection', (socket, request) => {
|
|
connections++;
|
|
assert.equal(request.url, '/api/notification-events');
|
|
assert.equal(request.headers.authorization, 'Bearer fixture-key');
|
|
assert.equal(request.headers['x-sybil-client'], 'backend-observer-v1');
|
|
socket.send(JSON.stringify({ type: 'notification_changed', version: 1 }));
|
|
});
|
|
const stop = subscribeNotificationEvents({ baseUrl: `http://127.0.0.1:${(server.address() as any).port}`, apiKey: 'fixture-key' }, () => { wakes++; }, { retryMs: 20 });
|
|
t.after(async () => { stop(); for (const socket of sockets.clients) socket.terminate(); sockets.close(); await new Promise<void>(resolve => server.close(() => resolve())); });
|
|
const waitFor = async (count: number) => { const deadline = Date.now() + 3000; while (wakes < count) { assert.ok(Date.now() < deadline); await new Promise(resolve => setTimeout(resolve, 10)); } };
|
|
await waitFor(1); for (const socket of sockets.clients) socket.terminate(); await waitFor(2);
|
|
assert.equal(connections, 2); stop(); await new Promise(resolve => setTimeout(resolve, 80)); assert.equal(connections, 2);
|
|
});
|