|
1 | 1 | // npx vitest run src/api/providers/__tests__/gemini.spec.ts |
2 | 2 |
|
3 | | -import { NoOutputGeneratedError } from "ai" |
4 | | - |
5 | 3 | const mockCaptureException = vitest.fn() |
6 | 4 |
|
7 | 5 | vitest.mock("@roo-code/telemetry", () => ({ |
@@ -105,84 +103,6 @@ describe("GeminiHandler", () => { |
105 | 103 | ) |
106 | 104 | }) |
107 | 105 |
|
108 | | - it("should yield informative message when stream produces no text content", async () => { |
109 | | - // Stream with only reasoning (no text-delta) simulates thinking-only response |
110 | | - const mockFullStream = (async function* () { |
111 | | - yield { type: "reasoning-delta", id: "1", text: "thinking..." } |
112 | | - })() |
113 | | - |
114 | | - mockStreamText.mockReturnValue({ |
115 | | - fullStream: mockFullStream, |
116 | | - usage: Promise.resolve({ inputTokens: 10, outputTokens: 0 }), |
117 | | - providerMetadata: Promise.resolve({}), |
118 | | - }) |
119 | | - |
120 | | - const stream = handler.createMessage(systemPrompt, mockMessages) |
121 | | - const chunks = [] |
122 | | - |
123 | | - for await (const chunk of stream) { |
124 | | - chunks.push(chunk) |
125 | | - } |
126 | | - |
127 | | - // Should have: reasoning chunk, empty-stream informative message, usage |
128 | | - const textChunks = chunks.filter((c) => c.type === "text") |
129 | | - expect(textChunks).toHaveLength(1) |
130 | | - expect(textChunks[0]).toEqual({ |
131 | | - type: "text", |
132 | | - text: "Model returned an empty response. This may be caused by an unsupported thinking configuration or content filtering.", |
133 | | - }) |
134 | | - }) |
135 | | - |
136 | | - it("should suppress NoOutputGeneratedError when no text content was yielded", async () => { |
137 | | - // Empty stream - nothing yielded at all |
138 | | - const mockFullStream = (async function* () { |
139 | | - // empty stream |
140 | | - })() |
141 | | - |
142 | | - mockStreamText.mockReturnValue({ |
143 | | - fullStream: mockFullStream, |
144 | | - usage: Promise.reject(new NoOutputGeneratedError({ message: "No output generated." })), |
145 | | - providerMetadata: Promise.resolve({}), |
146 | | - }) |
147 | | - |
148 | | - const stream = handler.createMessage(systemPrompt, mockMessages) |
149 | | - const chunks = [] |
150 | | - |
151 | | - // Should NOT throw - the error is suppressed |
152 | | - for await (const chunk of stream) { |
153 | | - chunks.push(chunk) |
154 | | - } |
155 | | - |
156 | | - // Should have the informative empty-stream message only (no usage since it errored) |
157 | | - const textChunks = chunks.filter((c) => c.type === "text") |
158 | | - expect(textChunks).toHaveLength(1) |
159 | | - expect(textChunks[0]).toMatchObject({ |
160 | | - type: "text", |
161 | | - text: expect.stringContaining("empty response"), |
162 | | - }) |
163 | | - }) |
164 | | - |
165 | | - it("should re-throw NoOutputGeneratedError when text content was yielded", async () => { |
166 | | - // Stream yields text content but usage still throws NoOutputGeneratedError (unexpected) |
167 | | - const mockFullStream = (async function* () { |
168 | | - yield { type: "text-delta", text: "Hello" } |
169 | | - })() |
170 | | - |
171 | | - mockStreamText.mockReturnValue({ |
172 | | - fullStream: mockFullStream, |
173 | | - usage: Promise.reject(new NoOutputGeneratedError({ message: "No output generated." })), |
174 | | - providerMetadata: Promise.resolve({}), |
175 | | - }) |
176 | | - |
177 | | - const stream = handler.createMessage(systemPrompt, mockMessages) |
178 | | - |
179 | | - await expect(async () => { |
180 | | - for await (const _chunk of stream) { |
181 | | - // consume stream |
182 | | - } |
183 | | - }).rejects.toThrow() |
184 | | - }) |
185 | | - |
186 | 106 | it("should handle API errors", async () => { |
187 | 107 | const mockError = new Error("Gemini API error") |
188 | 108 | ;(handler["client"].models.generateContentStream as any).mockRejectedValue(mockError) |
|
0 commit comments