OmniRoute/open-sse/mcp-server/__tests__/advancedTools.test.ts

141 lines
4.2 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);
describe("MCP Advanced Tools", () => {
beforeEach(() => {
mockFetch.mockReset();
});
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);
});
});
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);
});
});
});