Files
chimera-Public/test/server/ch-0204-install-destination.test.js

76 lines
3.6 KiB
JavaScript

'use strict';
const assert = require('node:assert/strict');
const fs = require('node:fs');
const path = require('node:path');
const test = require('node:test');
const { createInstallDestinationService } = require('../../src/services/install-destination-service');
const now = 10_000_000;
function volume(overrides = {}) {
return {
id: 10,
stableVolumeKey: 'internal',
mountPath: '/mnt/sandbox/pfsmnt',
capacityBytes: 1_000,
freeBytes: 600,
capacityEvidence: { source: 'sentinel', observedAt: now - 1_000 },
capabilities: { canInstall: true },
capabilityEvidence: { source: 'sentinel', observedAt: now - 1_000 },
availabilityState: 'available',
...overrides,
};
}
function service(current) {
return createInstallDestinationService({
now: () => now,
staleAfterMs: 60_000,
inventory: { list: () => ({ devices: [{ id: 1, displayName: 'PS5', deviceType: 'internal', availabilityState: 'available', volumes: [current.value] }] }) },
});
}
test('capacity policy reports sufficient and insufficient projected space', () => {
const current = { value: volume() };
const selector = service(current);
const sufficient = selector.listDestinations({ requiredBytes: 500, titleId: 'PPSA00001' }).destinations[0];
assert.equal(sufficient.eligible, true);
assert.equal(sufficient.projectedFreeBytes, 100);
const insufficient = selector.listDestinations({ requiredBytes: 700, titleId: 'PPSA00001' }).destinations[0];
assert.equal(insufficient.eligible, false);
assert.ok(insufficient.reasons.includes('insufficient-capacity'));
});
test('offline volume and disabled install capability explain ineligibility', () => {
const current = { value: volume({ availabilityState: 'unavailable', capabilities: { canInstall: false } }) };
const result = service(current).listDestinations({ requiredBytes: 100 }).destinations[0];
assert.ok(result.reasons.includes('offline-volume'));
assert.ok(result.reasons.includes('install-capability-disabled'));
});
test('stale telemetry blocks normal destination selection', () => {
const current = { value: volume({ capacityEvidence: { source: 'sentinel', observedAt: now - 120_000 } }) };
const result = service(current).listDestinations({ requiredBytes: 100 }).destinations[0];
assert.equal(result.eligible, false);
assert.ok(result.reasons.includes('stale-capacity-telemetry'));
});
test('execution resolves the selected volume again and rejects changed evidence', () => {
const current = { value: volume() };
const selector = service(current);
assert.equal(selector.resolveForExecution({ volumeId: 10, requiredBytes: 500, titleId: 'PPSA00001' }).suggestedRemotePath, '/mnt/sandbox/pfsmnt/PPSA00001-app');
current.value = volume({ freeBytes: 100 });
assert.throws(() => selector.resolveForExecution({ volumeId: 10, requiredBytes: 500, titleId: 'PPSA00001' }), /no longer eligible.*insufficient-capacity/i);
});
test('normal UI submits volume id and keeps raw path behind Expert details', () => {
const root = path.join(__dirname, '..', '..');
const html = fs.readFileSync(path.join(root, 'renderer', 'index.html'), 'utf8');
const modal = fs.readFileSync(path.join(root, 'renderer', 'modules', 'modal.js'), 'utf8');
const registry = fs.readFileSync(path.join(root, 'src', 'server', 'create-registry.js'), 'utf8');
assert.match(html, /<select id="install-destination-volume"/);
assert.match(html, /<details id="install-expert-destination"[^>]+data-expert-only="true"/);
assert.match(modal, /destinationVolumeId: destination\.destinationVolumeId/);
assert.match(registry, /resolveForExecution\(\{ volumeId: input\.destinationVolumeId, requiredBytes, titleId: id \}\)/);
});