all repos — sz-chrome-remote-cdp @ master

pi-browser-harness, patched to drive a Chrome on another host over CDP, with castle_cdp_search web search

test/cdp/session-events-test.ts (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
import { test, describe } from "node:test";
import assert from "node:assert/strict";
import { setImmediate as tick } from "node:timers/promises";
import { createCdpSession } from "../../src/cdp/session";
import { createOwnershipRegistry } from "../../src/cdp/ownership";
import { createStubTransport } from "../domains/fake-client";
import { ok } from "../../src/util/result";

const flush = async (): Promise<void> => {
  await tick();
  await tick();
};

const twoTabSession = async () => {
  const stub = createStubTransport({
    "Target.setDiscoverTargets": ok({}),
    "Target.getTargets": ok({
      targetInfos: [
        { targetId: "t1", type: "page", title: "One", url: "https://one.test/" },
        { targetId: "t2", type: "page", title: "Two", url: "https://two.test/" },
      ],
    }),
    "Target.attachToTarget": [ok({ sessionId: "s1" }), ok({ sessionId: "s2" }), ok({ sessionId: "s3" })],
    "Browser.getWindowForTarget": ok({ windowId: 7 }),
    "Target.activateTarget": ok({}),
  });
  const ownership = createOwnershipRegistry({ ownedTargetIds: ["t1", "t2"] });
  const session = createCdpSession(stub.transport, ownership);
  const attached = await session.attachFirstPage();
  assert.equal(attached.success, true);
  await session.switchTo("t2");
  return { stub, session };
};

describe("CdpSession event routing across tabs", () => {
  test("a console event from a background tab reaches that tab's buffer", async () => {
    const { stub, session } = await twoTabSession();
    stub.emit({
      method: "Runtime.consoleAPICalled",
      sessionId: "s1",
      params: { type: "error", args: [{ type: "string", value: "boom" }] },
    });
    await flush();
    assert.equal(session.drainConsoleBuffer({}).records.length, 0);
    await session.switchTo("t1");
    const drained = session.drainConsoleBuffer({});
    assert.equal(drained.records.length, 1);
    assert.equal(drained.records[0]?.text, "boom");
  });

  test("a network event from a background tab reaches that tab's buffer", async () => {
    const { stub, session } = await twoTabSession();
    stub.emit({
      method: "Network.requestWillBeSent",
      sessionId: "s1",
      params: { requestId: "r1", request: { url: "https://one.test/api", method: "GET" }, type: "XHR" },
    });
    await flush();
    await session.switchTo("t1");
    const drained = session.drainNetworkBuffer({});
    assert.equal(drained.records.length, 1);
    assert.equal(drained.records[0]?.url, "https://one.test/api");
  });

  test("a background tab's dialog is recorded against that tab, not the active one", async () => {
    const { stub, session } = await twoTabSession();
    stub.emit({
      method: "Page.javascriptDialogOpening",
      sessionId: "s1",
      params: { type: "confirm", message: "really?" },
    });
    await flush();
    assert.equal(session.takeDialog(), null);
    await session.switchTo("t1");
    assert.equal(session.takeDialog()?.message, "really?");
  });

  test("a background tab's navigation marks that tab's page info dirty, not the active one", async () => {
    const { stub, session } = await twoTabSession();
    session.drainPageInfoInvalidations();
    stub.emit({ method: "Page.loadEventFired", sessionId: "s1", params: {} });
    await flush();
    assert.equal(session.drainPageInfoInvalidations(), false);
    await session.switchTo("t1");
    assert.equal(session.drainPageInfoInvalidations(), true);
  });

  test("an event from a session this instance never attached is ignored", async () => {
    const { stub, session } = await twoTabSession();
    stub.emit({
      method: "Runtime.consoleAPICalled",
      sessionId: "unknown-session",
      params: { type: "error", args: [{ type: "string", value: "stranger" }] },
    });
    await flush();
    assert.equal(session.drainConsoleBuffer({}).records.length, 0);
    await session.switchTo("t1");
    assert.equal(session.drainConsoleBuffer({}).records.length, 0);
  });
});