import test from 'node:test'; import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; test('changed file list has an independently scrollable bounded layout', async () => { const css = await readFile(new URL('../src/renderer/styles.css', import.meta.url), 'utf8'); assert.match(css, /\.main-canvas\.repository-canvas\s*\{[^}]*overflow:\s*hidden/); assert.match(css, /\.file-panel\s*\{[^}]*min-height:\s*0[^}]*overflow:\s*hidden/); assert.match(css, /\.file-list\s*\{[^}]*flex:\s*1 1 auto[^}]*overflow-y:\s*auto/); }); test('commit workflow explains every disabled prerequisite', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(renderer, /Commit message required/); assert.match(renderer, /Enter a commit message to enable commit and push/); assert.match(renderer, /ForgeFlow stages the selected files automatically/); assert.match(renderer, /Commit selected & push to Gitea/); }); test('ITWorx branding is integrated into titlebar and setup', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(renderer, /itworx-mark\.png/); assert.match(renderer, /itworx-wordmark-(?:light|dark)\.png/); }); test('all modal content stays inside the viewport with a persistent action footer', async () => { const css = await readFile(new URL('../src/renderer/styles.css', import.meta.url), 'utf8'); assert.match(css, /\.modal\s*\{[^}]*max-height:\s*calc\(100dvh[^}]*display:\s*flex[^}]*flex-direction:\s*column/); assert.match(css, /\.modal-body\s*\{[^}]*min-height:\s*0[^}]*overflow-y:\s*auto/); assert.match(css, /\.modal-footer\s*\{[^}]*flex:\s*0 0 auto/); }); test('settings provides one-click normalization for legacy Gitea origins', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(renderer, /data-action="normalize-origins"/); assert.match(renderer, /Normalize all origins/); }); test('Git mutations are serialized per repository and expose repair actions', async () => { const ipc = await readFile(new URL('../src/main/ipc.cjs', import.meta.url), 'utf8'); const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(ipc, /repositoryMutations = new Map/); assert.match(ipc, /withRepositoryMutation/); assert.match(ipc, /GIT_LOCKS_RECENT/); assert.match(ipc, /setTimeout\(resolve, 2_500\)/); assert.match(renderer, /data-action="repair-git-locks"/); assert.match(renderer, /Repository troubleshooting/); assert.match(renderer, /data-action="repair-origin"/); assert.match(renderer, /Open guided repository repair/); }); test('SSH secrets are captured before the loading render clears password inputs', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); const passwordCapture = renderer.indexOf("const password = document.querySelector('#server-password')"); const loading = renderer.indexOf("setLoading(true, 'Saving encrypted SSH configuration…')"); assert.ok(passwordCapture >= 0 && loading > passwordCapture); }); test('SSH deployments are polled in the background and Portfolio casing is preserved', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(renderer, /function startOperationPolling\(\)/); assert.match(renderer, /startOperationPolling\(\);/); assert.match(renderer, /Visible container name/); assert.match(renderer, /Compose service \(internal\)/); }); test('deployment profiles expose built-in/uploaded DockerMan icons and automatic metadata repair', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); assert.match(renderer, /Built-in high-contrast ITWorx mark/); assert.match(renderer, /profile-icon-mode/); assert.match(renderer, /Repair DockerMan integration/); assert.match(renderer, /reconcile-deployment/); }); test('repository troubleshooting offers personalized synchronization repair actions', async () => { const renderer = await readFile(new URL('../src/renderer/app.js', import.meta.url), 'utf8'); const ipc = await readFile(new URL('../src/main/ipc.cjs', import.meta.url), 'utf8'); assert.match(renderer, /repair-repository-sync/); assert.match(renderer, /safety branch/); assert.match(ipc, /repository:repair-sync/); });