mirror of
https://github.com/morluto/rea.git
synced 2026-10-29 10:55:57 +00:00
128 lines
5.1 KiB
TypeScript
128 lines
5.1 KiB
TypeScript
import { EventEmitter } from "node:events";
|
|
import type { Page } from "playwright-core";
|
|
import { expect, it } from "vitest";
|
|
|
|
import { browserScenarioSchema } from "../domain/browserScenario.js";
|
|
import { resolveScenarioSecrets } from "../../tests/fixtures/browserScenarioSecrets.js";
|
|
import { PlaywrightScenarioEvents } from "./PlaywrightScenarioEvents.js";
|
|
|
|
it("omits a request without a frame in a shared context", () => {
|
|
const context = new EventEmitter();
|
|
const page = new EventEmitter() as unknown as Page;
|
|
const scenario = browserScenarioSchema.parse({
|
|
browser: { mode: "launch", executable_path: "/opt/chromium" },
|
|
start_url: { url: "https://app.example.test/" },
|
|
actions: [{ step_id: "wait", action: "wait_for_timeout", duration_ms: 1 }],
|
|
capture: { events: ["network"] },
|
|
});
|
|
const secrets = resolveScenarioSecrets(scenario, {});
|
|
const events = new PlaywrightScenarioEvents({
|
|
page,
|
|
context: context as never,
|
|
ownsContext: false,
|
|
enabled: new Set(["network"]),
|
|
secrets,
|
|
});
|
|
const unknownRequest = {
|
|
frame: () => {
|
|
throw new Error("Frame for this navigation request is unavailable");
|
|
},
|
|
url: () => "https://unrelated.example.test/private",
|
|
};
|
|
context.emit("request", unknownRequest);
|
|
expect(events.result().items).toEqual([]);
|
|
const limitations = events.limitations().join("\n");
|
|
expect(limitations).toContain("Shared-context network capture");
|
|
expect(limitations).toContain("excludes requests");
|
|
expect(limitations).toContain("without a known root or descendant");
|
|
});
|
|
|
|
it("detaches root and popup listeners when a scenario finishes", async () => {
|
|
const context = new EventEmitter();
|
|
const page = new EventEmitter() as unknown as Page;
|
|
const popup = Object.assign(new EventEmitter(), {
|
|
url: () => "https://app.example.test/popup",
|
|
});
|
|
const scenario = browserScenarioSchema.parse({
|
|
browser: { mode: "launch", executable_path: "/opt/chromium" },
|
|
start_url: { url: "https://app.example.test/" },
|
|
actions: [{ step_id: "wait", action: "wait_for_timeout", duration_ms: 1 }],
|
|
capture: { events: ["console", "popups"] },
|
|
});
|
|
const secrets = resolveScenarioSecrets(scenario, {});
|
|
const events = new PlaywrightScenarioEvents({
|
|
page,
|
|
context: context as never,
|
|
ownsContext: false,
|
|
enabled: new Set(["console", "popups"]),
|
|
secrets,
|
|
});
|
|
(page as unknown as EventEmitter).emit("popup", popup);
|
|
expect((page as unknown as EventEmitter).listenerCount("console")).toBe(1);
|
|
expect(popup.listenerCount("console")).toBe(1);
|
|
// Popup closure is recorded, then its page-owned listeners are released.
|
|
expect(popup.listenerCount("close")).toBe(2);
|
|
await events.finish();
|
|
expect((page as unknown as EventEmitter).listenerCount("console")).toBe(0);
|
|
expect((page as unknown as EventEmitter).listenerCount("popup")).toBe(0);
|
|
expect(popup.listenerCount("console")).toBe(0);
|
|
expect(popup.listenerCount("popup")).toBe(0);
|
|
expect(popup.listenerCount("close")).toBe(0);
|
|
});
|
|
|
|
it("detaches worker and websocket listeners when a scenario finishes", async () => {
|
|
const context = new EventEmitter();
|
|
const page = new EventEmitter() as unknown as Page;
|
|
const socket = Object.assign(new EventEmitter(), {
|
|
url: () => "wss://app.example.test/socket",
|
|
});
|
|
const worker = Object.assign(new EventEmitter(), {
|
|
url: () => "https://app.example.test/worker.js",
|
|
});
|
|
const scenario = browserScenarioSchema.parse({
|
|
browser: { mode: "launch", executable_path: "/opt/chromium" },
|
|
start_url: { url: "https://app.example.test/" },
|
|
actions: [{ step_id: "wait", action: "wait_for_timeout", duration_ms: 1 }],
|
|
capture: { events: ["websockets", "workers"] },
|
|
});
|
|
const secrets = resolveScenarioSecrets(scenario, {});
|
|
const events = new PlaywrightScenarioEvents({
|
|
page,
|
|
context: context as never,
|
|
ownsContext: false,
|
|
enabled: new Set(["websockets", "workers"]),
|
|
secrets,
|
|
});
|
|
(page as unknown as EventEmitter).emit("websocket", socket);
|
|
(page as unknown as EventEmitter).emit("worker", worker);
|
|
expect(socket.listenerCount("framesent")).toBe(1);
|
|
expect(worker.listenerCount("close")).toBe(1);
|
|
await events.finish();
|
|
expect(socket.listenerCount("framesent")).toBe(0);
|
|
expect(socket.listenerCount("framereceived")).toBe(0);
|
|
expect(socket.listenerCount("close")).toBe(0);
|
|
expect(worker.listenerCount("close")).toBe(0);
|
|
});
|
|
|
|
it("detaches owned-context popup discovery when a scenario finishes", async () => {
|
|
const context = new EventEmitter();
|
|
const page = new EventEmitter() as unknown as Page;
|
|
const scenario = browserScenarioSchema.parse({
|
|
browser: { mode: "launch", executable_path: "/opt/chromium" },
|
|
start_url: { url: "https://app.example.test/" },
|
|
actions: [{ step_id: "wait", action: "wait_for_timeout", duration_ms: 1 }],
|
|
capture: { events: ["console"] },
|
|
});
|
|
const secrets = resolveScenarioSecrets(scenario, {});
|
|
const events = new PlaywrightScenarioEvents({
|
|
page,
|
|
context: context as never,
|
|
ownsContext: true,
|
|
enabled: new Set(["console"]),
|
|
secrets,
|
|
});
|
|
expect(context.listenerCount("page")).toBe(1);
|
|
await events.finish();
|
|
expect(context.listenerCount("page")).toBe(0);
|
|
});
|