first commit
This commit is contained in:
@@ -0,0 +1,121 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import {
|
||||
applyThemePalette,
|
||||
defaultThemeBackgroundId,
|
||||
defaultThemePaletteId,
|
||||
getThemeBackgroundPreset,
|
||||
getThemePalette,
|
||||
themeBackgroundPresets,
|
||||
themePaletteChangeEvent,
|
||||
themePalettes
|
||||
} from "./tokens";
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
describe("platform web theme palettes", () => {
|
||||
it("offers black mecha and magical-girl palettes with usable swatches", () => {
|
||||
expect(themePalettes.map((palette) => palette.label)).toEqual(["黑色机甲", "魔法少女"]);
|
||||
|
||||
for (const palette of themePalettes) {
|
||||
expect(palette.swatches.length).toBeGreaterThanOrEqual(5);
|
||||
expect(palette.variables["--accent"]).toMatch(/^#[0-9a-f]{6}$/i);
|
||||
expect(palette.variables["--surface"]).toContain("rgba");
|
||||
expect(palette.variables["--rim-light"]).toContain("rgba");
|
||||
expect(palette.variables["--crystal-rim"]).toContain("rgba");
|
||||
expect(palette.variables["--sparkle-gold"]).toContain("rgba");
|
||||
expect(palette.variables["--panel-material"]).toContain("var");
|
||||
expect(palette.variables["--menu-item-bg"]).toContain("gradient");
|
||||
expect(palette.variables["--frame-accessory-top"]).toContain("data:image/svg+xml");
|
||||
expect(palette.variables["--frame-accessory-bottom"]).toContain("data:image/svg+xml");
|
||||
expect(palette.variables["--frame-accessory-opacity"]).toMatch(/^0\.\d{2}$/);
|
||||
expect(accessorySizeNumbers(palette.variables["--frame-accessory-size"])).toEqual(
|
||||
expect.arrayContaining([expect.any(Number)])
|
||||
);
|
||||
expect(palette.variables["--custom-background-overlay"]).toBe("transparent");
|
||||
|
||||
const accessoryOpacity = Number(palette.variables["--frame-accessory-opacity"]);
|
||||
const largestAccessoryDimension = Math.max(...accessorySizeNumbers(palette.variables["--frame-accessory-size"]));
|
||||
|
||||
if (palette.id === "magical-girl") {
|
||||
expect(accessoryOpacity).toBeGreaterThanOrEqual(0.65);
|
||||
expect(largestAccessoryDimension).toBeGreaterThanOrEqual(56);
|
||||
expect(largestAccessoryDimension).toBeLessThanOrEqual(80);
|
||||
expect(
|
||||
new Set([
|
||||
palette.variables["--frame-accessory-heart"],
|
||||
palette.variables["--frame-accessory-wand"],
|
||||
palette.variables["--frame-accessory-moon"],
|
||||
palette.variables["--frame-accessory-ribbon"],
|
||||
palette.variables["--frame-accessory-crystal"],
|
||||
palette.variables["--frame-accessory-circle"]
|
||||
]).size
|
||||
).toBe(6);
|
||||
} else {
|
||||
expect(accessoryOpacity).toBeLessThanOrEqual(0.4);
|
||||
expect(largestAccessoryDimension).toBeLessThanOrEqual(60);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("falls back to the default black mecha palette", () => {
|
||||
expect(defaultThemePaletteId).toBe("mecha-black");
|
||||
expect(getThemePalette("missing").id).toBe("mecha-black");
|
||||
});
|
||||
|
||||
it("clears stale palette variables and publishes the active palette", () => {
|
||||
const removeProperty = vi.fn();
|
||||
const setProperty = vi.fn();
|
||||
const dispatchEvent = vi.fn(() => true);
|
||||
|
||||
class TestCustomEvent<T> {
|
||||
readonly type: string;
|
||||
readonly detail: T | null;
|
||||
|
||||
constructor(type: string, init?: CustomEventInit<T>) {
|
||||
this.type = type;
|
||||
this.detail = init?.detail ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
vi.stubGlobal("document", {
|
||||
documentElement: {
|
||||
dataset: {},
|
||||
style: { removeProperty, setProperty }
|
||||
}
|
||||
});
|
||||
vi.stubGlobal("window", { dispatchEvent });
|
||||
vi.stubGlobal("CustomEvent", TestCustomEvent);
|
||||
|
||||
applyThemePalette("mecha-black");
|
||||
|
||||
expect(removeProperty).toHaveBeenCalledWith("--frame-accessory-heart");
|
||||
expect(setProperty).toHaveBeenCalledWith("--accent", "#48e6ff");
|
||||
expect(dispatchEvent).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
type: themePaletteChangeEvent,
|
||||
detail: { paletteId: "mecha-black" }
|
||||
})
|
||||
);
|
||||
});
|
||||
|
||||
it("offers mecha and magical desktop presets with a mecha default", () => {
|
||||
expect(defaultThemeBackgroundId).toBe("mecha-grid");
|
||||
expect(themeBackgroundPresets.map((preset) => preset.label)).toEqual(["机甲格纳库", "粉月魔法阵"]);
|
||||
|
||||
for (const preset of themeBackgroundPresets) {
|
||||
expect(preset.preview).toContain("gradient");
|
||||
expect(preset.variables["--workspace-background-pattern-image"]).toContain("gradient");
|
||||
expect(preset.variables["--workspace-background-pattern-opacity"]).toMatch(/^0\./);
|
||||
}
|
||||
|
||||
expect(getThemeBackgroundPreset("missing").id).toBe("mecha-grid");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function accessorySizeNumbers(sizeValue: string): number[] {
|
||||
return Array.from(sizeValue.matchAll(/(\d+)px/g), (match) => Number(match[1]));
|
||||
}
|
||||
Reference in New Issue
Block a user