import { mkdtemp, rm } from 'node:fs/promises'; import { spawn, spawnSync } from 'node:child_process'; import { tmpdir } from 'node:os'; import path from 'node:path'; const cwd = path.resolve('.next/standalone'); const directory = await mkdtemp(path.join(tmpdir(), 'portfolio-e2e-')); const port = process.env.PLAYWRIGHT_PORT || '43119'; const env = { ...process.env, DATA_DIR: directory, SITE_URL: `http://127.0.0.1:${port}`, HOSTNAME: '127.0.0.1', PORT: port, OWNER_EMAIL: 'e2e@example.com', OWNER_PASSWORD: 'Only-for-isolated-e2e-tests-2026' }; for (const command of ['init', 'create-owner']) { const result = spawnSync(process.execPath, ['maintenance.mjs', command], { cwd, env, stdio: 'inherit' }); if (result.status !== 0) { await rm(directory, { recursive: true, force: true }); process.exit(result.status || 1); } } // Generic sample content keeps browser fixtures independent of a private portfolio. const seeded = spawnSync(process.execPath, ['--import', 'tsx', '-e', ` const { initialize } = require('./src/server/initialize.ts'); const { readContent, saveContent } = require('./src/server/content.ts'); const db = initialize(); saveContent(db, 'languages', { code: 'fa', name: 'فارسی', direction: 'rtl', enabled: true, messages: {} }); const project = readContent(db).entries.find(item => item.kind === 'projects'); project.shared.liveUrl = 'https://example.com'; project.shared.caseStudy.gallery = [1, 2].map(index => ({ image: project.shared.image, alt: 'Sample image ' + index, caption: 'Sample caption ' + index })); saveContent(db, 'entries', project); saveContent(db, 'entries', { ...project, id: 'another-project', position: 1, shared: { ...project.shared, title: 'Another project' } }); db.sqlite.close(); `], { cwd: path.resolve('.'), env, stdio: 'inherit' }); if (seeded.status !== 0) { await rm(directory, { recursive: true, force: true }); process.exit(seeded.status || 1); } const server = spawn(process.execPath, ['server.js'], { cwd, env, stdio: 'inherit' }); process.on('SIGTERM', () => server.kill()); process.on('SIGINT', () => server.kill()); server.on('exit', async code => { await rm(directory, { recursive: true, force: true }); process.exit(code || 0); });