114 lines
5.1 KiB
TypeScript
114 lines
5.1 KiB
TypeScript
import { expect, test } from "./utils/test";
|
|
import { expectNoCriticalA11yViolations } from "./utils/axe";
|
|
import { compactMobileViewport, expectNoHorizontalOverflow, narrowMobileViewport } from "./utils/mobile";
|
|
|
|
test.describe("mobile public pages", () => {
|
|
test.use({ viewport: narrowMobileViewport, isMobile: true, hasTouch: true });
|
|
|
|
test("landing page fits a narrow mobile viewport", async ({ page }) => {
|
|
await page.goto("/", { waitUntil: "domcontentloaded" });
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
|
|
test("not-found page fits a narrow mobile viewport", async ({ page }) => {
|
|
await page.goto("/__nonexistent_route__", { waitUntil: "domcontentloaded" });
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
|
|
test("feature-disabled page has no mobile overflow or critical a11y violations", async ({ page }) => {
|
|
await page.goto("/feature-disabled?feature=Advanced%20reports&tenant=acme", { waitUntil: "domcontentloaded" });
|
|
|
|
await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
|
|
await expect(page.getByRole("link", { name: /dashboard/i })).toHaveAttribute("href", /\/acme\/dashboard$/);
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
|
|
for (const errorPath of ["/401", "/403", "/500"]) {
|
|
test(`${errorPath} has no mobile overflow or critical a11y violations`, async ({ page }) => {
|
|
await page.goto(errorPath, { waitUntil: "domcontentloaded" });
|
|
|
|
await expect(page.locator('[data-testid="error-page"]')).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
}
|
|
|
|
for (const publicPage of [
|
|
{ path: "/privacy-policy", heading: /privacy policy|datenschutzerklarung|datenschutzerklärung/i },
|
|
{ path: "/terms-and-conditions", heading: /terms and conditions|allgemeine geschaftsbedingungen|allgemeine geschäftsbedingungen/i },
|
|
]) {
|
|
test(`${publicPage.path} has no mobile overflow or critical a11y violations`, async ({ page }) => {
|
|
await page.goto(publicPage.path, { waitUntil: "domcontentloaded" });
|
|
|
|
await expect(page.getByRole("heading", { level: 1, name: publicPage.heading })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
}
|
|
|
|
test("public footer selectors open without mobile overflow", async ({ page }) => {
|
|
await page.goto("/privacy-policy", { waitUntil: "domcontentloaded" });
|
|
|
|
await page
|
|
.getByRole("button", { name: /language|sprache/i })
|
|
.last()
|
|
.click();
|
|
await expect(page.getByRole("menu", { name: /language|sprache/i })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await page.keyboard.press("Escape");
|
|
// Radix keeps the closing menu mounted during its exit animation; wait for it
|
|
// to detach so the theme menu is the only matching role="menu".
|
|
await expect(page.getByRole("menu", { name: /language|sprache/i })).toBeHidden();
|
|
|
|
await page.getByRole("button", { name: /theme/i }).last().click();
|
|
await expect(page.getByRole("menu", { name: /theme/i })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
});
|
|
|
|
test.describe("compact mobile public pages", () => {
|
|
test.use({ viewport: compactMobileViewport, isMobile: true, hasTouch: true });
|
|
|
|
for (const route of ["/", "/401", "/403", "/500", "/privacy-policy", "/terms-and-conditions"]) {
|
|
test(`${route} fits a 320px mobile viewport`, async ({ page }) => {
|
|
await page.goto(route, { waitUntil: "domcontentloaded" });
|
|
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
}
|
|
|
|
test("feature-disabled page handles long labels on compact mobile", async ({ page }) => {
|
|
const feature = "VeryLongUnbrokenFeatureNameThatShouldStillWrapSafelyOnSmallMobileScreens";
|
|
await page.goto(`/feature-disabled?feature=${feature}&tenant=acme`, { waitUntil: "domcontentloaded" });
|
|
|
|
await expect(page.getByRole("heading", { level: 1 })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
|
|
test("public footer selectors stay inside a 320px viewport", async ({ page }) => {
|
|
await page.goto("/privacy-policy", { waitUntil: "domcontentloaded" });
|
|
|
|
await page
|
|
.getByRole("button", { name: /language|sprache/i })
|
|
.last()
|
|
.click();
|
|
await expect(page.getByRole("menu", { name: /language|sprache/i })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await page.keyboard.press("Escape");
|
|
// Radix keeps the closing menu mounted during its exit animation; wait for it
|
|
// to detach so the theme menu is the only matching role="menu".
|
|
await expect(page.getByRole("menu", { name: /language|sprache/i })).toBeHidden();
|
|
|
|
await page.getByRole("button", { name: /theme/i }).last().click();
|
|
await expect(page.getByRole("menu", { name: /theme/i })).toBeVisible();
|
|
await expectNoHorizontalOverflow(page);
|
|
await expectNoCriticalA11yViolations(page);
|
|
});
|
|
});
|