// Stream S4 (PLAN C5): which theme and mode the page shows. brand.js runs in Node, so this is the code the browser runs. import test from 'node:test'; import assert from 'node:assert/strict'; import '../src/public/brand.js'; import { installedThemes } from '../../plugins/src/theme.mjs'; const { Brand } = globalThis; const { themes: installed } = await installedThemes(); const without = id => installed.filter(t => t.id !== id); const resolve = input => Brand.resolveAppearance(input); const frozen = v => Object.freeze(structuredClone(v)); test('S4 with nothing set the page is Harbor in the dark, from tokens.css alone', () => { for (const themes of [null, installed, []]) { const r = resolve({ themes }); assert.deepEqual([r.theme, r.mode, r.themeSource, r.modeSource, r.warning, r.entry, r.provisional], ['harbor', 'dark', 'default', 'default', null, null, false]); } // Harbor never needs its module: it is built in, so an empty or failed list gives no warning for it. assert.equal(resolve({ themes: [], saved: { theme: 'harbor' } }).warning, null); assert.equal(resolve({ themes: [], unavailable: true, saved: { theme: 'harbor' } }).warning, null); }); test('S4 precedence is the browser override, then the organization, then the default, one field at a time', () => { const saved = frozen({ theme: 'grove', mode: 'dim' }); const override = frozen({ theme: 'cobalt', mode: 'light' }); assert.deepEqual(pick(resolve({ themes: installed, saved, override })), ['cobalt', 'light', 'browser', 'browser']); assert.deepEqual(pick(resolve({ themes: installed, saved })), ['grove', 'dim', 'organization', 'organization']); assert.deepEqual(pick(resolve({ themes: installed })), ['harbor', 'dark', 'default', 'default']); // An override of one field leaves the other to the organization. assert.deepEqual(pick(resolve({ themes: installed, saved, override: { mode: 'system' } })), ['grove', 'system', 'organization', 'browser']); assert.deepEqual(pick(resolve({ themes: installed, saved, override: { theme: 'cobalt' } })), ['cobalt', 'dim', 'browser', 'organization']); // The organization may save only one field too. assert.deepEqual(pick(resolve({ themes: installed, saved: { theme: 'grove' } })), ['grove', 'dark', 'organization', 'default']); function pick(r) { return [r.theme, r.mode, r.themeSource, r.modeSource]; } }); test('S4 clearing the override restores the organization choice, and nothing is written back to the saved value', () => { const saved = frozen({ theme: 'grove', mode: 'dim' }); const chosen = resolve({ themes: installed, saved, override: { theme: 'carmine', mode: 'light' } }); assert.equal(chosen.theme, 'carmine'); const cleared = resolve({ themes: installed, saved, override: null }); assert.deepEqual([cleared.theme, cleared.mode, cleared.themeSource], ['grove', 'dim', 'organization']); assert.deepEqual(saved, { theme: 'grove', mode: 'dim' }); }); test('S4 an uninstalled or invalid saved theme renders the default with a warning and keeps the saved value', () => { for (const asked of ['no-such-theme', 'Bad Name', '../harbor', '', 7, `a${'b'.repeat(64)}`, '