Adds plugin-contributed light and dark app themes, including persistence, host-aware coalescing, fallback behavior, documentation, examples, and browser/iOS QA.
119 lines
4.4 KiB
TypeScript
119 lines
4.4 KiB
TypeScript
import { mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import path from "node:path";
|
|
import { expect, test } from "../support/fixtures";
|
|
import { connectNewWorkspaceDaemonClient } from "../support/helpers/new-workspace";
|
|
import { openSettingsSection } from "../support/helpers/settings";
|
|
|
|
const PLUGIN_ID = "plugin-theme-e2e";
|
|
|
|
// Catppuccin Mocha: base, text, surface0, surface1, mauve, subtext0, overlay0.
|
|
const PLUGIN_SOURCE = `export default function contribute(plugin) {
|
|
plugin.addTheme({
|
|
id: "mocha",
|
|
name: "Catppuccin Mocha",
|
|
appearance: "dark",
|
|
colors: {
|
|
background: "#1e1e2e",
|
|
foreground: "#cdd6f4",
|
|
raised: "#313244",
|
|
control: "#45475a",
|
|
border: "#45475a",
|
|
accent: "#cba6f7",
|
|
mutedForeground: "#a6adc8",
|
|
ring: "#6c7086",
|
|
},
|
|
});
|
|
plugin.addTheme({
|
|
id: "latte",
|
|
name: "Catppuccin Latte",
|
|
appearance: "light",
|
|
colors: {
|
|
background: "#eff1f5",
|
|
foreground: "#4c4f69",
|
|
raised: "#e6e9ef",
|
|
control: "#dce0e8",
|
|
border: "#ccd0da",
|
|
accent: "#8839ef",
|
|
mutedForeground: "#6c6f85",
|
|
ring: "#9ca0b0",
|
|
},
|
|
});
|
|
return () => {};
|
|
}`;
|
|
|
|
// settingsStyles.sectionHeaderTitle paints from foregroundMuted, so the section heading proves the
|
|
// contributed palette reached the semantic tokens rather than just the swatch.
|
|
const MOCHA_MUTED_FOREGROUND = "rgb(166, 173, 200)";
|
|
const LATTE_MUTED_FOREGROUND = "rgb(108, 111, 133)";
|
|
|
|
test("applies a contributed theme and falls back when its plugin is gone", async ({
|
|
page,
|
|
}, testInfo) => {
|
|
const directory = await mkdtemp(path.join(tmpdir(), "paseo-plugin-theme-e2e-"));
|
|
const client = await connectNewWorkspaceDaemonClient({ ownProjects: false });
|
|
const previousConfig = await client.getDaemonConfig();
|
|
await writeFile(path.join(directory, "paseo-plugin.json"), JSON.stringify({ id: PLUGIN_ID }));
|
|
await writeFile(path.join(directory, "index.ts"), PLUGIN_SOURCE);
|
|
|
|
try {
|
|
await client.patchDaemonConfig({ pluginsEnabled: true });
|
|
await client.installDirectoryPlugin(directory);
|
|
await page.goto("/settings");
|
|
await expect(page.getByTestId("settings-sidebar")).toBeVisible();
|
|
await openSettingsSection(page, "appearance");
|
|
|
|
const sectionTitle = page.getByText("Theme", { exact: true }).first();
|
|
await page.getByLabel("Theme: System", { exact: true }).click();
|
|
const mochaItem = page.getByText("Catppuccin Mocha", { exact: true });
|
|
await expect(mochaItem).toBeVisible({ timeout: 30_000 });
|
|
await page.screenshot({
|
|
path: testInfo.outputPath("plugin-theme-picker.png"),
|
|
animations: "disabled",
|
|
fullPage: true,
|
|
});
|
|
|
|
await test.step("a contributed light theme uses the light palette", async () => {
|
|
await page.getByText("Catppuccin Latte", { exact: true }).click();
|
|
await expect(page.getByLabel("Theme: Catppuccin Latte", { exact: true })).toBeVisible();
|
|
await expect(sectionTitle).toHaveCSS("color", LATTE_MUTED_FOREGROUND);
|
|
await page.getByLabel("Theme: Catppuccin Latte", { exact: true }).click();
|
|
});
|
|
|
|
await mochaItem.click();
|
|
await expect(page.getByLabel("Theme: Catppuccin Mocha", { exact: true })).toBeVisible();
|
|
await expect(sectionTitle).toHaveCSS("color", MOCHA_MUTED_FOREGROUND);
|
|
await page.screenshot({
|
|
path: testInfo.outputPath("plugin-theme-applied.png"),
|
|
fullPage: true,
|
|
});
|
|
|
|
await test.step("the selection survives a reload", async () => {
|
|
await page.reload();
|
|
await expect(page.getByLabel("Theme: Catppuccin Mocha", { exact: true })).toBeVisible({
|
|
timeout: 30_000,
|
|
});
|
|
await expect(sectionTitle).toHaveCSS("color", MOCHA_MUTED_FOREGROUND);
|
|
});
|
|
|
|
await test.step("removing the plugin falls back to the default theme", async () => {
|
|
await client.removePlugin(PLUGIN_ID);
|
|
await expect(page.getByLabel("Theme: System", { exact: true })).toBeVisible({
|
|
timeout: 30_000,
|
|
});
|
|
await expect(sectionTitle).not.toHaveCSS("color", MOCHA_MUTED_FOREGROUND);
|
|
await page.screenshot({
|
|
path: testInfo.outputPath("plugin-theme-fallback.png"),
|
|
fullPage: true,
|
|
});
|
|
});
|
|
} finally {
|
|
await client.removePlugin(PLUGIN_ID).catch(() => undefined);
|
|
await client
|
|
.patchDaemonConfig({ pluginsEnabled: previousConfig.config.pluginsEnabled ?? false })
|
|
.catch(() => undefined);
|
|
await client.close().catch(() => undefined);
|
|
await rm(directory, { recursive: true, force: true });
|
|
}
|
|
});
|