mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
fix(test): keep the suites off a developer's real database
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.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { assertTestDatabase } from '../../helpers/test-database';
|
||||
|
||||
const CREDENTIALS = 'openframe:hunter2';
|
||||
|
||||
function url(database: string, host = 'localhost:5432'): string {
|
||||
return `postgresql://${CREDENTIALS}@${host}/${database}?schema=public`;
|
||||
}
|
||||
|
||||
describe('assertTestDatabase', () => {
|
||||
it.each([
|
||||
['the name the compose file and CI both use', 'openframe_test'],
|
||||
['a per-suite database from a parallel api run', 'openframe_test_api'],
|
||||
['a dash instead of an underscore', 'openframe-test'],
|
||||
['a leading test segment', 'test_openframe'],
|
||||
['nothing but the word itself', 'test'],
|
||||
['an upper-case spelling', 'openframe_TEST'],
|
||||
])('accepts %s', (_label, database) => {
|
||||
expect(() => assertTestDatabase(url(database))).not.toThrow();
|
||||
});
|
||||
|
||||
it.each([
|
||||
['the production database', 'openframe'],
|
||||
['a name that merely starts with the letters', 'testimonials'],
|
||||
['a name that merely ends with them', 'latest'],
|
||||
['an empty database name', ''],
|
||||
])('rejects %s', (_label, database) => {
|
||||
expect(() => assertTestDatabase(url(database))).toThrow(/Refusing to run the test setup/);
|
||||
});
|
||||
|
||||
it('rejects a remote host just the same when the name is not a test one', () => {
|
||||
expect(() => assertTestDatabase(url('openframe', '157.90.147.190:3799'))).toThrow(
|
||||
/database "openframe" on 157\.90\.147\.190/
|
||||
);
|
||||
});
|
||||
|
||||
it('points at the missing .env.test, which is what actually causes this', () => {
|
||||
expect(() => assertTestDatabase(url('openframe'))).toThrow(
|
||||
/cp \.env\.test\.example \.env\.test/
|
||||
);
|
||||
});
|
||||
|
||||
it('keeps the password out of the message, which ends up in logs', () => {
|
||||
expect(() => assertTestDatabase(url('openframe'))).toThrow(
|
||||
expect.objectContaining({ message: expect.not.stringContaining('hunter2') })
|
||||
);
|
||||
});
|
||||
|
||||
it('decodes a percent-encoded database name before judging it', () => {
|
||||
expect(() => assertTestDatabase(url('openframe%5Ftest'))).not.toThrow();
|
||||
});
|
||||
|
||||
it('refuses a connection string it cannot parse rather than assuming the best', () => {
|
||||
expect(() => assertTestDatabase('not-a-url')).toThrow(/not a valid connection string/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user