aboutsummaryrefslogtreecommitdiff
path: root/test-suite/unit/shared-window.test.mjs
blob: 66041f45e963282bb2c3db8b2b85205cf7899e07 (plain)
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
// Each session has its own window: a window shows only one tab, so sessions sharing one hid each
// other's tabs (no real input, blank screenshots). A session's extra tabs go into its own window.
import assert from "node:assert/strict";
import fs from "node:fs";
import vm from "node:vm";
import { test } from "node:test";

const workerSource = fs.readFileSync(new URL("../../extensions/chrome-profile-bridge/browser-extension/service_worker.js", import.meta.url), "utf8");

function worker({ groups = [], windows = { 5: { id: 5, type: "normal" } } } = {}) {
  const calls = [];
  const listener = { addListener() {}, removeListener() {} };
  let nextTab = 100;
  const w = {
    console, setTimeout, clearTimeout, setInterval: () => 0, navigator: { userAgent: "unit-test" }, fetch: async () => { throw new Error("offline"); },
    chrome: {
      runtime: { id: "test", getManifest: () => ({ version: "0.0.0" }), onInstalled: listener, onStartup: listener },
      alarms: { create() {}, onAlarm: listener }, action: { onClicked: listener }, webNavigation: { onCommitted: listener },
      debugger: { onDetach: listener, onEvent: listener, getTargets: (cb) => cb([]) },
      storage: { session: { get: async () => ({}), set: async (v) => { calls.push({ method: 'storage.set', json: JSON.stringify(v) }); } } },
      tabGroups: { query: async () => groups },
      windows: {
        get: async (id) => windows[id] ?? Promise.reject(new Error("No window")),
        create: async (props) => { calls.push({ method: "windows.create", props }); return { id: 9, tabs: [{ id: 900, windowId: 9 }] }; },
      },
      tabs: {
        create: async (props) => { calls.push({ method: "tabs.create", props }); return { id: nextTab++, windowId: props.windowId }; },
        query: async () => [], get: async () => null, onUpdated: listener,
      },
    },
  };
  w.self = w;
  vm.runInNewContext(workerSource, w);
  return { w, calls };
}

const piGroup = (windowId, name = "Pi Session: claude-code 1 other") => ({ id: 1, windowId, title: name });
const ops = (calls) => calls.filter((c) => c.method !== "storage.set").map((c) => c.method);

test("a new session gets its own window even when another session's window exists", async () => {
  const { w, calls } = worker({ groups: [piGroup(5)] });
  await w.createAutomationTarget("claude-code 2 mine", "Pi Session: claude-code 2 mine");
  assert.deepEqual(ops(calls), ["windows.create"]);
});

test("a session that already has a group adds its tab to that group's window", async () => {
  const { w, calls } = worker({ groups: [piGroup(5, "Pi Session: claude-code 2 mine")] });
  await w.createAutomationTarget("claude-code 2 mine", "Pi Session: claude-code 2 mine");
  assert.deepEqual(ops(calls), ["tabs.create"]);
  assert.equal(calls.find((c) => c.method === "tabs.create").props.windowId, 5);
});

test("chrome_tab new for a session with no group goes to the session's own window, not the focused one", async () => {
  const { w, calls } = worker({ groups: [piGroup(5)] });
  w.groupTab = async (tab) => tab;
  w.bringToFront = async () => {};
  await w.dispatch("tab.new", { url: "https://x.test/", groupTitle: "Pi Session: claude-code 2 mine", sessionKey: "claude-code 2 mine" });
  assert.deepEqual(ops(calls), ["windows.create"]);
  assert.equal(calls[0].props.url, "https://x.test/");
  assert.equal(calls[0].props.focused, false);
});