From c085c9e6d04737fbfbc3d1f1c3b73af718f6ec9e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Thu, 19 Feb 2026 07:23:44 +0000 Subject: [PATCH] test(browser): dedupe CDP and download setup helpers --- src/browser/cdp.test.ts | 167 ++++++++---------- ...-core.waits-next-download-saves-it.test.ts | 46 +++-- 2 files changed, 98 insertions(+), 115 deletions(-) diff --git a/src/browser/cdp.test.ts b/src/browser/cdp.test.ts index 24a97d1aa..07f6d688c 100644 --- a/src/browser/cdp.test.ts +++ b/src/browser/cdp.test.ts @@ -1,6 +1,6 @@ import { createServer } from "node:http"; import { afterEach, describe, expect, it } from "vitest"; -import { WebSocketServer } from "ws"; +import { type WebSocket, WebSocketServer } from "ws"; import { rawDataToString } from "../infra/ws.js"; import { createTargetViaCdp, evaluateJavaScript, normalizeCdpWsUrl, snapshotAria } from "./cdp.js"; @@ -14,6 +14,29 @@ describe("cdp", () => { return (wsServer.address() as { port: number }).port; }; + const startWsServerWithMessages = async ( + onMessage: ( + msg: { id?: number; method?: string; params?: Record }, + socket: WebSocket, + ) => void, + ) => { + const wsPort = await startWsServer(); + if (!wsServer) { + throw new Error("ws server not initialized"); + } + wsServer.on("connection", (socket) => { + socket.on("message", (data) => { + const msg = JSON.parse(rawDataToString(data)) as { + id?: number; + method?: string; + params?: Record; + }; + onMessage(msg, socket); + }); + }); + return wsPort; + }; + afterEach(async () => { await new Promise((resolve) => { if (!httpServer) { @@ -32,28 +55,16 @@ describe("cdp", () => { }); it("creates a target via the browser websocket", async () => { - const wsPort = await startWsServer(); - if (!wsServer) { - throw new Error("ws server not initialized"); - } - - wsServer.on("connection", (socket) => { - socket.on("message", (data) => { - const msg = JSON.parse(rawDataToString(data)) as { - id?: number; - method?: string; - params?: { url?: string }; - }; - if (msg.method !== "Target.createTarget") { - return; - } - socket.send( - JSON.stringify({ - id: msg.id, - result: { targetId: "TARGET_123" }, - }), - ); - }); + const wsPort = await startWsServerWithMessages((msg, socket) => { + if (msg.method !== "Target.createTarget") { + return; + } + socket.send( + JSON.stringify({ + id: msg.id, + result: { targetId: "TARGET_123" }, + }), + ); }); httpServer = createServer((req, res) => { @@ -82,32 +93,20 @@ describe("cdp", () => { }); it("evaluates javascript via CDP", async () => { - const wsPort = await startWsServer(); - if (!wsServer) { - throw new Error("ws server not initialized"); - } - - wsServer.on("connection", (socket) => { - socket.on("message", (data) => { - const msg = JSON.parse(rawDataToString(data)) as { - id?: number; - method?: string; - params?: { expression?: string }; - }; - if (msg.method === "Runtime.enable") { - socket.send(JSON.stringify({ id: msg.id, result: {} })); - return; - } - if (msg.method === "Runtime.evaluate") { - expect(msg.params?.expression).toBe("1+1"); - socket.send( - JSON.stringify({ - id: msg.id, - result: { result: { type: "number", value: 2 } }, - }), - ); - } - }); + const wsPort = await startWsServerWithMessages((msg, socket) => { + if (msg.method === "Runtime.enable") { + socket.send(JSON.stringify({ id: msg.id, result: {} })); + return; + } + if (msg.method === "Runtime.evaluate") { + expect(msg.params?.expression).toBe("1+1"); + socket.send( + JSON.stringify({ + id: msg.id, + result: { result: { type: "number", value: 2 } }, + }), + ); + } }); const res = await evaluateJavaScript({ @@ -120,47 +119,35 @@ describe("cdp", () => { }); it("captures an aria snapshot via CDP", async () => { - const wsPort = await startWsServer(); - if (!wsServer) { - throw new Error("ws server not initialized"); - } - - wsServer.on("connection", (socket) => { - socket.on("message", (data) => { - const msg = JSON.parse(rawDataToString(data)) as { - id?: number; - method?: string; - }; - if (msg.method === "Accessibility.enable") { - socket.send(JSON.stringify({ id: msg.id, result: {} })); - return; - } - if (msg.method === "Accessibility.getFullAXTree") { - socket.send( - JSON.stringify({ - id: msg.id, - result: { - nodes: [ - { - nodeId: "1", - role: { value: "RootWebArea" }, - name: { value: "" }, - childIds: ["2"], - }, - { - nodeId: "2", - role: { value: "button" }, - name: { value: "OK" }, - backendDOMNodeId: 42, - childIds: [], - }, - ], - }, - }), - ); - return; - } - }); + const wsPort = await startWsServerWithMessages((msg, socket) => { + if (msg.method === "Accessibility.enable") { + socket.send(JSON.stringify({ id: msg.id, result: {} })); + return; + } + if (msg.method === "Accessibility.getFullAXTree") { + socket.send( + JSON.stringify({ + id: msg.id, + result: { + nodes: [ + { + nodeId: "1", + role: { value: "RootWebArea" }, + name: { value: "" }, + childIds: ["2"], + }, + { + nodeId: "2", + role: { value: "button" }, + name: { value: "OK" }, + backendDOMNodeId: 42, + childIds: [], + }, + ], + }, + }), + ); + } }); const snap = await snapshotAria({ wsUrl: `ws://127.0.0.1:${wsPort}` }); diff --git a/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts b/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts index 8324acfbe..d4e8ad263 100644 --- a/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts +++ b/src/browser/pw-tools-core.waits-next-download-saves-it.test.ts @@ -27,15 +27,8 @@ describe("pw-tools-core", () => { downloadUrl: string; suggestedFilename: string; }) { - let downloadHandler: ((download: unknown) => void) | undefined; - const on = vi.fn((event: string, handler: (download: unknown) => void) => { - if (event === "download") { - downloadHandler = handler; - } - }); - const off = vi.fn(); + const harness = createDownloadEventHarness(); const saveAs = vi.fn(async () => {}); - setPwToolsCoreCurrentPage({ on, off }); const p = mod.waitForDownloadViaPlaywright({ cdpUrl: "http://127.0.0.1:18792", @@ -44,7 +37,7 @@ describe("pw-tools-core", () => { }); await Promise.resolve(); - downloadHandler?.({ + harness.trigger({ url: () => params.downloadUrl, suggestedFilename: () => params.suggestedFilename, saveAs, @@ -55,7 +48,7 @@ describe("pw-tools-core", () => { return { res, outPath }; } - it("waits for the next download and saves it", async () => { + function createDownloadEventHarness() { let downloadHandler: ((download: unknown) => void) | undefined; const on = vi.fn((event: string, handler: (download: unknown) => void) => { if (event === "download") { @@ -63,6 +56,19 @@ describe("pw-tools-core", () => { } }); const off = vi.fn(); + setPwToolsCoreCurrentPage({ on, off }); + return { + trigger: (download: unknown) => { + downloadHandler?.(download); + }, + expectArmed: () => { + expect(downloadHandler).toBeDefined(); + }, + }; + } + + it("waits for the next download and saves it", async () => { + const harness = createDownloadEventHarness(); const saveAs = vi.fn(async () => {}); const download = { @@ -71,8 +77,6 @@ describe("pw-tools-core", () => { saveAs, }; - setPwToolsCoreCurrentPage({ on, off }); - const targetPath = path.resolve("/tmp/file.bin"); const p = mod.waitForDownloadViaPlaywright({ cdpUrl: "http://127.0.0.1:18792", @@ -82,21 +86,15 @@ describe("pw-tools-core", () => { }); await Promise.resolve(); - expect(downloadHandler).toBeDefined(); - downloadHandler?.(download); + harness.expectArmed(); + harness.trigger(download); const res = await p; expect(saveAs).toHaveBeenCalledWith(targetPath); expect(res.path).toBe(targetPath); }); it("clicks a ref and saves the resulting download", async () => { - let downloadHandler: ((download: unknown) => void) | undefined; - const on = vi.fn((event: string, handler: (download: unknown) => void) => { - if (event === "download") { - downloadHandler = handler; - } - }); - const off = vi.fn(); + const harness = createDownloadEventHarness(); const click = vi.fn(async () => {}); setPwToolsCoreCurrentRefLocator({ click }); @@ -108,8 +106,6 @@ describe("pw-tools-core", () => { saveAs, }; - setPwToolsCoreCurrentPage({ on, off }); - const targetPath = path.resolve("/tmp/report.pdf"); const p = mod.downloadViaPlaywright({ cdpUrl: "http://127.0.0.1:18792", @@ -120,10 +116,10 @@ describe("pw-tools-core", () => { }); await Promise.resolve(); - expect(downloadHandler).toBeDefined(); + harness.expectArmed(); expect(click).toHaveBeenCalledWith({ timeout: 1000 }); - downloadHandler?.(download); + harness.trigger(download); const res = await p; expect(saveAs).toHaveBeenCalledWith(targetPath);