Файли
openidea/src/platform/themes.test.ts
T
Walter WangтаClaude 3b608355a3 feat(themes): Built-in Solarized and One light/dark themes (#85)
Adds Solarized Light, Solarized Dark, One Light and One Dark as built-in themes across the workbench, editor, terminal and Mermaid, keeping the original palettes (MIT notices in THIRD_PARTY_LICENSES.md, mapping in docs/themes.md).

- Native window colours are read from tokens.css at build time (`theme_frame.rs`) instead of a second colour table.
- Startup restores the built-in palette before first paint.
- Editor schemes, the terminal and Mermaid refresh on switches between themes of the same kind.
- The plugin packages of the same themes are removed.
- A test requires every built-in palette theme to define each token (only listed ones may inherit from the base theme), so new tokens can't silently miss them.

Co-authored-by: Claude <[email protected]>
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
2026-10-27 18:53:12 +08:00

77 рядки
3.8 KiB
TypeScript

import { readFileSync } from "node:fs";
import { afterEach, describe, expect, it } from "vitest";
import { BUILTIN_THEMES, isBuiltinTheme, themeKind } from "./themes";
import { _setSchemeSource, effectiveScheme, schemeCss, schemeTokens, themeScheme } from "./colorScheme";
import { applyThemeAttributes, resolveTheme, resolveThemeId } from "@/workbench/theme";
import { validateSettings } from "@/features/settings/model/schema";
import { applyPluginTheme } from "@/features/plugins/bridge";
const css = readFileSync("src/styles/tokens.css", "utf8");
_setSchemeSource(css);
afterEach(() => {
applyPluginTheme(null);
delete document.documentElement.dataset.colorTheme;
delete document.documentElement.dataset.contrast;
});
describe("built-in palettes", () => {
it.each(BUILTIN_THEMES)("preserves $id through validation and system resolution", ({ id, kind }) => {
const a = { theme: id, preferredLightTheme: id, preferredDarkTheme: id };
expect(validateSettings({ appearance: a }).appearance).toMatchObject(a);
expect(resolveThemeId(a, false)).toBe(id);
expect(resolveTheme(id, false)).toBe(kind);
expect(resolveThemeId({ ...a, syncWithOs: true }, true)).toBe(id);
expect(resolveThemeId({ ...a, theme: "system" }, false)).toBe(id);
applyThemeAttributes(id);
expect(document.documentElement.dataset.theme).toBe(kind);
expect(themeScheme()).toBe(id);
expect(effectiveScheme(id)).toBe(id);
expect(schemeCss("theme-default", undefined)).toBe("");
expect(schemeTokens(id).get("--bg-editor")).not.toContain("var(");
});
it("rejects unknown ids and retains legacy fallbacks", () => {
expect(isBuiltinTheme("not-a-theme")).toBe(false);
expect(resolveThemeId({ theme: "bad" }, true)).toBe("light");
expect(resolveThemeId({ theme: "system", preferredDarkTheme: "bad" }, false)).toBe("dark");
expect(themeKind("solarized-light")).toBe("light");
});
// Token coverage of every palette theme: settings/__tests__/contrast.test.ts.
it("resolves editor scheme tokens from the palettes", () => {
expect(schemeTokens("solarized-light").get("--bg-editor")).toBe("#fdf6e3");
expect(schemeTokens("solarized-dark").get("--bg-editor")).toBe("#002b36");
expect(schemeTokens("solarized-dark").get("--syn-string")).toBe("#2aa198");
expect(schemeTokens("solarized-light").get("--ansi-bright-blue")).toBe("#839496");
expect(schemeTokens("one-light").get("--syn-keyword")).toBe("hsl(301, 63%, 40%)");
expect(schemeTokens("one-dark").get("--syn-string")).toBe("hsl(95, 38%, 62%)");
});
it("keeps explicit editor schemes and per-scheme edits independent of UI palettes", () => {
applyThemeAttributes("solarized-light");
expect(schemeCss("one-dark", undefined)).toContain("--bg-editor: hsl(220, 13%, 18%) !important");
expect(schemeCss("theme-default", { "solarized-light": { keyword: { foreground: "#123456" } } })).toContain(
"--syn-keyword: #123456 !important",
);
applyThemeAttributes("one-light");
expect(schemeCss("theme-default", { "solarized-light": { keyword: { foreground: "#123456" } } })).toBe("");
});
it("clears the palette for plugins and restores it when the plugin is removed", () => {
const root = document.documentElement;
applyThemeAttributes("one-dark", root);
root.dataset.pluginThemeKind = "light";
applyThemeAttributes("one-dark", root);
expect(root.dataset.colorTheme).toBeUndefined();
expect(root.dataset.theme).toBe("light");
delete root.dataset.pluginThemeKind;
applyThemeAttributes("one-dark", root);
expect(root.dataset.colorTheme).toBe("one-dark");
applyThemeAttributes("dark-hc", root);
expect(root.dataset.colorTheme).toBeUndefined();
expect(root.dataset.contrast).toBe("high");
applyThemeAttributes("solarized-dark", root);
expect(root.dataset.contrast).toBeUndefined();
});
});