import test from 'node:test' import assert from 'node:assert/strict' import { readFileSync, readdirSync } from 'node:fs' test('workers.css: nur wk-Klassen, @font-face, keine Hex-Farben, reduzierte Bewegung', () => { const css = readFileSync(new URL('../../src/styles/workers.css', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '') // Kommentare vorher entfernen for (const m of css.matchAll(/([^{}]+)\{/g)) { const pre = m[1].trim(); if (pre.startsWith('@')) continue; for (const sel of pre.split(',')) assert.ok(sel.trim().startsWith('.wk-'), sel) } // jede Regel beginnt mit einer wk-Klasse (Nachfahren dürfen globale Klassen nutzen) assert.match(css, /@font-face\s*\{[^}]*font-family:\s*"Pixelify Sans"[^}]*PixelifySans-Variable\.woff2[^}]*font-display:\s*swap/s); assert.doesNotMatch(css, /#[0-9a-fA-F]{3,8}\b/) assert.match(css, /prefers-reduced-motion/); assert.match(css, /@media \(max-width: 1100px\)/); assert.match(css, /@media \(max-width: 860px\)/) }) test('jede im JSX verwendete wk-Klasse ist definiert', () => { const css = readFileSync(new URL('../../src/styles/workers.css', import.meta.url), 'utf8'); const dir = new URL('../../src/components/workers/', import.meta.url) for (const f of readdirSync(dir).filter((x) => x.endsWith('.jsx'))) for (const m of readFileSync(new URL(f, dir), 'utf8').matchAll(/(? { const css = readFileSync(new URL('../../src/styles/workers.css', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '') const rule = (selector) => css.match(new RegExp(`${selector.replace(/[.~]/g, '\\$&')}\\s*\\{([^}]*)\\}`))?.[1] ?? '' assert.match(rule('.wk-zoom'), /bottom:\s*8px/); assert.match(rule('.wk-zoom'), /right:\s*8px/); assert.doesNotMatch(rule('.wk-zoom'), /\btop:/) assert.match(rule('.wk-toolbar ~ .msg'), /margin-bottom:\s*16px/) }) test('workers.css: die Karte bleibt beim Anspringen unter der festen Leiste der Handy-Ansicht (scroll-margin-top)', () => { const css = readFileSync(new URL('../../src/styles/workers.css', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '') assert.match(css, /\.wk-card\s*\{[^}]*scroll-margin-top:\s*12px/) const phone = css.slice(css.indexOf('@media (max-width: 860px)')) assert.match(phone, /\.wk-card\s*\{\s*scroll-margin-top:\s*64px/) // 52 px Leiste + Luft }) test('workers.css: die globale Regel .page section + section (36 px) verlängert den Abstand der Panel-Abschnitte nicht (W4)', () => { const global = readFileSync(new URL('../../src/styles/global.css', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '') const css = readFileSync(new URL('../../src/styles/workers.css', import.meta.url), 'utf8').replace(/\/\*[\s\S]*?\*\//g, '') assert.match(global, /\.page section \+ section\s*\{\s*margin-top:\s*36px/) // die Regel, gegen die das Panel sich behaupten muss: Spezifität (0,1,2) const m = css.match(/(\.wk-prospect [^{}]*\.wk-prospect-section \+ \.wk-prospect-section)\s*\{([^}]*)\}/) assert.ok(m, 'Regel für zwei benachbarte Abschnitte im Panel') assert.match(m[2], /margin-top:\s*0\b/) // Spezifität: zwei Klassen (0,2,0) schlagen schon (0,1,2); eine einzelne Klasse (0,1,0) verlöre assert.ok((m[1].match(/\.[\w-]+/g) || []).length >= 2, 'mindestens zwei Klassen') // der Abstand der Abschnitte kommt aus gap, nicht aus einem eigenen margin-top assert.match(css, /\.wk-prospect\s*\{[^}]*gap:\s*16px/) assert.doesNotMatch(css.match(/\.wk-prospect-section\s*\{([^}]*)\}/)[1], /margin-top/) })