const test = require('node:test'); const assert = require('node:assert/strict'); const EventEmitter = require('events'); const Valve = require('../../../valve/src/specificClass'); const ValveGroupControl = require('../../src/specificClass'); function buildValve({ runtimeOptions = {} } = {}) { return new Valve( { general: { name: 'valve-topology-test', logging: { enabled: false, logLevel: 'error' }, }, asset: { supplier: 'binder', category: 'valve', type: 'control', model: 'ECDV', unit: 'm3/h', }, functionality: { positionVsParent: 'atEquipment', }, }, { general: { logging: { enabled: false, logLevel: 'error' }, }, movement: { speed: 1 }, time: { starting: 0, warmingup: 0, stopping: 0, coolingdown: 0 }, }, runtimeOptions ); } function buildGroup() { return new ValveGroupControl({ general: { name: 'vgc-source-test', logging: { enabled: false, logLevel: 'error' }, unit: 'm3/h', }, functionality: { positionVsParent: 'atEquipment', }, }); } function buildSource({ id, softwareType, serviceType = null, status = 'resolved', }) { const emitter = new EventEmitter(); let contract = { status, serviceType }; return { emitter, config: { general: { id, name: id }, functionality: { softwareType }, asset: { serviceType: serviceType || undefined, }, }, measurements: { emitter: new EventEmitter(), }, getFluidContract() { return { ...contract }; }, setFluidContract(next) { contract = { ...contract, ...next }; }, }; } test('valveGroupControl accepts machine source and syncs upstream flow events', () => { const group = buildGroup(); const machine = buildSource({ id: 'machine-1', softwareType: 'machine', serviceType: 'liquid', }); assert.equal(group.registerChild(machine, 'machine'), true); machine.measurements.emitter.emit('flow.measured.downstream', { value: 150, unit: 'm3/h', }); const totalMeasuredFlow = group.measurements .type('flow') .variant('measured') .position('atEquipment') .getCurrentValue('m3/h'); assert.ok(Math.abs(totalMeasuredFlow - 150) < 1e-9); const contract = group.getFluidContract(); assert.equal(contract.status, 'resolved'); assert.equal(contract.serviceType, 'liquid'); group.destroy(); }); test('valveGroupControl exposes conflict when upstream sources mix fluid contracts', () => { const group = buildGroup(); const machineLiquid = buildSource({ id: 'machine-liquid', softwareType: 'machine', serviceType: 'liquid', }); const machineGas = buildSource({ id: 'machine-gas', softwareType: 'machine', serviceType: 'gas', }); assert.equal(group.registerChild(machineLiquid, 'machine'), true); assert.equal(group.registerChild(machineGas, 'machine'), true); const contract = group.getFluidContract(); assert.equal(contract.status, 'conflict'); assert.deepEqual(new Set(contract.upstreamServiceTypes), new Set(['liquid', 'gas'])); group.destroy(); }); test('valve can validate fluid contract propagated by valveGroupControl', () => { const group = buildGroup(); const machine = buildSource({ id: 'machine-1', softwareType: 'machine', serviceType: 'liquid', }); const valve = buildValve({ runtimeOptions: { serviceType: 'gas' } }); assert.equal(group.registerChild(machine, 'machine'), true); assert.equal(valve.registerChild(group, 'valvegroupcontrol'), true); const compatibility = valve.getFluidCompatibility(); assert.equal(compatibility.status, 'mismatch'); assert.equal(compatibility.expectedServiceType, 'gas'); assert.equal(compatibility.receivedServiceType, 'liquid'); valve.destroy(); group.destroy(); });