Files
SnapOtter/tests/e2e/auth.setup.ts
T
SnapOtterandGitHub 6917a8b0c7 fix(test): repair integration suite after analytics column/endpoint removal (#340)
* fix(test): repair integration suite after analytics column/endpoint removal

#336 moved analytics to a build-time bake: migration 0005 dropped the
users.analytics_enabled and analytics_consent_* columns and removed the
PUT /api/v1/user/analytics endpoint. Two integration tests were left
referencing the old shape and went red on main (13 failures):

- migrate-from-sqlite.test.ts built 1.x SQLite fixtures whose users table
  declared the analytics columns. The generic SELECT *-based importer then
  tried to INSERT them into the 2.0 target, which no longer has those
  columns, failing with Postgres 42703 and rolling back the whole import
  (cascading to all 12 assertions). 1.x never had analytics columns, so the
  fixtures are corrected to drop them. Also removed the now-dead analytics
  entries from the importer's TS/BOOL conversion sets.

- analytics.test.ts asserted the removed PUT endpoint returns 404 but sent
  the request unauthenticated, so the global auth preHandler answered 401
  first. It now authenticates, reaching Fastify's not-found handler (404).

Also removed the stale /api/v1/user/analytics path from openapi.yaml.

Verified locally: full platform integration bucket 1029 passed / 0 failed;
monorepo typecheck clean.

* test(e2e): drop orphaned analytics-consent dismissal calls

#336 deleted the entire analytics consent system (consent page, consent
module, and PUT /api/v1/user/analytics), but six tests/e2e files still
PUT to that removed endpoint to 'dismiss analytics consent.' The calls
were silent no-ops (Playwright request.put / fetch don't throw on 4xx),
so they passed while hitting a dead route.

There is no consent prompt to dismiss anymore, so remove the calls:
- auth.setup.ts / qa-auth.setup.ts: keep the waitForFunction that syncs on
  login completion, drop the now-unused token capture, the dead PUT, and
  the stale 'consent guard' comments.
- rbac / rbac-full / gui-settings-rbac / gui-settings-expanded specs: the
  re-login blocks existed solely to obtain a token for the PUT (reLoginData
  was used nowhere else and the block was the tail of each helper), so
  remove the whole block. The meaningful create-user/login/change-password
  work is untouched.

Verified: no /api/v1/user/analytics refs remain in tests/e2e; biome clean
(no unused vars).
2026-06-24 13:30:18 +08:00

49 lines
2.2 KiB
TypeScript

import fs from "node:fs";
import path from "node:path";
import { test as setup } from "@playwright/test";
const authFile = path.join(process.cwd(), ".playwright", ".auth", "user.json");
setup("authenticate", async ({ page }) => {
// Ensure directory exists
const dir = path.dirname(authFile);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
await page.goto("/login");
await page.getByLabel("Username").fill("admin");
await page.getByLabel("Password").fill("admin");
await page.getByRole("button", { name: /login/i }).click();
// Wait for login to complete (the token lands in localStorage)
await page.waitForFunction(() => localStorage.getItem("snapotter-token"), null, {
timeout: 15_000,
});
// Navigate to "/" and let any client-side redirect settle
// Use waitUntil: "domcontentloaded" to avoid racing with client-side redirects
await page.goto("/", { waitUntil: "domcontentloaded" });
// Wait for the URL to settle (app may redirect through auth guards)
await page.waitForURL((url) => url.pathname === "/", { timeout: 30_000 }).catch(() => {});
await page.waitForLoadState("load");
// Fail fast on a misconfigured/stale e2e server. A correctly-configured e2e
// API (SKIP_MUST_CHANGE_PASSWORD=true, fresh per-run DB) lands the admin on
// "/". If we end up on /change-password or /login instead, the server on
// :13490 is almost certainly a stale reused process (e.g. a leftover
// `pnpm dev` without the e2e env, or a server bound to a mutated DB) that
// playwright's `reuseExistingServer` picked up. Without this guard that state
// silently poisons every loggedInPage test with cascading change-password
// redirects, so surface it loudly with the fix.
const landedPath = new URL(page.url()).pathname;
if (landedPath !== "/") {
throw new Error(
`Auth setup landed on "${landedPath}" instead of "/". The e2e API on :13490 is likely a ` +
`stale/misconfigured server reused by playwright. Kill any process on the e2e ports and re-run:\n` +
` lsof -ti :13490 :2349 | xargs kill -9`,
);
}
// Save storage state (includes localStorage with the token)
await page.context().storageState({ path: authFile });
});