Skip to content

Commit 692f457

Browse files
committed
test(api): enforce exhaustive provider routing
1 parent 186ebb9 commit 692f457

1 file changed

Lines changed: 50 additions & 35 deletions

File tree

src/api/__tests__/index.spec.ts

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,12 @@ vitest.mock("../providers/native-ollama", () => ({
2121
NativeOllamaHandler: class {},
2222
}))
2323

24-
import { providerIdentifiers, retiredProviderIdentifiers, type ProviderNameWithRetired } from "@roo-code/types"
24+
import {
25+
providerIdentifiers,
26+
retiredProviderIdentifiers,
27+
type ProviderName,
28+
type ProviderNameWithRetired,
29+
} from "@roo-code/types"
2530

2631
import { buildApiHandler } from "../index"
2732
import {
@@ -61,41 +66,51 @@ import {
6166
} from "../providers"
6267
import { NativeOllamaHandler } from "../providers/native-ollama"
6368

69+
type HandlerConstructor = new (...args: never[]) => object
70+
71+
const expectedHandlers = {
72+
[providerIdentifiers.anthropic]: AnthropicHandler,
73+
[providerIdentifiers.openrouter]: OpenRouterHandler,
74+
[providerIdentifiers.bedrock]: AwsBedrockHandler,
75+
[providerIdentifiers.openai]: OpenAiHandler,
76+
[providerIdentifiers.ollama]: NativeOllamaHandler,
77+
[providerIdentifiers.lmstudio]: LmStudioHandler,
78+
[providerIdentifiers.gemini]: GeminiHandler,
79+
// Gemini CLI currently relies on the factory's default Anthropic handler.
80+
[providerIdentifiers.geminiCli]: AnthropicHandler,
81+
[providerIdentifiers.openaiCodex]: OpenAiCodexHandler,
82+
[providerIdentifiers.openaiNative]: OpenAiNativeHandler,
83+
[providerIdentifiers.deepseek]: DeepSeekHandler,
84+
[providerIdentifiers.qwenCode]: QwenCodeHandler,
85+
[providerIdentifiers.moonshot]: MoonshotHandler,
86+
[providerIdentifiers.kimiCode]: KimiCodeHandler,
87+
[providerIdentifiers.vscodeLm]: VsCodeLmHandler,
88+
[providerIdentifiers.mistral]: MistralHandler,
89+
[providerIdentifiers.requesty]: RequestyHandler,
90+
[providerIdentifiers.unbound]: UnboundHandler,
91+
[providerIdentifiers.fakeAi]: FakeAIHandler,
92+
[providerIdentifiers.xai]: XAIHandler,
93+
[providerIdentifiers.litellm]: LiteLLMHandler,
94+
[providerIdentifiers.sambanova]: SambaNovaHandler,
95+
[providerIdentifiers.mimo]: MimoHandler,
96+
[providerIdentifiers.zai]: ZAiHandler,
97+
[providerIdentifiers.fireworks]: FireworksHandler,
98+
[providerIdentifiers.friendli]: FriendliHandler,
99+
[providerIdentifiers.vercelAiGateway]: VercelAiGatewayHandler,
100+
[providerIdentifiers.opencodeGo]: OpencodeGoHandler,
101+
[providerIdentifiers.kenari]: KenariHandler,
102+
[providerIdentifiers.zooGateway]: ZooGatewayHandler,
103+
[providerIdentifiers.minimax]: MiniMaxHandler,
104+
[providerIdentifiers.baseten]: BasetenHandler,
105+
[providerIdentifiers.poe]: PoeHandler,
106+
} satisfies Record<Exclude<ProviderName, typeof providerIdentifiers.vertex>, HandlerConstructor>
107+
108+
const expectedHandlerEntries = Object.entries(expectedHandlers) as Array<
109+
[Exclude<ProviderName, typeof providerIdentifiers.vertex>, HandlerConstructor]
110+
>
111+
64112
describe("buildApiHandler", () => {
65-
it.each([
66-
[providerIdentifiers.anthropic, AnthropicHandler],
67-
[providerIdentifiers.openrouter, OpenRouterHandler],
68-
[providerIdentifiers.bedrock, AwsBedrockHandler],
69-
[providerIdentifiers.openai, OpenAiHandler],
70-
[providerIdentifiers.ollama, NativeOllamaHandler],
71-
[providerIdentifiers.lmstudio, LmStudioHandler],
72-
[providerIdentifiers.gemini, GeminiHandler],
73-
[providerIdentifiers.openaiCodex, OpenAiCodexHandler],
74-
[providerIdentifiers.openaiNative, OpenAiNativeHandler],
75-
[providerIdentifiers.deepseek, DeepSeekHandler],
76-
[providerIdentifiers.qwenCode, QwenCodeHandler],
77-
[providerIdentifiers.moonshot, MoonshotHandler],
78-
[providerIdentifiers.kimiCode, KimiCodeHandler],
79-
[providerIdentifiers.vscodeLm, VsCodeLmHandler],
80-
[providerIdentifiers.mistral, MistralHandler],
81-
[providerIdentifiers.requesty, RequestyHandler],
82-
[providerIdentifiers.unbound, UnboundHandler],
83-
[providerIdentifiers.fakeAi, FakeAIHandler],
84-
[providerIdentifiers.xai, XAIHandler],
85-
[providerIdentifiers.litellm, LiteLLMHandler],
86-
[providerIdentifiers.sambanova, SambaNovaHandler],
87-
[providerIdentifiers.mimo, MimoHandler],
88-
[providerIdentifiers.zai, ZAiHandler],
89-
[providerIdentifiers.fireworks, FireworksHandler],
90-
[providerIdentifiers.friendli, FriendliHandler],
91-
[providerIdentifiers.vercelAiGateway, VercelAiGatewayHandler],
92-
[providerIdentifiers.opencodeGo, OpencodeGoHandler],
93-
[providerIdentifiers.kenari, KenariHandler],
94-
[providerIdentifiers.zooGateway, ZooGatewayHandler],
95-
[providerIdentifiers.minimax, MiniMaxHandler],
96-
[providerIdentifiers.baseten, BasetenHandler],
97-
[providerIdentifiers.poe, PoeHandler],
98-
] as const)("returns the expected handler for %s", (apiProvider, Handler) => {
113+
it.each(expectedHandlerEntries)("returns the expected handler for %s", (apiProvider, Handler) => {
99114
const handler = buildApiHandler({ apiProvider })
100115

101116
expect(handler).toBeInstanceOf(Handler)

0 commit comments

Comments
 (0)