import { readFileSync } from 'node:fs'; import { resolve } from 'node:path'; import { describe, expect, it } from 'vitest'; // Als Text lesen: vitest verarbeitet CSS-Importe (auch ?raw) nicht zu Text. const accountCss = readFileSync(resolve(import.meta.dirname, '../account/account.css'), 'utf8'); const communityCss = readFileSync(resolve(import.meta.dirname, 'community.css'), 'utf8'); /** Die Deklarationen einer Regel, deren Auswahlkriterium genau `selector` ist (mehrere Regeln: alle zusammen). */ function declarations(css: string, selector: string): string { const found: string[] = []; for (const rule of css.matchAll(/([^{}]+)\{([^{}]*)\}/g)) { const selectors = rule[1].replace(/\/\*[\s\S]*?\*\//g, '').split(',').map((part) => part.trim()); if (selectors.includes(selector)) found.push(rule[2]); } return found.join('\n'); } describe('Live-Regionen (role alert/status) bleiben gerendert, auch leer', () => { it.each([ ['community.css', '.detail-msg:empty', communityCss], ['account.css', '.auth-msg:empty', accountCss], ])('%s: %s ist nicht display: none, sondern aus dem Layout genommen und optisch leer', (_file, selector, css) => { const rule = declarations(css, selector); expect(rule).not.toBe(''); expect(rule).not.toMatch(/display\s*:\s*none/); expect(rule).not.toMatch(/visibility\s*:\s*hidden/); expect(rule).toMatch(/position\s*:\s*absolute/); // kein Platz im Layout (kein Gap im Flex-Container) expect(rule).toMatch(/width\s*:\s*1px/); }); });