commit 7a4185a036944dc917773ec1eb7c1ad7cfde3ad0
parent 0c7e4393bbeca4e43cfd3a5e7feb4387f6886541
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date: Fri, 25 Sep 2026 21:50:41 -0400
editor: theme.spec seeds the base key and covers the migration (brand S2)
Seeds `ytdlp-tb:base` (dark, light, sepia, system under an OS dark) and checks
data-base and .dark after a reload. Migration: a stored selenized + dark
becomes the dark base, archive + light becomes sepia, and both legacy keys are
deleted.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Diffstat:
1 file changed, 73 insertions(+), 29 deletions(-)
diff --git a/editor/e2e/theme.spec.ts b/editor/e2e/theme.spec.ts
@@ -1,57 +1,101 @@
-import { test, expect } from "@playwright/test";
+import { test, expect, type Page } from "@playwright/test";
import { resetData } from "./helpers";
-// Regression: refreshing the editor must honor the persisted theme mode. The
-// pre-paint <ThemeScript> sets `.dark` on <html>, but <html> is server-rendered
-// with a static className that omits `dark`; the mutation was lost across the
-// hydration boundary and nothing re-asserted it, so the page loaded light until
-// a manual toggle. ThemeProvider now re-applies the persisted theme on mount.
-const THEME_KEY = "ytdlp-tb:theme";
-const MODE_KEY = "ytdlp-tb:mode";
-
-async function seed(
- page: import("@playwright/test").Page,
- values: Record<string, string>,
-) {
+// Regression: refreshing the editor must honor the persisted theme. The
+// pre-paint <ThemeScript> sets `data-base` and `.dark` on <html>, but <html> is
+// server-rendered with a static className that omits `dark`; the mutation was
+// once lost across the hydration boundary and nothing re-asserted it, so the
+// page loaded light until a manual toggle. ThemeProvider re-applies the
+// persisted base on mount.
+//
+// And the one-time migration: the retired `ytdlp-tb:theme` / `ytdlp-tb:mode`
+// keys become a base (archive + light → sepia) and are deleted.
+const BASE_KEY = "ytdlp-tb:base";
+const LEGACY_THEME_KEY = "ytdlp-tb:theme";
+const LEGACY_MODE_KEY = "ytdlp-tb:mode";
+
+async function seed(page: Page, values: Record<string, string>) {
// Need an origin before localStorage is writable.
await page.goto("/");
- await page.evaluate((vals) => {
- for (const [k, v] of Object.entries(vals)) localStorage.setItem(k, v);
- }, values);
+ await page.evaluate(
+ ({ vals, keys }) => {
+ for (const k of keys) localStorage.removeItem(k);
+ for (const [k, v] of Object.entries(vals)) localStorage.setItem(k, v);
+ },
+ { vals: values, keys: [BASE_KEY, LEGACY_THEME_KEY, LEGACY_MODE_KEY] },
+ );
+}
+
+function storage(page: Page) {
+ return page.evaluate(
+ (keys) => keys.map((k) => localStorage.getItem(k)),
+ [BASE_KEY, LEGACY_THEME_KEY, LEGACY_MODE_KEY],
+ );
}
test.beforeEach(async () => {
await resetData("empty");
});
-test("explicit dark mode survives a reload without toggling", async ({
+test("explicit dark base survives a reload without toggling", async ({
page,
}) => {
- await seed(page, { [MODE_KEY]: "dark" });
+ await seed(page, { [BASE_KEY]: "dark" });
+ await page.reload();
+ const html = page.locator("html");
+ await expect(html).toHaveClass(/(^|\s)dark(\s|$)/);
+ await expect(html).toHaveAttribute("data-base", "dark");
+});
+
+test("explicit light base loads light", async ({ page }) => {
+ await seed(page, { [BASE_KEY]: "light" });
await page.reload();
- await expect(page.locator("html")).toHaveClass(/(^|\s)dark(\s|$)/);
+ const html = page.locator("html");
+ await expect(html).not.toHaveClass(/(^|\s)dark(\s|$)/);
+ await expect(html).toHaveAttribute("data-base", "light");
});
-test("explicit light mode loads light", async ({ page }) => {
- await seed(page, { [MODE_KEY]: "light" });
+test("sepia loads as a light ground (no .dark) and survives a reload", async ({
+ page,
+}) => {
+ await seed(page, { [BASE_KEY]: "sepia" });
await page.reload();
- await expect(page.locator("html")).not.toHaveClass(/(^|\s)dark(\s|$)/);
+ const html = page.locator("html");
+ await expect(html).toHaveAttribute("data-base", "sepia");
+ await expect(html).not.toHaveClass(/(^|\s)dark(\s|$)/);
});
-test.describe("system mode with OS dark", () => {
+test.describe("system base with OS dark", () => {
test.use({ colorScheme: "dark" });
- test("system mode resolves to dark on reload", async ({ page }) => {
- await seed(page, { [MODE_KEY]: "system" });
+ test("system resolves to dark on reload", async ({ page }) => {
+ await seed(page, { [BASE_KEY]: "system" });
await page.reload();
- await expect(page.locator("html")).toHaveClass(/(^|\s)dark(\s|$)/);
+ const html = page.locator("html");
+ await expect(html).toHaveClass(/(^|\s)dark(\s|$)/);
+ await expect(html).toHaveAttribute("data-base", "dark");
});
});
-test("non-base family + dark persist across reload", async ({ page }) => {
- await seed(page, { [MODE_KEY]: "dark", [THEME_KEY]: "selenized" });
+test("migration: a stored selenized + dark becomes the dark base; the old keys go", async ({
+ page,
+}) => {
+ await seed(page, { [LEGACY_MODE_KEY]: "dark", [LEGACY_THEME_KEY]: "selenized" });
await page.reload();
const html = page.locator("html");
await expect(html).toHaveClass(/(^|\s)dark(\s|$)/);
- await expect(html).toHaveAttribute("data-theme", "selenized");
+ await expect(html).toHaveAttribute("data-base", "dark");
+ await expect(html).not.toHaveAttribute("data-theme", /.*/);
+ expect(await storage(page)).toEqual(["dark", null, null]);
+});
+
+test("migration: a stored archive + light (the paper look) becomes sepia", async ({
+ page,
+}) => {
+ await seed(page, { [LEGACY_MODE_KEY]: "light", [LEGACY_THEME_KEY]: "archive" });
+ await page.reload();
+ const html = page.locator("html");
+ await expect(html).toHaveAttribute("data-base", "sepia");
+ await expect(html).not.toHaveClass(/(^|\s)dark(\s|$)/);
+ expect(await storage(page)).toEqual(["sepia", null, null]);
});