Spaces:
Running
Running
| import { describe, expect, it } from "vitest" | |
| // Executable spec for `notes/transformations/05-slug-candidates.md`. | |
| // | |
| // Replicates pipelineSlugify, getModelDetailSlugCandidates, and | |
| // getDeveloperSlugCandidates from lib/model-data.ts:150-211 verbatim. | |
| // Pipeline must produce identical outputs for every case below. | |
| function pipelineSlugify(text: string): string { | |
| return ( | |
| text | |
| .replace(/[\x00-\x1f\x7f]/g, "") | |
| .replace(/[^a-zA-Z0-9._-]/g, "_") | |
| .replace(/^_+|_+$/g, "") || "unknown" | |
| ) | |
| } | |
| function getModelDetailSlugCandidates(modelId: string): string[] { | |
| const normalized = modelId.trim() | |
| const candidates = new Set<string>() | |
| const withSlash = normalized.replace(/\//g, "__") | |
| const withDots = withSlash.replace(/\./g, "-") | |
| candidates.add(pipelineSlugify(withSlash)) | |
| candidates.add(pipelineSlugify(withSlash.toLowerCase())) | |
| candidates.add(pipelineSlugify(withDots)) | |
| candidates.add(pipelineSlugify(withDots.toLowerCase())) | |
| candidates.add(pipelineSlugify(normalized)) | |
| candidates.add(pipelineSlugify(normalized.toLowerCase())) | |
| return Array.from(candidates) | |
| } | |
| function getDeveloperSlugCandidates(developerOrRouteId: string): string[] { | |
| const normalized = developerOrRouteId.trim() | |
| const candidates = new Set<string>() | |
| const lowercase = normalized.toLowerCase() | |
| const underscoreSlug = pipelineSlugify(normalized) | |
| const lowercaseUnderscoreSlug = pipelineSlugify(lowercase) | |
| const hyphenSlug = lowercase | |
| .replace(/[\x00-\x1f\x7f]/g, "") | |
| .replace(/[^a-z0-9]+/g, "-") | |
| .replace(/^-+|-+$/g, "") | |
| const compactSlug = lowercase.replace(/[^a-z0-9]+/g, "") | |
| candidates.add(underscoreSlug) | |
| candidates.add(lowercaseUnderscoreSlug) | |
| candidates.add(underscoreSlug.replace(/_/g, "-")) | |
| candidates.add(lowercaseUnderscoreSlug.replace(/_/g, "-")) | |
| if (hyphenSlug) candidates.add(hyphenSlug) | |
| if (compactSlug) candidates.add(compactSlug) | |
| return Array.from(candidates) | |
| } | |
| // --------------------------------------------------------------------------- | |
| // Group A β pipelineSlugify | |
| // --------------------------------------------------------------------------- | |
| describe("Group A β pipelineSlugify", () => { | |
| const cases = [ | |
| { input: "openai__gpt-5", expected: "openai__gpt-5", why: "passthrough (alnum + dash + underscore)" }, | |
| { input: "openai__gpt-5.2", expected: "openai__gpt-5.2", why: "passthrough (dot allowed)" }, | |
| { input: "openai/gpt-5", expected: "openai_gpt-5", why: "slash β underscore (slash not in allowed set)" }, | |
| { input: "OpenAI", expected: "OpenAI", why: "case preserved" }, | |
| { input: "x0000001", expected: "x0000001", why: "passthrough" }, | |
| { input: "foo bar", expected: "foo_bar", why: "space β underscore" }, | |
| { input: "foo!@#bar", expected: "foo___bar", why: "each special char β underscore" }, | |
| { input: "___foo___", expected: "foo", why: "trim leading/trailing underscores" }, | |
| { input: "!!!", expected: "unknown", why: "empty after trim β 'unknown' fallback" }, | |
| { input: "", expected: "unknown", why: "empty β 'unknown' fallback" }, | |
| { input: "_", expected: "unknown", why: "single underscore trimmed β empty β 'unknown'" }, | |
| { input: "a.b.c", expected: "a.b.c", why: "dots passthrough" }, | |
| { input: "a-b-c", expected: "a-b-c", why: "dashes passthrough" }, | |
| ] | |
| it.each(cases)("'$input' β '$expected' ($why)", ({ input, expected }) => { | |
| expect(pipelineSlugify(input)).toBe(expected) | |
| }) | |
| }) | |
| // --------------------------------------------------------------------------- | |
| // Group B β getModelDetailSlugCandidates | |
| // --------------------------------------------------------------------------- | |
| describe("Group B β getModelDetailSlugCandidates", () => { | |
| const cases = [ | |
| { | |
| input: "openai/gpt-5", | |
| expected: ["openai__gpt-5", "openai_gpt-5"], | |
| why: "lowercase + no dots β only slash + slash-stripped variants survive Set dedup", | |
| }, | |
| { | |
| input: "openai/gpt-5.2", | |
| expected: ["openai__gpt-5.2", "openai__gpt-5-2", "openai_gpt-5.2"], | |
| why: "dotted form β slash, slash+dot-stripped, fallback", | |
| }, | |
| { | |
| input: "OpenAI/GPT-5", | |
| expected: ["OpenAI__GPT-5", "openai__gpt-5", "OpenAI_GPT-5", "openai_gpt-5"], | |
| why: "mixed case β both case variants survive", | |
| }, | |
| { | |
| input: "anthropic/claude-3.7-sonnet", | |
| expected: ["anthropic__claude-3.7-sonnet", "anthropic__claude-3-7-sonnet", "anthropic_claude-3.7-sonnet"], | |
| why: "dotted version variant", | |
| }, | |
| { | |
| input: "unknown/foo", | |
| expected: ["unknown__foo", "unknown_foo"], | |
| why: "lowercase + no dots β 2 candidates", | |
| }, | |
| { | |
| input: "openai__gpt-5", | |
| expected: ["openai__gpt-5"], | |
| why: "no slashes, no dots, lowercase β all variants collapse to one", | |
| }, | |
| ] | |
| it.each(cases)("'$input' β $expected ($why)", ({ input, expected }) => { | |
| expect(getModelDetailSlugCandidates(input)).toEqual(expected) | |
| }) | |
| }) | |
| // --------------------------------------------------------------------------- | |
| // Group C β getDeveloperSlugCandidates | |
| // --------------------------------------------------------------------------- | |
| describe("Group C β getDeveloperSlugCandidates", () => { | |
| const cases = [ | |
| { | |
| input: "openai", | |
| expected: ["openai"], | |
| why: "lowercase + no special chars β all 6 variants collapse to one", | |
| }, | |
| { | |
| input: "OpenAI", | |
| expected: ["OpenAI", "openai"], | |
| why: "case-mixed β 2 candidates (the case variant differs)", | |
| }, | |
| { | |
| input: "01-ai", | |
| expected: ["01-ai", "01ai"], | |
| why: "compactSlug strips the dash β 2 candidates", | |
| }, | |
| { | |
| input: "Mistral AI", | |
| expected: ["Mistral_AI", "mistral_ai", "Mistral-AI", "mistral-ai", "mistralai"], | |
| why: "space β underscore variants + hyphen variants + compact", | |
| }, | |
| { | |
| input: "01_ai", | |
| expected: ["01_ai", "01-ai", "01ai"], | |
| why: "underscore-slug + dash variant + compact", | |
| }, | |
| { | |
| input: "Allenai", | |
| expected: ["Allenai", "allenai"], | |
| why: "case-mixed but no special chars", | |
| }, | |
| ] | |
| it.each(cases)("'$input' β $expected ($why)", ({ input, expected }) => { | |
| expect(getDeveloperSlugCandidates(input)).toEqual(expected) | |
| }) | |
| }) | |
| // --------------------------------------------------------------------------- | |
| // Group D β Production sanity (fixture-based) | |
| // --------------------------------------------------------------------------- | |
| // | |
| // Concrete production cases from the audit (2026-04-28). For each, document | |
| // which candidate position resolves to the actual file. These are the cases | |
| // the pipeline-side fix needs to make redundant. | |
| describe("Group D β production sanity (which candidate position wins)", () => { | |
| it("openai/gpt-5.2 needs the dotβdash variant (position 1)", () => { | |
| const candidates = getModelDetailSlugCandidates("openai/gpt-5.2") | |
| expect(candidates[0]).toBe("openai__gpt-5.2") // would be the file IF cache used dotted form (it doesn't) | |
| expect(candidates[1]).toBe("openai__gpt-5-2") // this is what actually exists in cache | |
| }) | |
| it("anthropic/claude-3.7-sonnet needs the dotβdash variant (position 1)", () => { | |
| const candidates = getModelDetailSlugCandidates("anthropic/claude-3.7-sonnet") | |
| expect(candidates).toContain("anthropic__claude-3-7-sonnet") | |
| }) | |
| it("OpenAI developer needs lowercase variant (position 1)", () => { | |
| const candidates = getDeveloperSlugCandidates("Google") | |
| expect(candidates).toEqual(["Google", "google"]) | |
| }) | |
| it("Allenai developer needs lowercase variant (position 1)", () => { | |
| const candidates = getDeveloperSlugCandidates("Allenai") | |
| expect(candidates).toEqual(["Allenai", "allenai"]) | |
| }) | |
| }) | |