@@ -18,6 +18,7 @@ import { ApiProviderError, OpenAiServiceTier, SERVICE_TIER_KEY, serviceTiers } f
1818import { OpenAiNativeHandler } from "../openai-native"
1919import { ApiHandlerOptions } from "../../../shared/api"
2020import { Package } from "../../../shared/package"
21+ import { asyncStreamFrom , collectStream } from "../../../test-utils/stream"
2122
2223// Mock OpenAI client - now everything uses Responses API
2324const mockResponsesCreate = vitest . fn ( )
@@ -141,18 +142,14 @@ describe("OpenAiNativeHandler", () => {
141142
142143 describe ( "createMessage" , ( ) => {
143144 it . each ( serviceTiers ) ( "should include the selected %s service tier" , async ( serviceTier ) => {
144- mockResponsesCreate . mockResolvedValue ( {
145- async * [ Symbol . asyncIterator ] ( ) { } ,
146- } )
145+ mockResponsesCreate . mockResolvedValue ( asyncStreamFrom ( [ ] ) )
147146 handler = new OpenAiNativeHandler ( {
148147 ...mockOptions ,
149148 apiModelId : "gpt-5.6-sol" ,
150149 openAiNativeServiceTier : serviceTier ,
151150 } )
152151
153- for await ( const chunk of handler . createMessage ( systemPrompt , messages ) ) {
154- void chunk
155- }
152+ await collectStream ( handler . createMessage ( systemPrompt , messages ) )
156153
157154 expect ( mockResponsesCreate ) . toHaveBeenCalledWith (
158155 expect . objectContaining ( { [ SERVICE_TIER_KEY ] : serviceTier } ) ,
@@ -163,27 +160,24 @@ describe("OpenAiNativeHandler", () => {
163160 it . each ( serviceTierPricingCases ) (
164161 "prices SDK stream usage using resolved $resolvedTier tier instead of requested $requestedTier tier" ,
165162 async ( { requestedTier, resolvedTier, expectedCost } ) => {
166- mockResponsesCreate . mockResolvedValue ( {
167- async * [ Symbol . asyncIterator ] ( ) {
168- yield {
163+ mockResponsesCreate . mockResolvedValue (
164+ asyncStreamFrom ( [
165+ {
169166 type : "response.done" ,
170167 response : {
171168 [ SERVICE_TIER_KEY ] : resolvedTier ,
172169 usage : { input_tokens : 100 , output_tokens : 20 } ,
173170 } ,
174- }
175- } ,
176- } )
171+ } ,
172+ ] ) ,
173+ )
177174 handler = new OpenAiNativeHandler ( {
178175 ...mockOptions ,
179176 apiModelId : "gpt-5.6-sol" ,
180177 openAiNativeServiceTier : requestedTier ,
181178 } )
182179
183- const chunks = [ ]
184- for await ( const chunk of handler . createMessage ( systemPrompt , messages ) ) {
185- chunks . push ( chunk )
186- }
180+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
187181
188182 expect ( chunks ) . toContainEqual (
189183 expect . objectContaining ( {
@@ -219,9 +213,9 @@ describe("OpenAiNativeHandler", () => {
219213 expectedCost : 0.088 ,
220214 } ,
221215 ] ) ( "retains standard pricing for $name" , async ( { modelId, requestedTier, resolvedTier, expectedCost } ) => {
222- mockResponsesCreate . mockResolvedValue ( {
223- async * [ Symbol . asyncIterator ] ( ) {
224- yield {
216+ mockResponsesCreate . mockResolvedValue (
217+ asyncStreamFrom ( [
218+ {
225219 type : "response.done" ,
226220 response : {
227221 ...( resolvedTier ? { [ SERVICE_TIER_KEY ] : resolvedTier } : { } ) ,
@@ -231,19 +225,16 @@ describe("OpenAiNativeHandler", () => {
231225 cache_read_input_tokens : 20_000 ,
232226 } ,
233227 } ,
234- }
235- } ,
236- } )
228+ } ,
229+ ] ) ,
230+ )
237231 handler = new OpenAiNativeHandler ( {
238232 ...mockOptions ,
239233 apiModelId : modelId ,
240234 openAiNativeServiceTier : requestedTier ,
241235 } )
242236
243- const chunks = [ ]
244- for await ( const chunk of handler . createMessage ( systemPrompt , messages ) ) {
245- chunks . push ( chunk )
246- }
237+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
247238
248239 const usageChunk = chunks . find ( ( chunk ) => chunk . type === "usage" )
249240 expect ( usageChunk ) . toBeDefined ( )
@@ -281,10 +272,7 @@ describe("OpenAiNativeHandler", () => {
281272 openAiNativeServiceTier : requestedTier ,
282273 } )
283274
284- const chunks = [ ]
285- for await ( const chunk of handler . createMessage ( systemPrompt , messages ) ) {
286- chunks . push ( chunk )
287- }
275+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
288276
289277 const [ , request ] = mockFetch . mock . calls [ 0 ]
290278 expect ( JSON . parse ( request . body ) ) . toMatchObject ( { [ SERVICE_TIER_KEY ] : requestedTier } )
@@ -328,10 +316,7 @@ describe("OpenAiNativeHandler", () => {
328316 openAiNativeServiceTier : requestedTier ,
329317 } )
330318
331- const chunks = [ ]
332- for await ( const chunk of handler . createMessage ( systemPrompt , messages ) ) {
333- chunks . push ( chunk )
334- }
319+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
335320
336321 expect ( chunks ) . toContainEqual (
337322 expect . objectContaining ( {
@@ -371,11 +356,7 @@ describe("OpenAiNativeHandler", () => {
371356 // Mock SDK to fail so it falls back to fetch
372357 mockResponsesCreate . mockRejectedValue ( new Error ( "SDK not available" ) )
373358
374- const stream = handler . createMessage ( systemPrompt , messages )
375- const chunks : any [ ] = [ ]
376- for await ( const chunk of stream ) {
377- chunks . push ( chunk )
378- }
359+ const chunks = await collectStream ( handler . createMessage ( systemPrompt , messages ) )
379360
380361 expect ( chunks . length ) . toBeGreaterThan ( 0 )
381362 const textChunks = chunks . filter ( ( chunk ) => chunk . type === "text" )
@@ -2023,10 +2004,7 @@ describe("GPT-5 streaming event coverage (additional)", () => {
20232004
20242005 // Should throw an error when encountering error event
20252006 await expect ( async ( ) => {
2026- const chunks = [ ]
2027- for await ( const chunk of stream ) {
2028- chunks . push ( chunk )
2029- }
2007+ await collectStream ( stream )
20302008 } ) . rejects . toThrow ( "Responses API error: Model overloaded" )
20312009 } )
20322010
0 commit comments