188 lines
6.6 KiB
JavaScript
188 lines
6.6 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const NodeClass = require('../../src/nodeClass');
|
|
const { makeNodeStub, makeREDStub } = require('../helpers/factories');
|
|
|
|
test('input handler routes topics to source methods', () => {
|
|
const inst = Object.create(NodeClass.prototype);
|
|
const node = makeNodeStub();
|
|
|
|
const calls = [];
|
|
inst.node = node;
|
|
inst.RED = makeREDStub({
|
|
child1: {
|
|
source: { id: 'child-source' },
|
|
},
|
|
});
|
|
|
|
inst.source = {
|
|
childRegistrationUtils: {
|
|
registerChild(childSource, pos) {
|
|
calls.push(['registerChild', childSource, pos]);
|
|
},
|
|
},
|
|
setMode(mode) {
|
|
calls.push(['setMode', mode]);
|
|
},
|
|
handleInput(source, action, parameter) {
|
|
calls.push(['handleInput', source, action, parameter]);
|
|
},
|
|
showWorkingCurves() {
|
|
return { ok: true };
|
|
},
|
|
showCoG() {
|
|
return { cog: 1 };
|
|
},
|
|
updateSimulatedMeasurement(type, position, value) {
|
|
calls.push(['updateSimulatedMeasurement', type, position, value]);
|
|
},
|
|
updateMeasuredPressure(value, position) {
|
|
calls.push(['updateMeasuredPressure', value, position]);
|
|
},
|
|
updateMeasuredFlow(value, position) {
|
|
calls.push(['updateMeasuredFlow', value, position]);
|
|
},
|
|
updateMeasuredPower(value, position) {
|
|
calls.push(['updateMeasuredPower', value, position]);
|
|
},
|
|
updateMeasuredTemperature(value, position) {
|
|
calls.push(['updateMeasuredTemperature', value, position]);
|
|
},
|
|
isUnitValidForType() {
|
|
return true;
|
|
},
|
|
};
|
|
|
|
inst._attachInputHandler();
|
|
const onInput = node._handlers.input;
|
|
|
|
onInput({ topic: 'setMode', payload: 'auto' }, () => {}, () => {});
|
|
onInput({ topic: 'execSequence', payload: { source: 'GUI', action: 'execSequence', parameter: 'startup' } }, () => {}, () => {});
|
|
onInput({ topic: 'flowMovement', payload: { source: 'GUI', action: 'flowMovement', setpoint: 123 } }, () => {}, () => {});
|
|
onInput({ topic: 'emergencystop', payload: { source: 'GUI', action: 'emergencystop' } }, () => {}, () => {});
|
|
onInput({ topic: 'registerChild', payload: 'child1', positionVsParent: 'downstream' }, () => {}, () => {});
|
|
onInput({ topic: 'simulateMeasurement', payload: { type: 'pressure', position: 'upstream', value: 250, unit: 'mbar' } }, () => {}, () => {});
|
|
onInput({ topic: 'simulateMeasurement', payload: { type: 'power', position: 'atEquipment', value: 7.5, unit: 'kW' } }, () => {}, () => {});
|
|
|
|
assert.deepEqual(calls[0], ['setMode', 'auto']);
|
|
assert.deepEqual(calls[1], ['handleInput', 'GUI', 'execSequence', 'startup']);
|
|
assert.deepEqual(calls[2], ['handleInput', 'GUI', 'flowMovement', 123]);
|
|
assert.deepEqual(calls[3], ['handleInput', 'GUI', 'emergencystop', undefined]);
|
|
assert.deepEqual(calls[4], ['registerChild', { id: 'child-source' }, 'downstream']);
|
|
assert.deepEqual(calls[5], ['updateSimulatedMeasurement', 'pressure', 'upstream', 250]);
|
|
assert.deepEqual(calls[6], ['updateMeasuredPower', 7.5, 'atEquipment']);
|
|
});
|
|
|
|
test('simulateMeasurement warns and ignores invalid payloads', () => {
|
|
const inst = Object.create(NodeClass.prototype);
|
|
const node = makeNodeStub();
|
|
|
|
const calls = [];
|
|
inst.node = node;
|
|
inst.RED = makeREDStub();
|
|
inst.source = {
|
|
childRegistrationUtils: { registerChild() {} },
|
|
setMode() {},
|
|
handleInput() {},
|
|
showWorkingCurves() { return {}; },
|
|
showCoG() { return {}; },
|
|
updateSimulatedMeasurement() { calls.push('updateSimulatedMeasurement'); },
|
|
updateMeasuredPressure() { calls.push('updateMeasuredPressure'); },
|
|
updateMeasuredFlow() { calls.push('updateMeasuredFlow'); },
|
|
updateMeasuredPower() { calls.push('updateMeasuredPower'); },
|
|
updateMeasuredTemperature() { calls.push('updateMeasuredTemperature'); },
|
|
};
|
|
|
|
inst._attachInputHandler();
|
|
const onInput = node._handlers.input;
|
|
|
|
onInput({ topic: 'simulateMeasurement', payload: { type: 'pressure', position: 'upstream', value: 'not-a-number' } }, () => {}, () => {});
|
|
onInput({ topic: 'simulateMeasurement', payload: { type: 'flow', position: 'upstream', value: 12 } }, () => {}, () => {});
|
|
onInput({ topic: 'simulateMeasurement', payload: { type: 'unknown', position: 'upstream', value: 12, unit: 'm3/h' } }, () => {}, () => {});
|
|
|
|
assert.equal(calls.length, 0);
|
|
assert.equal(node._warns.length, 3);
|
|
assert.match(String(node._warns[0]), /finite number/i);
|
|
assert.match(String(node._warns[1]), /payload\.unit is required/i);
|
|
assert.match(String(node._warns[2]), /unsupported simulatemeasurement type/i);
|
|
});
|
|
|
|
test('status shows warning when pressure inputs are not initialized', () => {
|
|
const inst = Object.create(NodeClass.prototype);
|
|
const node = makeNodeStub();
|
|
|
|
inst.node = node;
|
|
inst.source = {
|
|
currentMode: 'virtualControl',
|
|
state: {
|
|
getCurrentState() {
|
|
return 'operational';
|
|
},
|
|
getCurrentPosition() {
|
|
return 50;
|
|
},
|
|
},
|
|
getPressureInitializationStatus() {
|
|
return { initialized: false, hasUpstream: false, hasDownstream: false, hasDifferential: false };
|
|
},
|
|
measurements: {
|
|
type() {
|
|
return {
|
|
variant() {
|
|
return {
|
|
position() {
|
|
return { getCurrentValue() { return 0; } };
|
|
},
|
|
};
|
|
},
|
|
};
|
|
},
|
|
},
|
|
};
|
|
|
|
const status = inst._updateNodeStatus();
|
|
const statusAgain = inst._updateNodeStatus();
|
|
|
|
assert.equal(status.fill, 'yellow');
|
|
assert.equal(status.shape, 'ring');
|
|
assert.match(status.text, /pressure not initialized/i);
|
|
assert.equal(statusAgain.fill, 'yellow');
|
|
assert.equal(node._warns.length, 1);
|
|
assert.match(String(node._warns[0]), /Pressure input is not initialized/i);
|
|
});
|
|
|
|
test('showWorkingCurves and CoG route reply messages to process output index', () => {
|
|
const inst = Object.create(NodeClass.prototype);
|
|
const node = makeNodeStub();
|
|
inst.node = node;
|
|
inst.RED = makeREDStub();
|
|
inst.source = {
|
|
childRegistrationUtils: { registerChild() {} },
|
|
setMode() {},
|
|
handleInput() {},
|
|
showWorkingCurves() {
|
|
return { curve: [1, 2, 3] };
|
|
},
|
|
showCoG() {
|
|
return { cog: 0.77 };
|
|
},
|
|
};
|
|
|
|
inst._attachInputHandler();
|
|
const onInput = node._handlers.input;
|
|
const sent = [];
|
|
const send = (out) => sent.push(out);
|
|
|
|
onInput({ topic: 'showWorkingCurves', payload: { request: true } }, send, () => {});
|
|
onInput({ topic: 'CoG', payload: { request: true } }, send, () => {});
|
|
|
|
assert.equal(sent.length, 2);
|
|
assert.equal(Array.isArray(sent[0]), true);
|
|
assert.equal(sent[0].length, 3);
|
|
assert.equal(sent[0][0].topic, 'showWorkingCurves');
|
|
assert.equal(sent[0][1], null);
|
|
assert.equal(sent[0][2], null);
|
|
assert.equal(sent[1][0].topic, 'showCoG');
|
|
});
|