test(browser): cover downloads + responsebody

This commit is contained in:
Peter Steinberger
2026-01-12 19:40:55 +00:00
parent d4f7dc067e
commit f839d949b2
2 changed files with 180 additions and 2 deletions

View File

@@ -2,7 +2,12 @@ import { beforeEach, describe, expect, it, vi } from "vitest";
let currentPage: Record<string, unknown> | null = null;
let currentRefLocator: Record<string, unknown> | null = null;
let pageState: { console: unknown[]; armIdUpload: number; armIdDialog: number };
let pageState: {
console: unknown[];
armIdUpload: number;
armIdDialog: number;
armIdDownload: number;
};
const sessionMocks = vi.hoisted(() => ({
getPageForTargetId: vi.fn(async () => {
@@ -26,7 +31,12 @@ describe("pw-tools-core", () => {
beforeEach(() => {
currentPage = null;
currentRefLocator = null;
pageState = { console: [], armIdUpload: 0, armIdDialog: 0 };
pageState = {
console: [],
armIdUpload: 0,
armIdDialog: 0,
armIdDownload: 0,
};
for (const fn of Object.values(sessionMocks)) fn.mockClear();
});
@@ -279,6 +289,113 @@ describe("pw-tools-core", () => {
});
});
it("waits for the next download and saves it", 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 saveAs = vi.fn(async () => {});
const download = {
url: () => "https://example.com/file.bin",
suggestedFilename: () => "file.bin",
saveAs,
};
currentPage = { on, off };
const mod = await importModule();
const p = mod.waitForDownloadViaPlaywright({
cdpUrl: "http://127.0.0.1:18792",
targetId: "T1",
path: "/tmp/file.bin",
timeoutMs: 1000,
});
await Promise.resolve();
expect(downloadHandler).toBeDefined();
downloadHandler?.(download);
const res = await p;
expect(saveAs).toHaveBeenCalledWith("/tmp/file.bin");
expect(res.path).toBe("/tmp/file.bin");
});
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 click = vi.fn(async () => {});
currentRefLocator = { click };
const saveAs = vi.fn(async () => {});
const download = {
url: () => "https://example.com/report.pdf",
suggestedFilename: () => "report.pdf",
saveAs,
};
currentPage = { on, off };
const mod = await importModule();
const p = mod.downloadViaPlaywright({
cdpUrl: "http://127.0.0.1:18792",
targetId: "T1",
ref: "e12",
path: "/tmp/report.pdf",
timeoutMs: 1000,
});
await Promise.resolve();
expect(downloadHandler).toBeDefined();
expect(click).toHaveBeenCalledWith({ timeout: 1000 });
downloadHandler?.(download);
const res = await p;
expect(saveAs).toHaveBeenCalledWith("/tmp/report.pdf");
expect(res.path).toBe("/tmp/report.pdf");
});
it("waits for a matching response and returns its body", async () => {
let responseHandler: ((resp: unknown) => void) | undefined;
const on = vi.fn((event: string, handler: (resp: unknown) => void) => {
if (event === "response") responseHandler = handler;
});
const off = vi.fn();
currentPage = { on, off };
const resp = {
url: () => "https://example.com/api/data",
status: () => 200,
headers: () => ({ "content-type": "application/json" }),
text: async () => '{"ok":true,"value":123}',
};
const mod = await importModule();
const p = mod.responseBodyViaPlaywright({
cdpUrl: "http://127.0.0.1:18792",
targetId: "T1",
url: "**/api/data",
timeoutMs: 1000,
maxChars: 10,
});
await Promise.resolve();
expect(responseHandler).toBeDefined();
responseHandler?.(resp);
const res = await p;
expect(res.url).toBe("https://example.com/api/data");
expect(res.status).toBe(200);
expect(res.body).toBe('{"ok":true');
expect(res.truncated).toBe(true);
});
it("rewrites strict mode violations into snapshot hints", async () => {
const click = vi.fn(async () => {
throw new Error(

View File

@@ -24,6 +24,11 @@ const pwMocks = vi.hoisted(() => ({
clickViaPlaywright: vi.fn(async () => {}),
closePageViaPlaywright: vi.fn(async () => {}),
closePlaywrightBrowserConnection: vi.fn(async () => {}),
downloadViaPlaywright: vi.fn(async () => ({
url: "https://example.com/report.pdf",
suggestedFilename: "report.pdf",
path: "/tmp/report.pdf",
})),
dragViaPlaywright: vi.fn(async () => {}),
evaluateViaPlaywright: vi.fn(async () => "ok"),
fillFormViaPlaywright: vi.fn(async () => {}),
@@ -32,6 +37,12 @@ const pwMocks = vi.hoisted(() => ({
navigateViaPlaywright: vi.fn(async () => ({ url: "https://example.com" })),
pdfViaPlaywright: vi.fn(async () => ({ buffer: Buffer.from("pdf") })),
pressKeyViaPlaywright: vi.fn(async () => {}),
responseBodyViaPlaywright: vi.fn(async () => ({
url: "https://example.com/api/data",
status: 200,
headers: { "content-type": "application/json" },
body: '{"ok":true}',
})),
resizeViewportViaPlaywright: vi.fn(async () => {}),
selectOptionViaPlaywright: vi.fn(async () => {}),
setInputFilesViaPlaywright: vi.fn(async () => {}),
@@ -40,6 +51,11 @@ const pwMocks = vi.hoisted(() => ({
buffer: Buffer.from("png"),
})),
typeViaPlaywright: vi.fn(async () => {}),
waitForDownloadViaPlaywright: vi.fn(async () => ({
url: "https://example.com/report.pdf",
suggestedFilename: "report.pdf",
path: "/tmp/report.pdf",
})),
waitForViaPlaywright: vi.fn(async () => {}),
}));
@@ -558,6 +574,51 @@ describe("browser control server", () => {
timeoutMs: 5678,
});
const waitDownload = await realFetch(`${base}/wait/download`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path: "/tmp/report.pdf", timeoutMs: 1111 }),
}).then((r) => r.json());
expect(waitDownload).toMatchObject({ ok: true });
expect(pwMocks.waitForDownloadViaPlaywright).toHaveBeenCalledWith({
cdpUrl: cdpBaseUrl,
targetId: "abcd1234",
path: "/tmp/report.pdf",
timeoutMs: 1111,
});
const download = await realFetch(`${base}/download`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ ref: "e12", path: "/tmp/report.pdf" }),
}).then((r) => r.json());
expect(download).toMatchObject({ ok: true });
expect(pwMocks.downloadViaPlaywright).toHaveBeenCalledWith({
cdpUrl: cdpBaseUrl,
targetId: "abcd1234",
ref: "e12",
path: "/tmp/report.pdf",
timeoutMs: undefined,
});
const responseBody = await realFetch(`${base}/response/body`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
url: "**/api/data",
timeoutMs: 2222,
maxChars: 10,
}),
}).then((r) => r.json());
expect(responseBody).toMatchObject({ ok: true });
expect(pwMocks.responseBodyViaPlaywright).toHaveBeenCalledWith({
cdpUrl: cdpBaseUrl,
targetId: "abcd1234",
url: "**/api/data",
timeoutMs: 2222,
maxChars: 10,
});
const consoleRes = (await realFetch(`${base}/console?level=error`).then(
(r) => r.json(),
)) as { ok: boolean; messages?: unknown[] };