The e2e suite names its own origins, and refuses a live instance
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
Playwright Tests / test-playwright (1, 2) (push) Canceled after 0s
Playwright Tests / test-playwright (2, 2) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Compose Smoke Test / test-compose (push) Canceled after 0s
Playwright Tests / merge-reports (push) Canceled after 0s
`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
This commit is contained in:
@@ -17,3 +17,31 @@ function getEnvVar(name: string): string {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user