Files
govoplan-core/webui/scripts/test-theme-contract.mjs
T

31 lines
1.5 KiB
JavaScript

import assert from "node:assert/strict";
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const webuiRoot = resolve(import.meta.dirname, "..");
const repositoryRoot = resolve(webuiRoot, "..", "..");
const tokens = readFileSync(resolve(webuiRoot, "src/styles/tokens.css"), "utf8");
const app = readFileSync(resolve(webuiRoot, "src/App.tsx"), "utf8");
const settings = readFileSync(resolve(webuiRoot, "src/features/settings/SettingsPage.tsx"), "utf8");
assert.match(tokens, /:root\[data-theme="dark"\]/, "dark token overrides are required");
assert.match(tokens, /color-scheme:\s*dark/, "native controls must receive the dark color scheme");
assert.match(app, /matchMedia\?\.\("\(prefers-color-scheme: dark\)"\)/, "system theme must follow OS changes");
assert.match(app, /dataset\.themePreference/, "the selected preference must remain inspectable");
for (const theme of ["system", "light", "dark"]) {
assert.match(settings, new RegExp(`value:\\s*"${theme}"`), `Settings must expose ${theme}`);
}
const representativeModules = [
"govoplan-campaign/webui/src/styles/campaign-workspace.css",
"govoplan-calendar/webui/src/styles/calendar.css",
"govoplan-files/webui/src/styles/file-manager.css",
"govoplan-mail/webui/src/styles/mail-profiles.css",
];
for (const relativePath of representativeModules) {
const css = readFileSync(resolve(repositoryRoot, relativePath), "utf8");
assert.match(css, /var\(--/, `${relativePath} must consume shared theme tokens`);
}
console.log("Theme contract passed for core and representative module surfaces.");