- globals.css: Hell, Dunkel und Druck mit den Spec-Werten aus 4.2, Fokusring = --primary-ink, Verlaufs-Token entfernt. - Codemod scripts/codemod-t5-colors.mjs: text-primary/-warning auf -ink, Vordergrund nur auf voller Fläche, Auswahlrahmen dunkel; --check-Modus und Spec halten src sauber. - Kontrast-Wächter misst die echte globals.css (VALUES_SWITCHED), alle 21 Zeilen aus 4.4 in allen vier Sätzen; keine dark:-Klassen mehr in src. - Dunkel ist ohne Entwickler-Schalter wählbar, Standard bleibt Hell. - Review-Nacharbeit: Auswahl-Umrisse und aktueller Schritt in Vordergrund, deaktivierte Felder bg-muted, Avatar ohne Blend, Honig-Check-Rahmen über --input. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
69 lines
2.8 KiB
TypeScript
69 lines
2.8 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", () => {
|
|
it("no file passes a gradient prop any more", () => {
|
|
const offenders = sourceFiles(SRC).filter((file) => {
|
|
const text = readFileSync(file, "utf8");
|
|
return /gradient=|var\(--gradient-|\[background-image:var\(--gradient/.test(text);
|
|
});
|
|
expect(offenders).toEqual([]);
|
|
});
|
|
|
|
it("no source uses or defines the --gradient tokens any more (removed in task A4)", () => {
|
|
const offenders = sourceFiles(SRC).filter((file) => /--gradient-/.test(readFileSync(file, "utf8")));
|
|
expect(offenders).toEqual([]);
|
|
});
|
|
|
|
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([]);
|
|
});
|
|
|
|
it("no white text outside the hive stage", () => {
|
|
const offenders = sourceFiles(SRC)
|
|
.filter((file) => !file.replaceAll("\\", "/").includes("/components/hive/"))
|
|
.filter((file) => /\btext-white\b/.test(readFileSync(file, "utf8")));
|
|
expect(offenders).toEqual([]);
|
|
});
|
|
|
|
it("the stage overlay on the hive stage uses the holo label colour instead of white", () => {
|
|
expect(read("components/hive/editor/editor-stage-overlay.tsx")).not.toMatch(/\btext-white\b/);
|
|
});
|
|
});
|