TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { describe, it, expect } from "vitest";2import type { PolyModel } from "@/lib/ai/core/types";3import { slugify, modelSlug, compareSlug, parseCompareSlug, findModelBySlug, resolveCompareSlug } from "@/lib/models/slug";45const 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 };6function m(provider: PolyModel["provider"], id: string, displayName: string, over: Partial<PolyModel> = {}): PolyModel {7 return { key: `${provider}/${id}`, id, provider, displayName, capabilities: caps, parameters: {}, status: "active", pricing: null, metadata: { sortWeight: 50 }, ...over };8}910const MODELS = [11 m("openai", "gpt-5.5", "GPT-5.5"),12 m("openai", "gpt-5.5-2026-04-01", "GPT-5.5 (2026-04-01)", { metadata: { sortWeight: 40 } }),13 m("anthropic", "claude-sonnet-5", "Claude Sonnet 5"),14 m("openrouter", "openai/gpt-5.5", "OpenAI: GPT-5.5"),15 m("openrouter", "meta-llama/llama-3.1-8b-instruct:free", "Meta: Llama 3.1 8B Instruct (free)"),16 m("gemini", "gemini-3.8-flash", "Gemini 3.8 Flash"),17];1819describe("slug", () => {20 it("slugifies keeping dots", () => {21 expect(slugify("GPT-5.5")).toBe("gpt-5.5");22 expect(slugify("Claude Sonnet 5")).toBe("claude-sonnet-5");23 expect(slugify("meta-llama/llama-3.1-8b-instruct:free")).toBe("meta-llama-llama-3.1-8b-instruct-free");24 expect(slugify(" --weird__ id. ")).toBe("weird-id");25 });26 it("builds and parses compare slugs", () => {27 expect(compareSlug([MODELS[0], MODELS[2]])).toBe("gpt-5.5-vs-claude-sonnet-5");28 expect(parseCompareSlug("gpt-5.5-vs-claude-sonnet-5")).toEqual(["gpt-5.5", "claude-sonnet-5"]);29 expect(parseCompareSlug("a-vs-b-vs-c-vs-d")).toHaveLength(4);30 expect(parseCompareSlug("only-one")).toBeNull();31 expect(parseCompareSlug("a-vs-b-vs-c-vs-d-vs-e")).toBeNull();32 expect(parseCompareSlug("a-vs-")).toBeNull();33 expect(parseCompareSlug("a-vs-b c")).toBeNull();34 });35 it("resolves parts by id or display name, preferring native providers", () => {36 expect(findModelBySlug(MODELS, "gpt-5.5")?.key).toBe("openai/gpt-5.5");37 expect(findModelBySlug(MODELS, "claude-sonnet-5")?.key).toBe("anthropic/claude-sonnet-5");38 expect(findModelBySlug(MODELS, "gemini-3.8-flash")?.key).toBe("gemini/gemini-3.8-flash");39 expect(findModelBySlug(MODELS, "openai-gpt-5.5")?.key).toBe("openai/gpt-5.5");40 expect(findModelBySlug(MODELS, "meta-llama-llama-3.1-8b-instruct-free")?.provider).toBe("openrouter");41 expect(findModelBySlug(MODELS, "nope")).toBeUndefined();42 });43 it("resolves full compare slugs and rejects duplicates / unknowns", () => {44 expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-claude-sonnet-5")?.map((x) => x.key)).toEqual(["openai/gpt-5.5", "anthropic/claude-sonnet-5"]);45 expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-gpt-5.5")).toBeNull();46 expect(resolveCompareSlug(MODELS, "gpt-5.5-vs-unknown-model")).toBeNull();47 expect(modelSlug(MODELS[3])).toBe("openai-gpt-5.5");48 });49});50