1import { describe, expect, it } from "vite-plus/test";
2
3import { buildModelPickerSearchText, scoreModelPickerSearch } from "./modelPickerSearch";
4
5describe("buildModelPickerSearchText", () => {
6 it("builds provider-agnostic search text from generic fields", () => {
7 expect(
8 buildModelPickerSearchText({
9 driverKind: "opencode",
10 providerDisplayName: "opencode",
11 name: "Claude Opus 4.7",
12 subProvider: "GitHub Copilot",
13 }),
14 ).toBe("claude opus 4.7 github copilot opencode opencode");
15 });
16});
17
18describe("scoreModelPickerSearch", () => {
19 it("matches typo-tolerant multi-token queries", () => {
20 expect(
21 scoreModelPickerSearch(
22 {
23 driverKind: "opencode",
24 providerDisplayName: "opencode",
25 name: "Claude Opus 4.7",
26 subProvider: "GitHub Copilot",
27 },
28 "coplt op",
29 ),
30 ).not.toBeNull();
31 });
32
33 it("rejects results when any query token does not match", () => {
34 expect(
35 scoreModelPickerSearch(
36 {
37 driverKind: "codex",
38 providerDisplayName: "codex",
39 name: "GPT-5 Codex",
40 },
41 "coplt op",
42 ),
43 ).toBeNull();
44 });
45
46 it("ranks exact token matches ahead of fuzzier matches", () => {
47 const exactScore = scoreModelPickerSearch(
48 {
49 driverKind: "opencode",
50 providerDisplayName: "opencode",
51 name: "Claude Opus 4.7",
52 subProvider: "GitHub Copilot",
53 },
54 "copilot opus",
55 );
56 const fuzzyScore = scoreModelPickerSearch(
57 {
58 driverKind: "opencode",
59 providerDisplayName: "opencode",
60 name: "Claude Opus 4.7",
61 subProvider: "GitHub Copilot",
62 },
63 "coplt op",
64 );
65
66 expect(exactScore).not.toBeNull();
67 expect(fuzzyScore).not.toBeNull();
68 expect(exactScore!).toBeLessThan(fuzzyScore!);
69 });
70
71 it("gives favorite models a strong enough ranking boost for partial queries", () => {
72 const favoriteScore = scoreModelPickerSearch(
73 {
74 driverKind: "claudeAgent",
75 providerDisplayName: "Claude",
76 name: "Claude Opus 4.7",
77 isFavorite: true,
78 },
79 "opu",
80 );
81 const nonFavoriteScore = scoreModelPickerSearch(
82 {
83 driverKind: "cursor",
84 providerDisplayName: "Cursor",
85 name: "Opus 4.5",
86 },
87 "opu",
88 );
89
90 expect(favoriteScore).not.toBeNull();
91 expect(nonFavoriteScore).not.toBeNull();
92 expect(favoriteScore!).toBeLessThan(nonFavoriteScore!);
93 });
94
95 it("does not let the favorite boost outrank clearly better textual matches", () => {
96 const favoriteScore = scoreModelPickerSearch(
97 {
98 driverKind: "claudeAgent",
99 providerDisplayName: "Claude",
100 name: "Claude Opus 4.7",
101 isFavorite: true,
102 },
103 "opus 4.7",
104 );
105 const nonFavoriteExactScore = scoreModelPickerSearch(
106 {
107 driverKind: "cursor",
108 providerDisplayName: "Cursor",
109 name: "Opus 4.7",
110 },
111 "opus 4.7",
112 );
113
114 expect(favoriteScore).not.toBeNull();
115 expect(nonFavoriteExactScore).not.toBeNull();
116 expect(nonFavoriteExactScore!).toBeLessThan(favoriteScore!);
117 });
118
119 it("matches a custom instance's display name against its models", () => {
120 expect(
121 scoreModelPickerSearch(
122 {
123 driverKind: "codex",
124 providerDisplayName: "Codex Personal",
125 name: "GPT-5 Codex",
126 },
127 "personal",
128 ),
129 ).not.toBeNull();
130 });
131});