aboutsummaryrefslogtreecommitdiff
path: root/test-suite/unit
diff options
context:
space:
mode:
authorTianren Dong <tianrendong.dtr@gmail.com>2026-09-28 19:47:21 -0400
committerGitHub <noreply@github.com>2026-09-28 19:47:21 -0400
commitc78b1dc8ebced75957cb45623d33ed8c8351ed96 (patch)
tree362a08c4721e65f084390cf6976292ccda375253 /test-suite/unit
parent6c5d31eddd145697f4c6f9d4964000c6e2068cb1 (diff)
parentb33d18552599664901356ae27db0270df3cc3129 (diff)
Merge pull request #24 from tianrendong/fix/fill-textarea-and-new-tab-capture
Fill whole textareas; cover new tabs' first page with early capture
Diffstat (limited to 'test-suite/unit')
-rw-r--r--test-suite/unit/automation-target.test.mjs11
-rw-r--r--test-suite/unit/console-capture.test.mjs21
-rw-r--r--test-suite/unit/input-reliability.test.mjs12
3 files changed, 39 insertions, 5 deletions
diff --git a/test-suite/unit/automation-target.test.mjs b/test-suite/unit/automation-target.test.mjs
index 7f46597..73fbc77 100644
--- a/test-suite/unit/automation-target.test.mjs
+++ b/test-suite/unit/automation-target.test.mjs
@@ -87,14 +87,17 @@ function makeChrome(state, { withWindows = true, withStorage = true, withTabGrou
// Chrome closes a window automatically when its final tab is removed.
if (tab && ![...tabs.values()].some((other) => other.windowId === tab.windowId)) windows.delete(tab.windowId);
},
- group: async ({ groupId, tabIds = [] } = {}) => {
+ // Like Chrome: a new group goes into createProperties.windowId, else the *current* window
+ // (the user's), and grouped tabs move into the group's window.
+ group: async ({ groupId, tabIds = [], createProperties } = {}) => {
let gid = groupId;
if (typeof gid !== "number") {
gid = alloc.group();
- const firstTab = tabs.get(tabIds[0]);
- groups.set(gid, { id: gid, title: "", color: "grey", collapsed: false, windowId: firstTab ? firstTab.windowId : userWindowId });
+ const windowId = typeof createProperties?.windowId === "number" ? createProperties.windowId : userWindowId;
+ groups.set(gid, { id: gid, title: "", color: "grey", collapsed: false, windowId });
}
- for (const tid of tabIds) { const t = tabs.get(tid); if (t) t.groupId = gid; }
+ const groupWindow = groups.get(gid).windowId;
+ for (const tid of tabIds) { const t = tabs.get(tid); if (t) { t.groupId = gid; t.windowId = groupWindow; } }
return gid;
},
ungroup: async (id) => { const ids = Array.isArray(id) ? id : [id]; for (const tid of ids) { const t = tabs.get(tid); if (t) t.groupId = -1; } },
diff --git a/test-suite/unit/console-capture.test.mjs b/test-suite/unit/console-capture.test.mjs
index ba0410b..48430ca 100644
--- a/test-suite/unit/console-capture.test.mjs
+++ b/test-suite/unit/console-capture.test.mjs
@@ -20,7 +20,8 @@ function loadWorker() {
debugger: { onDetach: noop, onEvent: noop },
storage: { session: { get: async () => ({}), set: async () => {} } },
scripting: { executeScript: async (options) => { injected.push(options); return []; } },
- tabs: { get: async () => null },
+ tabs: { get: async () => null, create: async () => { throw new Error("not mocked"); } },
+ tabGroups: { query: async () => [] },
};
const w = { chrome, console, setTimeout, clearTimeout, setInterval: () => 0, navigator: { userAgent: "unit-test" }, fetch: async () => { throw new Error("offline"); } };
w.self = w;
@@ -120,3 +121,21 @@ test("early capture is injected only into tabs Pi owns or tracks", async () => {
assert.deepEqual(h.injected.map((o) => o.target.tabId), [11, 12]);
assert.ok(h.injected.every((o) => o.func.name === "installEarlyCapture" && o.injectImmediately === true));
});
+
+test("a Pi tab whose first page commits before tab.new tracks it still gets early capture", async () => {
+ const h = loadWorker();
+ let commit;
+ h.w.chrome.tabs.create = async (props) => {
+ // Chrome can commit the first document while tab.new is still recording ownership.
+ commit = h.commit(21);
+ return { id: 21, windowId: 1, url: props.url, status: "loading" };
+ };
+ h.w.groupTab = async (tab) => ({ tab: { id: tab.id }, group: { title: "Pi" } });
+ h.w.waitForTabSettled = async () => true;
+ h.w.formatTab = async (tab) => tab;
+ await h.w.dispatch("tab.new", { url: "https://site.test/", background: true, sessionKey: "s" });
+ await commit;
+ assert.deepEqual(h.injected.map((o) => o.target.tabId), [21]);
+ await h.commit(22);
+ assert.deepEqual(h.injected.map((o) => o.target.tabId), [21], "unrelated tabs stay untouched");
+});
diff --git a/test-suite/unit/input-reliability.test.mjs b/test-suite/unit/input-reliability.test.mjs
index 4a47e9c..8ea4bc5 100644
--- a/test-suite/unit/input-reliability.test.mjs
+++ b/test-suite/unit/input-reliability.test.mjs
@@ -215,6 +215,18 @@ for (const perCharacter of [false, true]) {
});
}
+test("fill selects a textarea's whole value with the selectAll command, not just the clicked line", async () => {
+ const h = harness({ tag: "TEXTAREA", editable: false });
+ const result = await h.call("fill", { selector: "#target", text: "NEW", domFallback: false });
+ assert.equal(result.input, "chrome");
+ const keys = h.commands("Input.dispatchKeyEvent");
+ const selectAll = keys.findIndex((c) => (c.params.commands || []).includes("selectAll"));
+ const del = keys.findIndex((c) => c.params.key === "Delete" && c.params.type === "keyDown");
+ assert.ok(selectAll >= 0, "selectAll editing command sent");
+ assert.ok(del > selectAll, "delete follows select-all");
+ assert.equal(h.selected.length, 0, "no DOM range selection for value fields");
+});
+
test("fill refuses to select an unrelated focused editor", async () => {
const h = harness({ initial: "keep this" });
h.page.document.activeElement = { isContentEditable: true, contains: () => false };