feat: add advanced context actions and optional translation

This commit is contained in:
golem
2026-10-05 15:38:16 -06:00
parent 33c4dad00f
commit 5308932bf1
34 changed files with 1579 additions and 159 deletions
+82
View File
@@ -0,0 +1,82 @@
import test from "node:test";
import assert from "node:assert/strict";
import { initializeShortcut } from "../options/shortcut.js";
function setup(commands) {
const elements = Object.fromEntries([
"shortcut-intro", "shortcut-hint", "shortcut-current", "change-shortcut",
].map((id) => [id, Object.assign(new EventTarget(), { textContent: "", hidden: true })]));
const document = Object.assign(new EventTarget(), {
visibilityState: "visible",
getElementById: (id) => elements[id],
});
const window = new EventTarget();
const ready = initializeShortcut({ commands, document, window });
return { elements, document, window, ready };
}
const flush = () => new Promise((resolve) => setImmediate(resolve));
const command = (shortcut) => ({ name: "ask-chatgpt", description: "Ask ChatGPT", shortcut });
test("shows the configured command rather than another command or the default", async () => {
const { elements, ready } = setup({ getAll: async () => [
{ name: "other", description: "Other", shortcut: "Alt+O" }, command("Ctrl+Shift+Y"),
] });
await ready;
for (const id of ["shortcut-intro", "shortcut-hint", "shortcut-current"]) {
assert.match(elements[id].textContent, /Ctrl\+Shift\+Y/);
assert.doesNotMatch(elements[id].textContent, /Alt\+Shift\+G|Alt\+O/);
}
});
test("updates an open page when the shortcut is removed", async () => {
let changed;
let shortcut = "Alt+Shift+G";
const { elements, ready } = setup({
getAll: async () => [command(shortcut)],
onChanged: { addListener: (listener) => { changed = listener; } },
});
await ready;
shortcut = "";
changed({ name: "ask-chatgpt", newShortcut: "", oldShortcut: "Alt+Shift+G" });
await flush();
assert.match(elements["shortcut-current"].textContent, /No keyboard shortcut assigned/);
assert.doesNotMatch(elements["shortcut-intro"].textContent, /press|Alt\+Shift\+G/i);
});
test("refreshes on focus and visibility without the change event API", async () => {
let shortcut = "Alt+Shift+G";
const { elements, window, document, ready } = setup({ getAll: async () => [command(shortcut)] });
await ready;
shortcut = "Ctrl+Shift+Y";
window.dispatchEvent(new Event("focus"));
await flush();
assert.match(elements["shortcut-current"].textContent, /Ctrl\+Shift\+Y/);
shortcut = "Alt+J";
document.dispatchEvent(new Event("visibilitychange"));
await flush();
assert.match(elements["shortcut-current"].textContent, /Alt\+J/);
});
test("missing commands and failed reads never claim the default is assigned", async () => {
for (const commands of [undefined, { getAll: async () => [] }, {
getAll: async () => { throw new Error("Unavailable"); },
}]) {
const { elements, ready } = setup(commands);
await ready;
assert.doesNotMatch(elements["shortcut-current"].textContent, /Alt\+Shift\+G/);
assert.equal(elements["change-shortcut"].hidden, true);
}
});
test("shortcut editor failure displays manual recovery instructions", async () => {
const { elements, ready } = setup({
getAll: async () => [command("Alt+J")],
openShortcutSettings: async () => { throw new Error("Unavailable"); },
});
await ready;
assert.equal(elements["change-shortcut"].hidden, false);
elements["change-shortcut"].dispatchEvent(new Event("click"));
await flush();
assert.match(elements["shortcut-current"].textContent, /Manage Extension Shortcuts/);
});