fix(ai): liste de modeles corrompue et cles i18n brutes (BUG-009)
CI / lint (push) Successful in 1m9s
CI / security (push) Successful in 43s
CI / test (push) Successful in 1m58s
CI / build (push) Successful in 41s
CI / e2e (push) Successful in 10m31s

Locales chargees en cache no-store + SW_VERSION v4 pour eviter les cles brutes (fr.json obsolete). Picker : styles critiques en ligne (popover/liste/options), plafond de 200 modeles avec indicateur, et non-chevauchement entre la liste de modeles et la bulle de capacites.
This commit is contained in:
2026-09-12 13:15:27 -04:00
parent d6b7c0e9cb
commit 7f0e34d318
10 changed files with 95 additions and 11 deletions
+30
View File
@@ -959,6 +959,36 @@ async function main() {
localStorage.clear();
});
// ── 42. Picker handles very long model lists (OpenRouter) ──
await test("picker caps long model lists and keeps options block-laid-out", async () => {
localStorage.clear();
const models = Array.from({ length: 250 }, (_, i) => `vendor-${i}/model-${i}:free`);
globalThis.fetch = async (url) => {
const u = String(url);
if (u.includes("/api/ai/status")) {
return { ok: true, status: 200, json: async () => ({ configured: true, providers: { openrouter: { available: true } } }) };
}
if (u.includes("/api/config/ai-models")) {
return { ok: true, status: 200, json: async () => ({ models, source: "live" }) };
}
if (u.includes("/api/ai/model-capabilities")) {
return { ok: true, status: 200, json: async () => ({ capabilities: { chat: true, vision: true } }) };
}
return { ok: true, status: 200, json: async () => ({}) };
};
localStorage.setItem("obsigate_ai_picker", JSON.stringify({ provider: "openrouter" }));
const picker = await ai.buildAIPickerUI();
document.body.appendChild(picker);
await sleep(30);
picker.querySelector(".ai-picker-model-trigger").click();
const options = picker.querySelectorAll(".ai-picker-model-option");
assert.equal(options.length, 200, "rendered options are capped");
assert.ok(picker.querySelector(".ai-picker-model-more"), "a 'more results' hint is shown");
assert.ok(options[0].style.display === "block", "options are block-laid-out even without CSS");
picker.remove();
localStorage.clear();
});
// ── Summary ──
console.log(`\n${passCount}/${testCount} tests passed`);
if (passCount !== testCount) {