Files
ai-parallel/tests/provider-catalog.test.js

76 lines
3.2 KiB
JavaScript

const assert = require("node:assert/strict");
const fs = require("node:fs");
const path = require("node:path");
const test = require("node:test");
const vm = require("node:vm");
const extensionRoot = path.join(__dirname, "..", "apps", "browser-extension");
function loadCatalog() {
const context = { URL };
context.globalThis = context;
vm.createContext(context);
vm.runInContext(fs.readFileSync(path.join(extensionRoot, "shared", "provider-catalog.js"), "utf8"), context, {
filename: "shared/provider-catalog.js"
});
return context.AIParallelProviderCatalog;
}
test("shared provider catalog matches manifest host coverage", () => {
const catalog = loadCatalog();
const manifest = JSON.parse(fs.readFileSync(path.join(extensionRoot, "manifest.json"), "utf8"));
const permissionHosts = new Set(manifest.host_permissions);
const contentScriptMatches = new Set(manifest.content_scripts[0].matches);
assert.deepEqual(Array.from(catalog, (provider) => provider.id), [
"chatgpt",
"deepseek",
"zhipu",
"qwen",
"kimi",
"claude",
"gemini",
"grok"
]);
for (const provider of catalog) {
for (const host of provider.hosts) {
const match = `https://${host}/*`;
assert.ok(permissionHosts.has(match), `${provider.id} missing host permission ${match}`);
assert.ok(contentScriptMatches.has(match), `${provider.id} missing content-script match ${match}`);
}
assert.equal(new URL(provider.url).origin, provider.origins[0]);
assert.equal(provider.adapter, provider.id);
assert.equal(provider.adapterType, "dom");
assert.equal(provider.adapterContract, "provider-adapter-v1");
assert.equal(provider.capabilities.send, true);
assert.equal(provider.capabilities.collect, true);
assert.equal(provider.capabilities.newChat, true);
assert.equal(provider.capabilities.retry, true);
assert.equal(provider.capabilities.streaming, false);
assert.equal(provider.capabilities.timeout, true);
assert.equal(provider.capabilities.cancel, true);
}
});
test("shared provider catalog protects metadata arrays from mutation", () => {
const catalog = loadCatalog();
assert.equal(Object.isFrozen(catalog), true);
assert.equal(Object.isFrozen(catalog[0]), true);
assert.equal(Object.isFrozen(catalog[0].hosts), true);
assert.equal(Object.isFrozen(catalog[0].origins), true);
assert.equal(Object.isFrozen(catalog[0].capabilities), true);
});
test("extension entry points load the catalog before consuming it", () => {
const popupHtml = fs.readFileSync(path.join(extensionRoot, "popup.html"), "utf8");
const workspaceHtml = fs.readFileSync(path.join(extensionRoot, "workspace", "index.html"), "utf8");
const serviceWorker = fs.readFileSync(path.join(extensionRoot, "service-worker.js"), "utf8");
assert.match(popupHtml, /shared\/provider-catalog\.js[\s\S]*popup\.js/);
assert.match(workspaceHtml, /\.\.\/shared\/provider-catalog\.js[\s\S]*workspace\.js/);
assert.match(workspaceHtml, /\.\.\/shared\/provider-adapter-contract\.js[\s\S]*workspace\.js/);
assert.match(workspaceHtml, /\.\.\/shared\/provider-task-runtime\.js[\s\S]*workspace\.js/);
assert.match(serviceWorker, /^importScripts\("shared\/provider-catalog\.js"\);/);
});