diff options
| author | Paul Buetow <paul@buetow.org> | 2026-05-17 15:25:52 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-05-17 15:25:52 +0300 |
| commit | 914bd7cd6aa14e839332a98d91c30b19865b0cf2 (patch) | |
| tree | 02b11537237a204048589e14ed24938b805e42f7 /web/js/tests/admin-rescan.test.js | |
| parent | 3b24f0e1be832584d6550e8cc3e5d24329f66f90 (diff) | |
Restructure repo: move Go server into player-server/
Diffstat (limited to 'web/js/tests/admin-rescan.test.js')
| -rw-r--r-- | web/js/tests/admin-rescan.test.js | 178 |
1 files changed, 0 insertions, 178 deletions
diff --git a/web/js/tests/admin-rescan.test.js b/web/js/tests/admin-rescan.test.js deleted file mode 100644 index 2ce5f1b..0000000 --- a/web/js/tests/admin-rescan.test.js +++ /dev/null @@ -1,178 +0,0 @@ -import { initKeyboard } from '../keyboard.js'; -import { renderScanProgress, triggerRescan } from '../views/admin-status.js'; -import { readFileSync } from 'node:fs'; - -const failures = []; -const requests = []; -let keydownHandler = null; -let rescanStatus = 200; - -function assert(cond, msg) { - if (!cond) failures.push(msg || 'assertion failed'); -} - -const indicator = mockElement(); -const indicatorText = mockElement(); -const toastEl = { - className: '', - textContent: '', - classList: { remove() {} }, -}; - -globalThis.document = { - addEventListener(type, handler) { - if (type === 'keydown') keydownHandler = handler; - }, - getElementById(id) { - if (id === 'scan-indicator') return indicator; - if (id === 'scan-indicator-text') return indicatorText; - if (id === 'toast') return toastEl; - return null; - }, -}; -globalThis.location = { pathname: '/', href: '' }; -globalThis.setTimeout = () => 0; - -globalThis.fetch = async (url, options = {}) => { - requests.push({ url: String(url), method: options.method || 'GET' }); - if (String(url) === '/api/admin/rescan') { - if (rescanStatus !== 200) { - return jsonResponse({ error: 'admin only' }, rescanStatus); - } - return jsonResponse({ status: 'ok' }); - } - if (String(url) === '/api/admin/scan-progress') { - return jsonResponse({ - running: true, - current_set: 'movies', - sets_total: 2, - sets_done: 1, - files_total: 9, - files_done: 4, - }); - } - return jsonResponse({}); -}; - -function jsonResponse(body, status = 200) { - return new Response(JSON.stringify(body), { - status, - headers: { 'content-type': 'application/json' }, - }); -} - -function mockElement() { - return { - textContent: '', - hidden: true, - classList: { - add(name) { - if (name === 'hidden') this.hidden = true; - }, - remove(name) { - if (name === 'hidden') this.hidden = false; - }, - hidden: true, - }, - }; -} - -function pressKey(key) { - let prevented = false; - keydownHandler?.({ - key, - code: `Key${key.toUpperCase()}`, - target: { tagName: 'BODY', isContentEditable: false }, - preventDefault() { prevented = true; }, - }); - return prevented; -} - -function testKeyboardRescanHandler() { - let rescans = 0; - initKeyboard({ rescanMedia: () => { rescans += 1; } }); - - const prevented = pressKey('M'); - - assert(prevented, 'M should prevent default browser handling'); - assert(rescans === 1, 'M should call the rescan handler'); -} - -function testRenderRunningProgress() { - renderScanProgress({ - running: true, - current_set: 'music', - sets_total: 3, - sets_done: 2, - files_total: 20, - files_done: 7, - }); - - assert(indicator.classList.hidden === false, 'running progress should show the indicator'); - assert(indicatorText.textContent === 'Scanning music 2/3 sets, 7/20 files', 'running progress text should include set and file counts'); -} - -function testRenderIdleProgressHidesIndicator() { - renderScanProgress({ running: false }); - - assert(indicator.classList.hidden === true, 'idle progress should hide the indicator'); -} - -function testScanIndicatorOutsideHeader() { - const html = readFileSync(new URL('../../index.html', import.meta.url), 'utf8'); - const header = html.slice(html.indexOf('<header'), html.indexOf('</header>')); - const afterHeader = html.slice(html.indexOf('</header>')); - - assert(!header.includes('id="scan-indicator"'), 'scan indicator should not be inside the collapsible header'); - assert(afterHeader.includes('id="scan-indicator"'), 'scan indicator should remain in the document after the header'); -} - -function testScanIndicatorAboveModalOverlay() { - const css = readFileSync(new URL('../../css/layout.css', import.meta.url), 'utf8'); - const scanRule = css.match(/\.scan-indicator\s*\{[^}]*z-index:\s*(\d+)/); - const modalRule = css.match(/\.modal-overlay\s*\{[^}]*z-index:\s*(\d+)/); - - assert(scanRule, 'scan indicator should define a z-index'); - assert(modalRule, 'modal overlay should define a z-index'); - assert(Number(scanRule?.[1]) > Number(modalRule?.[1]), 'scan indicator should render above open admin modal overlay'); -} - -async function testTriggerRescanRefreshesProgress() { - requests.length = 0; - rescanStatus = 200; - await triggerRescan(); - - assert(requests[0]?.url === '/api/admin/rescan', 'trigger should call rescan endpoint first'); - assert(requests[0]?.method === 'POST', 'trigger should post to rescan endpoint'); - assert(requests[1]?.url === '/api/admin/scan-progress', 'trigger should refresh progress after starting scan'); - assert(indicator.classList.hidden === false, 'trigger should show refreshed running progress'); -} - -async function testTriggerRescanErrorDoesNotPollProgress() { - requests.length = 0; - toastEl.textContent = ''; - rescanStatus = 403; - - await triggerRescan(); - - assert(requests.length === 1, 'failed trigger should not poll scan progress'); - assert(toastEl.textContent === 'admin only', 'failed trigger should show the API error'); -} - -console.log('Running admin rescan frontend tests...'); -testKeyboardRescanHandler(); -testRenderRunningProgress(); -testRenderIdleProgressHidesIndicator(); -testScanIndicatorOutsideHeader(); -testScanIndicatorAboveModalOverlay(); -await testTriggerRescanRefreshesProgress(); -await testTriggerRescanErrorDoesNotPollProgress(); - -if (failures.length) { - console.error('FAILURES:'); - failures.forEach((m) => console.error(' - ' + m)); - process.exit(1); -} else { - console.log('All admin rescan frontend tests passed.'); - process.exit(0); -} |
