For all 11 nodes with auto-gen markers: wiki/Home.md sections 5 (topic contract) and 9 (data model) regenerated via npm run wiki:all. New Unit column shows '<measure> (default <unit>)' for declared topics, '—' otherwise. Effect column now uses descriptor.description (P11.2 field) overriding the generic per-prefix fallback. For rotatingMachine + reactor: Phase 10 test rewrites — 3 + 8 files moved off private nodeClass internals (_attachInputHandler, _commands, _pendingExtras, _registerChild, _tick, etc.) to the public BaseNodeAdapter surface (node.handlers.input, node.source.*). +6 / +7 net new tests. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
92 lines
3.0 KiB
JavaScript
92 lines
3.0 KiB
JavaScript
'use strict';
|
|
|
|
// Phase 10 rewrite: drives only the public BaseNodeAdapter surface for
|
|
// the nodeClass-level checks, and the public Reactor_CSTR engine surface
|
|
// for the domain-level checks. The pre-refactor private nodeClass methods
|
|
// are gone — `buildDomainConfig` is the documented override hook
|
|
// (CONTRACTS.md §2) and is fair game to call on a real constructed
|
|
// instance.
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const nodeClass = require('../../src/nodeClass');
|
|
const { Reactor_CSTR } = require('../../src/specificClass');
|
|
const { makeReactorConfig, makeUiConfig } = require('../helpers/factories');
|
|
|
|
function makeRED() { return { nodes: { getNode: () => null } }; }
|
|
|
|
function makeNode(id = 'reactor-node-1') {
|
|
const sends = [];
|
|
const statuses = [];
|
|
const handlers = {};
|
|
return {
|
|
id, sends, statuses, handlers,
|
|
send(arr) { sends.push(arr); },
|
|
status(b) { statuses.push(b); },
|
|
on(ev, fn) { handlers[ev] = fn; },
|
|
warn() {}, error() {},
|
|
};
|
|
}
|
|
|
|
function closeNode(node) {
|
|
if (node.handlers.close) node.handlers.close(() => {});
|
|
}
|
|
|
|
test('Reactor_CSTR engine defaults speedUpFactor to 1 when not in config', () => {
|
|
const config = makeReactorConfig();
|
|
const reactor = new Reactor_CSTR(config);
|
|
assert.equal(reactor.speedUpFactor, 1, 'speedUpFactor should default to 1');
|
|
});
|
|
|
|
test('Reactor_CSTR engine accepts speedUpFactor from config', () => {
|
|
const config = makeReactorConfig();
|
|
config.speedUpFactor = 10;
|
|
const reactor = new Reactor_CSTR(config);
|
|
assert.equal(reactor.speedUpFactor, 10, 'speedUpFactor should be read from config');
|
|
});
|
|
|
|
test('Reactor_CSTR engine accepts speedUpFactor = 60 for accelerated simulation', () => {
|
|
const config = makeReactorConfig();
|
|
config.speedUpFactor = 60;
|
|
const reactor = new Reactor_CSTR(config);
|
|
assert.equal(reactor.speedUpFactor, 60, 'speedUpFactor=60 should be accepted');
|
|
});
|
|
|
|
test('buildDomainConfig propagates speedUpFactor from uiConfig', () => {
|
|
const node = makeNode();
|
|
const inst = new nodeClass(makeUiConfig(), makeRED(), node, 'reactor');
|
|
try {
|
|
const dc = inst.buildDomainConfig(makeUiConfig({ speedUpFactor: 5 }));
|
|
assert.equal(dc.reactor.speedUpFactor, 5);
|
|
} finally {
|
|
closeNode(node);
|
|
}
|
|
});
|
|
|
|
test('buildDomainConfig defaults speedUpFactor to 1 when missing from uiConfig', () => {
|
|
const node = makeNode();
|
|
const inst = new nodeClass(makeUiConfig(), makeRED(), node, 'reactor');
|
|
try {
|
|
const ui = makeUiConfig();
|
|
delete ui.speedUpFactor;
|
|
const dc = inst.buildDomainConfig(ui);
|
|
assert.equal(dc.reactor.speedUpFactor, 1);
|
|
} finally {
|
|
closeNode(node);
|
|
}
|
|
});
|
|
|
|
test('updateState with speedUpFactor=1 advances roughly real-time', () => {
|
|
const config = makeReactorConfig();
|
|
config.speedUpFactor = 1;
|
|
config.n_inlets = 1;
|
|
const reactor = new Reactor_CSTR(config);
|
|
|
|
const t0 = reactor.currentTime;
|
|
reactor.updateState(t0 + 2000);
|
|
|
|
const elapsed = reactor.currentTime - t0;
|
|
assert.ok(elapsed < 5000, `Elapsed ${elapsed}ms should be close to 2000ms, not 120000ms (old 60x factor)`);
|
|
});
|