// Builds an Express app with the production middleware stack pointed at a // test pool, listens on an ephemeral port, returns { baseUrl, server, pool, cleanup }. // Tests use fetch() against baseUrl — no supertest dep needed. import express from 'express'; import cors from 'cors'; import session from 'express-session'; import connectPgSimple from 'connect-pg-simple'; import { setupTestDb } from './setup-db.js'; const PgStore = connectPgSimple(session); export async function createTestApp({ authEnabled = true } = {}) { const pool = await setupTestDb(); process.env.AUTH_ENABLED = authEnabled ? 'true' : 'false'; process.env.SESSION_SECRET = process.env.SESSION_SECRET || 'test-secret-' + Math.random(); const app = express(); app.use(cors({ origin: true, credentials: true })); app.use(express.json({ limit: '5mb' })); app.use(session({ store: new PgStore({ pool, tableName: 'sessions' }), secret: process.env.SESSION_SECRET, name: 'dragonflight.sid', cookie: { httpOnly: true, sameSite: 'lax', secure: false, path: '/', maxAge: 8 * 3600 * 1000 }, rolling: false, resave: false, saveUninitialized: false, })); app.get('/health', (_req, res) => res.json({ status: 'ok' })); // Tests that need additional routes mount them on the returned `app` // before calling listen. return new Promise(resolve => { const server = app.listen(0, '127.0.0.1', () => { const port = server.address().port; const baseUrl = `http://127.0.0.1:${port}`; const cleanup = async () => { await new Promise(r => server.close(r)); await pool.end(); }; resolve({ app, server, pool, baseUrl, cleanup }); }); }); }