Skip to content

Commit 8dee9bf

Browse files
committed
Fix failing tests
1 parent d4a1e49 commit 8dee9bf

File tree

1 file changed

+134
-71
lines changed

1 file changed

+134
-71
lines changed

src/services/code-index/embedders/__tests__/openrouter.spec.ts

Lines changed: 134 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,65 @@
1+
import type { MockedClass, MockedFunction } from "vitest"
12
import { describe, it, expect, beforeEach, vi } from "vitest"
3+
import { OpenAI } from "openai"
24
import { OpenRouterEmbedder } from "../openrouter"
35
import { getModelDimension, getDefaultModelId } from "../../../../shared/embeddingModels"
46

5-
// Mock global fetch
6-
const mockFetch = vi.fn()
7-
global.fetch = mockFetch
7+
// Mock the OpenAI SDK
8+
vi.mock("openai")
9+
10+
// Mock TelemetryService
11+
vi.mock("@roo-code/telemetry", () => ({
12+
TelemetryService: {
13+
instance: {
14+
captureEvent: vi.fn(),
15+
},
16+
},
17+
TelemetryEventName: {},
18+
}))
19+
20+
// Mock i18n
21+
vi.mock("../../../../i18n", () => ({
22+
t: (key: string, params?: Record<string, any>) => {
23+
const translations: Record<string, string> = {
24+
"embeddings:validation.apiKeyRequired": "validation.apiKeyRequired",
25+
"embeddings:authenticationFailed":
26+
"Failed to create embeddings: Authentication failed. Please check your OpenRouter API key.",
27+
"embeddings:failedWithStatus": `Failed to create embeddings after ${params?.attempts} attempts: HTTP ${params?.statusCode} - ${params?.errorMessage}`,
28+
"embeddings:failedWithError": `Failed to create embeddings after ${params?.attempts} attempts: ${params?.errorMessage}`,
29+
"embeddings:failedMaxAttempts": `Failed to create embeddings after ${params?.attempts} attempts`,
30+
"embeddings:textExceedsTokenLimit": `Text at index ${params?.index} exceeds maximum token limit (${params?.itemTokens} > ${params?.maxTokens}). Skipping.`,
31+
"embeddings:rateLimitRetry": `Rate limit hit, retrying in ${params?.delayMs}ms (attempt ${params?.attempt}/${params?.maxRetries})`,
32+
}
33+
return translations[key] || key
34+
},
35+
}))
36+
37+
const MockedOpenAI = OpenAI as MockedClass<typeof OpenAI>
838

