Files
HealthLog/e2e/login.spec.ts
T
Marc-André BombeckandClaude Opus 4.7 46e686f396 fix(e2e): switch mobile project to chromium and repair spec flakiness
Three orthogonal fixes that account for most of the e2e suite's
ongoing red:

- The `chromium-mobile` project was actually iPhone 13 (webkit) — CI's
  `playwright install chromium` therefore could not launch it
  (`webkit-2272/pw_run.sh` does not exist). Renaming-to-Pixel-5 makes
  the project name match what the runner provides without expanding
  the install footprint.
- `locale-switch.spec.ts` tried to anchor the cookie at `page.url()`,
  which on a fresh context is `about:blank`; Playwright rejected the
  cookie outright. Using the project's configured baseURL is the
  documented way and works regardless of navigation timing.
- `login.spec.ts` looked for the username/password inputs immediately
  after navigation, but the password form is mounted lazily once the
  user clicks "Login with password" (passkey is the default mode).
  A small helper now opens the form before the assertions run.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 01:52:57 +02:00

66 lines
2.2 KiB
TypeScript

import { expect, test } from "@playwright/test";
/**
* Smoke checks on the login surface — must render, must wire the
* password-manager autofill hints (autoComplete="username" /
* "current-password"), must let the user submit.
*
* These do NOT log in (no DB seed required); the password-flow
* roundtrip is exercised by the integration test in
* tests/integration/auth-flow.test.ts.
*/
async function openPasswordForm(page: import("@playwright/test").Page) {
await page.goto("/auth/login");
// The login page defaults to passkey mode; the password form is
// mounted only after clicking the "Login with password" / "Mit
// Passwort anmelden" outline button.
await page
.getByRole("button", { name: /login with password|mit passwort/i })
.click();
}
test.describe("login page", () => {
test("renders username + password inputs with the right autoComplete", async ({
page,
}) => {
await openPasswordForm(page);
const username = page
.getByLabel(/username|benutzername|email|e-mail/i)
.first();
await expect(username).toBeVisible();
await expect(username).toHaveAttribute("autoComplete", /username|email/);
const password = page.locator('input[type="password"]').first();
await expect(password).toBeVisible();
await expect(password).toHaveAttribute("autoComplete", "current-password");
});
test("rejects an obviously-wrong credential pair", async ({ page }) => {
await openPasswordForm(page);
await page
.getByLabel(/username|benutzername|email|e-mail/i)
.first()
.fill("nobody-here");
await page.locator('input[type="password"]').first().fill("not-the-pw");
// Intercept the API call so the test does not depend on a real
// backend rejecting the credentials. The login form's error
// surfacing is what we actually want to prove here.
await page.route("**/api/auth/login", (route) =>
route.fulfill({
status: 401,
contentType: "application/json",
body: JSON.stringify({ error: "Invalid credentials" }),
}),
);
await page.getByRole("button", { name: /login|anmelden|sign in/i }).click();
await expect(
page.getByText(/invalid credentials|ungültig|falsch/i),
).toBeVisible({ timeout: 5_000 });
});
});