diff --git a/web/apps/desk/index.html b/web/apps/desk/index.html index eba368b2d..4db0b38cd 100644 --- a/web/apps/desk/index.html +++ b/web/apps/desk/index.html @@ -2,6 +2,8 @@ + + @@ -21,7 +23,7 @@ `, 'black'], + ] + it.each(catches)('catches %s', (_name, text, value) => { + expect(findLiterals(text, false).map(([, v]) => v)).toContain(value) + }) + + it('does not call a variable read or a token class a literal', () => { + const ok = `

` + expect(findLiterals(ok, false)).toEqual([]) + }) + + it('an allowlisted literal does not exempt the rest of its file', () => { + const file = 'desk/index.html' + const allowed = ALLOWED.find((a) => a.file === file) + const planted = `${allowed?.value ?? ''}

` + const left = findLiterals(planted, false).filter( + ([, v]) => !ALLOWED.some((a) => a.file === file && a.value === v), + ) + expect(left.map(([, v]) => v)).toEqual(['#123456']) + }) +}) diff --git a/web/apps/desk/src/test/theme-boot.test.ts b/web/apps/desk/src/test/theme-boot.test.ts new file mode 100644 index 000000000..1597feda0 --- /dev/null +++ b/web/apps/desk/src/test/theme-boot.test.ts @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: LicenseRef-OpenLBM-Surface-1.0 +// SPDX-FileCopyrightText: 2026 FutureBuild, Inc. and OpenLBM contributors + +/** + * The boot script both pages load before the first paint: it applies the + * stored light choice and leaves Industrial Dark alone otherwise. It is a + * same origin file because the page's CSP (script-src 'self') refuses an + * inline script; both boot screens must load it. + */ +import { describe, it, expect, beforeEach } from 'vitest' +import { readFileSync } from 'node:fs' +import { resolve } from 'node:path' + +const script = readFileSync(resolve(process.cwd(), 'public/theme-boot.js'), 'utf8') + +function boot(): void { + new Function(script)() +} + +beforeEach(() => { + localStorage.clear() + delete document.documentElement.dataset.theme +}) + +describe('theme boot script', () => { + it('applies a stored light choice', () => { + localStorage.setItem('gable_theme', 'light') + boot() + expect(document.documentElement.dataset.theme).toBe('light') + }) + + it('leaves Industrial Dark when nothing or dark is stored', () => { + boot() + expect(document.documentElement.dataset.theme).toBeUndefined() + localStorage.setItem('gable_theme', 'dark') + boot() + expect(document.documentElement.dataset.theme).toBeUndefined() + }) + + it('is loaded by both boot screens', () => { + for (const page of ['index.html', '../front-door/index.html']) { + const html = readFileSync(resolve(process.cwd(), page), 'utf8') + expect(html, page).toContain('') + } + }) +}) diff --git a/web/apps/front-door/index.html b/web/apps/front-door/index.html index f2c9fa26d..52b27194a 100644 --- a/web/apps/front-door/index.html +++ b/web/apps/front-door/index.html @@ -2,6 +2,8 @@ + +