TypeScript 97.4%
SQL 1%
JavaScript 0.9%
CSS 0.6%
1import { describe, expect, it } from "vitest";2import { curatePublicModels, formatContext, formatPricePair, type CurationInput } from "@/lib/marketing/public-models";34const NOW = new Date("2026-09-11T12:00:00Z");5const days = (n: number) => new Date(NOW.getTime() - n * 86_400_000);67function row(partial: Partial<CurationInput> & Pick<CurationInput, "key" | "provider">): CurationInput {8 return {9 displayName: partial.key,10 status: "active",11 sortWeight: 0,12 firstSeenAt: days(120),13 contextTokens: 128_000,14 inputPerMillion: 1,15 outputPerMillion: 4,16 ...partial,17 };18}1920describe("curatePublicModels", () => {21 it("drops hidden and deprecated/unknown models", () => {22 const out = curatePublicModels(23 [row({ key: "openai/a", provider: "openai" }), row({ key: "openai/b", provider: "openai", hidden: true }), row({ key: "openai/c", provider: "openai", status: "deprecated" }), row({ key: "openai/d", provider: "openai", status: "unknown" })],24 NOW,25 );26 expect(out.map((m) => m.key)).toEqual(["openai/a"]);27 });2829 it("puts new releases first, then flagships by sortWeight, interleaved per provider", () => {30 const out = curatePublicModels(31 [32 row({ key: "openai/old-flagship", provider: "openai", sortWeight: 100 }),33 row({ key: "openai/new", provider: "openai", sortWeight: 10, firstSeenAt: days(3) }),34 row({ key: "anthropic/flagship", provider: "anthropic", sortWeight: 90 }),35 row({ key: "anthropic/small", provider: "anthropic", sortWeight: 5 }),36 row({ key: "gemini/only", provider: "gemini", sortWeight: 1 }),37 ],38 NOW,39 );40 expect(out.map((m) => m.key)).toEqual(["openai/new", "anthropic/flagship", "gemini/only", "openai/old-flagship", "anthropic/small"]);41 });4243 it("caps the list and never leaks extra fields", () => {44 const rows = Array.from({ length: 60 }, (_, i) => row({ key: `openai/m${i}`, provider: "openai", sortWeight: i }));45 const out = curatePublicModels(rows, NOW, 40);46 expect(out).toHaveLength(40);47 expect(out[0].key).toBe("openai/m59");48 expect(Object.keys(out[0]).sort()).toEqual(["contextTokens", "displayName", "firstSeenAt", "inputPerMillion", "outputPerMillion", "provider", "status"].concat(["key"]).sort());49 });50});5152describe("formatters", () => {53 it("formats context windows", () => {54 expect(formatContext(1_000_000)).toBe("1M");55 expect(formatContext(2_000_000)).toBe("2M");56 expect(formatContext(400_000)).toBe("400K");57 expect(formatContext(null)).toBe("—");58 });59 it("formats price pairs", () => {60 expect(formatPricePair(1.25, 10)).toBe("$1.25 / $10");61 expect(formatPricePair(0.3, 2.5)).toBe("$0.30 / $2.50");62 expect(formatPricePair(0, 0)).toBe("free / free");63 expect(formatPricePair(null, null)).toBeNull();64 });65});66