import assert from 'node:assert/strict' import { spawnSync } from 'node:child_process' import { fileURLToPath } from 'node:url' const fixture = new URL('./t56-live-fixture.mjs', import.meta.url).href const verifier = fileURLToPath(new URL('./t56-latest-live.mjs', import.meta.url)) const cases = [ ['normal', null], ['zero', null], ['missing', null], ['wrong-unit', /source unit mismatch/], ['wrong-node', /Source node identity mismatch/], ['invalid-time', /invalid source timestamp/], ['phantom-temperature', /Missing real source metric ENV_NODE_2_TEMPERATURE/], ['no-source', /Node 2: no source must not produce a reading/], ] for (const [scenario, expectedFailure] of cases) { const result = spawnSync(process.execPath, ['--import', fixture, verifier, 'http://fixture.invalid/api/cockpit/v1'], { encoding: 'utf8', timeout: 15000, env: { ...process.env, T56_LIVE_SCENARIO: scenario }, }) assert.ifError(result.error) assert.equal(result.status, expectedFailure ? 1 : 0, `${scenario}: ${result.stderr}`) if (expectedFailure) assert.match(result.stderr, expectedFailure, `${scenario}: failure must identify the actual assertion`) console.log(`PASS ${scenario}: ${expectedFailure ? 'expected assertion caught' : 'source readings match'}`) } console.log(`PASS live-verifier guards: ${cases.length}/${cases.length} offline transport scenarios`)