import { describe, it, expect } from "vitest"; import type { PolyModel } from "@/lib/ai/core/types"; import { slugify, modelSlug, compareSlug, parseCompareSlug, findModelBySlug, resolveCompareSlug } from "@/lib/models/slug"; const caps: PolyModel["capabilities"] = { text: true, vision: false, audioInput: false, audioOutput: false, imageGeneration: false, video: false, reasoning: false, tools: false, structuredOutput: false, streaming: true, files: false, webSearch: false }; function m(provider: PolyModel["provider"], id: string, displayName: string, over: Partial = {}): PolyModel { return { key: `${provider}/${id}`, id, provider, displayName, capabilities: caps, parameters: {}, status: "active", pricing: null, metadata: { sortWeight: 50 }, ...over }; } const MODELS = [ m("openai", "gpt-5.5", "GPT-5.5"), m("openai", "gpt-5.5-2026-04-01", "GPT-5.5 (2026-04-01)", { metadata: { sortWeight: 40 } }), m("anthropic", "claude-sonnet-5", "Claude Sonnet 5"), m("openrouter", "openai/gpt-5.5", "OpenAI: GPT-5.5"), m("openrouter", "meta-llama/llama-3.1-8b-instruct:free", "Meta: Llama 3.1 8B Instruct (free)"), m("gemini", "gemini-3.8-flash", "Gemini 3.8 Flash"), ]; describe("slug", () => { it("slugifies keeping dots", () => { expect(slugify("GPT-5.5")).toBe("gpt-5.5"); expect(slugify("Claude Sonnet 5")).toBe("claude-sonnet-5"); expect(slugify("meta-llama/llama-3.1-8b-instruct:free")).toBe("meta-llama-llama-3.1-8b-instruct-free"); expect(slugify(" --weird__ id. ")).toBe("weird-id"); }); it("builds and parses compare slugs", () => { expect(compareSlug([MODELS[0], MODELS[2]])).toBe("gpt-5.5-vs-claude-sonnet-5"); expect(parseCompareSlug("gpt-5.5-vs-claude-sonnet-5")).toEqual(["gpt-5.5", "claude-sonnet-5"]); expect(parseCompareSlug("a-vs-b-vs-c-vs-d")).toHaveLength(4); expect(parseCompareSlug("only-one")).toBeNull(); expect(parseCompareSlug("a-vs-b-vs-c-vs-d-vs-e")).toBeNull(); expect(parseCompareSlug("a-vs-")).toBeNull(); expect(parseCompareSlug("a-vs-b c")).toBeNull(); }); it("resolves parts by id or display name, preferring native providers", () => { expect(findModelBySlug(MODELS, "gpt-5.5")?.key).toBe("openai/gpt-5.5"); expect(findModelBySlug(MODELS, "claude-sonnet-5")?.key).toBe("anthropic/claude-sonnet-5"); expect(findModelBySlug(MODELS, "gemini-3.8-flash")?.key).toBe("gemini/gemini-3.8-flash"); expect(findModelBySlug(MODELS, "openai-gpt-5.5")?.key).toBe("openai/gpt-5.5"); expect(findModelBySlug(MODELS, "meta-llama-llama-3.1-8b-instruct-free")?.provider).toBe("openrouter"); expect(findModelBySlug(MODELS, "nope")).toBeUndefined(); }); it("resolves full compare slugs and rejects duplicates / unknowns", () => { expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-claude-sonnet-5")?.map((x) => x.key)).toEqual(["openai/gpt-5.5", "anthropic/claude-sonnet-5"]); expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-gpt-5.5")).toBeNull(); expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-unknown-model")).toBeNull(); expect(modelSlug(MODELS[3])).toBe("openai-gpt-5.5"); }); });