Files
Goldebek/scripts/run-e2e.mjs
T
Per Hoener 0d45331f5c
Deploy / validate-dispatch (push) Successful in 43s
Deploy / scheduled-rebuild-dev (push) Skipped
Deploy / scheduled-rebuild-master (push) Skipped
Deploy / rollback-dev (push) Skipped
Deploy / rollback-master (push) Skipped
Deploy / changes (push) Successful in 13s
Deploy / secret-scan (push) Successful in 9s
Deploy / app-quality (push) Successful in 11m21s
Deploy / security-deps (push) Successful in 14s
Deploy / context (push) Failing after 1s
Deploy / app-image (push) Skipped
Deploy / deploy-dev (push) Skipped
Deploy / deploy-master (push) Skipped
Initial commit
2026-09-18 23:37:19 +02:00

87 lines
2.8 KiB
JavaScript

import { spawn } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
const root = path.resolve(import.meta.dirname, "..");
const appPort = Number(process.env.E2E_PORT ?? 3100);
const fixturePort = Number(process.env.FIXTURE_PORT ?? 3101);
const baseUrl = `http://127.0.0.1:${appPort}`;
const children = [];
function run(command, args, options = {}) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, { cwd: root, env: process.env, stdio: "inherit", ...options });
child.once("error", reject);
child.once("exit", (code) => code === 0
? resolve()
: reject(new Error(`${command} ${args.join(" ")} exited with code ${code ?? "null"}`)));
});
}
function start(command, args, env = {}) {
const child = spawn(command, args, {
cwd: root,
env: { ...process.env, ...env },
stdio: "inherit",
});
children.push(child);
return child;
}
async function waitFor(url) {
for (let attempt = 0; attempt < 60; attempt += 1) {
try {
const response = await fetch(url);
if (response.ok) return;
} catch {
// The process is still starting.
}
await new Promise((resolve) => setTimeout(resolve, 250));
}
throw new Error(`Timed out waiting for ${url}`);
}
async function stopChildren() {
await Promise.all(children.map((child) => new Promise((resolve) => {
if (child.exitCode !== null) return resolve();
child.once("exit", resolve);
child.kill("SIGTERM");
setTimeout(() => {
if (child.exitCode === null) child.kill("SIGKILL");
}, 3_000).unref();
})));
}
async function prepareStandaloneServer() {
const standaloneRoot = path.join(root, ".next", "standalone");
await fs.rm(path.join(standaloneRoot, "public"), { recursive: true, force: true });
await fs.rm(path.join(standaloneRoot, ".next", "static"), { recursive: true, force: true });
await fs.cp(path.join(root, "public"), path.join(standaloneRoot, "public"), { recursive: true });
await fs.cp(
path.join(root, ".next", "static"),
path.join(standaloneRoot, ".next", "static"),
{ recursive: true },
);
}
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
try {
await run(npm, ["run", "build"]);
await prepareStandaloneServer();
start(process.execPath, ["e2e/fixture-server.mjs"], { FIXTURE_PORT: String(fixturePort) });
start(process.execPath, [".next/standalone/server.js"], {
CALENDAR_URL: `http://127.0.0.1:${fixturePort}/calendar.ics`,
APP_URL: baseUrl,
CORS_ORIGIN: baseUrl,
PORT: String(appPort),
HOSTNAME: "127.0.0.1",
});
await waitFor(`${baseUrl}/api/events`);
await run(process.execPath, ["--test", "e2e/smoke.e2e.mjs"], {
env: { ...process.env, E2E_BASE_URL: baseUrl },
});
} finally {
await stopChildren();
}