Files
llm-browser/frontend/tests/check-tokens.test.mjs
T
2026-10-19 16:04:17 +02:00

96 lines
3.0 KiB
JavaScript

import { execFileSync } from 'node:child_process'
import { mkdtempSync, writeFileSync, mkdirSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { describe, expect, it } from 'vitest'
const GUARD = join(process.cwd(), 'scripts', 'check-tokens.mjs')
function runIn(files) {
const dir = mkdtempSync(join(tmpdir(), 'token-guard-'))
mkdirSync(join(dir, 'src'))
for (const [name, content] of Object.entries(files)) {
writeFileSync(join(dir, 'src', name), content)
}
try {
execFileSync(process.execPath, [GUARD, join(dir, 'src')], { encoding: 'utf8' })
return { code: 0, output: '' }
} catch (err) {
return { code: err.status, output: err.stdout + String(err.stderr ?? '') }
}
}
const TOKENS = ':root { --primary: lab(50% 0 0); --space-2: 0.5rem; }\n'
describe('check-tokens guard', () => {
it('passes a clean file', () => {
const result = runIn({
'tokens.css': TOKENS,
'a.tsx': `export const A = () => <div style={{ color: 'var(--primary)', padding: 'var(--space-2)' }} />\n`,
})
expect(result.code).toBe(0)
})
it('flags hex, named colors and hsl()/oklch() inside style={{ }}', () => {
const result = runIn({
'tokens.css': TOKENS,
'a.tsx': `export const A = () => (
<div style={{
color: '#fff',
background: 'oklch(70% 0.1 200)',
borderColor: 'red',
}} />
)\n`,
})
expect(result.code).toBe(1)
expect(result.output).toMatch(/hex color #fff/)
expect(result.output).toMatch(/oklch\(\) color/)
expect(result.output).toMatch(/named color "red"/)
})
it('allows color-mix over tokens and neutral rgba shines', () => {
const result = runIn({
'tokens.css': TOKENS,
'a.tsx': `export const A = () => (
<div style={{
background: 'color-mix(in srgb, var(--primary) 12%, transparent)',
boxShadow: '0 8px 24px rgba(0, 0, 0, 0.2)',
}} />
)\n`,
})
expect(result.code).toBe(0)
})
it('reads values split across lines in css', () => {
const result = runIn({
'tokens.css': TOKENS,
'b.css': `.b {\n background:\n linear-gradient(\n to right,\n crimson,\n navy\n );\n}\n`,
})
expect(result.code).toBe(1)
expect(result.output).toMatch(/named color "crimson"/)
})
it('flags px font sizes in css and tsx', () => {
const result = runIn({
'tokens.css': TOKENS,
'b.css': `.b { font-size: 14px; }\n`,
'a.tsx': `export const A = () => <div style={{ fontSize: '14px' }} />\n`,
})
expect(result.code).toBe(1)
expect(result.output.match(/px font size/g)).toHaveLength(2)
})
it('fails on var(--x) that no css file defines', () => {
const result = runIn({
'tokens.css': TOKENS,
'a.tsx': `export const A = () => <div style={{ color: 'var(--priamry)' }} />\n`,
})
expect(result.code).toBe(1)
expect(result.output).toMatch(/var\(--priamry\) is never defined/)
})
it('keeps the real repo clean', () => {
expect(() => execFileSync(process.execPath, [GUARD], { stdio: 'pipe' })).not.toThrow()
})
})