import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import { fileURLToPath } from 'node:url'; import path from 'node:path'; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..'); const [popupHtml, popupJs, overlayJs, backgroundJs] = await Promise.all([ readFile(path.join(repoRoot, 'extension', 'popup.html'), 'utf8'), readFile(path.join(repoRoot, 'extension', 'popup.js'), 'utf8'), readFile(path.join(repoRoot, 'extension', 'chat-overlay.js'), 'utf8'), readFile(path.join(repoRoot, 'extension', 'background.js'), 'utf8') ]); function detailsSection(marker) { const markerIndex = popupHtml.indexOf(marker); assert.notEqual(markerIndex, -1, `missing settings marker: ${marker}`); const start = popupHtml.lastIndexOf('', markerIndex); assert.ok(start >= 0 && end > markerIndex, `invalid details section: ${marker}`); return popupHtml.slice(start, end + ''.length); } const chatSection = detailsSection('data-i18n="CHAT_TITLE"'); const syncSection = detailsSection('data-i18n="LABEL_SETTINGS_GROUP_SYNC"'); for (const id of ['chatEnabled', 'chatNotifications', 'chatPosition', 'chatSize', 'chatStartMode']) { assert.match(chatSection, new RegExp(`id="${id}"`), `${id} belongs in the dedicated chat settings section`); } assert.doesNotMatch(syncSection, /id="chatEnabled"/, 'chat enablement must not remain under Playback & Sync'); for (const value of ['right', 'left', 'detached']) { assert.match(chatSection, new RegExp(`