// node:events as guests use it: classes, EventEmitter.call(this), prototype mixins. import { test, expect } from "@playwright/test"; import { guestLines, runGuest } from "./guest"; test("listener order, once, prepend, removal and introspection match Node", async ({ page }) => { const lines = await guestLines(page, { "/app/main.cjs": [ 'const EventEmitter = require("node:events");', "const e = new EventEmitter();", "const seen = [];", 'const b = () => seen.push("b");', 'e.on("x", () => seen.push("a"));', 'e.on("x", b);', 'e.once("x", () => seen.push("once"));', 'e.prependListener("x", () => seen.push("first"));', 'e.emit("x"); e.emit("x");', 'e.off("x", b); e.emit("x");', "console.log(seen.join(','));", 'console.log(e.listenerCount("x"), e.eventNames().join(","), e.emit("nobody"));', 'console.log(EventEmitter.EventEmitter === EventEmitter, typeof EventEmitter.once, e.setMaxListeners(1) === e, e.getMaxListeners());', ].join("\n"), }, "/app/main.cjs"); expect(lines).toEqual([ "first,a,b,once,first,a,b,first,a", "2 x false", "true function true 1", ]); }); test("EventEmitter.call(this) inheritance and prototype mixins work", async ({ page }) => { const lines = await guestLines(page, { "/app/main.cjs": [ 'const { EventEmitter } = require("events");', "function Legacy() { EventEmitter.call(this); }", "Object.setPrototypeOf(Legacy.prototype, EventEmitter.prototype);", "const l = new Legacy();", 'l.on("hi", (v) => console.log("legacy", v)); l.emit("hi", 1);', "const app = function () {};", "for (const k of Object.getOwnPropertyNames(EventEmitter.prototype)) if (k !== 'constructor') app[k] = EventEmitter.prototype[k];", 'app.on("mount", (v) => console.log("mixin", v)); app.emit("mount", 2);', 'console.log(l instanceof EventEmitter, app.listeners("mount").length);', ].join("\n"), }, "/app/main.cjs"); expect(lines).toEqual(["legacy 1", "mixin 2", "true 1"]); }); test("ESM named imports and events.once resolve with the emitted args", async ({ page }) => { const lines = await guestLines(page, { "/app/main.mjs": [ 'import { EventEmitter, once } from "node:events";', "const e = new EventEmitter();", 'setTimeout(() => e.emit("ready", 1, 2), 1);', 'console.log(JSON.stringify(await once(e, "ready")));', ].join("\n"), }, "/app/main.mjs"); expect(lines).toEqual(["[1,2]"]); }); test("an 'error' with no listener throws the error", async ({ page }) => { const res = await runGuest(page, { "/app/main.cjs": 'const E = require("node:events"); new E().emit("error", new Error("kaboom"));\n', }, "/app/main.cjs"); expect(res.code).toBe(1); expect(res.stderr).toContain("Error: kaboom"); });