- Router: onRouteChange meldet jede neue Seite (vor dem Aufbau). Die Kopfzeile markiert damit den aktuellen Navigationslink mit aria-current="page" („Community“ auch auf der Detailseite) und leert das Suchfeld, wenn die neue Seite nicht die Startseite mit ?q= ist (bisher blieb „testbank“ auf /gestalten stehen). - Spenden-Knopf in der Kopfzeile trägt title „Unterstützen“ (zwischen 600 und 1179 px nur Symbol). - .detail-msg:empty und .auth-msg:empty sind nicht mehr display: none (Live-Regionen standen nicht im Zugänglichkeitsbaum), sondern ohne Platz im Layout, aber gerendert; Test liest die CSS-Dateien. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
32 lines
1.5 KiB
TypeScript
32 lines
1.5 KiB
TypeScript
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/);
|
|
});
|
|
});
|