tests/e2e/marketing-mobile-header.spec.ts
Rama main · réplica de lectura del repositorio original.
import { expect, test, type Locator } from "@playwright/test";
/* Regression for #391 / #392: at phone widths the marketing header keeps
only the brand, Start now, and the menu toggle. A broad
`.mpx-button.is-small { margin-left: auto }` rule used to split the free
space between brand → Sign in → Start now and right-align form submit
buttons. These assertions go red if that selector comes back. */
const MOBILE_VIEWPORT = { width: 390, height: 844 };
const NAV_GAP_PX = 16;
const GAP_TOLERANCE_PX = 2;
async function boxOf(locator: Locator) {
const box = await locator.boundingBox();
if (!box) throw new Error(`No bounding box for ${String(locator)}`);
return box;
}
test.describe("marketing header on mobile", () => {
test.use({ viewport: MOBILE_VIEWPORT });
test("groups Start now and the menu toggle on the right and hides Sign in", async ({
page,
}) => {
await page.goto("/");
const nav = page.getByRole("navigation", { name: "Primary navigation" });
await expect(nav).toBeVisible();
const brand = nav.getByRole("link", { name: "Mogplex home" });
const signIn = nav.getByRole("link", { name: "Sign in" });
const startNow = nav.getByRole("link", { name: "Start now" });
const toggle = nav.getByRole("button", { name: "Open menu" });
await expect(signIn).toBeHidden();
await expect(startNow).toBeVisible();
await expect(toggle).toBeVisible();
const [navBox, brandBox, startBox, toggleBox] = await Promise.all([
boxOf(nav),
boxOf(brand),
boxOf(startNow),
boxOf(toggle),
]);
// Start now and the toggle keep the nav's normal gap between them.
const actionGap = toggleBox.x - (startBox.x + startBox.width);
expect(Math.abs(actionGap - NAV_GAP_PX)).toBeLessThanOrEqual(
GAP_TOLERANCE_PX
);
// All remaining free space sits between the brand and Start now, so the
// actions hug the right edge rather than floating mid-bar.
const brandToStart = startBox.x - (brandBox.x + brandBox.width);
expect(brandToStart).toBeGreaterThan(NAV_GAP_PX * 4);
const toggleToEdge =
navBox.x + navBox.width - (toggleBox.x + toggleBox.width);
expect(toggleToEdge).toBeLessThan(NAV_GAP_PX * 2);
});
test("keeps Sign in inside the mobile menu", async ({ page }) => {
await page.goto("/");
const mobileNav = page.getByRole("navigation", {
name: "Mobile navigation",
});
await expect(mobileNav).toBeHidden();
await page.getByRole("button", { name: "Open menu" }).click();
await expect(mobileNav).toBeVisible();
await expect(
mobileNav.getByRole("link", { name: "Sign in" })
).toBeVisible();
});
test("leaves the new-code submit button flush with its form", async ({
page,
}) => {
await page.goto("/login/new-code");
const input = page.getByRole("textbox", { name: /email/i });
const submit = page.getByRole("button", { name: /Email me a new code/ });
await expect(submit).toBeVisible();
const [inputBox, submitBox] = await Promise.all([
boxOf(input),
boxOf(submit),
]);
expect(Math.abs(submitBox.x - inputBox.x)).toBeLessThanOrEqual(1);
});
test("legacy login lands on the current mobile sign-in form", async ({
page,
}) => {
await page.goto("/login/beta");
await expect(page).toHaveURL(/\/login\?next=%2F$/);
const input = page.getByTestId("signin-email");
const submit = page.getByTestId("signin-submit");
await expect(submit).toBeVisible();
const [inputBox, submitBox] = await Promise.all([
boxOf(input),
boxOf(submit),
]);
expect(Math.abs(submitBox.x - inputBox.x)).toBeLessThanOrEqual(1);
});
});