fix(test): Fix DATABASE_URL environment setup for integration tests
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed

Fixes integration test failures caused by missing DATABASE_URL environment variable.

Changes:
- Add dotenv as dev dependency to load .env.test in vitest setup
- Add .env.test to .gitignore to prevent committing test credentials
- Create .env.test.example with warning comments for documentation
- Add conditional test skipping when DATABASE_URL is not available
- Add DATABASE_URL format validation in vitest setup
- Add error handling to test cleanup to prevent silent failures
- Remove filesystem path disclosure from error messages

The fix allows integration tests to:
- Load DATABASE_URL from .env.test locally for developers with database setup
- Skip gracefully if DATABASE_URL is not available (no database running)
- Connect to postgres service in CI where DATABASE_URL is explicitly provided

Tests affected: auth-rls.integration.spec.ts and other integration tests
requiring real database connections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-07 17:46:59 -06:00
parent 4552c2c460
commit 0b0666558e
6 changed files with 565 additions and 496 deletions

1
.gitignore vendored
View File

@@ -30,6 +30,7 @@ Thumbs.db
# Environment # Environment
.env .env
.env.local .env.local
.env.test
.env.development.local .env.development.local
.env.test.local .env.test.local
.env.production.local .env.production.local

View File

@@ -0,0 +1,9 @@
# WARNING: These are example test credentials for local integration testing.
# Copy this file to .env.test and customize the values for your local environment.
# NEVER use these credentials in any shared environment or commit .env.test to git.
DATABASE_URL="postgresql://test:test@localhost:5432/test"
ENCRYPTION_KEY="test-encryption-key-32-characters"
JWT_SECRET="test-jwt-secret"
INSTANCE_NAME="Test Instance"
INSTANCE_URL="https://test.example.com"

View File

@@ -89,6 +89,7 @@
"@types/sanitize-html": "^2.16.0", "@types/sanitize-html": "^2.16.0",
"@types/supertest": "^6.0.3", "@types/supertest": "^6.0.3",
"@vitest/coverage-v8": "^4.0.18", "@vitest/coverage-v8": "^4.0.18",
"dotenv": "^17.2.4",
"express": "^5.2.1", "express": "^5.2.1",
"prisma": "^6.19.2", "prisma": "^6.19.2",
"supertest": "^7.2.2", "supertest": "^7.2.2",

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1,31 @@
import "reflect-metadata"; import "reflect-metadata";
import * as dotenv from "dotenv";
import * as path from "path";
import * as fs from "fs";
// Load environment variables from .env.test if it exists
// This allows local integration tests to run with a local database
// CI environments explicitly provide DATABASE_URL in the test step
const envTestPath = path.resolve(__dirname, ".env.test");
if (fs.existsSync(envTestPath)) {
const result = dotenv.config({ path: envTestPath });
if (result.error) {
throw new Error(
`Failed to load test environment configuration: ${result.error.message}\n` +
`Ensure .env.test exists in the api directory and is properly formatted.`
);
}
// Validate DATABASE_URL format if provided
if (process.env.DATABASE_URL && !process.env.DATABASE_URL.startsWith("postgresql://")) {
throw new Error(
"Invalid DATABASE_URL format in .env.test. " +
"Expected format: postgresql://user:password@host:port/database"
);
}
// Log only in debug mode
if (process.env.DEBUG) {
console.debug("Test environment variables loaded from .env.test");
}
}

13
pnpm-lock.yaml generated
View File

@@ -244,6 +244,9 @@ importers:
'@vitest/coverage-v8': '@vitest/coverage-v8':
specifier: ^4.0.18 specifier: ^4.0.18
version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)) version: 4.0.18(vitest@4.0.18(@opentelemetry/api@1.9.0)(@types/node@22.19.7)(jiti@2.6.1)(jsdom@26.1.0)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2))
dotenv:
specifier: ^17.2.4
version: 17.2.4
express: express:
specifier: ^5.2.1 specifier: ^5.2.1
version: 5.2.1 version: 5.2.1
@@ -4103,8 +4106,8 @@ packages:
resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==} resolution: {integrity: sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==}
engines: {node: '>=12'} engines: {node: '>=12'}
dotenv@17.2.3: dotenv@17.2.4:
resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} resolution: {integrity: sha512-mudtfb4zRB4bVvdj0xRo+e6duH1csJRM8IukBqfTRvHotn9+LBXB8ynAidP9zHqoRC/fsllXgk4kCKlR21fIhw==}
engines: {node: '>=12'} engines: {node: '>=12'}
drizzle-orm@0.41.0: drizzle-orm@0.41.0:
@@ -7040,7 +7043,7 @@ snapshots:
c12: 3.3.3(magicast@0.3.5) c12: 3.3.3(magicast@0.3.5)
chalk: 5.6.2 chalk: 5.6.2
commander: 12.1.0 commander: 12.1.0
dotenv: 17.2.3 dotenv: 17.2.4
drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)) drizzle-orm: 0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))
open: 10.2.0 open: 10.2.0
pg: 8.17.2 pg: 8.17.2
@@ -10150,7 +10153,7 @@ snapshots:
chokidar: 5.0.0 chokidar: 5.0.0
confbox: 0.2.2 confbox: 0.2.2
defu: 6.1.4 defu: 6.1.4
dotenv: 17.2.3 dotenv: 17.2.4
exsolve: 1.0.8 exsolve: 1.0.8
giget: 2.0.0 giget: 2.0.0
jiti: 2.6.1 jiti: 2.6.1
@@ -10748,7 +10751,7 @@ snapshots:
dotenv@16.6.1: {} dotenv@16.6.1: {}
dotenv@17.2.3: {} dotenv@17.2.4: {}
drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)): drizzle-orm@0.41.0(@opentelemetry/api@1.9.0)(@prisma/client@6.19.2(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3))(typescript@5.9.3))(@types/pg@8.16.0)(better-sqlite3@12.6.2)(kysely@0.28.10)(pg@8.17.2)(prisma@6.19.2(magicast@0.3.5)(typescript@5.9.3)):
optionalDependencies: optionalDependencies: