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>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-09 01:52:57 +02:00
1 parent 1adda80944
commit 46e686f396
3 files changed
+27 -6

No files matched your search

+6 -1
View File
@@ -16,11 +16,16 @@ test.describe("locale switch", () => {
page,
context,
}) => {
// Cookies must be addressable to a real origin — `page.url()` on
// a fresh context returns `about:blank`, which Playwright rejects.
// Anchor at the configured base URL explicitly.
const baseURL =
test.info().project.use.baseURL ?? "http://localhost:3000";
await context.addCookies([
{
name: "healthlog_locale",
value: locale,
url: page.url() || "http://localhost:3000",
url: baseURL,
},
]);
await page.goto("/auth/login");
+16 -4
View File
@@ -9,13 +9,25 @@ import { expect, test } from "@playwright/test";
* 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 page.goto("/auth/login");
await openPasswordForm(page);
const username = page.getByLabel(/username|benutzername/i).first();
const username = page
.getByLabel(/username|benutzername|email|e-mail/i)
.first();
await expect(username).toBeVisible();
await expect(username).toHaveAttribute("autoComplete", /username|email/);
@@ -25,10 +37,10 @@ test.describe("login page", () => {
});
test("rejects an obviously-wrong credential pair", async ({ page }) => {
await page.goto("/auth/login");
await openPasswordForm(page);
await page
.getByLabel(/username|benutzername/i)
.getByLabel(/username|benutzername|email|e-mail/i)
.first()
.fill("nobody-here");
await page.locator('input[type="password"]').first().fill("not-the-pw");
+5 -1
View File
@@ -44,7 +44,11 @@ export default defineConfig({
{
name: "chromium-mobile",
use: {
...devices["iPhone 13"],
// Pixel 5 — Chromium-based mobile profile so CI only needs
// `playwright install chromium` instead of also pulling
// webkit. iPhone-13 is intentionally avoided here; the
// mobile-Safari smoke is exercised by the iOS app suite.
...devices["Pixel 5"],
},
},
],