Fix e2e tests for ESM and podman-compose compatibility
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:
@@ -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
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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',
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user