updates
This commit is contained in:
109
test/basic/nodeClass-config.basic.test.js
Normal file
109
test/basic/nodeClass-config.basic.test.js
Normal file
@@ -0,0 +1,109 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const NodeClass = require('../../src/nodeClass');
|
||||
const { makeNodeStub } = require('../helpers/factories');
|
||||
|
||||
function makeUiConfig(overrides = {}) {
|
||||
return {
|
||||
unit: 'm3/h',
|
||||
enableLog: true,
|
||||
logLevel: 'debug',
|
||||
supplier: 'hidrostal',
|
||||
category: 'machine',
|
||||
assetType: 'pump',
|
||||
model: 'hidrostal-H05K-S03R',
|
||||
curvePressureUnit: 'mbar',
|
||||
curveFlowUnit: 'm3/h',
|
||||
curvePowerUnit: 'kW',
|
||||
curveControlUnit: '%',
|
||||
positionVsParent: 'atEquipment',
|
||||
speed: 1,
|
||||
movementMode: 'staticspeed',
|
||||
startup: 0,
|
||||
warmup: 0,
|
||||
shutdown: 0,
|
||||
cooldown: 0,
|
||||
...overrides,
|
||||
};
|
||||
}
|
||||
|
||||
test('_loadConfig maps legacy editor fields for asset identity', () => {
|
||||
const inst = Object.create(NodeClass.prototype);
|
||||
inst.node = makeNodeStub();
|
||||
inst.name = 'rotatingMachine';
|
||||
|
||||
inst._loadConfig(
|
||||
makeUiConfig({
|
||||
uuid: 'uuid-from-editor',
|
||||
assetTagNumber: 'TAG-123',
|
||||
}),
|
||||
inst.node
|
||||
);
|
||||
|
||||
assert.equal(inst.config.asset.uuid, 'uuid-from-editor');
|
||||
assert.equal(inst.config.asset.tagCode, 'TAG-123');
|
||||
assert.equal(inst.config.asset.tagNumber, 'TAG-123');
|
||||
});
|
||||
|
||||
test('_loadConfig prefers explicit assetUuid/assetTagCode when present', () => {
|
||||
const inst = Object.create(NodeClass.prototype);
|
||||
inst.node = makeNodeStub();
|
||||
inst.name = 'rotatingMachine';
|
||||
|
||||
inst._loadConfig(
|
||||
makeUiConfig({
|
||||
uuid: 'legacy-uuid',
|
||||
assetUuid: 'explicit-uuid',
|
||||
assetTagNumber: 'legacy-tag',
|
||||
assetTagCode: 'explicit-tag',
|
||||
}),
|
||||
inst.node
|
||||
);
|
||||
|
||||
assert.equal(inst.config.asset.uuid, 'explicit-uuid');
|
||||
assert.equal(inst.config.asset.tagCode, 'explicit-tag');
|
||||
});
|
||||
|
||||
test('_loadConfig builds explicit curveUnits and falls back for invalid flow unit', () => {
|
||||
const inst = Object.create(NodeClass.prototype);
|
||||
inst.node = makeNodeStub();
|
||||
inst.name = 'rotatingMachine';
|
||||
|
||||
inst._loadConfig(
|
||||
makeUiConfig({
|
||||
unit: 'not-a-unit',
|
||||
curvePressureUnit: 'mbar',
|
||||
curveFlowUnit: 'm3/h',
|
||||
curvePowerUnit: 'kW',
|
||||
curveControlUnit: '%',
|
||||
}),
|
||||
inst.node
|
||||
);
|
||||
|
||||
assert.equal(inst.config.general.unit, 'm3/h');
|
||||
assert.equal(inst.config.asset.unit, 'm3/h');
|
||||
assert.equal(inst.config.asset.curveUnits.pressure, 'mbar');
|
||||
assert.equal(inst.config.asset.curveUnits.flow, 'm3/h');
|
||||
assert.equal(inst.config.asset.curveUnits.power, 'kW');
|
||||
assert.equal(inst.config.asset.curveUnits.control, '%');
|
||||
assert.ok(inst.node._warns.length >= 1);
|
||||
});
|
||||
|
||||
test('_setupSpecificClass propagates logging settings into state config', () => {
|
||||
const inst = Object.create(NodeClass.prototype);
|
||||
inst.node = makeNodeStub();
|
||||
inst.name = 'rotatingMachine';
|
||||
const uiConfig = makeUiConfig({
|
||||
enableLog: true,
|
||||
logLevel: 'warn',
|
||||
uuid: 'uuid-test',
|
||||
assetTagNumber: 'TAG-9',
|
||||
});
|
||||
|
||||
inst._loadConfig(uiConfig, inst.node);
|
||||
inst._setupSpecificClass(uiConfig);
|
||||
|
||||
assert.equal(inst.source.state.config.general.logging.enabled, true);
|
||||
assert.equal(inst.source.state.config.general.logging.logLevel, 'warn');
|
||||
});
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -17,6 +17,12 @@ function makeMachineConfig(overrides = {}) {
|
||||
type: 'pump',
|
||||
model: 'hidrostal-H05K-S03R',
|
||||
unit: 'm3/h',
|
||||
curveUnits: {
|
||||
pressure: 'mbar',
|
||||
flow: 'm3/h',
|
||||
power: 'kW',
|
||||
control: '%',
|
||||
},
|
||||
},
|
||||
...overrides,
|
||||
};
|
||||
|
||||
@@ -19,6 +19,21 @@ test('calcEfficiency runs through coolprop path without mocks', () => {
|
||||
const eff = machine.measurements.type('efficiency').variant('predicted').position('atEquipment').getCurrentValue();
|
||||
assert.equal(typeof eff, 'number');
|
||||
assert.ok(eff > 0);
|
||||
|
||||
const pressureDiffPa = (1200 - 800) * 100; // mbar -> Pa
|
||||
const flowM3s = 120 / 3600; // m3/h -> m3/s
|
||||
const expectedHydraulicPower = pressureDiffPa * flowM3s;
|
||||
const expectedHydraulicEfficiency = expectedHydraulicPower / 12000; // 12kW -> W
|
||||
|
||||
const hydraulicPower = machine.measurements.type('hydraulicPower').variant('predicted').position('atEquipment').getCurrentValue('W');
|
||||
const hydraulicEfficiency = machine.measurements.type('nHydraulicEfficiency').variant('predicted').position('atEquipment').getCurrentValue();
|
||||
const head = machine.measurements.type('pumpHead').variant('predicted').position('atEquipment').getCurrentValue('m');
|
||||
|
||||
assert.ok(Number.isFinite(hydraulicPower));
|
||||
assert.ok(Number.isFinite(hydraulicEfficiency));
|
||||
assert.ok(Number.isFinite(head));
|
||||
assert.ok(Math.abs(hydraulicPower - expectedHydraulicPower) < 1);
|
||||
assert.ok(Math.abs(hydraulicEfficiency - expectedHydraulicEfficiency) < 0.01);
|
||||
});
|
||||
|
||||
test('predictions use initialized medium pressure and not the minimum-pressure fallback', () => {
|
||||
@@ -33,7 +48,7 @@ test('predictions use initialized medium pressure and not the minimum-pressure f
|
||||
assert.equal(pressureStatus.initialized, true);
|
||||
assert.equal(pressureStatus.hasDifferential, true);
|
||||
|
||||
const expectedDiff = mediumDownstreamMbar - mediumUpstreamMbar;
|
||||
const expectedDiff = (mediumDownstreamMbar - mediumUpstreamMbar) * 100; // mbar -> Pa canonical
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), expectedDiff);
|
||||
assert.ok(machine.predictFlow.fDimension > 0);
|
||||
});
|
||||
|
||||
75
test/integration/prediction-health.integration.test.js
Normal file
75
test/integration/prediction-health.integration.test.js
Normal file
@@ -0,0 +1,75 @@
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
|
||||
const Machine = require('../../src/specificClass');
|
||||
const { makeMachineConfig, makeStateConfig } = require('../helpers/factories');
|
||||
|
||||
test('flow drift is assessed with NRMSE and exposed in output', () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
|
||||
machine.updateMeasuredPressure(700, 'upstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-up' });
|
||||
machine.updateMeasuredPressure(1100, 'downstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-down' });
|
||||
machine.updatePosition();
|
||||
|
||||
const predictedFlow = machine.measurements
|
||||
.type('flow')
|
||||
.variant('predicted')
|
||||
.position('downstream')
|
||||
.getCurrentValue('m3/h');
|
||||
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
machine.updateMeasuredFlow(predictedFlow * 0.92, 'downstream', {
|
||||
timestamp: Date.now() + i,
|
||||
unit: 'm3/h',
|
||||
childName: 'ft-down',
|
||||
});
|
||||
}
|
||||
|
||||
const output = machine.getOutput();
|
||||
assert.ok(Number.isFinite(output.flowNrmse));
|
||||
assert.equal(typeof output.flowImmediateLevel, 'number');
|
||||
assert.equal(typeof output.flowLongTermLevel, 'number');
|
||||
assert.ok(['high', 'medium', 'low', 'invalid'].includes(output.predictionQuality));
|
||||
assert.ok(Number.isFinite(output.predictionConfidence));
|
||||
assert.equal(output.predictionPressureSource, 'differential');
|
||||
assert.ok(Array.isArray(output.predictionFlags));
|
||||
});
|
||||
|
||||
test('power drift is assessed when measured power is provided', () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
|
||||
machine.updateMeasuredPressure(700, 'upstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-up' });
|
||||
machine.updateMeasuredPressure(1100, 'downstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-down' });
|
||||
machine.updatePosition();
|
||||
|
||||
const predictedPower = machine.measurements
|
||||
.type('power')
|
||||
.variant('predicted')
|
||||
.position('atEquipment')
|
||||
.getCurrentValue('kW');
|
||||
|
||||
for (let i = 0; i < 10; i += 1) {
|
||||
machine.updateMeasuredPower(predictedPower * 1.08, 'atEquipment', {
|
||||
timestamp: Date.now() + i,
|
||||
unit: 'kW',
|
||||
childName: 'power-meter',
|
||||
});
|
||||
}
|
||||
|
||||
const output = machine.getOutput();
|
||||
assert.ok(Number.isFinite(output.powerNrmse));
|
||||
assert.equal(typeof output.powerImmediateLevel, 'number');
|
||||
assert.equal(typeof output.powerLongTermLevel, 'number');
|
||||
});
|
||||
|
||||
test('single-side pressure lowers prediction confidence category', () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
machine.updateMeasuredPressure(950, 'downstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-down' });
|
||||
|
||||
const output = machine.getOutput();
|
||||
assert.equal(output.predictionPressureSource, 'downstream');
|
||||
assert.ok(output.predictionConfidence < 0.9);
|
||||
assert.equal(output.pressureDriftLevel, 1);
|
||||
assert.ok(Array.isArray(output.predictionFlags));
|
||||
assert.ok(output.predictionFlags.includes('single_side_pressure'));
|
||||
});
|
||||
@@ -27,8 +27,8 @@ test('pressure initialization combinations are handled explicitly', () => {
|
||||
assert.equal(status.hasDifferential, false);
|
||||
assert.equal(status.source, 'upstream');
|
||||
const upstreamValue = machine.getMeasuredPressure();
|
||||
assert.equal(Math.round(upstreamValue), upstreamOnly);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), upstreamOnly);
|
||||
assert.equal(Math.round(upstreamValue), upstreamOnly * 100);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), upstreamOnly * 100);
|
||||
|
||||
// downstream only
|
||||
machine = createMachine();
|
||||
@@ -41,8 +41,8 @@ test('pressure initialization combinations are handled explicitly', () => {
|
||||
assert.equal(status.hasDifferential, false);
|
||||
assert.equal(status.source, 'downstream');
|
||||
const downstreamValue = machine.getMeasuredPressure();
|
||||
assert.equal(Math.round(downstreamValue), downstreamOnly);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), downstreamOnly);
|
||||
assert.equal(Math.round(downstreamValue), downstreamOnly * 100);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), downstreamOnly * 100);
|
||||
|
||||
// downstream and upstream
|
||||
machine = createMachine();
|
||||
@@ -57,8 +57,8 @@ test('pressure initialization combinations are handled explicitly', () => {
|
||||
assert.equal(status.hasDifferential, true);
|
||||
assert.equal(status.source, 'differential');
|
||||
const differentialValue = machine.getMeasuredPressure();
|
||||
assert.equal(Math.round(differentialValue), downstream - upstream);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), downstream - upstream);
|
||||
assert.equal(Math.round(differentialValue), (downstream - upstream) * 100);
|
||||
assert.equal(Math.round(machine.predictFlow.fDimension), (downstream - upstream) * 100);
|
||||
});
|
||||
|
||||
test('real pressure child data has priority over simulated dashboard pressure', async () => {
|
||||
@@ -66,7 +66,7 @@ test('real pressure child data has priority over simulated dashboard pressure',
|
||||
|
||||
machine.updateSimulatedMeasurement('pressure', 'upstream', 900, { unit: 'mbar', timestamp: Date.now() });
|
||||
machine.updateSimulatedMeasurement('pressure', 'downstream', 1200, { unit: 'mbar', timestamp: Date.now() });
|
||||
assert.equal(Math.round(machine.getMeasuredPressure()), 300);
|
||||
assert.equal(Math.round(machine.getMeasuredPressure()), 30000);
|
||||
|
||||
const upstreamChild = makeChildMeasurement({ id: 'pt-up-real', name: 'PT Up', positionVsParent: 'upstream', type: 'pressure', unit: 'mbar' });
|
||||
const downstreamChild = makeChildMeasurement({ id: 'pt-down-real', name: 'PT Down', positionVsParent: 'downstream', type: 'pressure', unit: 'mbar' });
|
||||
@@ -77,7 +77,7 @@ test('real pressure child data has priority over simulated dashboard pressure',
|
||||
upstreamChild.measurements.type('pressure').variant('measured').position('upstream').value(700, Date.now(), 'mbar');
|
||||
downstreamChild.measurements.type('pressure').variant('measured').position('downstream').value(1300, Date.now(), 'mbar');
|
||||
|
||||
assert.equal(Math.round(machine.getMeasuredPressure()), 600);
|
||||
assert.equal(Math.round(machine.getMeasuredPressure()), 60000);
|
||||
const status = machine.getPressureInitializationStatus();
|
||||
assert.equal(status.source, 'differential');
|
||||
assert.equal(status.initialized, true);
|
||||
|
||||
@@ -25,3 +25,29 @@ test('registerChild listens to measurement events and stores measured pressure',
|
||||
assert.equal(typeof stored, 'number');
|
||||
assert.equal(Math.round(stored), 123);
|
||||
});
|
||||
|
||||
test('registerChild deduplicates listeners on re-registration', async () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig());
|
||||
const child = makeChildMeasurement({ id: 'pt-dup', positionVsParent: 'downstream', type: 'pressure', unit: 'mbar' });
|
||||
const eventName = 'pressure.measured.downstream';
|
||||
|
||||
let handlerCalls = 0;
|
||||
const originalUpdatePressure = machine.updateMeasuredPressure.bind(machine);
|
||||
machine.updateMeasuredPressure = (...args) => {
|
||||
handlerCalls += 1;
|
||||
return originalUpdatePressure(...args);
|
||||
};
|
||||
|
||||
machine.registerChild(child, 'measurement');
|
||||
machine.registerChild(child, 'measurement');
|
||||
|
||||
assert.equal(child.measurements.emitter.listenerCount(eventName), 1);
|
||||
|
||||
child.measurements
|
||||
.type('pressure')
|
||||
.variant('measured')
|
||||
.position('downstream')
|
||||
.value(321, Date.now(), 'mbar');
|
||||
|
||||
assert.equal(handlerCalls, 1);
|
||||
});
|
||||
|
||||
@@ -12,11 +12,13 @@ test('execSequence startup reaches operational with zero transition times', asyn
|
||||
assert.equal(machine.state.getCurrentState(), 'operational');
|
||||
});
|
||||
|
||||
test('execMovement updates controller position in operational state', async () => {
|
||||
test('execMovement constrains controller position to safe bounds in operational state', async () => {
|
||||
const machine = new Machine(makeMachineConfig(), makeStateConfig({ state: { current: 'operational' } }));
|
||||
const { max } = machine._resolveSetpointBounds();
|
||||
|
||||
await machine.handleInput('parent', 'execMovement', 10);
|
||||
|
||||
const pos = machine.state.getCurrentPosition();
|
||||
assert.ok(pos >= 9.9 && pos <= 10);
|
||||
assert.ok(pos <= max);
|
||||
assert.equal(pos, max);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user