4fa4f13558
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
83 lines
2.2 KiB
JavaScript
83 lines
2.2 KiB
JavaScript
import { spawn } from "node:child_process";
|
|
import net from "node:net";
|
|
|
|
const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
|
|
const getFreePort = async () => {
|
|
for (let i = 0; i < 30; i++) {
|
|
const port = 20000 + Math.floor(Math.random() * 20000);
|
|
const ok = await new Promise((resolve) => {
|
|
const server = net.createServer();
|
|
server.once("error", () => resolve(false));
|
|
server.listen(port, "127.0.0.1", () => {
|
|
server.close(() => resolve(true));
|
|
});
|
|
});
|
|
if (ok) return port;
|
|
}
|
|
throw new Error("Failed to find a free port for smoke test.");
|
|
};
|
|
|
|
const main = async () => {
|
|
const port = await getFreePort();
|
|
const url = `http://127.0.0.1:${port}/`;
|
|
|
|
const child = spawn(process.execPath, ["server/index.js", "--dev"], {
|
|
env: {
|
|
...process.env,
|
|
HOST: "127.0.0.1",
|
|
PORT: String(port),
|
|
},
|
|
stdio: ["ignore", "pipe", "pipe"],
|
|
});
|
|
|
|
const lines = [];
|
|
const pushLines = (chunk) => {
|
|
const text = String(chunk ?? "");
|
|
for (const line of text.split(/\r?\n/)) {
|
|
if (!line) continue;
|
|
lines.push(line);
|
|
if (lines.length > 80) lines.shift();
|
|
}
|
|
};
|
|
child.stdout.on("data", pushLines);
|
|
child.stderr.on("data", pushLines);
|
|
|
|
const deadline = Date.now() + 60_000;
|
|
let lastErr = null;
|
|
|
|
try {
|
|
while (Date.now() < deadline) {
|
|
if (child.exitCode !== null) {
|
|
throw new Error(`Dev server exited early with code ${child.exitCode}.`);
|
|
}
|
|
|
|
try {
|
|
const res = await fetch(url, { redirect: "manual" });
|
|
if (res.status >= 200 && res.status < 500) {
|
|
process.stdout.write(`OK ${res.status} ${url}\n`);
|
|
return;
|
|
}
|
|
lastErr = new Error(`Unexpected status ${res.status} for ${url}`);
|
|
} catch (err) {
|
|
lastErr = err;
|
|
}
|
|
|
|
await sleep(500);
|
|
}
|
|
|
|
throw new Error(
|
|
`Timed out waiting for dev server to respond at ${url}. Last error: ${lastErr?.message || "unknown"}`
|
|
);
|
|
} finally {
|
|
child.kill("SIGTERM");
|
|
await Promise.race([new Promise((r) => child.once("exit", r)), sleep(2000)]);
|
|
}
|
|
};
|
|
|
|
main().catch((err) => {
|
|
process.stderr.write(String(err?.stack || err) + "\n");
|
|
process.exitCode = 1;
|
|
});
|
|
|