import { describe, it, expect, vi } from "vitest"; // Don't use the global mock — we test the real recyclePage vi.unmock("../services/browser.js"); // Mock puppeteer so initBrowser doesn't launch real browsers vi.mock("puppeteer", () => ({ default: { launch: vi.fn(), }, })); describe("recyclePage", () => { it("cleans up request interception listeners before navigating to about:blank", async () => { // Dynamic import to get the real (unmocked) module const { recyclePage } = await import("../services/browser.js"); const callOrder: string[] = []; const mockPage = { createCDPSession: vi.fn().mockResolvedValue({ send: vi.fn().mockResolvedValue(undefined), detach: vi.fn().mockResolvedValue(undefined), }), removeAllListeners: vi.fn().mockImplementation((event: string) => { callOrder.push(`removeAllListeners:${event}`); return mockPage; }), setRequestInterception: vi.fn().mockImplementation((val: boolean) => { callOrder.push(`setRequestInterception:${val}`); return Promise.resolve(); }), cookies: vi.fn().mockResolvedValue([]), deleteCookie: vi.fn(), goto: vi.fn().mockImplementation((url: string) => { callOrder.push(`goto:${url}`); return Promise.resolve(); }), }; await recyclePage(mockPage as any); // Verify request interception cleanup happens expect(mockPage.removeAllListeners).toHaveBeenCalledWith("request"); expect(mockPage.setRequestInterception).toHaveBeenCalledWith(false); // Verify cleanup happens BEFORE navigation to about:blank const removeIdx = callOrder.indexOf("removeAllListeners:request"); const interceptIdx = callOrder.indexOf("setRequestInterception:false"); const gotoIdx = callOrder.indexOf("goto:about:blank"); expect(removeIdx).toBeGreaterThanOrEqual(0); expect(interceptIdx).toBeGreaterThanOrEqual(0); expect(gotoIdx).toBeGreaterThanOrEqual(0); expect(removeIdx).toBeLessThan(gotoIdx); expect(interceptIdx).toBeLessThan(gotoIdx); }); });