forked from SmartDropLabs/smartdrop-frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvisual-regression.spec.ts
More file actions
162 lines (132 loc) · 4.99 KB
/
Copy pathvisual-regression.spec.ts
File metadata and controls
162 lines (132 loc) · 4.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { expect, test, type ConsoleMessage, type Page } from "@playwright/test";
function leaderboardEntry(i: number) {
return {
address: `GLEADER${String(i).padStart(3, "0")}${"A".repeat(45)}`.slice(0, 56),
totalCredits: 1000 - i,
totalStake: 100 + i,
boostUtilization: i % 2 === 0 ? 10 : 25,
};
}
async function installVisualStabilityHooks(page: Page) {
await page.addInitScript(() => {
document.addEventListener("DOMContentLoaded", () => {
const style = document.createElement("style");
style.textContent = `
*,
*::before,
*::after {
animation: none !important;
transition: none !important;
caret-color: transparent !important;
scroll-behavior: auto !important;
}
`;
document.head.appendChild(style);
});
});
}
async function mockLeaderboardApi(page: Page, total: number): Promise<void> {
await page.route("**/__mock-leaderboard-api**", async (route) => {
const url = new URL(route.request().url());
const offset = Number(url.searchParams.get("offset") ?? 0);
const limit = Number(url.searchParams.get("limit") ?? 10);
const sort = url.searchParams.get("sort") ?? "credits";
const all = Array.from({ length: total }, (_, i) => leaderboardEntry(i));
all.sort((a, b) =>
sort === "credits"
? b.totalCredits - a.totalCredits
: b.totalStake - a.totalStake,
);
await route.fulfill({
contentType: "application/json",
body: JSON.stringify({
entries: all.slice(offset, offset + limit),
total,
}),
});
});
}
function trackConsoleErrors(page: Page) {
const errors: string[] = [];
page.on("console", (message: ConsoleMessage) => {
if (message.type() === "error") {
errors.push(message.text());
}
});
page.on("pageerror", (error: Error) => {
errors.push(error.message);
});
return errors;
}
test.describe("visual regression coverage", () => {
test.beforeEach(async ({ page }) => {
await installVisualStabilityHooks(page);
});
test("unknown routes render the 404 page and recover back home", async ({ page }) => {
const consoleErrors = trackConsoleErrors(page);
await page.addInitScript(() => {
localStorage.setItem("chakra-ui-color-mode", "light");
});
await page.goto("/definitely-not-a-real-route");
await page.waitForLoadState("networkidle");
await expect(page.getByText("404")).toBeVisible();
await expect(page.getByText("This page doesn't exist")).toBeVisible();
await expect(page.getByRole("link", { name: "Back to home" })).toBeVisible();
await expect(page).toHaveScreenshot("404-page-light.png", {
fullPage: true,
});
await page.getByRole("link", { name: "Back to home" }).click();
await expect(page).toHaveURL("/");
await expect(page.getByText("SmartDrop Dashboard")).toBeVisible();
expect(consoleErrors).toEqual([]);
});
test("theme toggle persists across reloads on the 404 page", async ({ page }) => {
const consoleErrors = trackConsoleErrors(page);
await page.addInitScript(() => {
localStorage.setItem("chakra-ui-color-mode", "light");
});
await page.goto("/still-not-a-real-route");
await page.waitForLoadState("networkidle");
const toggle = page.getByRole("button", { name: "Toggle colour mode" });
await expect(toggle).toBeVisible();
await toggle.click();
await expect.poll(async () => {
return page.evaluate(() => localStorage.getItem("chakra-ui-color-mode"));
}).toBe("dark");
await page.reload();
await page.waitForLoadState("networkidle");
await expect.poll(async () => {
return page.evaluate(() => localStorage.getItem("chakra-ui-color-mode"));
}).toBe("dark");
await expect(page).toHaveScreenshot("404-page-dark.png", {
fullPage: true,
});
expect(consoleErrors).toEqual([]);
});
test("leaderboard renders deterministically and keeps sorting stable", async ({ page }) => {
const consoleErrors = trackConsoleErrors(page);
await page.clock.setFixedTime(new Date("2026-01-15T12:00:00.000Z"));
await mockLeaderboardApi(page, 25);
await page.goto("/leaderboard");
await page.waitForLoadState("networkidle");
await expect(page.getByText("Leaderboard", { exact: true })).toBeVisible();
await expect(page.getByRole("cell", { name: "1" }).first()).toBeVisible();
await expect(page.getByRole("columnheader", { name: /credits/i })).toHaveAttribute(
"aria-sort",
"descending",
);
await expect(page).toHaveScreenshot("leaderboard-credits.png", {
fullPage: true,
});
await page.getByRole("button", { name: "Stake" }).click();
await expect(page.getByRole("columnheader", { name: /stake/i })).toHaveAttribute(
"aria-sort",
"descending",
);
await expect(page.getByRole("cell", { name: "124" }).first()).toBeVisible();
await expect(page).toHaveScreenshot("leaderboard-stake.png", {
fullPage: true,
});
expect(consoleErrors).toEqual([]);
});
});