Add unit tests and new components for edge gateway workflows:

- Introduced unit tests for edge gateway workflow helpers, including workflow step resolution, incident action mapping, relay health row formatting, and workspace state merging.
- Added new components for advanced operations, configuration panel, context panel, fleet rail, and health summary.
- Enhanced gateway management UI with support for advanced actions, fallback operations, relay health visualization, and device binding features.
This commit is contained in:
Jeppe Bundgaard
2026-04-16 13:44:36 +02:00
parent 2d94322021
commit bef9eaeb72
34 changed files with 5296 additions and 2369 deletions
+70 -14
View File
@@ -10,6 +10,8 @@ const runtimeNamespace = String(process.env.PLAYWRIGHT_ARTIFACT_NAMESPACE || `po
.trim()
.replace(/[^a-zA-Z0-9._-]+/g, "-");
const pidFile = path.resolve(process.cwd(), "output/playwright", `dev-server-${runtimeNamespace}.json`);
const posViewsDirectory = path.resolve(process.cwd(), "src/views/dashboards/departmentDashboard/modules/Pos");
const shopComponentsDirectory = path.resolve(process.cwd(), "src/components/shop");
async function getListeningProcessOnWindows(port) {
const { stdout } = await execFileAsync("netstat", ["-ano", "-p", "tcp"], {
@@ -102,6 +104,63 @@ async function waitForServerReady(url, timeoutMs = 120_000) {
throw new Error(`Timed out waiting for the local Playwright dev server at ${url}.`);
}
async function buildWarmupTargets() {
const [posViewFiles, shopComponentFiles] = await Promise.all([
fs.readdir(posViewsDirectory),
fs.readdir(shopComponentsDirectory),
]);
return [
{ pathname: "/admin/12/modules/pos?step=1", expectedContentType: "text/html" },
{ pathname: "/admin/12/modules/pos/orders/54518", expectedContentType: "text/html" },
{ pathname: "/@vite/client", expectedContentType: "javascript" },
{ pathname: "/src/main.js", expectedContentType: "javascript" },
{ pathname: "/src/router.js", expectedContentType: "javascript" },
...posViewFiles
.filter((fileName) => fileName.endsWith(".vue"))
.map((fileName) => ({
pathname: `/src/views/dashboards/departmentDashboard/modules/Pos/${fileName}`,
expectedContentType: "javascript",
})),
...shopComponentFiles
.filter((fileName) => fileName.endsWith(".vue"))
.map((fileName) => ({
pathname: `/src/components/shop/${fileName}`,
expectedContentType: "javascript",
})),
];
}
async function warmUpAsset(url, expectedContentType, timeoutMs = 120_000) {
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
try {
const response = await fetch(url, { redirect: "manual" });
const contentType = response.headers.get("content-type") || "";
if (response.ok && contentType.toLowerCase().includes(expectedContentType)) {
await response.arrayBuffer();
return;
}
} catch {
// keep polling until the Vite transform is ready
}
await new Promise((resolve) => setTimeout(resolve, 500));
}
throw new Error(`Timed out warming Playwright dev asset ${url}.`);
}
async function warmUpDevServer(url) {
const warmupTargets = await buildWarmupTargets();
for (const target of warmupTargets) {
await warmUpAsset(new URL(target.pathname, url).toString(), target.expectedContentType);
}
}
export default async function globalSetup() {
if (process.env.PLAYWRIGHT_BASE_URL) {
return;
@@ -121,20 +180,16 @@ export default async function globalSetup() {
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,
env: {
...process.env,
PLAYWRIGHT: "1",
},
stdio: "ignore",
windowsHide: true,
}
)
? spawn("cmd.exe", ["/d", "/s", "/c", `npm.cmd run dev -- --host localhost --port ${devPort} --strictPort`], {
cwd: process.cwd(),
detached: true,
env: {
...process.env,
PLAYWRIGHT: "1",
},
stdio: "ignore",
windowsHide: true,
})
: spawn("npm", ["run", "dev", "--", "--host", "localhost", "--port", String(devPort), "--strictPort"], {
cwd: process.cwd(),
detached: true,
@@ -151,6 +206,7 @@ export default async function globalSetup() {
try {
await waitForServerReady(baseURL);
await warmUpDevServer(baseURL);
} catch (error) {
await killProcessTree(serverProcess.pid);
throw error;