Fix e2e tests for ESM and podman-compose compatibility
All checks were successful
CI / backend-lint (push) Successful in 9s
CI / actions-lint (push) Successful in 14s
CI / frontend-lint (push) Successful in 21s

Replace __dirname with import.meta.url (required by "type": "module").
Replace --wait flag with manual health polling (unsupported by
podman-compose). Use explicit -p project name to isolate test
containers from dev environment.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-20 20:19:17 +01:00
parent a7ec49fcad
commit a12478f24b
3 changed files with 37 additions and 15 deletions

View File

@@ -1,5 +1,8 @@
import { readFileSync } from 'node:fs' import { readFileSync } from 'node:fs'
import { resolve } from 'node:path' import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
interface Fixtures { interface Fixtures {
gameId: number gameId: number

View File

@@ -1,9 +1,12 @@
import { execSync } from 'node:child_process' import { execSync } from 'node:child_process'
import { writeFileSync } from 'node:fs' import { writeFileSync } from 'node:fs'
import { resolve } from 'node:path' import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const API_BASE = 'http://localhost:8000/api/v1' const API_BASE = 'http://localhost:8000/api/v1'
const COMPOSE_FILE = resolve(__dirname, '../../docker-compose.test.yml') const COMPOSE_FILE = resolve(__dirname, '../../docker-compose.test.yml')
const COMPOSE = `docker compose -p nuzlocke-test -f ${COMPOSE_FILE}`
const FIXTURES_PATH = resolve(__dirname, '.fixtures.json') const FIXTURES_PATH = resolve(__dirname, '.fixtures.json')
function run(cmd: string): string { function run(cmd: string): string {
@@ -11,6 +14,19 @@ function run(cmd: string): string {
return execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'inherit'] }) return execSync(cmd, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'inherit'] })
} }
async function waitForApi(url: string, maxAttempts = 30): Promise<void> {
for (let i = 0; i < maxAttempts; i++) {
try {
const res = await fetch(url)
if (res.ok) return
} catch {
// not ready yet
}
await new Promise((r) => setTimeout(r, 2000))
}
throw new Error(`API at ${url} not ready after ${maxAttempts} attempts`)
}
async function api<T>( async function api<T>(
path: string, path: string,
options?: RequestInit, options?: RequestInit,
@@ -28,19 +44,19 @@ async function api<T>(
export default async function globalSetup() { export default async function globalSetup() {
// 1. Start test DB + API // 1. Start test DB + API
run(`docker compose -f ${COMPOSE_FILE} up -d --wait`) run(`${COMPOSE} up -d --build`)
// 2. Run migrations // 2. Wait for API to be healthy
run( console.log('[setup] Waiting for API to be ready...')
`docker compose -f ${COMPOSE_FILE} exec -T test-api alembic -c /app/alembic.ini upgrade head`, await waitForApi('http://localhost:8000/')
)
// 3. Seed reference data (run from /app/src where the app package lives) // 3. Run migrations
run( run(`${COMPOSE} exec -T test-api alembic -c /app/alembic.ini upgrade head`)
`docker compose -f ${COMPOSE_FILE} exec -T -w /app/src test-api python -m app.seeds`,
)
// 4. Create test fixtures via API // 4. Seed reference data (run from /app/src where the app package lives)
run(`${COMPOSE} exec -T -w /app/src test-api python -m app.seeds`)
// 5. Create test fixtures via API
const games = await api<Array<{ id: number; name: string }>>('/games') const games = await api<Array<{ id: number; name: string }>>('/games')
const game = games[0] const game = games[0]
if (!game) throw new Error('No games found after seeding') if (!game) throw new Error('No games found after seeding')
@@ -96,7 +112,7 @@ export default async function globalSetup() {
}), }),
}) })
// 5. Write fixtures file // 6. Write fixtures file
const fixtures = { const fixtures = {
gameId: game.id, gameId: game.id,
runId: testRun.id, runId: testRun.id,

View File

@@ -1,13 +1,16 @@
import { execSync } from 'node:child_process' import { execSync } from 'node:child_process'
import { rmSync } from 'node:fs' import { rmSync } from 'node:fs'
import { resolve } from 'node:path' import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const __dirname = dirname(fileURLToPath(import.meta.url))
const COMPOSE_FILE = resolve(__dirname, '../../docker-compose.test.yml') const COMPOSE_FILE = resolve(__dirname, '../../docker-compose.test.yml')
const COMPOSE = `docker compose -p nuzlocke-test -f ${COMPOSE_FILE}`
const FIXTURES_PATH = resolve(__dirname, '.fixtures.json') const FIXTURES_PATH = resolve(__dirname, '.fixtures.json')
export default async function globalTeardown() { export default async function globalTeardown() {
console.log('[teardown] Stopping test containers...') console.log('[teardown] Stopping test containers...')
execSync(`docker compose -f ${COMPOSE_FILE} down -v`, { execSync(`${COMPOSE} down -v --remove-orphans`, {
encoding: 'utf-8', encoding: 'utf-8',
stdio: 'inherit', stdio: 'inherit',
}) })