55 lines
2.6 KiB
JavaScript
55 lines
2.6 KiB
JavaScript
import test from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
import { tmpdir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
import * as bus from '../src/broker.mjs';
|
|
import { Store } from '../src/store.mjs';
|
|
|
|
function fixture(t) {
|
|
const root = mkdtempSync(join(tmpdir(), 'pt-'));
|
|
const store = new Store(root);
|
|
t.after(() => { store.close(); rmSync(root, { recursive: true, force: true }); });
|
|
const broker = new bus.Broker({ store, businesses: {
|
|
acme: { id: 'acme', human: 'jason', roles: {
|
|
pm: { authority: { withinRole: [], crossRole: [] } },
|
|
cto: { authority: { withinRole: [], crossRole: [] } },
|
|
}, arbiters: { technical: 'cto', delivery: 'pm' } },
|
|
} });
|
|
const human = broker.bindHuman({ business: 'acme', human: 'jason', via: 'cli', outsideAgent: true });
|
|
return { broker, human };
|
|
}
|
|
|
|
test('person task vocabulary pins exactly the five frozen store verbs', () => {
|
|
assert.deepEqual(bus.PERSON_TASK_VERBS, [
|
|
'tasks.create', 'tasks.edit', 'tasks.archive', 'tasks.unarchive', 'tasks.delete',
|
|
]);
|
|
assert.ok(Object.isFrozen(bus.PERSON_TASK_VERBS));
|
|
});
|
|
|
|
test('every person task handler is declared in the vocabulary, even if the dispatch guard regresses', () => {
|
|
const source = readFileSync(new URL('../src/broker.mjs', import.meta.url), 'utf8');
|
|
const handlers = [...source.matchAll(/^\s*case\s+(['"])(tasks\.[^'"]+)\1\s*:/gm)].map(match => match[2]);
|
|
assert.deepEqual(handlers.sort(), [...bus.PERSON_TASK_VERBS].sort());
|
|
});
|
|
|
|
test('every listed person task verb reaches its handler, while an unlisted verb is unknown', t => {
|
|
const { broker, human } = fixture(t);
|
|
assert.ok(Array.isArray(bus.PERSON_TASK_VERBS));
|
|
for (const verb of bus.PERSON_TASK_VERBS) {
|
|
// Missing required fields reaches the handler's field validation, not unknown-verb.
|
|
assert.throws(() => broker.request(human, { verb, args: {} }), { code: 'invalid-request' }, verb);
|
|
}
|
|
assert.throws(() => broker.request(human, { verb: 'tasks.foo', args: {} }), { code: 'unknown-verb' });
|
|
});
|
|
|
|
test('unknown person task verbs retain common argument and reader refusal precedence', t => {
|
|
const { broker, human } = fixture(t);
|
|
assert.throws(() => broker.request(human, { verb: 'tasks.foo', args: [] }), { code: 'invalid-request' });
|
|
const reader = broker.bindReader({ business: 'acme' });
|
|
assert.throws(() => broker.request(reader, { verb: 'tasks.foo' }), { code: 'read-only' });
|
|
for (const verb of ['tasks.foo', 'tasks.create']) {
|
|
assert.throws(() => broker.request(reader, { verb }), { code: 'read-only' }, verb);
|
|
}
|
|
});
|