939
describe("OpenRouterEmbedder", () => {
1040
const mockApiKey = "test-api-key"
41+
let mockEmbeddingsCreate: MockedFunction<any>
42+
let mockOpenAIInstance: any
43+
44+
beforeEach(() => {
45+
vi.clearAllMocks()
46+
vi.spyOn(console, "warn").mockImplementation(() => {})
47+
vi.spyOn(console, "error").mockImplementation(() => {})
48+
49+
// Setup mock OpenAI instance
50+
mockEmbeddingsCreate = vi.fn()
51+
mockOpenAIInstance = {
52+
embeddings: {
53+
create: mockEmbeddingsCreate,
54+
},
55+
}
56+
57+
MockedOpenAI.mockImplementation(() => mockOpenAIInstance)
58+
})
59+
60+
afterEach(() => {
61+
vi.restoreAllMocks()
62+
})
1163

1264
describe("constructor", () => {
1365
it("should create an instance with valid API key", () => {
@@ -16,7 +68,7 @@ describe("OpenRouterEmbedder", () => {
1668
})
1769

1870
it("should throw error with empty API key", () => {
19-
expect(() => new OpenRouterEmbedder("")).toThrow("API key is required")
71+
expect(() => new OpenRouterEmbedder("")).toThrow("validation.apiKeyRequired")
2072
})
2173

2274
it("should use default model when none specified", () => {
@@ -46,93 +98,99 @@ describe("OpenRouterEmbedder", () => {
4698

4799
beforeEach(() => {
48100
embedder = new OpenRouterEmbedder(mockApiKey)
49-
mockFetch.mockClear()
50101
})
51102

52103
it("should create embeddings successfully", async () => {
104+
// Create base64 encoded embedding with values that can be exactly represented in Float32
105+
const testEmbedding = new Float32Array([0.25, 0.5, 0.75])
106+
const base64String = Buffer.from(testEmbedding.buffer).toString("base64")
107+
53108
const mockResponse = {
54-
ok: true,
55-
json: vi.fn().mockResolvedValue({
56-
data: [
57-
{
58-
embedding: Buffer.from(new Float32Array([0.1, 0.2, 0.3]).buffer).toString("base64"),
59-
},
60-
],
61-
usage: {
62-
prompt_tokens: 5,
63-
total_tokens: 5,
109+
data: [
110+
{
111+
embedding: base64String,
64112
},
65-
}),
113+
],
114+
usage: {
115+
prompt_tokens: 5,
116+
total_tokens: 5,
117+
},
66118
}
67119

68-
mockFetch.mockResolvedValue(mockResponse)
120+
mockEmbeddingsCreate.mockResolvedValue(mockResponse)
69121

70122
const result = await embedder.createEmbeddings(["test text"])
71123

124+
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
125+
input: ["test text"],
126+
model: "openai/text-embedding-3-large",
127+
encoding_format: "base64",
128+
})
72129
expect(result.embeddings).toHaveLength(1)
73-
expect(result.embeddings[0]).toEqual([0.1, 0.2, 0.3])
130+
expect(result.embeddings[0]).toEqual([0.25, 0.5, 0.75])
74131
expect(result.usage?.promptTokens).toBe(5)
75132
expect(result.usage?.totalTokens).toBe(5)
76133
})
77134

78135
it("should handle multiple texts", async () => {
136+
const embedding1 = new Float32Array([0.25, 0.5])
137+
const embedding2 = new Float32Array([0.75, 1.0])
138+
const base64String1 = Buffer.from(embedding1.buffer).toString("base64")
139+
const base64String2 = Buffer.from(embedding2.buffer).toString("base64")
140+
79141
const mockResponse = {
80-
ok: true,
81-
json: vi.fn().mockResolvedValue({
82-
data: [
83-
{
84-
embedding: Buffer.from(new Float32Array([0.1, 0.2]).buffer).toString("base64"),
85-
},
86-
{
87-
embedding: Buffer.from(new Float32Array([0.3, 0.4]).buffer).toString("base64"),
88-
},
89-
],
90-
usage: {
91-
prompt_tokens: 10,
92-
total_tokens: 10,
142+
data: [
143+
{
144+
embedding: base64String1,
145+
},
146+
{
147+
embedding: base64String2,
93148
},
94-
}),
149+
],
150+
usage: {
151+
prompt_tokens: 10,
152+
total_tokens: 10,
153+
},
95154
}
96155

97-
mockFetch.mockResolvedValue(mockResponse)
156+
mockEmbeddingsCreate.mockResolvedValue(mockResponse)
98157

99158
const result = await embedder.createEmbeddings(["text1", "text2"])
100159

101160
expect(result.embeddings).toHaveLength(2)
102-
expect(result.embeddings[0]).toEqual([0.1, 0.2])
103-
expect(result.embeddings[1]).toEqual([0.3, 0.4])
161+
expect(result.embeddings[0]).toEqual([0.25, 0.5])
162+
expect(result.embeddings[1]).toEqual([0.75, 1.0])
104163
})
105164

106165
it("should use custom model when provided", async () => {
107166
const customModel = "mistralai/mistral-embed-2312"
108167
const embedderWithCustomModel = new OpenRouterEmbedder(mockApiKey, customModel)
109168

169+
const testEmbedding = new Float32Array([0.25, 0.5])
170+
const base64String = Buffer.from(testEmbedding.buffer).toString("base64")
171+
110172
const mockResponse = {
111-
ok: true,
112-
json: vi.fn().mockResolvedValue({
113-
data: [
114-
{
115-
embedding: Buffer.from(new Float32Array([0.1, 0.2]).buffer).toString("base64"),
116-
},
117-
],
118-
usage: {
119-
prompt_tokens: 5,
120-
total_tokens: 5,
173+
data: [
174+
{
175+
embedding: base64String,
121176
},
122-
}),
177+
],
178+
usage: {
179+
prompt_tokens: 5,
180+
total_tokens: 5,
181+
},
123182
}
124183

125-
mockFetch.mockResolvedValue(mockResponse)
184+
mockEmbeddingsCreate.mockResolvedValue(mockResponse)
126185

127186
await embedderWithCustomModel.createEmbeddings(["test"])
128187

129-
// Verify the fetch was called with the custom model
130-
expect(mockFetch).toHaveBeenCalledWith(
131-
expect.stringContaining("openrouter.ai/api/v1/embeddings"),
132-
expect.objectContaining({
133-
body: expect.stringContaining(`"model":"${customModel}"`),
134-
}),
135-
)
188+
// Verify the embeddings.create was called with the custom model
189+
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
190+
input: ["test"],
191+
model: customModel,
192+
encoding_format: "base64",
193+
})
136194
})
137195
})
138196

@@ -141,42 +199,47 @@ describe("OpenRouterEmbedder", () => {
141199

142200
beforeEach(() => {
143201
embedder = new OpenRouterEmbedder(mockApiKey)
144-
mockFetch.mockClear()
145202
})
146203

147204
it("should validate configuration successfully", async () => {
205+
const testEmbedding = new Float32Array([0.25, 0.5])
206+
const base64String = Buffer.from(testEmbedding.buffer).toString("base64")
207+
148208
const mockResponse = {
149-
ok: true,
150-
json: vi.fn().mockResolvedValue({
151-
data: [
152-
{
153-
embedding: Buffer.from(new Float32Array([0.1, 0.2]).buffer).toString("base64"),
154-
},
155-
],
156-
}),
209+
data: [
210+
{
211+
embedding: base64String,
212+
},
213+
],
214+
usage: {
215+
prompt_tokens: 1,
216+
total_tokens: 1,
217+
},
157218
}
158219

159-
mockFetch.mockResolvedValue(mockResponse)
220+
mockEmbeddingsCreate.mockResolvedValue(mockResponse)
160221

161222
const result = await embedder.validateConfiguration()
162223

163224
expect(result.valid).toBe(true)
164225
expect(result.error).toBeUndefined()
226+
expect(mockEmbeddingsCreate).toHaveBeenCalledWith({
227+
input: ["test"],
228+
model: "openai/text-embedding-3-large",
229+
encoding_format: "base64",
230+
})
165231
})
166232

167233
it("should handle validation failure", async () => {
168-
const mockResponse = {
169-
ok: false,
170-
status: 401,
171-
text: vi.fn().mockResolvedValue("Unauthorized"),
172-
}
234+
const authError = new Error("Invalid API key")
235+
;(authError as any).status = 401
173236

174-
mockFetch.mockResolvedValue(mockResponse)
237+
mockEmbeddingsCreate.mockRejectedValue(authError)
175238

176239
const result = await embedder.validateConfiguration()
177240

178241
expect(result.valid).toBe(false)
179-
expect(result.error).toBeDefined()
242+
expect(result.error).toBe("embeddings:validation.authenticationFailed")
180243
})
181244
})
182245

0 commit comments

Comments
 (0)