test: isolate tests on void_test DB (stop resetDb wiping prod void)
resetDb() DROPs schema; dev DATABASE_URL pointed at the shared prod void DB on .215. setup.js now forces a dedicated void_test DB (TEST_DATABASE_URL or derived) and throws if it would target prod. Created void_test + pg_hba rule on CT 310. Verified: full suite green, prod void space count unchanged (2→2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
51
docs/testing.md
Normal file
51
docs/testing.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Testing — database isolation
|
||||
|
||||
## TL;DR
|
||||
|
||||
Tests run `resetDb()` → **`DROP SCHEMA public CASCADE`**. They MUST run against a
|
||||
dedicated **`void_test`** database, never the prod `void` DB. This is enforced
|
||||
in code (`tests/helpers/setup.js` throws if the resolved URL still targets
|
||||
`/void`).
|
||||
|
||||
## Why
|
||||
|
||||
The void2 Postgres cluster on `192.168.1.215` (CT 310) is shared: the prod app
|
||||
(CT 311) and dev runs both use it. The dev `DATABASE_URL` points at the prod
|
||||
`void` database. Before isolation, `npm test` wiped production data on every run
|
||||
(spaces/tasks/etc. gone; migrations + the seeded `companion` agent re-created by
|
||||
`migrateUp`, which masked the damage).
|
||||
|
||||
## Setup (already done — 2026-06-01)
|
||||
|
||||
1. **`void_test` database** created on the `.215` cluster, owned by `void`:
|
||||
```sql
|
||||
-- run while connected to the `void` db (the `postgres` maintenance db is
|
||||
-- not reachable from the dev box per pg_hba.conf):
|
||||
CREATE DATABASE void_test OWNER void;
|
||||
```
|
||||
2. **`pg_hba.conf`** on CT 310 (`/etc/postgresql/16/main/pg_hba.conf`) — added a
|
||||
rule mirroring the `void` one, then `systemctl reload postgresql@16-main`:
|
||||
```
|
||||
host void_test void 192.168.1.0/24 scram-sha-256
|
||||
```
|
||||
3. **`tests/helpers/setup.js`** (vitest `setupFiles`) forces the test DB and
|
||||
guards against prod:
|
||||
- uses `TEST_DATABASE_URL` if set, else derives it by swapping `/void` →
|
||||
`/void_test` in `DATABASE_URL`;
|
||||
- **throws** if the resolved URL still points at `/void`.
|
||||
4. Dev **`.env`** has `TEST_DATABASE_URL=postgres://void:…@192.168.1.215:5432/void_test`.
|
||||
|
||||
## Running tests
|
||||
|
||||
```bash
|
||||
npm test # vitest; binds the pool to void_test via setup.js
|
||||
```
|
||||
|
||||
`resetDb()` + `migrateUp()` rebuild `void_test`'s schema each run. Prod `void`
|
||||
is never touched. The guard makes a misconfiguration fail loudly instead of
|
||||
silently wiping prod.
|
||||
|
||||
## Note
|
||||
|
||||
`.env` (incl. `TEST_DATABASE_URL`) is git-ignored and not deployed — this is a
|
||||
dev-box concern only. Prod (CT 311) never runs the test suite.
|
||||
@@ -1 +1,24 @@
|
||||
import 'dotenv/config';
|
||||
|
||||
// SAFETY GUARD — tests call resetDb() which runs `DROP SCHEMA public CASCADE`.
|
||||
// The dev DATABASE_URL points at the prod "void" database on the shared .215
|
||||
// cluster, so running tests against it WIPES PRODUCTION. Force a dedicated test
|
||||
// database here, and refuse to run if we'd still be pointed at "void".
|
||||
//
|
||||
// Resolution order:
|
||||
// 1. TEST_DATABASE_URL (explicit), else
|
||||
// 2. derive from DATABASE_URL by swapping the "/void" db name for "/void_test".
|
||||
const resolved =
|
||||
process.env.TEST_DATABASE_URL ||
|
||||
(process.env.DATABASE_URL || '').replace(/\/void(\?|$)/, '/void_test$1');
|
||||
|
||||
if (!resolved || /\/void(\?|$)/.test(resolved)) {
|
||||
throw new Error(
|
||||
'Refusing to run tests: would target the prod "void" database. ' +
|
||||
'Set TEST_DATABASE_URL to a dedicated test DB (e.g. .../void_test).'
|
||||
);
|
||||
}
|
||||
|
||||
// pool.js reads process.env.DATABASE_URL on first import; this setupFile runs
|
||||
// before the test module graph loads, so the pool binds to the test DB.
|
||||
process.env.DATABASE_URL = resolved;
|
||||
|
||||
Reference in New Issue
Block a user