updates
This commit is contained in:
@@ -12,6 +12,28 @@ test('setpoint rejects negative inputs without throwing', async () => {
|
||||
});
|
||||
});
|
||||
|
||||
test('setpoint is constrained to safe movement/curve bounds', async () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
const requested = [];
|
||||
machine.state.moveTo = async (target) => {
|
||||
requested.push(target);
|
||||
};
|
||||
|
||||
const stateMin = machine.state.movementManager.minPosition;
|
||||
const stateMax = machine.state.movementManager.maxPosition;
|
||||
const curveMin = machine.predictFlow.currentFxyXMin;
|
||||
const curveMax = machine.predictFlow.currentFxyXMax;
|
||||
const min = Math.max(stateMin, curveMin);
|
||||
const max = Math.min(stateMax, curveMax);
|
||||
|
||||
await machine.setpoint(min - 100);
|
||||
await machine.setpoint(max + 100);
|
||||
|
||||
assert.equal(requested.length, 2);
|
||||
assert.equal(requested[0], min);
|
||||
assert.equal(requested[1], max);
|
||||
});
|
||||
|
||||
test('nodeClass _updateNodeStatus returns error status on internal failure', () => {
|
||||
const inst = Object.create(NodeClass.prototype);
|
||||
const node = makeNodeStub();
|
||||
@@ -29,3 +51,24 @@ test('nodeClass _updateNodeStatus returns error status on internal failure', ()
|
||||
assert.equal(status.text, 'Status Error');
|
||||
assert.equal(node._errors.length, 1);
|
||||
});
|
||||
|
||||
test('measurement handlers reject incompatible units', () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
|
||||
assert.equal(machine.isUnitValidForType('flow', 'm3/h'), true);
|
||||
assert.equal(machine.isUnitValidForType('flow', 'mbar'), false);
|
||||
|
||||
machine.updateMeasuredFlow(100, 'downstream', {
|
||||
timestamp: Date.now(),
|
||||
unit: 'mbar',
|
||||
childName: 'bad-ft',
|
||||
});
|
||||
|
||||
const measuredFlow = machine.measurements
|
||||
.type('flow')
|
||||
.variant('measured')
|
||||
.position('downstream')
|
||||
.getCurrentValue();
|
||||
|
||||
assert.equal(measuredFlow, null);
|
||||
});
|
||||
|
||||
@@ -43,9 +43,15 @@ test('input handler routes topics to source methods', () => {
|
||||
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();
|
||||
@@ -53,13 +59,53 @@ test('input handler routes topics to source methods', () => {
|
||||
|
||||
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], ['registerChild', { id: 'child-source' }, 'downstream']);
|
||||
assert.deepEqual(calls[3], ['updateSimulatedMeasurement', 'pressure', 'upstream', 250]);
|
||||
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', () => {
|
||||
|
||||
Reference in New Issue
Block a user