Skip to content
This repository was archived by the owner on May 15, 2026. It is now read-only.

Commit d7be2b9

Browse files
committed
test: add 35 Azure provider verification tests
- Handler: createAzure constructor args, dual-ID getModel lookup, processUsageMetrics, getMaxOutputTokens, reasoning events, tool-call ignoring, completePrompt error propagation, provider metadata key mismatch - Validation: 4 Azure branches in validate.spec.ts - Config: 4 Azure cases in checkExistApiConfig.spec.ts - Types: 6 model definition correctness tests, 3 Zod schema round-trips - URL parser: 3 additional edge cases Total: 105 tests across 6 suites (was 70)
1 parent b7278ae commit d7be2b9

7 files changed

Lines changed: 612 additions & 1 deletion

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import type { ModelInfo } from "../model.js"
2+
import { azureModels, azureDefaultModelId, azureDefaultModelInfo } from "../providers/azure.js"
3+
4+
// Object.entries loses the per-key literal types from `as const satisfies`,
5+
// so we cast each value back to ModelInfo to access optional properties.
6+
const modelEntries = Object.entries(azureModels) as [string, ModelInfo][]
7+
8+
describe("Azure model definitions", () => {
9+
it("all models have required ModelInfo fields with valid values", () => {
10+
for (const [id, info] of modelEntries) {
11+
expect(info.maxTokens, `${id} maxTokens`).toBeGreaterThan(0)
12+
expect(info.contextWindow, `${id} contextWindow`).toBeGreaterThan(0)
13+
expect(typeof info.supportsImages, `${id} supportsImages`).toBe("boolean")
14+
expect(typeof info.supportsPromptCache, `${id} supportsPromptCache`).toBe("boolean")
15+
expect(info.inputPrice, `${id} inputPrice`).toBeGreaterThanOrEqual(0)
16+
expect(info.outputPrice, `${id} outputPrice`).toBeGreaterThanOrEqual(0)
17+
}
18+
})
19+
20+
it("default model ID exists in model map", () => {
21+
expect(azureModels[azureDefaultModelId]).toBeDefined()
22+
})
23+
24+
it("default model info matches the default model ID entry", () => {
25+
expect(azureDefaultModelInfo).toBe(azureModels[azureDefaultModelId])
26+
})
27+
28+
it("models with supportsReasoningEffort have a valid reasoningEffort default", () => {
29+
for (const [id, info] of modelEntries) {
30+
if (Array.isArray(info.supportsReasoningEffort)) {
31+
expect(info.reasoningEffort, `${id} missing reasoningEffort default`).toBeDefined()
32+
expect(
33+
info.supportsReasoningEffort,
34+
`${id} reasoningEffort not in supportsReasoningEffort array`,
35+
).toContain(info.reasoningEffort)
36+
}
37+
}
38+
})
39+
40+
it("models claiming prompt cache support have cacheReadsPrice defined", () => {
41+
for (const [id, info] of modelEntries) {
42+
if (info.supportsPromptCache) {
43+
// Azure models with cache support define cacheReadsPrice but not
44+
// cacheWritesPrice — Azure does not charge separately for cache writes.
45+
expect(info.cacheReadsPrice, `${id} supports cache but missing cacheReadsPrice`).toBeDefined()
46+
}
47+
}
48+
})
49+
50+
it("maxTokens never exceeds contextWindow for any model", () => {
51+
for (const [id, info] of modelEntries) {
52+
expect(
53+
info.maxTokens,
54+
`${id} maxTokens (${info.maxTokens}) exceeds contextWindow (${info.contextWindow})`,
55+
).toBeLessThanOrEqual(info.contextWindow)
56+
}
57+
})
58+
})

packages/types/src/__tests__/provider-settings.test.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { getApiProtocol } from "../provider-settings.js"
1+
import { getApiProtocol, providerSettingsSchemaDiscriminated } from "../provider-settings.js"
22

33
describe("getApiProtocol", () => {
44
describe("Anthropic-style providers", () => {
@@ -62,6 +62,37 @@ describe("getApiProtocol", () => {
6262
})
6363
})
6464

65+
describe("azure provider settings", () => {
66+
it("accepts valid Azure config with all fields", () => {
67+
const result = providerSettingsSchemaDiscriminated.safeParse({
68+
apiProvider: "azure",
69+
azureApiKey: "test-key-123",
70+
azureBaseUrl: "https://my-resource.openai.azure.com/openai",
71+
azureDeploymentName: "gpt-5.2",
72+
azureApiVersion: "2024-10-21",
73+
apiModelId: "gpt-5.2",
74+
})
75+
expect(result.success).toBe(true)
76+
})
77+
78+
it("accepts Azure config without optional azureApiKey (managed identity)", () => {
79+
const result = providerSettingsSchemaDiscriminated.safeParse({
80+
apiProvider: "azure",
81+
azureBaseUrl: "https://my-resource.openai.azure.com/openai",
82+
azureDeploymentName: "gpt-4o",
83+
})
84+
expect(result.success).toBe(true)
85+
})
86+
87+
it("rejects Azure config with invalid field types", () => {
88+
const result = providerSettingsSchemaDiscriminated.safeParse({
89+
apiProvider: "azure",
90+
azureApiKey: 12345,
91+
})
92+
expect(result.success).toBe(false)
93+
})
94+
})
95+
6596
describe("Edge cases", () => {
6697
it("should return 'openai' when provider is undefined", () => {
6798
expect(getApiProtocol(undefined)).toBe("openai")

pnpm-lock.yaml

Lines changed: 28 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)