fix(ai): liens sans vault, navigation clavier des menus et purge caches (BUG-013, BUG-014)
CI / lint (push) Successful in 1m9s
CI / security (push) Successful in 45s
CI / test (push) Successful in 2m27s
CI / build (push) Successful in 40s
CI / e2e (push) Successful in 10m47s

BUG-013: _openFileLink/_revealPath utilisent _activeVault() (contexte -> selection -> premier vault). BUG-014: navigation up/down geree au niveau du panneau en phase de capture, independante du focus. Caches: SW_VERSION v6 + migration qui purge tous les caches obsigate-*.
This commit is contained in:
2026-09-12 16:44:12 -04:00
parent ee4c273d73
commit a5201a62e0
7 changed files with 108 additions and 14 deletions
+51
View File
@@ -1070,6 +1070,57 @@ async function main() {
localStorage.clear();
});
await test("active vault falls back to the first available vault", async () => {
const stateMod = await import(pathToFileURL(path.join(JS_DIR, "state.js")).href);
const prevVaults = stateMod.state.allVaults;
const prevSelected = stateMod.state.selectedContextVault;
stateMod.state.allVaults = [{ name: "V1" }, { name: "V2" }];
stateMod.state.selectedContextVault = "all";
const b = new BooksLM();
b._vault = null;
assert.equal(b._activeVault(), "V1", "first vault used for links/@ browsing");
stateMod.state.selectedContextVault = "V2";
assert.equal(b._activeVault(), "V2", "selected context vault takes precedence");
stateMod.state.allVaults = prevVaults;
stateMod.state.selectedContextVault = prevSelected;
});
await test("menu navigation works from the panel, not only the textarea", async () => {
localStorage.clear();
globalThis.fetch = async (url) => {
if (String(url).includes("/api/ai/skills")) {
return {
ok: true, status: 200,
json: async () => ({
skills: [
{ id: "a", label: "Alpha", type: "skill", description: "d" },
{ id: "b", label: "Beta", type: "skill", description: "d" },
],
commands: [],
}),
};
}
return { ok: true, status: 200, json: async () => ({}) };
};
const b = new BooksLM();
b._panel = b._render();
document.body.appendChild(b._panel);
const ta = b._panel.querySelector("textarea");
ta.value = "/";
ta.selectionStart = ta.selectionEnd = 1;
b._onComposerInput();
await sleep(20);
const items = () => Array.from(b._panel.querySelectorAll(".bookslm-command-menu .bookslm-menu-item"));
assert.equal(items().length, 2);
// Dispatch on the panel itself (focus elsewhere) — the capture handler must
// still navigate the menu.
b._panel.dispatchEvent(new w.KeyboardEvent("keydown", { key: "ArrowDown", bubbles: true, cancelable: true }));
assert.ok(items()[1].classList.contains("active"), "ArrowDown from the panel moves the highlight");
b._panel.remove();
localStorage.clear();
});
// ── Summary ──
console.log(`\n${passCount}/${testCount} tests passed`);
if (passCount !== testCount) {