For all 11 nodes with auto-gen markers: wiki/Home.md sections 5 (topic contract) and 9 (data model) regenerated via npm run wiki:all. New Unit column shows '<measure> (default <unit>)' for declared topics, '—' otherwise. Effect column now uses descriptor.description (P11.2 field) overriding the generic per-prefix fallback. For rotatingMachine + reactor: Phase 10 test rewrites — 3 + 8 files moved off private nodeClass internals (_attachInputHandler, _commands, _pendingExtras, _registerChild, _tick, etc.) to the public BaseNodeAdapter surface (node.handlers.input, node.source.*). +6 / +7 net new tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
69 lines
1.7 KiB
JavaScript
69 lines
1.7 KiB
JavaScript
'use strict';
|
|
|
|
// Phase 10 rewrite: drives only the public BaseNodeAdapter surface. The
|
|
// commands registry built by BaseNodeAdapter logs a warn on unknown topics
|
|
// and still calls done — no throw.
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const nodeClass = require('../../src/nodeClass');
|
|
const { makeUiConfig } = require('../helpers/factories');
|
|
|
|
function makeRED() { return { nodes: { getNode: () => null } }; }
|
|
|
|
function makeNode(id = 'reactor-node-1') {
|
|
const sends = [];
|
|
const statuses = [];
|
|
const handlers = {};
|
|
return {
|
|
id, sends, statuses, handlers,
|
|
send(arr) { sends.push(arr); },
|
|
status(b) { statuses.push(b); },
|
|
on(ev, fn) { handlers[ev] = fn; },
|
|
warn() {}, error() {},
|
|
};
|
|
}
|
|
|
|
function closeNode(node) {
|
|
if (node.handlers.close) node.handlers.close(() => {});
|
|
}
|
|
|
|
test('unknown input topic does not throw and still calls done', async () => {
|
|
const node = makeNode();
|
|
new nodeClass(makeUiConfig(), makeRED(), node, 'reactor');
|
|
|
|
try {
|
|
let doneCalled = 0;
|
|
await assert.doesNotReject(async () => {
|
|
await node.handlers.input(
|
|
{ topic: 'somethingUnknown', payload: 1 },
|
|
() => {},
|
|
() => { doneCalled += 1; },
|
|
);
|
|
});
|
|
assert.equal(doneCalled, 1);
|
|
} finally {
|
|
closeNode(node);
|
|
}
|
|
});
|
|
|
|
test('missing topic field is handled gracefully', async () => {
|
|
const node = makeNode();
|
|
new nodeClass(makeUiConfig(), makeRED(), node, 'reactor');
|
|
|
|
try {
|
|
let doneCalled = 0;
|
|
await assert.doesNotReject(async () => {
|
|
await node.handlers.input(
|
|
{ payload: 'no-topic-here' },
|
|
() => {},
|
|
() => { doneCalled += 1; },
|
|
);
|
|
});
|
|
assert.equal(doneCalled, 1);
|
|
} finally {
|
|
closeNode(node);
|
|
}
|
|
});
|