import assert from 'node:assert/strict'; import test from 'node:test'; import { themeDoctor } from '../src/themeDoctor.ts'; import { sanitizeSpec } from '../src/themeSpec.ts'; const ids = (raw: unknown) => themeDoctor(sanitizeSpec(raw)).map(advice => advice.id); test('a theme made of tokens and component settings gets no advice', () => { assert.deepEqual(ids({ name: 'Clean', colors: { bg: '#000000', text: '#ffffff', accent: '#1d9bf0' }, components: { button: { radius: 4 } } }), []); }); test('free-form CSS is pointed at the lighter mechanism and its costs', () => { const css = [ 'a { border-radius: 0; }', '.x { display: none; }', '.y { color: #ff0000; }', '.z { font-family: Comic Sans MS; }', 'div:has(img) { opacity: .9; }', '* { box-sizing: border-box; }', '.g { backdrop-filter: blur(8px); }', 'button:focus { outline: none; }', '.m { transition: all .2s; }', '.b { box-shadow: inset 1px 1px #fff, inset -1px -1px #000, inset 2px 2px #ddd; }', ].join('\n'); const found = ids({ name: 'Heavy', css }); for (const id of ['css-radius', 'css-hide', 'css-color', 'css-font', 'css-has', 'css-universal', 'css-blur', 'css-outline-none', 'css-motion', 'css-bevel']) { assert.ok(found.includes(id), `${id} is reported`); } }); test('advice is a hint, never a change: the theme is left as it was', () => { const theme = sanitizeSpec({ name: 'Keep', css: '.x { display: none; }' }); const before = JSON.stringify(theme); themeDoctor(theme); assert.equal(JSON.stringify(theme), before); }); test('unreadable colors are named with their contrast', () => { const advice = themeDoctor(sanitizeSpec({ name: 'Low', colors: { bg: '#000000', text: '#111111', accent: '#1d9bf0' } })); const text = advice.find(item => item.id === 'contrast-text'); assert.ok(text, 'text contrast is reported'); assert.equal(text.kind, 'contrast'); assert.match(text.text, /\d\.\d\d:1/); });