nxtgauge-frontend-solid/tests/e2e/helpers/otp.ts
Ashwin Kumar Sivakumar 8801440459
All checks were successful
build-and-release / build (push) Successful in 2m25s
fix(e2e): use env-aware URLs, captcha-solving, and real Redis OTP retrieval
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>
2026-08-14 00:51:55 +05:30

42 lines
1.5 KiB
TypeScript

import { execFileSync } from "child_process";
/**
* Reads a registration OTP straight out of Redis, the same way a human would
* never get to (the API deliberately never returns it — see
* apps/users/src/handlers/auth.rs's RegisterResponse.otp, which is only
* populated for the DEMO_ACCOUNT_EMAILS allowlist, unset in this environment).
*
* This only works when the machine running the tests has `kubectl` access to
* the cluster (redis-master-0 in the `data` namespace) — i.e. run from the
* same host used for the rest of the live-server runbook, not arbitrary CI.
* Auths via the redis pod's own mounted password file rather than a secret
* value passed on our end, matching how docs/LIVE_SERVER_RUNBOOK.md's manual
* verification steps do it.
*/
export async function getOtpFromRedis(userId: string): Promise<string | null> {
try {
const out = execFileSync(
"kubectl",
[
"-n",
"data",
"exec",
"redis-master-0",
"--",
"sh",
"-c",
'redis-cli -a "$(cat /opt/bitnami/redis/secrets/redis-password)" GET "otp:plain:$1"',
"--", // end of sh -c's own options, "$1" below binds to this
userId,
],
{ encoding: "utf8" }
).trim();
// redis-cli prints "(nil)" for a missing key rather than exiting non-zero.
if (!out || out === "(nil)" || !/^\d{4,}$/.test(out)) return null;
return out;
} catch (e: any) {
console.log("⚠️ Could not read OTP from Redis via kubectl:", e.message);
return null;
}
}