'use strict'; const test = require('node:test'); const assert = require('node:assert/strict'); const PredictionHealth = require('../../src/drift/predictionHealth'); const DriftAssessor = require('../../src/drift/driftAssessor'); function makeHealth(overrides = {}) { return new PredictionHealth({ getPressureInitializationStatus: () => ({ initialized: true, hasDifferential: true, source: 'differential', }), isOperational: () => true, applyDriftPenalty: new DriftAssessor({}).applyDriftPenalty.bind(new DriftAssessor({})), ...overrides, }); } test('empty snapshots + differential pressure → nominal health, confidence=0.9', () => { const ph = makeHealth(); const { health, confidence } = ph.evaluate({ flow: null, power: null, pressure: { level: 0, flags: [], source: 'differential' }, }); assert.equal(health.level, 0); assert.ok(Math.abs(confidence - 0.9) < 1e-9); assert.equal(typeof health.message, 'string'); }); test('pressure not initialized + flow drift level 2 → composite level >= 2 and multiple flags', () => { const ph = makeHealth({ getPressureInitializationStatus: () => ({ initialized: false, hasDifferential: false, source: null, }), }); const { health, confidence } = ph.evaluate({ flow: { valid: true, nrmse: 0.3, immediateLevel: 2, longTermLevel: 0 }, power: null, pressure: { level: 2, flags: ['no_pressure_input'], source: null }, }); assert.ok(health.level >= 2); assert.ok(health.flags.includes('no_pressure_input')); assert.ok(health.flags.includes('flow_medium_immediate_drift')); assert.ok(confidence < 0.5); }); test('returned object has both health and confidence', () => { const ph = makeHealth(); const out = ph.evaluate({ flow: null, power: null, pressure: { level: 0, flags: [], source: 'differential' } }); assert.ok('health' in out); assert.ok('confidence' in out); assert.equal(typeof out.confidence, 'number'); assert.equal(typeof out.health.level, 'number'); }); test('non-operational forces confidence=0 and bumps level >=2', () => { const ph = makeHealth({ isOperational: () => false }); const { health, confidence } = ph.evaluate({ flow: null, power: null, pressure: { level: 0, flags: [], source: 'differential' }, }); assert.equal(confidence, 0); assert.ok(health.flags.includes('not_operational')); assert.ok(health.level >= 2); }); test('curve-edge penalty applies when current position is near min/max', () => { const ph = makeHealth({ getCurrentPosition: () => 0.01, resolveSetpointBounds: () => ({ min: 0, max: 1 }), }); const { health, confidence } = ph.evaluate({ flow: null, power: null, pressure: { level: 0, flags: [], source: 'differential' }, }); assert.ok(health.flags.includes('near_curve_edge')); assert.ok(confidence < 0.9); }); test('HealthStatus shape — has the standardised five fields', () => { const ph = makeHealth(); const { health } = ph.evaluate({ flow: null, power: null, pressure: { level: 0, flags: [], source: 'differential' }, }); assert.ok('level' in health); assert.ok('flags' in health); assert.ok('message' in health); assert.ok('source' in health); assert.ok(Array.isArray(health.flags)); });