chore(infra): update dev compose, add playwright e2e suite & assets

This commit is contained in:
ahp
2026-10-20 17:51:23 +03:30
parent f6ce2bd340
commit 3c5a32394d
23 changed files with 542 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
import { test, expect } from "@playwright/test";
import { requireAuth, injectAuth } from "./helpers";
const VIEWPORTS = [
{ name: "mobile-sm (375px)", width: 375, height: 812 },
{ name: "mobile-lg (430px)", width: 430, height: 932 },
{ name: "tablet (768px)", width: 768, height: 1024 },
{ name: "desktop (1280px)", width: 1280, height: 800 },
{ name: "desktop-xl (1440px)", width: 1440, height: 900 },
];
const ROUTES = ["/cap", "/leaderboard", "/community", "/settings", "/notifications"];
for (const vp of VIEWPORTS) {
test(`no horizontal overflow — ${vp.name}`, async ({ page }) => {
requireAuth();
await page.setViewportSize({ width: vp.width, height: vp.height });
await injectAuth(page);
for (const route of ROUTES) {
await page.goto(route);
await page.waitForLoadState("networkidle", { timeout: 15_000 });
const overflow = await page.evaluate(() => {
return document.documentElement.scrollWidth > document.documentElement.clientWidth;
});
expect(overflow, `Horizontal overflow at ${route} / ${vp.name}`).toBe(false);
}
});
test(`no interactive elements clipped off-screen — ${vp.name}`, async ({ page }) => {
requireAuth();
await page.setViewportSize({ width: vp.width, height: vp.height });
await injectAuth(page);
await page.goto("/cap");
await page.waitForLoadState("networkidle", { timeout: 15_000 });
const clipped = await page.evaluate((vpWidth) => {
return Array.from(document.querySelectorAll("button, a, input"))
.filter((el) => {
const r = el.getBoundingClientRect();
return r.right < 0 || r.left > vpWidth + 50;
}).length;
}, vp.width);
expect(clipped, `${clipped} elements clipped at ${vp.name}`).toBe(0);
});
}