All checks were successful
build-and-release / build (push) Successful in 2m25s
The e2e suite only ever worked against a local docker-compose stack: - Hardcoded http://localhost:3000 / :9100 everywhere, ignoring TEST_ENV=production and playwright.config.ts's own baseURL logic. - /api/auth/login and /api/auth/register now require solving a math captcha first; none of these tests sent captcha_id/captcha_answer, so every login/register call 422'd against the live API. - OTP retrieval shelled out to a local, unauthenticated redis-cli, which can't reach the real (kubectl-exec + password-protected) Redis. - Several files launched their own chromium.launch({headless: false}), which crashes immediately on a server with no X display. - One file had a hardcoded macOS absolute path for screenshots. Added tests/e2e/helpers/{env,captcha,otp,auth-flow}.ts as shared, reusable fixes for all of the above, and updated every affected spec file to use them. Verified via a full run against test111.nxtgauge.com: 971 schemathesis-adjacent smoke assertions aside, the actual signal here is 0 of the 130 prior failures came from real product bugs - all were this environment mismatch. See docs/LIVE_SERVER_RUNBOOK.md step 5. Also fixes .gitignore: it excluded 'playwright-report' (singular) but playwright.config.ts's actual outputFolder is 'playwright-reports' (plural) - generated HTML report artifacts had been getting committed by accident. Untracked the existing ones; left tests/e2e/visual/*-snapshots/ (newly-generated visual regression baselines from this run) untracked for now since establishing baselines needs a human look, not a blind commit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
28 lines
1.1 KiB
TypeScript
28 lines
1.1 KiB
TypeScript
import { API_BASE } from "./env";
|
|
|
|
/**
|
|
* Fetches a fresh math captcha from the API and solves it.
|
|
* Captchas are single-use (Redis-backed) — call this immediately before the
|
|
* request that needs it, never cache/reuse a solved captcha_id.
|
|
*/
|
|
export async function solveCaptcha(): Promise<{ captcha_id: string; captcha_answer: string }> {
|
|
const res = await fetch(`${API_BASE}/auth/captcha`, { method: "POST" });
|
|
if (!res.ok) {
|
|
throw new Error(`Failed to fetch captcha: ${res.status} ${await res.text()}`);
|
|
}
|
|
const { captcha_id, challenge } = await res.json();
|
|
|
|
// Challenge format observed from the API: "N + N = ?" / "N - N = ?" (also
|
|
// tolerate "*" just in case). Keep this in sync with
|
|
// apps/users/src/handlers/auth.rs's captcha generator.
|
|
const match = String(challenge).match(/(-?\d+)\s*([+\-*])\s*(-?\d+)/);
|
|
if (!match) {
|
|
throw new Error(`Unrecognized captcha challenge format: "${challenge}"`);
|
|
}
|
|
const [, aStr, op, bStr] = match;
|
|
const a = Number(aStr);
|
|
const b = Number(bStr);
|
|
const answer = op === "+" ? a + b : op === "-" ? a - b : a * b;
|
|
|
|
return { captcha_id, captcha_answer: String(answer) };
|
|
}
|