Skip to content

Commit aa541f4

Browse files
author
Task Orchestrator Agent
committed
fix(visual): pin theme via localStorage["mode"] (MUI's real modeStorageKey)
pinTheme wrote localStorage["mui-color-scheme"], but MUI's InitColorSchemeScript/CssVarsProvider default modeStorageKey is the literal string "mode" — so the light theme never applied and the 3 light-mode baselines captured dark (byte-identical to their dark counterparts). Fix: write localStorage["mode"]. Dark tests are unaffected (defaultMode is already dark). Delete the 3 incorrectly-captured light baselines so CI regenerates them as genuine light-mode captures on the next run. Also confirmed the dashboard is deterministic: the two dark /dashboard captures differ only by sub-threshold anti-aliasing noise (0.00% at per-pixel threshold 8), well within Playwright's threshold:0.2.
1 parent 829f174 commit aa541f4

5 files changed

Lines changed: 10 additions & 6 deletions

web/tests/visual/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ Determinism is enforced in `visualHelpers.ts`:
105105

106106
- **Backend**: the in-memory SQLite screenshot server seeds fixed mock data
107107
(workflows, threads, assets, secrets). No clock, no network, no real auth.
108-
- **Theme**: written to `localStorage["mui-color-scheme"]` *before* first paint.
108+
- **Theme**: written to `localStorage["mode"]` (MUI's `modeStorageKey`) *before* first paint.
109109
- **Animations**: a global init script zeroes every CSS transition/animation;
110110
`toHaveScreenshot({ animations: "disabled" })` freezes the rest at capture.
111111
- **Viewport**: pinned per project.
Binary file not shown.
Binary file not shown.
Binary file not shown.

web/tests/visual/visualHelpers.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import { waitForAnimation } from "../benchmarks/helpers/waitHelpers";
2727

2828
export type Theme = "light" | "dark";
2929

30-
/** localStorage key MUI's CssVarsProvider reads to pick the initial scheme. */
31-
const MUI_COLOR_SCHEME_KEY = "mui-color-scheme";
30+
/** localStorage key MUI's CssVarsProvider / InitColorSchemeScript read to pick the
31+
* initial color scheme. MUI's default `modeStorageKey` is the literal string
32+
* `"mode"` (NOT "mui-color-scheme" — that is a common misconception). Verified
33+
* against @mui/system's `InitColorSchemeScript` (DEFAULT_MODE_STORAGE_KEY). */
34+
const MUI_COLOR_MODE_KEY = "mode";
3235

3336
// ─── Persisted panel store shapes ────────────────────────────────────────────
3437
// These mirror the zustand persist shapes used by the app (see
@@ -75,9 +78,10 @@ type GotoOptions = {
7578
export async function pinTheme(page: Page, theme: Theme): Promise<void> {
7679
await page.addInitScript((mode: string) => {
7780
try {
78-
// MUI's CssVarsProvider (InitColorSchemeScript) reads this key on first
79-
// paint to pick the initial light/dark scheme.
80-
window.localStorage.setItem(MUI_COLOR_SCHEME_KEY, mode);
81+
// MUI's CssVarsProvider + InitColorSchemeScript both read this key on
82+
// first paint to pick the initial light/dark scheme (the class added to
83+
// <html> selects the palette). Must run before any app script.
84+
window.localStorage.setItem(MUI_COLOR_MODE_KEY, mode);
8185
} catch {
8286
/* localStorage unavailable */
8387
}

0 commit comments

Comments
 (0)