// Generated, do not edit. sha256:dd655ee8d8d39adcd4b3b77241ca06552db9cdf6cc3583a38396eaddd1252282 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 { createCommand, claimNextCommand, resolveCommand, getCommand, pruneCommands } = await import('../../server/data/commands.js'); const { takeChanges } = await import('../../server/data/_events.js'); const { CONFIG } = await import('../../shared/config.js'); const straks = (seconden = 60) => new Date(Date.now() + seconden * 1000).toISOString(); const zoëven = (seconden = 60) => new Date(Date.now() - seconden * 1000).toISOString(); const doel = { route: 'system', tab: 'ai' }; beforeEach(() => { harness.recreate(); takeChanges(); }); describe('commands: klaarzetten', () => { it('legt een opdracht neer als open, met zijn lading', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); const c = getCommand(id); assert.equal(c.state, 'open'); assert.deepEqual(c.payload, doel, 'de lading komt als object terug, niet als JSON-tekst'); assert.equal(c.claimedBy, null); assert.equal(c.resolvedAt, null); }); it('meldt op de bus dát er iets klaarstaat, zonder te zeggen wát', async () => { await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); assert.deepEqual(takeChanges(), ['commands-changed']); }); it('weigert een verzonnen soort, en legt dan niets neer', async () => { await assert.rejects(() => createCommand({ kind: 'zweef', payload: doel }), /Invalid kind/); assert.equal(await claimNextCommand('tab-1'), null, 'er staat niets klaar'); assert.deepEqual(takeChanges(), [], 'en er gaat ook geen signaal uit'); }); }); describe('commands: het claim-model', () => { it('geeft de opdracht aan het tabblad dat hem als eerste pakt', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); const eerste = await claimNextCommand('tab-1'); assert.equal(eerste.id, id); assert.equal(eerste.state, 'claimed'); assert.equal(eerste.claimedBy, 'tab-1'); }); it('GEEFT HEM NIET AAN HET TWEEDE TABBLAD, en dat is de kern van deze fase', async () => { await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); const eerste = await claimNextCommand('tab-1'); const tweede = await claimNextCommand('tab-2'); assert.ok(eerste); assert.equal(tweede, null, 'de tweede krijgt niets en weet dus dat een ander hem heeft'); }); it('geeft null als er niets klaarstaat', async () => { assert.equal(await claimNextCommand('tab-1'), null); }); it('pakt de oudste eerst', async () => { const een = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); assert.equal((await claimNextCommand('tab-1')).id, een); }); it('weigert een claim zonder tabblad in plaats van hem aan niemand toe te wijzen', async () => { await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await assert.rejects(() => claimNextCommand(''), /without a tab/); }); }); describe('commands: claimen op soort', () => { it('LAAT LIGGEN WAT DIT TABBLAD NIET KAN, en dat is de reden dat de filter bestaat', async () => { const id = await createCommand({ kind: 'locate' }); assert.equal(await claimNextCommand('tab-1', ['navigate']), null, 'niet opgepakt'); assert.equal(getCommand(id).state, 'open', 'en ook niet afgewezen: hij blijft gewoon staan'); }); it('slaat een soort over en pakt de eerstvolgende die hij wél kent', async () => { await createCommand({ kind: 'locate' }); const kan = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); assert.equal((await claimNextCommand('tab-1', ['navigate'])).id, kan); }); it('pakt zonder filter nog steeds alles', async () => { const id = await createCommand({ kind: 'locate' }); assert.equal((await claimNextCommand('tab-1')).id, id); }); it('weigert een verzonnen soort en een lege lijst', async () => { await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await assert.rejects(() => claimNextCommand('tab-1', ['zweef']), /Invalid kind/); await assert.rejects(() => claimNextCommand('tab-1', []), /zero kinds/); }); }); describe('commands: verlopen', () => { it('pakt een verlopen opdracht niet op, maar sluit hem af', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: zoëven() }); assert.equal(await claimNextCommand('tab-1'), null); const c = getCommand(id); assert.equal(c.state, 'expired'); assert.ok(c.resolvedAt, 'en hij is afgehandeld, niet blijven hangen'); assert.match(c.detail, /op tijd/); }); it('laat een opdracht zonder verlooptijd staan', async () => { const id = await createCommand({ kind: 'navigate', payload: doel }); const c = await claimNextCommand('tab-1'); assert.equal(c.id, id, 'hij is gewoon op te pakken'); }); }); describe('commands: afsluiten', () => { it('rondt af als uitgevoerd', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await resolveCommand(id, 'tab-1', 'done'); const c = getCommand(id); assert.equal(c.state, 'done'); assert.ok(c.resolvedAt); }); it('rondt af als tegengehouden, met de reden erbij', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await resolveCommand(id, 'tab-1', 'rejected', 'Gestopt door de gebruiker.'); const c = getCommand(id); assert.equal(c.state, 'rejected'); assert.equal(c.detail, 'Gestopt door de gebruiker.'); }); it('LAAT EEN ANDER TABBLAD HEM NIET AFSLUITEN', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await resolveCommand(id, 'tab-2', 'done'); assert.equal(getCommand(id).state, 'claimed', 'onaangeroerd'); }); it('sluit een al afgesloten opdracht niet nog eens af', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await resolveCommand(id, 'tab-1', 'done'); await resolveCommand(id, 'tab-1', 'rejected', 'te laat'); assert.equal(getCommand(id).state, 'done', 'de eerste uitkomst blijft staan'); }); it('weigert een uitkomst die geen afronding is', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await assert.rejects(() => resolveCommand(id, 'tab-1', 'open'), /not a conclusion/); await assert.rejects(() => resolveCommand(id, 'tab-1', 'claimed'), /not a conclusion/); }); it('weigert een verzonnen uitkomst', async () => { const id = await createCommand({ kind: 'navigate', payload: doel, expiresAt: straks() }); await claimNextCommand('tab-1'); await assert.rejects(() => resolveCommand(id, 'tab-1', 'weggewaaid'), /Invalid state/); }); }); describe('commands: opruimen', () => { const verouder = (id) => harness.exports.run(`UPDATE Command SET resolvedAt = ? WHERE id = ?`, [new Date(Date.now() - (CONFIG.COMMANDS.RETENTION_HOURS + 1) * 3600_000).toISOString(), id]); it('gooit alleen afgehandelde opdrachten weg', async () => { const oud = await createCommand({ kind: 'navigate', payload: doel }); await claimNextCommand('tab-1'); await resolveCommand(oud, 'tab-1', 'done'); const open = await createCommand({ kind: 'navigate', payload: doel }); verouder(oud); assert.equal(pruneCommands(), 1); assert.equal(getCommand(oud), null); assert.ok(getCommand(open), 'wat nog openstaat blijft, hoe oud ook'); }); it('ruimt op zodra er een nieuwe opdracht wordt klaargezet', async () => { const oud = await createCommand({ kind: 'navigate', payload: doel }); await claimNextCommand('tab-1'); await resolveCommand(oud, 'tab-1', 'done'); verouder(oud); const nieuw = await createCommand({ kind: 'navigate', payload: doel }); assert.equal(getCommand(oud), null, 'de oude is weg zonder dat iemand erom vroeg'); assert.ok(getCommand(nieuw), 'en de nieuwe staat er gewoon'); }); it('laat een recent afgehandelde opdracht staan', async () => { const id = await createCommand({ kind: 'navigate', payload: doel }); await claimNextCommand('tab-1'); await resolveCommand(id, 'tab-1', 'done'); assert.equal(pruneCommands(), 0); assert.ok(getCommand(id)); }); });