2026-02-19 17:37:21 +01:00
|
|
|
const test = require('node:test');
|
|
|
|
|
const assert = require('node:assert/strict');
|
|
|
|
|
|
|
|
|
|
const NodeClass = require('../../src/nodeClass');
|
2026-05-10 20:39:54 +02:00
|
|
|
const commands = require('../../src/commands');
|
|
|
|
|
const { createRegistry } = require('generalFunctions');
|
2026-02-19 17:37:21 +01:00
|
|
|
const { makeNodeStub, makeREDStub } = require('../helpers/factories');
|
|
|
|
|
|
2026-05-10 20:39:54 +02:00
|
|
|
// These tests pinned the old private methods (_attachInputHandler /
|
|
|
|
|
// _registerChild) on the pre-refactor nodeClass. After the BaseNodeAdapter
|
|
|
|
|
// migration the same wiring is provided by the base class, but we still
|
|
|
|
|
// exercise it from a prototype-derived instance to keep the surface covered
|
|
|
|
|
// without booting a full Node-RED runtime.
|
|
|
|
|
|
|
|
|
|
test('input handler dispatches known topics to source methods', async () => {
|
2026-02-19 17:37:21 +01:00
|
|
|
const inst = Object.create(NodeClass.prototype);
|
|
|
|
|
const node = makeNodeStub();
|
|
|
|
|
const calls = [];
|
2026-05-10 20:39:54 +02:00
|
|
|
const source = {
|
|
|
|
|
mode: 'analog',
|
|
|
|
|
logger: { warn: () => {}, info: () => {}, debug: () => {}, error: () => {} },
|
2026-02-19 17:37:21 +01:00
|
|
|
toggleSimulation() { calls.push('simulator'); },
|
|
|
|
|
toggleOutlierDetection() { calls.push('outlierDetection'); },
|
|
|
|
|
calibrate() { calls.push('calibrate'); },
|
|
|
|
|
set inputValue(v) { calls.push(['measurement', v]); },
|
|
|
|
|
};
|
|
|
|
|
|
2026-05-10 20:39:54 +02:00
|
|
|
inst.node = node;
|
|
|
|
|
inst.RED = makeREDStub();
|
|
|
|
|
inst.source = source;
|
|
|
|
|
inst._commands = createRegistry(commands, { logger: source.logger });
|
2026-02-19 17:37:21 +01:00
|
|
|
inst._attachInputHandler();
|
|
|
|
|
|
2026-05-10 20:39:54 +02:00
|
|
|
const onInput = node._handlers.input;
|
|
|
|
|
await onInput({ topic: 'simulator' }, () => {}, () => {});
|
|
|
|
|
await onInput({ topic: 'outlierDetection' }, () => {}, () => {});
|
|
|
|
|
await onInput({ topic: 'calibrate' }, () => {}, () => {});
|
|
|
|
|
await onInput({ topic: 'measurement', payload: 12.3 }, () => {}, () => {});
|
2026-02-19 17:37:21 +01:00
|
|
|
|
|
|
|
|
assert.deepEqual(calls[0], 'simulator');
|
|
|
|
|
assert.deepEqual(calls[1], 'outlierDetection');
|
|
|
|
|
assert.deepEqual(calls[2], 'calibrate');
|
|
|
|
|
assert.deepEqual(calls[3], ['measurement', 12.3]);
|
|
|
|
|
});
|
|
|
|
|
|
2026-05-10 20:39:54 +02:00
|
|
|
test('registration emits delayed child.register message on output 2', () => {
|
2026-02-19 17:37:21 +01:00
|
|
|
const inst = Object.create(NodeClass.prototype);
|
|
|
|
|
const node = makeNodeStub();
|
|
|
|
|
|
|
|
|
|
inst.node = node;
|
|
|
|
|
inst.config = { functionality: { positionVsParent: 'upstream', distance: 5 } };
|
|
|
|
|
|
|
|
|
|
const originalSetTimeout = global.setTimeout;
|
|
|
|
|
global.setTimeout = (fn) => { fn(); return 1; };
|
|
|
|
|
try {
|
2026-05-10 20:39:54 +02:00
|
|
|
inst._scheduleRegistration();
|
2026-02-19 17:37:21 +01:00
|
|
|
} finally {
|
|
|
|
|
global.setTimeout = originalSetTimeout;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert.equal(node._sent.length, 1);
|
2026-05-10 20:39:54 +02:00
|
|
|
assert.equal(node._sent[0][2].topic, 'child.register');
|
2026-02-19 17:37:21 +01:00
|
|
|
assert.equal(node._sent[0][2].positionVsParent, 'upstream');
|
|
|
|
|
assert.equal(node._sent[0][2].distance, 5);
|
|
|
|
|
});
|