forked from WikiDeck/wikideck
v2
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { runInNewContext } from 'node:vm';
|
||||
import { DEFAULT_THEME, isTheme, resolveTheme, THEMES, THEME_STORAGE_KEY } from '../src/theme.ts';
|
||||
|
||||
const bootstrap = readFileSync(new URL('../public/theme-init.js', import.meta.url), 'utf8');
|
||||
function boot(saved: unknown, blocked = false) {
|
||||
const root = { dataset: {} as Record<string, string>, style: {} as Record<string, string> };
|
||||
let meta = '';
|
||||
runInNewContext(bootstrap, {
|
||||
localStorage: { getItem(key: string) {
|
||||
assert.equal(key, THEME_STORAGE_KEY);
|
||||
if (blocked) throw new Error('Storage access denied');
|
||||
return saved;
|
||||
} },
|
||||
document: { documentElement: root, querySelector: () => ({ setAttribute: (_key: string, value: string) => { meta = value; } }) },
|
||||
});
|
||||
return { theme: root.dataset.theme, scheme: root.style.colorScheme, meta };
|
||||
}
|
||||
|
||||
test('Mocha is the default, including missing, malicious, or inaccessible preferences', () => {
|
||||
assert.equal(DEFAULT_THEME, 'mocha');
|
||||
for (const value of [null, undefined, '', 'unknown', 'MOCHA', '__proto__', 'constructor', '<script>alert(1)</script>', {}, 1]) {
|
||||
assert.equal(isTheme(value), false);
|
||||
assert.equal(resolveTheme(value), 'mocha');
|
||||
assert.deepEqual(boot(value), { theme: 'mocha', scheme: 'dark', meta: '#1e1e2e' });
|
||||
}
|
||||
assert.deepEqual(boot('latte', true), { theme: 'mocha', scheme: 'dark', meta: '#1e1e2e' });
|
||||
});
|
||||
|
||||
test('every saved Catppuccin flavor boots with matching browser chrome and color scheme', () => {
|
||||
for (const theme of THEMES) {
|
||||
assert.equal(isTheme(theme.id), true);
|
||||
assert.equal(resolveTheme(theme.id), theme.id);
|
||||
assert.deepEqual(boot(theme.id), { theme: theme.id, scheme: theme.id === 'latte' ? 'light' : 'dark', meta: theme.base });
|
||||
}
|
||||
});
|
||||
|
||||
test('every flavor defines all 26 official palette roles with the correct base color', () => {
|
||||
const css = readFileSync(new URL('../src/themes.css', import.meta.url), 'utf8');
|
||||
const roles = ['rosewater', 'flamingo', 'pink', 'mauve', 'red', 'maroon', 'peach', 'yellow', 'green', 'teal',
|
||||
'sky', 'sapphire', 'blue', 'lavender', 'text', 'subtext1', 'subtext0', 'overlay2', 'overlay1', 'overlay0',
|
||||
'surface2', 'surface1', 'surface0', 'base', 'mantle', 'crust'];
|
||||
for (const theme of THEMES) {
|
||||
const block = css.match(new RegExp(`:root\\[data-theme='${theme.id}'\\]\\s*\\{([^}]+)\\}`))?.[1];
|
||||
assert.ok(block);
|
||||
for (const role of roles) assert.match(block, new RegExp(`--ctp-${role}: #[a-f0-9]{6};`));
|
||||
assert.ok(block.includes(`--ctp-base: ${theme.base};`));
|
||||
}
|
||||
});
|
||||
Reference in New Issue
Block a user