// Generated, do not edit. sha256:a27e8c58c9aae75ab07e5381309139cb5309819db52788dbf42ff055ad51599e import { describe, it, beforeEach, mock } from 'node:test'; import assert from 'node:assert/strict'; import { createDbHarness } from '../helpers/db-node.mjs'; const harness = createDbHarness(); mock.module('../../server/db.js', { namedExports: harness.exports }); const { flushChanges, changesSince, pruneChanges } = await import('../../server/data/bus.js'); const { emitChange } = await import('../../server/data/_events.js'); const { CONFIG } = await import('../../shared/config.js'); const rijen = () => harness.exports.all(`SELECT id, name, occurredAt FROM BusSignal ORDER BY id`); const oudeRij = (naam, urenGeleden) => harness.exports.run( `INSERT INTO BusSignal (name, occurredAt) VALUES (?,?)`, [naam, new Date(Date.now() - urenGeleden * 3600_000).toISOString()]); beforeEach(() => { harness.recreate(); flushChanges(); }); describe('bus: het mandje wegschrijven', () => { it('schrijft elke naam uit het mandje naar de tabel', async () => { emitChange('providers-changed'); emitChange('connections-changed'); const namen = flushChanges(); assert.deepEqual(namen.sort(), ['connections-changed', 'providers-changed']); assert.deepEqual(rijen().map(r => r.name).sort(), ['connections-changed', 'providers-changed']); assert.ok(rijen()[0].occurredAt, 'en er staat een moment bij'); }); it('voegt hetzelfde signaal binnen één eenheid werk samen', async () => { emitChange('providers-changed'); emitChange('providers-changed'); emitChange('providers-changed'); flushChanges(); assert.equal(rijen().length, 1); }); it('maakt het mandje leeg, zodat een tweede flush niets dubbel schrijft', async () => { emitChange('providers-changed'); flushChanges(); assert.deepEqual(flushChanges(), [], 'niets meer over'); assert.equal(rijen().length, 1); }); it('doet niets bij een leeg mandje, en schrijft dus ook geen lege rij', async () => { assert.deepEqual(flushChanges(), []); assert.equal(rijen().length, 0); }); it('GOOIT NOOIT WEG: twee opeenvolgende flushes bewaren allebei hun signaal', async () => { emitChange('eerst-dit'); flushChanges(); emitChange('daarna-dit'); flushChanges(); assert.deepEqual(rijen().map(r => r.name), ['eerst-dit', 'daarna-dit'], 'allebei, op volgorde'); }); }); describe('bus: teruglezen sinds een cursor', () => { it('geeft bij een nieuwe client alleen de stand en geen historie', async () => { emitChange('oud-nieuws'); flushChanges(); const r = changesSince(null); assert.deepEqual(r.names, []); assert.equal(r.cursor, 1, 'wél de stand, zodat de volgende poll wél iets kan opleveren'); assert.equal(r.reset, false); }); it('geeft alleen wat er ná de cursor bij kwam', async () => { emitChange('eerste'); flushChanges(); const na1 = changesSince(null).cursor; emitChange('tweede'); flushChanges(); const r = changesSince(na1); assert.deepEqual(r.names, ['tweede']); assert.equal(r.cursor, 2); }); it('ontdubbelt de namen, want een prikkel is inhoudsloos', async () => { emitChange('providers-changed'); flushChanges(); emitChange('providers-changed'); flushChanges(); assert.deepEqual(changesSince(0).names, ['providers-changed'], 'twee rijen, één naam'); }); it('geeft niets terug als er niets nieuws is, en houdt de cursor gelijk', async () => { emitChange('iets'); flushChanges(); const r = changesSince(1); assert.deepEqual(r.names, []); assert.equal(r.cursor, 1); }); it('zegt "ververs alles" als de cursor achterloopt op de oudste bewaarde rij', async () => { for (const naam of ['een', 'twee', 'drie']) { emitChange(naam); flushChanges(); } harness.exports.run(`DELETE FROM BusSignal WHERE id <= 2`); const r = changesSince(0); assert.equal(r.reset, true); assert.deepEqual(r.names, [], 'en géén halve lijst erbij, die zou suggereren dat het daarbij blijft'); assert.equal(r.cursor, 3); }); it('meldt geen reset als de cursor precies aansluit op de oudste rij', async () => { for (const naam of ['een', 'twee', 'drie']) { emitChange(naam); flushChanges(); } harness.exports.run(`DELETE FROM BusSignal WHERE id <= 2`); const r = changesSince(2); assert.equal(r.reset, false); assert.deepEqual(r.names, ['drie']); }); it('behandelt onzin als een nieuwe client in plaats van om te vallen', async () => { emitChange('iets'); flushChanges(); for (const raar of ['onzin', -1, 1.5, undefined, {}]) { const r = changesSince(raar); assert.deepEqual(r.names, [], `${JSON.stringify(raar)} hoort als "ik begin nu" te lezen`); assert.equal(r.reset, false); } }); it('geeft op een lege bus een cursor van nul en geen null', async () => { const r = changesSince(null); assert.deepEqual(r, { cursor: 0, names: [], reset: false }); }); }); describe('bus: opruimen', () => { it('gooit weg wat ouder is dan de bewaartermijn en laat de rest staan', async () => { oudeRij('van-gisteren', CONFIG.BUS.RETENTION_HOURS + 1); oudeRij('van-net', 1); assert.equal(pruneChanges(), 1, 'geeft terug hoeveel er weg zijn'); assert.deepEqual(rijen().map(r => r.name), ['van-net']); }); it('laat een rij die binnen de termijn valt staan', async () => { oudeRij('net-binnen', CONFIG.BUS.RETENTION_HOURS - 1); assert.equal(pruneChanges(), 0); assert.equal(rijen().length, 1); }); it('doet niets op een lege bus', async () => { assert.equal(pruneChanges(), 0); }); it('valt terug op de SSOT-waarde bij onzin', async () => { oudeRij('oud', CONFIG.BUS.RETENTION_HOURS + 2); assert.equal(pruneChanges('onzin'), 1); }); it('ruimt op tijdens het wegschrijven, zonder dat de aanroeper er iets voor doet', async () => { oudeRij('van-gisteren', CONFIG.BUS.RETENTION_HOURS + 1); emitChange('nieuw'); flushChanges(); assert.deepEqual(rijen().map(r => r.name), ['nieuw'], 'de oude rij is meegenomen'); }); it('ruimt bij élke schrijfactie op, ook de tweede', async () => { emitChange('eerste'); flushChanges(); oudeRij('van-gisteren', CONFIG.BUS.RETENTION_HOURS + 1); emitChange('tweede'); flushChanges(); assert.equal(rijen().some(r => r.name === 'van-gisteren'), false, 'ook nu meegenomen'); }); });