perf(test): trim browser smoke and speed canvas test reload

This commit is contained in:
Peter Steinberger
2026-02-14 01:47:47 +00:00
parent db8cabedde
commit c4f550ef2a
2 changed files with 34 additions and 118 deletions

View File

@@ -275,7 +275,7 @@ describe("browser control server", () => {
await stopBrowserControlServer();
});
it("covers primary control routes, validation, and attach-only compatibility", async () => {
it("covers primary control routes, validation, and profile compatibility", async () => {
const { startBrowserControlServerFromConfig } = await import("./server.js");
const started = await startBrowserControlServerFromConfig();
expect(started?.port).toBe(testPort);
@@ -356,78 +356,32 @@ describe("browser control server", () => {
});
expect(focusMissing.status).toBe(404);
const [
navMissing,
actMissing,
clickMissingRef,
scrollMissingRef,
scrollSelectorUnsupported,
clickBadButton,
clickBadModifiers,
typeBadText,
uploadMissingPaths,
dialogMissingAccept,
] = await Promise.all([
realFetch(`${base}/navigate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "click" }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "scrollIntoView" }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "scrollIntoView", selector: "button.save" }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "click", ref: "1", button: "nope" }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "click", ref: "1", modifiers: ["Nope"] }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "type", ref: "1", text: 123 }),
}),
realFetch(`${base}/hooks/file-chooser`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
realFetch(`${base}/hooks/dialog`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
]);
const [navMissing, clickMissingRef, scrollSelectorUnsupported, dialogMissingAccept] =
await Promise.all([
realFetch(`${base}/navigate`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "click" }),
}),
realFetch(`${base}/act`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ kind: "scrollIntoView", selector: "button.save" }),
}),
realFetch(`${base}/hooks/dialog`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({}),
}),
]);
expect(navMissing.status).toBe(400);
expect(actMissing.status).toBe(400);
expect(clickMissingRef.status).toBe(400);
expect(scrollMissingRef.status).toBe(400);
expect(scrollSelectorUnsupported.status).toBe(400);
expect(clickBadButton.status).toBe(400);
expect(clickBadModifiers.status).toBe(400);
expect(typeBadText.status).toBe(400);
expect(uploadMissingPaths.status).toBe(400);
expect(dialogMissingAccept.status).toBe(400);
const snapDefault = (await realFetch(`${base}/snapshot?format=wat`).then((r) => r.json())) as {
@@ -499,50 +453,5 @@ describe("browser control server", () => {
body: JSON.stringify({}),
});
expect(missing.status).toBe(400);
reachable = false;
cfgAttachOnly = true;
const attachStarted = (await realFetch(`${base}/start`, {
method: "POST",
}).then((r) => r.json())) as { error?: string };
expect(attachStarted.error ?? "").toMatch(/attachOnly/i);
const { startBrowserBridgeServer } = await import("./bridge-server.js");
const ensured = vi.fn(async () => {
reachable = true;
});
const bridge = await startBrowserBridgeServer({
resolved: {
enabled: true,
controlPort: 0,
cdpProtocol: "http",
cdpHost: "127.0.0.1",
cdpIsLoopback: true,
color: "#FF4500",
headless: true,
noSandbox: false,
attachOnly: true,
defaultProfile: "openclaw",
profiles: {
openclaw: { cdpPort: testPort + 1, color: "#FF4500" },
},
},
onEnsureAttachTarget: ensured,
});
const bridgeStarted = (await realFetch(`${bridge.baseUrl}/start`, {
method: "POST",
}).then((r) => r.json())) as { ok?: boolean; error?: string };
expect(bridgeStarted.error).toBeUndefined();
expect(bridgeStarted.ok).toBe(true);
const status = (await realFetch(`${bridge.baseUrl}/`).then((r) => r.json())) as {
running?: boolean;
};
expect(status.running).toBe(true);
expect(ensured).toHaveBeenCalledTimes(1);
await new Promise<void>((resolve) => bridge.server.close(() => resolve()));
});
});

View File

@@ -264,6 +264,10 @@ export async function createCanvasHostHandler(
const rootReal = await prepareCanvasRoot(rootDir);
const liveReload = opts.liveReload !== false;
const testMode = opts.allowInTests === true;
const reloadDebounceMs = testMode ? 12 : 75;
const writeStabilityThresholdMs = testMode ? 12 : 75;
const writePollIntervalMs = testMode ? 5 : 10;
const wss = liveReload ? new WebSocketServer({ noServer: true }) : null;
const sockets = new Set<WebSocket>();
if (wss) {
@@ -293,7 +297,7 @@ export async function createCanvasHostHandler(
debounce = setTimeout(() => {
debounce = null;
broadcastReload();
}, 75);
}, reloadDebounceMs);
debounce.unref?.();
};
@@ -301,8 +305,11 @@ export async function createCanvasHostHandler(
const watcher = liveReload
? chokidar.watch(rootReal, {
ignoreInitial: true,
awaitWriteFinish: { stabilityThreshold: 75, pollInterval: 10 },
usePolling: opts.allowInTests === true,
awaitWriteFinish: {
stabilityThreshold: writeStabilityThresholdMs,
pollInterval: writePollIntervalMs,
},
usePolling: testMode,
ignored: [
/(^|[\\/])\../, // dotfiles
/(^|[\\/])node_modules([\\/]|$)/,