const test = require('node:test'); const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); function loadBasicFlow() { const flowPath = path.join(__dirname, '../../examples/basic.flow.json'); return JSON.parse(fs.readFileSync(flowPath, 'utf8')); } function makeContextStub() { const store = {}; return { get(key) { return store[key]; }, set(key, value) { store[key] = value; }, }; } test('basic flow parser routes predicted_power to output index 2 with numeric payload', () => { const flow = loadBasicFlow(); const parser = flow.find((n) => n.id === 'rm_parse_output'); assert.ok(parser, 'rm_parse_output node should exist'); assert.equal(parser.outputs, 11); const func = new Function('msg', 'context', 'node', parser.func); const context = makeContextStub(); const node = { send() {} }; const msg = { payload: { 'flow.predicted.downstream.default': 220, 'power.predicted.atequipment.default': 50, ctrl: 40, NCogPercent: 72, state: 'operational', mode: 'virtualControl', runtime: 10.2, moveTimeleft: 0, maintenanceTime: 150.5, }, }; const out = func(msg, context, node); assert.ok(Array.isArray(out)); assert.equal(out.length, 11); assert.equal(out[1].topic, 'predicted_power'); assert.equal(typeof out[1].payload, 'number'); assert.ok(Number.isFinite(out[1].payload)); assert.equal(out[1].payload, 50); }); test('basic flow parser output index wiring matches chart nodes', () => { const flow = loadBasicFlow(); const parser = flow.find((n) => n.id === 'rm_parse_output'); const powerChart = flow.find((n) => n.id === 'rm_chart_power'); assert.ok(parser, 'rm_parse_output node should exist'); assert.ok(powerChart, 'rm_chart_power node should exist'); assert.equal(parser.wires[1][0], 'rm_chart_power'); assert.equal(powerChart.type, 'ui-chart'); assert.equal(powerChart.chartType, 'line'); assert.equal(powerChart.xAxisType, 'time'); }); test('basic flow parser routes pressure series to explicit pressure charts', () => { const flow = loadBasicFlow(); const parser = flow.find((n) => n.id === 'rm_parse_output'); const upChart = flow.find((n) => n.id === 'rm_chart_pressure_up'); const downChart = flow.find((n) => n.id === 'rm_chart_pressure_down'); const deltaChart = flow.find((n) => n.id === 'rm_chart_pressure_delta'); assert.ok(parser, 'rm_parse_output node should exist'); assert.ok(upChart, 'rm_chart_pressure_up node should exist'); assert.ok(downChart, 'rm_chart_pressure_down node should exist'); assert.ok(deltaChart, 'rm_chart_pressure_delta node should exist'); assert.equal(parser.wires[5][0], 'rm_chart_pressure_up'); assert.equal(parser.wires[6][0], 'rm_chart_pressure_down'); assert.equal(parser.wires[7][0], 'rm_chart_pressure_delta'); }); test('basic flow parser suppresses pressure chart messages when pressure inputs are incomplete', () => { const flow = loadBasicFlow(); const parser = flow.find((n) => n.id === 'rm_parse_output'); assert.ok(parser, 'rm_parse_output node should exist'); const func = new Function('msg', 'context', 'node', parser.func); const context = makeContextStub(); const node = { send() {} }; // Only upstream present: downstream/delta chart outputs should be null let out = func({ payload: { 'pressure.measured.upstream.default': 950 } }, context, node); assert.equal(out[5]?.topic, 'pressure_upstream'); assert.equal(out[6], null); assert.equal(out[7], null); // Once downstream arrives, delta should be emitted as finite numeric payload out = func({ payload: { 'pressure.measured.downstream.default': 1200 } }, context, node); assert.equal(out[6]?.topic, 'pressure_downstream'); assert.equal(out[7]?.topic, 'pressure_delta'); assert.equal(typeof out[7].payload, 'number'); assert.ok(Number.isFinite(out[7].payload)); });