'use strict'; const assert = require('node:assert/strict'); const fs = require('fs'); const path = require('path'); const test = require('node:test'); const { createCompatibilityGuidanceService } = require('../../src/services/compatibility-guidance-service'); const { createInstallDestinationService } = require('../../src/services/install-destination-service'); const renderer = require('../../renderer/modules/compatibility-guidance'); const provenance = { key: 'rule', severity: 'info', confidence: 'medium', explanation: 'Evidence rationale.', providerId: 'alpha', revision: 'r7', sourceUrl: 'https://compat.example.org/data.json', evidenceSha256: 'a'.repeat(64), fetchedAt: 1_721_600_000_000, conflictGroup: null }; const serviceFor = (findings, conflicts = []) => createCompatibilityGuidanceService({ compatibility: { merge: () => ({ findings, conflicts }) } }); test('compatible, incompatible, workaround, conflict and unknown remain distinct UI states', () => { const cases = [ ['compatible', [{ ...provenance, state: 'compatible' }], []], ['incompatible', [{ ...provenance, state: 'incompatible', severity: 'warning' }], []], ['workaround', [{ ...provenance, state: 'workaround', explanation: 'Use a verified staging copy.' }], []], ['conflict', [{ ...provenance, state: 'compatible', conflictGroup: 'group' }, { ...provenance, key: 'rule-2', state: 'incompatible', conflictGroup: 'group' }], [{ conflictGroup: 'group', states: ['compatible', 'incompatible'], providers: ['alpha', 'beta'] }]], ['unknown', [], []], ]; for (const [state, findings, conflicts] of cases) { const model = serviceFor(findings, conflicts).evaluate({ titleId: 'PPSA12345' }); assert.equal(model.state, state); assert.match(renderer.markup(model), new RegExp(`data-compatibility-state="${state}"`)); } const html = renderer.markup(serviceFor(cases[0][1]).evaluate({ titleId: 'PPSA12345' })); assert.match(html, /alpha \/ r7 \/ medium confidence/); assert.match(html, /https:\/\/compat\.example\.org\/data\.json/); }); test('only critical high-confidence unconflicted incompatibility blocks destinations', () => { const blockedGuidance = serviceFor([{ ...provenance, state: 'incompatible', severity: 'critical', confidence: 'high' }]); const informationalGuidance = serviceFor([{ ...provenance, state: 'incompatible', severity: 'warning', confidence: 'high' }]); const inventory = { list: () => ({ devices: [{ id: 'device', displayName: 'USB', deviceType: 'usb', availabilityState: 'available', volumes: [{ id: 'volume', stableVolumeKey: 'games', availabilityState: 'available', mountPath: '/mnt/usb', freeBytes: 10_000, capacityBytes: 20_000, capabilities: { canInstall: true }, capacityEvidence: { observedAt: 10_000 }, capabilityEvidence: { observedAt: 10_000 } }] }] }) }; const blocked = createInstallDestinationService({ inventory, compatibility: blockedGuidance, now: () => 10_001 }).listDestinations({ titleId: 'PPSA12345', requiredBytes: 100 }).destinations[0]; assert.equal(blocked.eligible, false); assert.ok(blocked.reasons.includes('compatibility-incompatible')); const allowed = createInstallDestinationService({ inventory, compatibility: informationalGuidance, now: () => 10_001 }).listDestinations({ titleId: 'PPSA12345', requiredBytes: 100 }).destinations[0]; assert.equal(allowed.eligible, true); assert.equal(allowed.compatibility.state, 'incompatible'); }); test('title, destination and recipe surfaces all expose shared rationale inspection', () => { const read = file => fs.readFileSync(path.join(__dirname, '../..', file), 'utf8'); assert.match(read('renderer/modules/title-workspace.js'), /chimeraCompatibilityGuidance\?\.load/); assert.match(read('renderer/modules/install-destination.js'), /chimeraCompatibilityGuidance\?\.markup/); assert.match(read('src/renderer/recipe-editor.js'), /recipe-compatibility-guidance[^]*chimeraCompatibilityGuidance\?\.load/); });