/**
* Global setup for Playwright E2E tests.
*
* Provisions an ephemeral Postgres database via Instagres (neon.new)
* and writes the connection string to .env.e2e for the Next.js dev server.
*
* The database expires after 72 hours, so no explicit teardown is needed.
*/
import { writeFileSync, existsSync, readFileSync } from 'node:fs';
import { randomBytes } from 'node:crypto';
import path from 'node:path';
const ENV_FILE = path.resolve(import.meta.dirname, '..', '.env.e2e');
async function provisionInstagresDb(): Promise<string> {
console.log('[e2e-setup] Provisioning Instagres database...');
const response = await fetch('https://instagres.com/api/v1/database', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ ref: 'mcp-server-neon-e2e-tests' }),
});
if (!response.ok) {
const body = await response.text();
throw new Error(
`Instagres provisioning failed: ${response.status} ${body}`,
);
}
const data = (await response.json()) as {
connection_string: string;
id: string;
expires_at: string;
};
console.log(
`[e2e-setup] Database provisioned (ID: ${data.id}, expires: ${data.expires_at})`,
);
return data.connection_string;
}
export default async function globalSetup() {
let connectionString: string | undefined;
let cookieSecret: string | undefined;
// Check if we already have a fresh .env.e2e (avoid re-provisioning on re-runs)
if (existsSync(ENV_FILE)) {
const content = readFileSync(ENV_FILE, 'utf-8');
const dbMatch = content.match(/OAUTH_DATABASE_URL=(.+)/);
const secretMatch = content.match(/COOKIE_SECRET=(.+)/);
if (dbMatch?.[1]) {
console.log(
'[e2e-setup] Using existing .env.e2e (delete to re-provision)',
);
connectionString = dbMatch[1].trim();
cookieSecret = secretMatch?.[1]?.trim();
}
}
if (!connectionString) {
connectionString = await provisionInstagresDb();
cookieSecret = randomBytes(32).toString('hex');
// Write .env.e2e for reuse on subsequent runs
const envContent = [
'# Auto-generated by e2e/global-setup.ts – do not commit',
`OAUTH_DATABASE_URL=${connectionString}`,
`COOKIE_SECRET=${cookieSecret}`,
'',
].join('\n');
writeFileSync(ENV_FILE, envContent);
console.log(`[e2e-setup] Wrote ${ENV_FILE}`);
}
// Fallback: generate a fresh secret if not found in .env.e2e
if (!cookieSecret) {
cookieSecret = randomBytes(32).toString('hex');
}
// Set env vars on process so the webServer subprocess inherits them.
// This is needed because Playwright evaluates config (including webServer.env)
// BEFORE globalSetup runs. But process.env changes propagate to spawned processes.
process.env.OAUTH_DATABASE_URL = connectionString;
process.env.COOKIE_SECRET = cookieSecret;
}