Prepares the full QA test infrastructure for the admin frontend before all prerequisite feature tasks (RCA-12–18) are complete. - playwright.config.ts: 6 browser/device projects (Chromium, Firefox, WebKit, mobile Chrome, mobile Safari, tablet) - tests/e2e/01-login.spec.ts: login form, route guards, setup wizard - tests/e2e/02-dashboard.spec.ts: stats cards, device list, quick actions - tests/e2e/03-cookies.spec.ts: cookie list, search, detail panel, delete - tests/e2e/04-devices.spec.ts: device cards, revoke flow, status filter - tests/e2e/05-settings.spec.ts: three-tab layout, save/error toasts - tests/e2e/06-responsive.spec.ts: no horizontal scroll on mobile/tablet - tests/api/admin-api.spec.ts: REST API contract tests for all /admin/* endpoints - helpers/auth.ts: loginViaUI + loginViaAPI helpers - helpers/mock-api.ts: route intercept fixtures for all pages Co-Authored-By: Paperclip <noreply@paperclip.ing>
64 lines
2.3 KiB
TypeScript
64 lines
2.3 KiB
TypeScript
import { test, expect, devices } from "@playwright/test";
|
|
import { loginViaAPI } from "./helpers/auth.js";
|
|
import { mockDashboard, mockCookies, mockDevices, mockSettings } from "./helpers/mock-api.js";
|
|
|
|
/**
|
|
* Responsive layout tests
|
|
*
|
|
* These run on the default desktop viewport; the Playwright projects
|
|
* in playwright.config.ts also exercise mobile-chrome, mobile-safari,
|
|
* and tablet viewports automatically.
|
|
*
|
|
* This file adds explicit viewport-override tests for key layout expectations.
|
|
*/
|
|
|
|
const PAGES = [
|
|
{ path: "/dashboard", name: "Dashboard" },
|
|
{ path: "/cookies", name: "Cookies" },
|
|
{ path: "/devices", name: "Devices" },
|
|
{ path: "/settings", name: "Settings" },
|
|
];
|
|
|
|
for (const { path, name } of PAGES) {
|
|
test.describe(`Responsive — ${name}`, () => {
|
|
test.beforeEach(async ({ page, request }) => {
|
|
await loginViaAPI(page, request);
|
|
await mockDashboard(page);
|
|
await mockCookies(page);
|
|
await mockDevices(page);
|
|
await mockSettings(page);
|
|
});
|
|
|
|
test("renders without horizontal scroll on mobile (375px)", async ({ page }) => {
|
|
await page.setViewportSize({ width: 375, height: 812 });
|
|
await page.goto(path);
|
|
await page.waitForLoadState("networkidle");
|
|
|
|
const scrollWidth = await page.evaluate(() => document.body.scrollWidth);
|
|
const clientWidth = await page.evaluate(() => document.body.clientWidth);
|
|
expect(scrollWidth).toBeLessThanOrEqual(clientWidth + 1); // 1px tolerance
|
|
});
|
|
|
|
test("renders without horizontal scroll on tablet (768px)", async ({ page }) => {
|
|
await page.setViewportSize({ width: 768, height: 1024 });
|
|
await page.goto(path);
|
|
await page.waitForLoadState("networkidle");
|
|
|
|
const scrollWidth = await page.evaluate(() => document.body.scrollWidth);
|
|
const clientWidth = await page.evaluate(() => document.body.clientWidth);
|
|
expect(scrollWidth).toBeLessThanOrEqual(clientWidth + 1);
|
|
});
|
|
|
|
test("navigation is reachable on mobile", async ({ page }) => {
|
|
await page.setViewportSize({ width: 375, height: 812 });
|
|
await page.goto(path);
|
|
|
|
// On mobile there's typically a hamburger menu or bottom nav
|
|
const nav = page
|
|
.getByRole("navigation")
|
|
.or(page.getByRole("button", { name: /menu|nav/i }));
|
|
await expect(nav.first()).toBeVisible();
|
|
});
|
|
});
|
|
}
|