const test = require('node:test'); const assert = require('node:assert/strict'); const MeasurementContainer = require('../src/measurements/MeasurementContainer.js'); function makeContainer() { return new MeasurementContainer({ windowSize: 10, defaultUnits: { flow: 'm3/h', pressure: 'mbar', }, }); } test('stores and retrieves measurements via chain API', () => { const c = makeContainer(); c.type('flow').variant('measured').position('upstream').value(100, 1, 'm3/h'); assert.equal(c.type('flow').variant('measured').position('upstream').getCurrentValue(), 100); assert.equal(c.type('flow').variant('measured').position('upstream').exists(), true); }); test('distance(null) auto-derives from position mapping', () => { const c = makeContainer(); c.type('pressure').variant('measured').position('upstream').distance(null).value(5, 1, 'mbar'); const m = c.type('pressure').variant('measured').position('upstream').get(); assert.equal(m.distance, Number.POSITIVE_INFINITY); }); test('getLaggedSample with requested unit converts sample value', () => { const c = makeContainer(); c.type('flow').variant('measured').position('upstream').value(3.6, 1, 'm3/h'); c.type('flow').variant('measured').position('upstream').value(7.2, 2, 'm3/h'); const previous = c.type('flow').variant('measured').position('upstream').getLaggedSample(1, 'm3/s'); assert.ok(previous); assert.equal(previous.unit, 'm3/s'); assert.ok(Math.abs(previous.value - 0.001) < 1e-8); }); test('difference computes current and average delta between positions', () => { const c = makeContainer(); c.type('pressure').variant('measured').position('downstream').value(120, 1, 'mbar'); c.type('pressure').variant('measured').position('downstream').value(130, 2, 'mbar'); c.type('pressure').variant('measured').position('upstream').value(100, 1, 'mbar'); c.type('pressure').variant('measured').position('upstream').value(110, 2, 'mbar'); const diff = c.type('pressure').variant('measured').difference(); assert.equal(diff.value, 20); assert.equal(diff.avgDiff, 20); assert.equal(diff.unit, 'mbar'); }); test('_convertPositionNum2Str maps signs to labels', () => { const c = makeContainer(); assert.equal(c._convertPositionNum2Str(0), 'atEquipment'); assert.equal(c._convertPositionNum2Str(1), 'downstream'); assert.equal(c._convertPositionNum2Str(-1), 'upstream'); }); test('storeCanonical stores anchor unit internally and can emit preferred output units', () => { const c = new MeasurementContainer({ windowSize: 10, autoConvert: true, defaultUnits: { flow: 'm3/h' }, preferredUnits: { flow: 'm3/h' }, canonicalUnits: { flow: 'm3/s' }, storeCanonical: true, }); c.type('flow').variant('measured').position('upstream').value(3.6, 1, 'm3/h'); const internal = c.type('flow').variant('measured').position('upstream').getCurrentValue(); assert.ok(Math.abs(internal - 0.001) < 1e-9); const flat = c.getFlattenedOutput({ requestedUnits: { flow: 'm3/h' } }); assert.ok(Math.abs(flat['flow.measured.upstream.default'] - 3.6) < 1e-9); }); test('strict unit validation rejects missing required unit and incompatible units', () => { const c = new MeasurementContainer({ windowSize: 10, strictUnitValidation: true, throwOnInvalidUnit: true, requireUnitForTypes: ['flow'], }); assert.throws(() => { c.type('flow').variant('measured').position('upstream').value(10, 1); }, /Missing source unit/i); assert.throws(() => { c.type('flow').variant('measured').position('upstream').value(10, 1, 'mbar'); }, /Incompatible|unknown source unit/i); });