Files
stroblmeandClaude Opus 5 41b2c28b2b The e2e suite names its own origins, and refuses a live instance
`tests/utils/api.ts` took the API origin from `VITE_API_URL`, which
`tests/config.ts` loads out of `app/.env`. In a checkout configured for a
deployment that names the deployment — so the browser went to the local stack
while every setup and teardown call, `deleteAll` included, went to the live
one. `privateApi.ts` had the same reading, and it creates users.

Both origins now come from one place: `PLAYWRIGHT_BASE_URL`, with the API
derived from it (`app.<domain>` → `api.<domain>`) or named outright by
`PLAYWRIGHT_API_URL`, which is what CI and the compose service set. Nothing in
the suite reads `VITE_API_URL` any more.

Belt and braces, since a stack served under a real domain answers to the same
names its production instance does: a global setup resolves both origins and
refuses anything that is not loopback or a private range, before a test runs.
`PLAYWRIGHT_ALLOW_PUBLIC=1` says you meant it.

`make test-frontend` is now that safe run — the Playwright image on the proxy
network with both names mapped onto Traefik by address, as the host user so it
does not leave root-owned results behind.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NUb8YpL2s3gmN9WTACTt4q
2026-08-20 20:46:04 +02:00

48 lines
1.7 KiB
TypeScript

import path from "node:path"
import { fileURLToPath } from "node:url"
import dotenv from "dotenv"
const __filename = fileURLToPath(import.meta.url)
const __dirname = path.dirname(__filename)
dotenv.config({ path: path.join(__dirname, "../../.env") })
function getEnvVar(name: string): string {
const value = process.env[name]
if (!value) {
throw new Error(`Environment variable ${name} is undefined`)
}
return value
}
export const firstSuperuser = getEnvVar("FIRST_SUPERUSER")
export const firstSuperuserPassword = getEnvVar("FIRST_SUPERUSER_PASSWORD")
/**
* The two origins a run talks to: the app in the browser, and the API for the
* setup and teardown around a spec.
*
* Deliberately *not* taken from `VITE_API_URL`, even though `../../.env` above
* has one. That variable belongs to the app build, and in a checkout configured
* for a deployment it names the deployment — so a suite reading it would drive
* a browser at the local stack while sending its `DELETE`s to the live
* instance. Both origins come from the same place instead: whatever the browser
* is pointed at is what teardown may write to.
*/
export const appUrl = process.env.PLAYWRIGHT_BASE_URL || "http://app.localhost"
export const apiUrl = process.env.PLAYWRIGHT_API_URL || apiOrigin(appUrl)
/** `app.<domain>` serves the SPA, `api.<domain>` serves its API. */
function apiOrigin(app: string): string {
const url = new URL(app)
if (!url.hostname.startsWith("app.")) {
throw new Error(
`Cannot derive the API origin from PLAYWRIGHT_BASE_URL=${app}. ` +
"Set PLAYWRIGHT_API_URL to name it.",
)
}
url.hostname = `api.${url.hostname.slice("app.".length)}`
return url.origin
}