mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 17:46:06 +00:00
bun loads a plain `.env` into process.env before anything runs, and tests/helpers/env.ts read that as a deliberate export, so it beat `.env.test` outright. `scripts/test.sh api` therefore pointed the api suites at whatever deployment `.env` describes: `prisma db push --accept-data-loss` for the schema, then a truncate of every table between tests. The e2e half was worse, because playwright.config.ts built and started the app with that DATABASE_URL and those R2 credentials, then wrote fixtures into it. CI never saw any of this: a runner has no `.env`. Three changes, in order of what each one catches: - helpers/dev-env.ts drops the values bun copied out of a development env file, leaving `.env.test` to fill them. Only values that match the file character-for-character go, so a real export still wins and the per-suite databases of a parallel api run keep working. - helpers/test-database.ts refuses a DATABASE_URL whose database name is not marked as a test one, at the single point every path into the setup passes through. This is the backstop, not the fix. - playwright.config.ts blanks the variables a development env file defines and the config does not. Dropping them from process.env is not enough there: `next build` and `next start` run @next/env themselves and read the files again. That is also why a local e2e run could not build at all (a set DISABLE_RATE_LIMIT throws in lib/rate-limit.ts under NODE_ENV=production) and why auth.spec.ts failed on a machine with SMTP configured. `scripts/test.sh` now creates `.env.test` from the committed example instead of asking for a one-line copy, so the guard above is something nobody has to meet.
59 lines
2.4 KiB
TypeScript
59 lines
2.4 KiB
TypeScript
// Guard that keeps the test suites off a real database.
|
|
//
|
|
// This is deliberately a separate, side-effect-free module rather than part of
|
|
// helpers/env.ts: importing that one loads .env.test and throws when
|
|
// DATABASE_URL is missing, which a unit test cannot exercise.
|
|
|
|
/**
|
|
* A database name that identifies a disposable test database.
|
|
*
|
|
* `test` has to be its own `_`/`-` delimited segment, so `openframe_test` and
|
|
* `openframe_test_api` (the per-suite databases the parallel api runs use) are
|
|
* accepted while `openframe` is not.
|
|
*/
|
|
const TEST_DATABASE_NAME = /(^|[_-])test([_-]|$)/i;
|
|
|
|
/**
|
|
* Throws unless `url` names a test database.
|
|
*
|
|
* The reason this exists: bun loads a plain `.env` into `process.env` on its
|
|
* own, so anything that reaches the test setup outside Vitest, such as
|
|
* `bun run test:db:bootstrap`, inherits the DATABASE_URL of whatever deployment
|
|
* `.env` happens to describe when `.env.test` is absent. tests/setup/db-global.ts
|
|
* then builds the schema with `prisma db push --accept-data-loss`, and the api
|
|
* suites truncate every table between tests. Neither is something you want
|
|
* pointed at a database holding real rows, and the failure is silent: the
|
|
* bootstrap prints its usual success line either way.
|
|
*
|
|
* CI is unaffected because it exports DATABASE_URL for a service container
|
|
* named openframe_test.
|
|
*/
|
|
export function assertTestDatabase(url: string): void {
|
|
let parsed: URL;
|
|
|
|
try {
|
|
parsed = new URL(url);
|
|
} catch {
|
|
throw new Error(
|
|
'DATABASE_URL is not a valid connection string, so there is no way to ' +
|
|
'tell whether it points at a test database. Refusing to continue.'
|
|
);
|
|
}
|
|
|
|
const name = decodeURIComponent(parsed.pathname).replace(/^\//, '');
|
|
|
|
if (TEST_DATABASE_NAME.test(name)) return;
|
|
|
|
throw new Error(
|
|
`Refusing to run the test setup against database "${name}" on ` +
|
|
`${parsed.hostname}: the name does not mark it as a test database.\n\n` +
|
|
'The setup builds the schema with `prisma db push --accept-data-loss` ' +
|
|
'and the api suites truncate every table, so this would destroy real ' +
|
|
'data.\n\n' +
|
|
'A test database is one whose name carries a `test` segment, for ' +
|
|
'example openframe_test or openframe_test_api.\n\n' +
|
|
'The usual cause is a missing .env.test, which leaves DATABASE_URL to be ' +
|
|
'inherited from .env: cp .env.test.example .env.test'
|
|
);
|
|
}
|