60 lines
2.7 KiB
JavaScript
60 lines
2.7 KiB
JavaScript
|
|
const test = require('node:test');
|
||
|
|
const assert = require('node:assert/strict');
|
||
|
|
|
||
|
|
const Machine = require('../../src/specificClass');
|
||
|
|
const { makeMachineConfig, makeStateConfig } = require('../helpers/factories');
|
||
|
|
|
||
|
|
test('emergencystop sequence reaches off state from operational', async () => {
|
||
|
|
const machine = new Machine(makeMachineConfig(), makeStateConfig());
|
||
|
|
|
||
|
|
// First start the machine
|
||
|
|
await machine.handleInput('parent', 'execSequence', 'startup');
|
||
|
|
assert.equal(machine.state.getCurrentState(), 'operational');
|
||
|
|
|
||
|
|
// Execute emergency stop
|
||
|
|
await machine.handleInput('GUI', 'emergencystop');
|
||
|
|
assert.equal(machine.state.getCurrentState(), 'off');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('emergencystop sequence reaches off state from idle', async () => {
|
||
|
|
const machine = new Machine(makeMachineConfig(), makeStateConfig());
|
||
|
|
assert.equal(machine.state.getCurrentState(), 'idle');
|
||
|
|
|
||
|
|
await machine.handleInput('GUI', 'emergencystop');
|
||
|
|
assert.equal(machine.state.getCurrentState(), 'off');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('emergencystop clears predicted flow and power to zero', async () => {
|
||
|
|
const machine = new Machine(makeMachineConfig(), makeStateConfig());
|
||
|
|
|
||
|
|
// Start and set a position so predictions are non-zero
|
||
|
|
await machine.handleInput('parent', 'execSequence', 'startup');
|
||
|
|
machine.updateMeasuredPressure(1000, 'downstream', { timestamp: Date.now(), unit: 'mbar', childName: 'pt-down' });
|
||
|
|
await machine.handleInput('parent', 'execMovement', 50);
|
||
|
|
|
||
|
|
const flowBefore = machine.measurements.type('flow').variant('predicted').position('downstream').getCurrentValue();
|
||
|
|
assert.ok(flowBefore > 0, 'Flow should be positive before emergency stop');
|
||
|
|
|
||
|
|
// Emergency stop
|
||
|
|
await machine.handleInput('GUI', 'emergencystop');
|
||
|
|
|
||
|
|
const flowAfter = machine.measurements.type('flow').variant('predicted').position('downstream').getCurrentValue();
|
||
|
|
const powerAfter = machine.measurements.type('power').variant('predicted').position('atEquipment').getCurrentValue();
|
||
|
|
assert.equal(flowAfter, 0, 'Flow should be zero after emergency stop');
|
||
|
|
assert.equal(powerAfter, 0, 'Power should be zero after emergency stop');
|
||
|
|
});
|
||
|
|
|
||
|
|
test('emergencystop is rejected when source is not allowed in current mode', async () => {
|
||
|
|
const machine = new Machine(makeMachineConfig(), makeStateConfig());
|
||
|
|
|
||
|
|
// In auto mode, only 'parent' source is typically allowed for sequences
|
||
|
|
machine.setMode('auto');
|
||
|
|
await machine.handleInput('parent', 'execSequence', 'startup');
|
||
|
|
assert.equal(machine.state.getCurrentState(), 'operational');
|
||
|
|
|
||
|
|
// GUI source attempting emergency stop in auto mode — should still work
|
||
|
|
// because emergencystop is allowed from all sources in config
|
||
|
|
await machine.handleInput('GUI', 'emergencystop');
|
||
|
|
// If we get here without throwing, action was either accepted or safely rejected
|
||
|
|
});
|