-
Notifications
You must be signed in to change notification settings - Fork 241
Expand file tree
/
Copy pathrtl-dashboard.spec.ts
More file actions
91 lines (85 loc) · 3.55 KB
/
Copy pathrtl-dashboard.spec.ts
File metadata and controls
91 lines (85 loc) · 3.55 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
/**
* RTL (right-to-left) smoke test for the dashboard shell.
*
* Forces dir="rtl" on the root <html> element and loads the dashboard
* route, then asserts that no element overflows the viewport and no
* text is visually clipped. Captures a screenshot artifact for manual
* visual review.
*
* RTL readiness is important because many layout primitives implicitly
* assume LTR (flex/grid gap ordering, margins, icon chevrons, absolute
* positioning). This test catches regressions in overflow / clipped
* text before eventual locale support lands.
*
* @see https://github.com/Stellopay/stellopay-frontend/issues/821
*/
import { test, expect } from "@playwright/test";
test.describe("Dashboard — RTL layout smoke test", () => {
test.beforeEach(async ({ page }) => {
// Force the document into RTL mode before any script runs.
await page.addInitScript(() => {
document.documentElement.setAttribute("dir", "rtl");
});
});
test("dashboard shell renders without viewport overflow or clipped text", async ({
page,
}) => {
await page.goto("/dashboard");
// The dashboard shows a loading state for ~1.5s before content settles.
await expect(page.locator("main, div").first()).toBeVisible();
await page.waitForTimeout(2500);
// -----------------------------------------------------------------------
// 1. Assert the page itself does not scroll horizontally under RTL.
// When dir="rtl" breaks a layout, the document grows wider than the
// viewport and a horizontal scrollbar appears — this is the classic
// RTL regression signal.
// -----------------------------------------------------------------------
const pageOverflow = await page.evaluate(() => {
const doc = document.documentElement;
return {
scrollWidth: doc.scrollWidth,
clientWidth: doc.clientWidth,
};
});
expect(pageOverflow.scrollWidth).toBeLessThanOrEqual(
pageOverflow.clientWidth + 1,
);
// -----------------------------------------------------------------------
// 2. Assert no visible element extends beyond the viewport's horizontal
// edges (content clipped to the right in RTL, i.e. the inline-start).
// We skip elements that are intentionally off-screen (sr-only,
// hidden, or zero-size) to avoid false positives.
// -----------------------------------------------------------------------
const offscreenCount = await page.evaluate(() => {
const viewportWidth = window.innerWidth;
let count = 0;
const all = document.querySelectorAll<HTMLElement>("body *");
for (const el of all) {
const style = window.getComputedStyle(el);
if (
style.display === "none" ||
style.visibility === "hidden" ||
Number(style.opacity) === 0
) {
continue;
}
const rect = el.getBoundingClientRect();
if (rect.width === 0 && rect.height === 0) continue;
// Anything sticking out more than 1px past the viewport edge is a
// likely RTL overflow bug.
if (rect.right > viewportWidth + 1 || rect.left < -1) {
count++;
}
}
return count;
});
expect(offscreenCount).toBe(0);
// -----------------------------------------------------------------------
// 3. Capture a full-page screenshot for manual visual review by the team.
// -----------------------------------------------------------------------
await page.screenshot({
path: "__screenshots__/rtl-dashboard.png",
fullPage: true,
});
});
});