'use strict'; const assert = require('node:assert/strict'); const fs = require('node:fs'); const path = require('node:path'); const test = require('node:test'); const workspace = require('../../renderer/modules/title-workspace'); const root = path.join(__dirname, '..', '..'); test('one canonical title projects multiple copies and confirmed installs as distinct locations', () => { const model = workspace.project({ id: 'title-1', localCopies: [ { id: 'copy-a', volume: { label: 'Archive A', device: { availabilityState: 'available' } }, version: { value: '1.00' } }, { id: 'copy-b', volume: { label: 'Archive B', device: { availabilityState: 'available' } }, version: { value: '1.02' } } ], consoleInstalls: [ { id: 'install-a', consoleName: 'Living room PS5', presenceState: 'present', version: { value: '1.02' } }, { id: 'install-b', consoleName: 'Lab PS5', presenceState: 'unknown' } ], protection: { state: 'healthy' } }); assert.equal(model.locations.length, 4); assert.equal(model.localCopies.length, 2); assert.equal(model.consoleInstalls.length, 2); assert.equal(model.installed, true); assert.deepEqual(model.badges.map(item => item.code), ['installed', 'local-copy', 'protected']); }); test('missing drive badge is derived from device evidence without erasing the copy', () => { const model = workspace.project({ id: 'title-2', localCopies: [{ id: 'copy-a', volume: { label: 'USB Archive', device: { availabilityState: 'disconnected' } } }], consoleInstalls: [] }); assert.equal(model.locations.length, 1); assert.equal(model.locations[0].missing, true); assert.equal(model.missingDrive, true); assert.ok(model.badges.some(item => item.code === 'missing-drive')); assert.ok(model.badges.some(item => item.code === 'needs-protection')); }); test('title detail exposes the required accessible tabs and responsive layout', () => { const html = fs.readFileSync(path.join(root, 'renderer', 'index.html'), 'utf8'); const css = fs.readFileSync(path.join(root, 'renderer', 'styles', 'title-workspace.css'), 'utf8'); const stateSource = fs.readFileSync(path.join(root, 'renderer', 'modules', 'state.js'), 'utf8'); const requiredTabs = ['copies', 'packages', 'compatibility', 'saves', 'trophies', 'media', 'activity']; for (const tab of requiredTabs) { assert.match(html, new RegExp(`role="tab"[^>]+aria-controls="mpanel-${tab}"[^>]+data-mtab="${tab}"`)); assert.match(html, new RegExp(`id="mpanel-${tab}"[^>]+role="tabpanel"`)); } assert.match(html, /data-mtab="info"[^>]*>Overview/); assert.match(html, /data-mtab="patches"[^>]*>Updates/); assert.match(css, /@media\s*\(max-width:\s*680px\)/); assert.match(css, /grid-template-columns:\s*1fr/); assert.match(stateSource, /ArrowLeft/); assert.match(stateSource, /ArrowRight/); assert.match(stateSource, /Home/); assert.match(stateSource, /End/); });