Files
OmniRoute/open-sse/mcp-server/__tests__/advancedTools.test.ts
SAMUEL AUGUSTO GUIMARAES LOPES d61d7f7f95 fix(mcp): remove non-standard x-provider field from omniroute_test_combo body (#9274)
Validated in local merge-train (devbox-vm-06-dev002) @ combined-tip (FAST gates green: static + changed tests + vitest — only pre-existing audit.test.ts flake). Evidence: /home/diegosouzapw/dev/proxys/OmniRoute/.claude/worktrees/merge-train-20260805-213228-suite.log
2026-08-05 21:45:41 -03:00

174 lines
5.5 KiB
TypeScript

/**
* Unit tests for MCP Advanced Tools (Phase 3)
*
* Tests all 8 advanced tool handlers.
*/
import { describe, it, expect, vi, beforeEach } from "vitest";
const mockFetch = vi.fn();
vi.stubGlobal("fetch", mockFetch);
const { handleTestCombo } = await import("../tools/advancedTools.ts");
describe("MCP Advanced Tools", () => {
beforeEach(() => {
mockFetch.mockReset();
// Re-assert the stub: importing advancedTools.ts triggers OmniRoute's own
// startup side effects (DB init, global fetch proxy patch) that overwrite
// globalThis.fetch after the top-level vi.stubGlobal() above ran.
vi.stubGlobal("fetch", mockFetch);
});
describe("simulate_route", () => {
it("should return simulation with fallback tree", async () => {
// Mock combos response
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => [
{
id: "combo-1",
name: "Fast",
enabled: true,
models: [
{ provider: "anthropic", model: "claude-sonnet", costPer1MTokens: 3 },
{ provider: "google", model: "gemini-pro", costPer1MTokens: 1 },
],
},
],
});
const response = await mockFetch("http://localhost:20128/api/combos");
const combos = await response.json();
expect(combos).toHaveLength(1);
expect(combos[0].models).toHaveLength(2);
});
});
describe("set_budget_guard", () => {
it("should accept valid budget parameters", () => {
const args = { maxCost: 5.0, action: "alert", degradeToTier: "cheap" };
expect(args.maxCost).toBeGreaterThan(0);
expect(["degrade", "block", "alert"]).toContain(args.action);
});
it("should reject invalid actions", () => {
const args = { maxCost: 5.0, action: "invalid" };
expect(["degrade", "block", "alert"]).not.toContain(args.action);
});
});
describe("set_resilience_profile", () => {
it("should accept valid profile names", () => {
const validProfiles = ["conservative", "balanced", "aggressive"];
for (const profile of validProfiles) {
expect(validProfiles).toContain(profile);
}
});
});
describe("test_combo", () => {
it("should test combo with all models", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => [
{
id: "test-combo",
models: [
{ provider: "anthropic", model: "claude-sonnet" },
{ provider: "google", model: "gemini-pro" },
],
},
],
});
const response = await mockFetch("http://localhost:20128/api/combos");
const combos = await response.json();
const combo = combos.find((c: { id?: string }) => c.id === "test-combo");
expect(combo).toBeDefined();
expect(combo.models).toHaveLength(2);
});
it("does not send a non-standard 'x-provider' body field upstream (regression, strict providers like Groq reject it with HTTP 400)", async () => {
mockFetch
.mockResolvedValueOnce({
ok: true,
json: async () => [
{
id: "groq-combo",
models: [{ provider: "groq", model: "groq/llama-3.1-8b-instant" }],
},
],
})
.mockResolvedValueOnce({
ok: true,
json: async () => ({ model: "llama-3.1-8b-instant", cost: 0, usage: {} }),
});
await handleTestCombo({ comboId: "groq-combo", testPrompt: "hi" });
const chatCompletionsCall = mockFetch.mock.calls.find(([url]) =>
String(url).includes("/v1/chat/completions")
);
expect(chatCompletionsCall).toBeDefined();
const sentBody = JSON.parse(chatCompletionsCall![1].body);
expect(sentBody).not.toHaveProperty("x-provider");
});
});
describe("get_provider_metrics", () => {
it("should return detailed metrics for a provider", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
provider: "anthropic",
requests: 100,
avgLatencyMs: 1200,
errorRate: 0.02,
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/analytics");
const data = await response.json();
expect(data).toHaveProperty("provider");
expect(data).toHaveProperty("requests");
expect(data.avgLatencyMs).toBeGreaterThan(0);
});
});
describe("best_combo_for_task", () => {
it("should recommend combo based on task type", () => {
const taskTypes = ["coding", "review", "planning", "analysis", "debugging", "documentation"];
for (const t of taskTypes) {
expect(taskTypes).toContain(t);
}
});
});
describe("explain_route", () => {
it("should accept a request ID", () => {
const requestId = "550e8400-e29b-41d4-a716-446655440000";
expect(requestId).toMatch(/^[0-9a-f-]+$/);
});
});
describe("get_session_snapshot", () => {
it("should return session data", async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
json: async () => ({
sessionStart: "2026-03-03T17:00:00Z",
requestCount: 42,
totalCost: 0.15,
}),
});
const response = await mockFetch("http://localhost:20128/api/usage/analytics?period=session");
const data = await response.json();
expect(data).toHaveProperty("sessionStart");
expect(data).toHaveProperty("requestCount");
expect(data.totalCost).toBeGreaterThanOrEqual(0);
});
});
});