test: add comprehensive tests for OpenRouter routing configuration and validation

This commit is contained in:
Matthijs Hoekstra 2026-01-29 13:43:04 +01:00
parent 56ccee35a0
commit f62291a0eb
3 changed files with 257 additions and 0 deletions

View File

@ -0,0 +1,117 @@
import { describe, expect, it } from "vitest";
import type { MoltbotConfig } from "../config/config.js";
describe("OpenRouter routing", () => {
it("config accepts openRouterRouting with 'only' field", () => {
const cfg: MoltbotConfig = {
env: {
OPENROUTER_API_KEY: "sk-or-test-key",
},
agents: {
defaults: {
model: { primary: "openrouter/anthropic/claude-sonnet-4-5" },
models: {
"openrouter/anthropic/claude-sonnet-4-5": {
alias: "Claude Sonnet",
compat: {
openRouterRouting: {
only: ["anthropic"],
},
},
},
},
},
},
};
const modelKey = "openrouter/anthropic/claude-sonnet-4-5";
const modelConfig = cfg.agents?.defaults?.models?.[modelKey];
expect(modelConfig?.compat?.openRouterRouting).toEqual({
only: ["anthropic"],
});
});
it("config accepts openRouterRouting with 'order' field", () => {
const cfg: MoltbotConfig = {
env: {
OPENROUTER_API_KEY: "sk-or-test-key",
},
agents: {
defaults: {
model: { primary: "openrouter/openai/gpt-5.2" },
models: {
"openrouter/openai/gpt-5.2": {
alias: "GPT-5.2",
compat: {
openRouterRouting: {
order: ["anthropic", "openai"],
},
},
},
},
},
},
};
const modelKey = "openrouter/openai/gpt-5.2";
const modelConfig = cfg.agents?.defaults?.models?.[modelKey];
expect(modelConfig?.compat?.openRouterRouting).toEqual({
order: ["anthropic", "openai"],
});
});
it("validates openRouterRouting config shape", () => {
const testCases = [
{
name: "only with single provider",
config: { only: ["anthropic"] },
},
{
name: "only with multiple providers",
config: { only: ["anthropic", "openai"] },
},
{
name: "order with single provider",
config: { order: ["anthropic"] },
},
{
name: "order with multiple providers",
config: { order: ["anthropic", "openai"] },
},
{
name: "empty routing",
config: {},
},
{
name: "both only and order",
config: { only: ["anthropic"], order: ["openai"] },
},
];
for (const testCase of testCases) {
const cfg: MoltbotConfig = {
env: { OPENROUTER_API_KEY: "sk-or-test-key" },
agents: {
defaults: {
model: { primary: "openrouter/anthropic/claude-sonnet-4-5" },
models: {
"openrouter/anthropic/claude-sonnet-4-5": {
compat: {
openRouterRouting: testCase.config,
},
},
},
},
},
};
expect(() => {
const modelConfig =
cfg.agents?.defaults?.models?.["openrouter/anthropic/claude-sonnet-4-5"];
expect(modelConfig?.compat?.openRouterRouting).toEqual(testCase.config);
}).not.toThrow();
}
});
});

View File

@ -0,0 +1,42 @@
import { expect, it } from "vitest";
it("example: openRouterRouting configuration", () => {
const config = {
agents: {
defaults: {
model: { primary: "openrouter/anthropic/claude-sonnet-4-5" },
models: {
"openrouter/anthropic/claude-sonnet-4-5": {
alias: "Claude Sonnet",
compat: {
openRouterRouting: {
only: ["anthropic"],
},
},
},
"openrouter/openai/gpt-5.2": {
alias: "GPT-5.2",
compat: {
openRouterRouting: {
order: ["anthropic", "openai"],
},
},
},
},
},
},
};
expect(
config.agents.defaults.models?.["openrouter/anthropic/claude-sonnet-4-5"]?.compat
?.openRouterRouting,
).toEqual({
only: ["anthropic"],
});
expect(
config.agents.defaults.models?.["openrouter/openai/gpt-5.2"]?.compat?.openRouterRouting,
).toEqual({
order: ["anthropic", "openai"],
});
});

View File

@ -0,0 +1,98 @@
import fs from "node:fs/promises";
import path from "node:path";
import { describe, expect, it } from "vitest";
import { withTempHome } from "./test-helpers.js";
describe("OpenRouter routing integration", () => {
it("validates and loads openRouterRouting config from moltbot.json", async () => {
await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
path.join(configDir, "moltbot.json"),
JSON.stringify(
{
agents: {
defaults: {
model: { primary: "openrouter/anthropic/claude-sonnet-4-5" },
models: {
"openrouter/anthropic/claude-sonnet-4-5": {
alias: "Claude Sonnet",
compat: {
openRouterRouting: {
only: ["anthropic"],
},
},
},
"openrouter/openai/gpt-5.2": {
alias: "GPT-5.2",
compat: {
openRouterRouting: {
order: ["anthropic", "openai"],
},
},
},
},
},
},
},
null,
2,
),
"utf-8",
);
const { loadConfig } = await import("./config.js");
const cfg = loadConfig();
expect(cfg.agents?.defaults?.model?.primary).toBe("openrouter/anthropic/claude-sonnet-4-5");
const sonnetModel = cfg.agents?.defaults?.models?.["openrouter/anthropic/claude-sonnet-4-5"];
expect(sonnetModel?.alias).toBe("Claude Sonnet");
expect(sonnetModel?.compat?.openRouterRouting).toEqual({
only: ["anthropic"],
});
const gptModel = cfg.agents?.defaults?.models?.["openrouter/openai/gpt-5.2"];
expect(gptModel?.alias).toBe("GPT-5.2");
expect(gptModel?.compat?.openRouterRouting).toEqual({
order: ["anthropic", "openai"],
});
});
});
it("accepts openRouterRouting with empty config", async () => {
await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdbot");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
path.join(configDir, "moltbot.json"),
JSON.stringify(
{
agents: {
defaults: {
model: { primary: "openrouter/anthropic/claude-sonnet-4-5" },
models: {
"openrouter/anthropic/claude-sonnet-4-5": {
compat: {
openRouterRouting: {},
},
},
},
},
},
},
null,
2,
),
"utf-8",
);
const { loadConfig } = await import("./config.js");
const cfg = loadConfig();
const model = cfg.agents?.defaults?.models?.["openrouter/anthropic/claude-sonnet-4-5"];
expect(model?.compat?.openRouterRouting).toEqual({});
});
});
});