Files
ApiCore/ApiCore-Frontend/src/components/area-migration.spec.ts
T
Nick.RosenloecherandClaude Opus 5.5 ce68729233 feat(t5): Fokusring für alle, 44-px-Ziele bei Touch, 16-px-Schrift (T5a A5)
- globals.css: eine Basisregel :where(:focus-visible) mit --focus-width
  und --focus-offset (Sonne 3 px), Firefox-:-moz-focusring gleichgezogen;
  --text-xs 0.8125rem.
- Fokus-Codemod (scripts/codemod-t5-focus.mjs): eigene Ringe und
  outline-none raus, sm:h-/sm:size- zu pointer-fine:, Label-Zeilen mit
  focus-ring-within; Skript-Fokus (Lücken-Liste, „Gespeichert“) bleibt.
- Button/Input 44 px, kompakt nur mit Maus; Icon-Knöpfe mit unsichtbarer
  44-px-Trefferfläche bei Touch, Nachbarn mit genug Abstand.
- 16 px in Feldern, Labels, Auswahl, Leerzuständen, Listentiteln.
- .holo-stage auf allen Beute-Bühnen, .stage-card holt den Seitenring.
- Baukasten-Wächter (src/styles/baukasten-guard.spec.ts) mit den Regeln
  aus A3–A5, Ausnahmen mit Grund; Kalender-Auswahl als Inset-Ring.

Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
2026-10-16 18:06:20 +02:00

47 lines
1.9 KiB
TypeScript

import { readdirSync, readFileSync, statSync } from "node:fs";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
const SRC = join(__dirname, "..");
function sourceFiles(dir: string): string[] {
return readdirSync(dir).flatMap((name) => {
const path = join(dir, name);
if (statSync(path).isDirectory()) {
return sourceFiles(path);
}
return /\.(tsx?|css)$/.test(name) && !/\.spec\./.test(name) ? [path] : [];
});
}
function read(relative: string): string {
return readFileSync(join(SRC, relative), "utf8");
}
describe("area migration", () => {
// The gradient and white-text rules live in src/styles/baukasten-guard.spec.ts (task A5).
it("harvest detail uses Scissors, extraction create FlaskConical and storage only Warehouse", () => {
expect(read("app/(app)/harvests/[id]/page.tsx")).toContain('area="harvests"');
expect(read("app/(app)/extractions/new/page.tsx")).toContain('area="extractions"');
const storage = read("app/(app)/storage/page.tsx");
expect(storage).toContain('area="storage"');
expect(storage).not.toMatch(/icon=\{Package\}/);
});
it("medicine packs, hive systems and voice settings use their own area icon", () => {
expect(read("app/(app)/medicines/[id]/page.tsx")).not.toMatch(/icon=\{Package\}/);
expect(read("app/(app)/medicines/lots/[id]/page.tsx")).toContain('area="medicines"');
expect(read("app/(app)/settings/hive-systems/page.tsx")).toContain('area="hive-systems"');
expect(read("app/(app)/settings/voice/page.tsx")).toContain('area="voice"');
});
it("no component passes a raw icon to the headers any more", () => {
const offenders = sourceFiles(SRC).filter((file) => {
const text = readFileSync(file, "utf8");
return /<(PageHeader|DetailHeader|EntityCard)\b[^>]*\bicon=/.test(text);
});
expect(offenders).toEqual([]);
});
});