trails/e2e/journal.test.ts
Ullrich Schäfer f94020a93a
Block unmocked external requests in E2E tests
Surface net for the class of bug we hit in #282 — a POI test silently
relied on a live Overpass server for months because its `page.route`
mock was targeting a URL the browser no longer hit directly. CI stayed
green on coincidence (real OSM data happened to satisfy the "any
marker renders" assertion) until upstream behaviour drifted.

Add a shared Playwright fixture (e2e/fixtures/test.ts) that installs a
catch-all `page.route("**", ...)` before each test. Requests to
localhost + known tile CDNs pass through via `route.continue()`;
anything else is aborted and accumulated. At test teardown, a non-empty
blocked list throws, failing the test with the offending URLs and a
pointer to the fixture.

All seven e2e *.test.ts files updated to import test/expect (+ types)
from ./fixtures/test.

Full suite passes with this fixture in place (50/50 at --workers=2;
catch-all never fires, meaning no test currently relies on an
unallowlisted external service).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 22:42:29 +02:00

53 lines
2.2 KiB
TypeScript

import { test, expect } from "./fixtures/test";
test.describe("Journal", () => {
test("loads the home page", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveTitle("trails.cool");
await expect(page.getByText("Your outdoor activity journal")).toBeVisible();
});
test("shows register and sign in when logged out", async ({ page }) => {
await page.goto("/");
// Nav bar has Register and Sign In links
await expect(page.getByRole("navigation").getByRole("link", { name: "Register" })).toBeVisible();
await expect(page.getByRole("navigation").getByRole("link", { name: "Sign In" })).toBeVisible();
});
test("registration page renders correctly", async ({ page }) => {
await page.goto("/auth/register");
await expect(page.getByRole("heading", { name: "Register" })).toBeVisible();
await expect(page.getByLabel("Email")).toBeVisible();
await expect(page.getByLabel("Username")).toBeVisible();
await expect(page.getByRole("button", { name: /Register with Passkey/ })).toBeVisible();
// No password field
await expect(page.locator('input[type="password"]')).not.toBeVisible();
});
test("login page has passkey and magic link options", async ({ page }) => {
await page.goto("/auth/login");
await expect(page.getByRole("button", { name: /Sign in with Passkey/ })).toBeVisible();
await expect(page.getByText(/magic link/i)).toBeVisible();
});
test("nav bar shows on all pages", async ({ page }) => {
await page.goto("/");
const nav = page.getByRole("navigation");
await expect(nav).toBeVisible();
// Logo/title links home
await expect(nav.getByRole("link", { name: "trails.cool" })).toBeVisible();
// Logged-out nav does not show Routes or Activities
await expect(nav.getByRole("link", { name: "Routes" })).not.toBeVisible();
await expect(nav.getByRole("link", { name: "Activities" })).not.toBeVisible();
});
test("routes page redirects to login when not authenticated", async ({ page }) => {
await page.goto("/routes");
await expect(page).toHaveURL(/auth\/login/);
});
test("activities page redirects to login when not authenticated", async ({ page }) => {
await page.goto("/activities");
await expect(page).toHaveURL(/auth\/login/);
});
});