Replace the M3H_TO_M3S constant in control/manual.js and the `* 3600` inline conversion in the status badge with this.unitPolicy.convert calls. Expose unitPolicy on the frozen control context so manual strategies pick it up without reaching into host. Matches the contract direction in .claude/refactor/CONTRACTS.md §6. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
2.3 KiB
JavaScript
72 lines
2.3 KiB
JavaScript
// Unit tests for the manual control strategy.
|
|
// Run with: node --test test/basic/control-manual.basic.test.js
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const { UnitPolicy } = require('generalFunctions');
|
|
const manual = require('../../src/control/manual');
|
|
|
|
const unitPolicy = UnitPolicy.declare({
|
|
canonical: { flow: 'm3/s' },
|
|
output: { flow: 'm3/s' },
|
|
requireUnitForTypes: [],
|
|
});
|
|
|
|
function makeGroup(name) {
|
|
const calls = { handleInput: [] };
|
|
return {
|
|
config: { general: { name } },
|
|
handleInput: async (...args) => { calls.handleInput.push(args); },
|
|
_calls: calls,
|
|
};
|
|
}
|
|
|
|
function makeMachine(name) {
|
|
const calls = { handleInput: [] };
|
|
return {
|
|
config: { general: { name } },
|
|
handleInput: async (...args) => { calls.handleInput.push(args); },
|
|
_calls: calls,
|
|
};
|
|
}
|
|
|
|
function makeLogger() {
|
|
return { info: () => {}, debug: () => {}, warn: () => {}, error: () => {} };
|
|
}
|
|
|
|
test('forwardDemand calls handleInput("parent", canonical m3/s demand) on every machine group', async () => {
|
|
const groups = { a: makeGroup('A'), b: makeGroup('B'), c: makeGroup('C') };
|
|
const ctx = { machineGroups: groups, machines: {}, unitPolicy, logger: makeLogger() };
|
|
|
|
await manual.forwardDemand(ctx, 360);
|
|
|
|
for (const g of Object.values(groups)) {
|
|
assert.equal(g._calls.handleInput.length, 1);
|
|
assert.deepEqual(g._calls.handleInput[0], ['parent', 0.1]);
|
|
}
|
|
});
|
|
|
|
test('forwardDemand with no machineGroups but direct machines splits demand evenly', async () => {
|
|
const machines = { m1: makeMachine('M1'), m2: makeMachine('M2'), m3: makeMachine('M3'), m4: makeMachine('M4') };
|
|
const ctx = { machineGroups: {}, machines, logger: makeLogger() };
|
|
|
|
await manual.forwardDemand(ctx, 80);
|
|
|
|
for (const m of Object.values(machines)) {
|
|
assert.equal(m._calls.handleInput.length, 1);
|
|
assert.deepEqual(m._calls.handleInput[0], ['parent', 'execMovement', 20]);
|
|
}
|
|
});
|
|
|
|
test('run() is a no-op (manual mode is event-driven)', async () => {
|
|
const groups = { a: makeGroup('A') };
|
|
const ctx = { machineGroups: groups, machines: {}, unitPolicy, logger: makeLogger() };
|
|
await manual.run(ctx, { percControl: 0 });
|
|
assert.equal(groups.a._calls.handleInput.length, 0);
|
|
});
|
|
|
|
test('manual exports name === "manual"', () => {
|
|
assert.equal(manual.name, 'manual');
|
|
});
|