@@ -49,6 +49,8 @@ const falInput = {
4949
5050describe ( 'image operations' , ( ) => {
5151 beforeEach ( ( ) => {
52+ mocks . fetch . mockReset ( )
53+ mockSecureFetchWithPinnedIP . mockReset ( )
5254 vi . stubGlobal ( 'fetch' , mocks . fetch )
5355 mockInterruptibleSleep . mockResolvedValue ( undefined )
5456 mockUploadCopilotFile . mockResolvedValue ( { url : 'https://sim.test/generated.png' } )
@@ -116,4 +118,98 @@ describe('image operations', () => {
116118 expect ( mockSecureFetchWithPinnedIP ) . not . toHaveBeenCalled ( )
117119 expect ( mockUploadCopilotFile ) . not . toHaveBeenCalled ( )
118120 } )
121+
122+ it ( 'rejects foreign fal queue hosts before sending credentials' , async ( ) => {
123+ mocks . fetch . mockResolvedValueOnce (
124+ Response . json ( {
125+ request_id : 'foreign-job' ,
126+ status_url : 'https://untrusted.example/status' ,
127+ } )
128+ )
129+ mockSecureFetchWithPinnedIP . mockResolvedValueOnce ( Response . json ( { status : 'FAILED' } ) )
130+
131+ const response = await executeImageGeneration ( falInput , {
132+ userId : 'user-1' ,
133+ requestId : 'foreign-queue' ,
134+ } )
135+
136+ expect ( response . status ) . toBe ( 500 )
137+ expect ( await response . json ( ) ) . toMatchObject ( { error : 'Invalid Fal.ai queue URL' } )
138+ expect ( mockSecureFetchWithPinnedIP ) . not . toHaveBeenCalled ( )
139+ } )
140+
141+ it ( 'retrieves nested fal jobs from the documented application request path' , async ( ) => {
142+ mocks . fetch . mockResolvedValueOnce ( Response . json ( { request_id : 'nested-job' } ) )
143+ mockSecureFetchWithPinnedIP . mockImplementation ( async ( url : string ) => {
144+ if ( url === 'https://queue.fal.run/fal-ai/bytedance/requests/nested-job/status' ) {
145+ return Response . json ( { status : 'COMPLETED' } )
146+ }
147+ if ( url === 'https://queue.fal.run/fal-ai/bytedance/requests/nested-job' ) {
148+ return Response . json ( { images : [ { url : 'data:image/png;base64,cG5n' } ] } )
149+ }
150+ return new Response ( 'Not found' , { status : 404 } )
151+ } )
152+
153+ const response = await executeImageGeneration (
154+ { ...falInput , model : 'seedream-v4.5' } ,
155+ {
156+ userId : 'user-1' ,
157+ requestId : 'nested-queue' ,
158+ }
159+ )
160+
161+ expect ( response . status ) . toBe ( 200 )
162+ expect ( ( await response . json ( ) ) . imageUrl ) . toBe ( 'https://sim.test/generated.png' )
163+ } )
164+
165+ it . each ( [ 'openai' , 'gemini' ] ) (
166+ 'does not purchase a fallback for an unknown %s model' ,
167+ async ( provider ) => {
168+ mocks . fetch . mockResolvedValueOnce ( new Response ( 'Unexpected generation' , { status : 502 } ) )
169+ const response = await executeImageGeneration (
170+ { ...falInput , provider, model : 'unknown-model' } ,
171+ {
172+ userId : 'user-1' ,
173+ requestId : 'unknown-model' ,
174+ }
175+ )
176+
177+ expect ( response . status ) . toBe ( 400 )
178+ expect ( mocks . fetch ) . not . toHaveBeenCalled ( )
179+ }
180+ )
181+
182+ it ( 'retains the completed fal receipt when delivery is interrupted' , async ( ) => {
183+ const controller = new AbortController ( )
184+ mocks . fetch . mockResolvedValueOnce ( Response . json ( { request_id : 'paid-job' } ) )
185+ mocks . getFalAICostMetadata . mockImplementation ( async ( { signal } : { signal ?: AbortSignal } ) => {
186+ signal ?. throwIfAborted ( )
187+ return {
188+ requestId : 'paid-job' ,
189+ endpointId : 'fal-ai/nano-banana-2' ,
190+ costDollars : 0.1 ,
191+ source : 'billing_events' ,
192+ }
193+ } )
194+ mockSecureFetchWithPinnedIP . mockResolvedValueOnce ( Response . json ( { status : 'COMPLETED' } ) )
195+ mockSecureFetchWithPinnedIP . mockImplementationOnce ( async ( ) => {
196+ controller . abort ( )
197+ return Response . json ( { status : 'COMPLETED' } )
198+ } )
199+
200+ await expect (
201+ executeImageGeneration (
202+ { ...falInput , useHostedCostTracking : true } ,
203+ {
204+ userId : 'user-1' ,
205+ requestId : 'completed-job' ,
206+ signal : controller . signal ,
207+ }
208+ )
209+ ) . rejects . toMatchObject ( { name : 'AbortError' } )
210+ expect ( mocks . getFalAICostMetadata ) . toHaveBeenCalledWith (
211+ expect . objectContaining ( { requestId : 'paid-job' } )
212+ )
213+ expect ( mocks . getFalAICostMetadata . mock . calls [ 0 ] [ 0 ] . signal ) . toBeUndefined ( )
214+ } )
119215} )
0 commit comments