Files
pleno-vue/playwright.global-setup.mjs
T
Jeppe Bundgaard 653aa63899 Refactor POS components and implement new features:
- Replaced `POSOrderReference.vue` with `OrderAttachmentsActionButton.vue` and added new features like attachment preview, upload, and management.
- Introduced `POSOrderCustomerWishes.vue` for handling customer wishes fields with autosave behavior.
- Added Playwright global setup/teardown scripts for managing dev server lifecycle during tests.
- Enhanced booking flow test utilities and adjusted visibility rules in `bookingFlow.ts`.
2026-04-13 15:27:34 +02:00

148 lines
3.9 KiB
JavaScript

import { execFile, spawn } from "node:child_process";
import fs from "node:fs/promises";
import path from "node:path";
import { promisify } from "node:util";
const execFileAsync = promisify(execFile);
const devPort = Number(process.env.PLAYWRIGHT_DEV_PORT || 5173);
const baseURL = `http://localhost:${devPort}`;
const pidFile = path.resolve(process.cwd(), "output/playwright/dev-server.json");
async function getListeningProcessOnWindows(port) {
const { stdout } = await execFileAsync("netstat", ["-ano", "-p", "tcp"], {
cwd: process.cwd(),
});
const match = stdout.match(new RegExp(`^\\s*TCP\\s+[^\\s]+:${port}\\s+[^\\s]+\\s+LISTENING\\s+(\\d+)\\s*$`, "mi"));
if (!match) {
return null;
}
const pid = Number(match[1]);
const command = `Get-CimInstance Win32_Process -Filter 'ProcessId = ${pid}' | Select-Object -ExpandProperty CommandLine`;
const processResult = await execFileAsync("powershell", ["-NoProfile", "-Command", command], {
cwd: process.cwd(),
}).catch(() => ({ stdout: "" }));
return {
Id: pid,
CommandLine: processResult.stdout.trim(),
};
}
async function getListeningProcessOnUnix(port) {
try {
const { stdout } = await execFileAsync("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN", "-Fp", "-Fc"], {
cwd: process.cwd(),
});
const pidMatch = stdout.match(/^p(\d+)$/m);
const commandMatch = stdout.match(/^c(.+)$/m);
if (!pidMatch) {
return null;
}
return {
Id: Number(pidMatch[1]),
CommandLine: commandMatch ? commandMatch[1] : "",
};
} catch {
return null;
}
}
async function getListeningProcess(port) {
if (process.platform === "win32") {
return getListeningProcessOnWindows(port);
}
return getListeningProcessOnUnix(port);
}
async function killProcessTree(pid) {
if (!pid) {
return;
}
if (process.platform === "win32") {
await execFileAsync("taskkill", ["/PID", String(pid), "/T", "/F"], { cwd: process.cwd() }).catch(() => {});
return;
}
try {
process.kill(-pid, "SIGTERM");
} catch {
try {
process.kill(pid, "SIGTERM");
} catch {
// ignore
}
}
}
async function waitForServerReady(url, timeoutMs = 120_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
try {
const response = await fetch(url, { redirect: "manual" });
if (response.status < 500) {
return;
}
} catch {
// keep polling until ready
}
await new Promise((resolve) => setTimeout(resolve, 1000));
}
throw new Error(`Timed out waiting for the local Playwright dev server at ${url}.`);
}
export default async function globalSetup() {
if (process.env.PLAYWRIGHT_BASE_URL) {
return;
}
await fs.mkdir(path.dirname(pidFile), { recursive: true });
const existing = await getListeningProcess(devPort);
if (existing) {
if (!/vite(?:\.js)?/i.test(existing.CommandLine || "")) {
throw new Error(`Port ${devPort} is already in use by a non-Vite process: ${existing.CommandLine}`);
}
await killProcessTree(existing.Id);
await new Promise((resolve) => setTimeout(resolve, 1000));
}
const serverProcess =
process.platform === "win32"
? spawn(
"cmd.exe",
["/d", "/s", "/c", `npm.cmd run dev -- --host localhost --port ${devPort} --strictPort`],
{
cwd: process.cwd(),
detached: true,
stdio: "ignore",
windowsHide: true,
}
)
: spawn("npm", ["run", "dev", "--", "--host", "localhost", "--port", String(devPort), "--strictPort"], {
cwd: process.cwd(),
detached: true,
stdio: "ignore",
});
serverProcess.unref();
await fs.writeFile(pidFile, JSON.stringify({ pid: serverProcess.pid, port: devPort }), "utf8");
try {
await waitForServerReady(baseURL);
} catch (error) {
await killProcessTree(serverProcess.pid);
throw error;
}
}