@@ -37,9 +37,10 @@ describe("fal video generation provider", () => {
3737
3838 function releasedJson ( value : unknown ) {
3939 return {
40- response : {
41- json : async ( ) => value ,
42- } ,
40+ response : new Response ( JSON . stringify ( value ) , {
41+ status : 200 ,
42+ headers : { "Content-Type" : "application/json" } ,
43+ } ) ,
4344 release : vi . fn ( async ( ) => { } ) ,
4445 } ;
4546 }
@@ -687,4 +688,50 @@ describe("fal video generation provider", () => {
687688 "fal Seedance reference-to-video requires at least one image or video reference when audio references are provided." ,
688689 ) ;
689690 } ) ;
691+
692+ it ( "bounds fal video generation JSON response reads" , async ( ) => {
693+ mockFalProviderRuntime ( ) ;
694+
695+ const ONE_MIB = 1024 * 1024 ;
696+ const TOTAL_CHUNKS = 32 ;
697+ const chunk = new Uint8Array ( ONE_MIB ) ;
698+ let bytesPulled = 0 ;
699+ let canceled = false ;
700+
701+ fetchGuardMock . mockResolvedValueOnce ( {
702+ response : new Response (
703+ new ReadableStream < Uint8Array > ( {
704+ pull ( controller ) {
705+ if ( bytesPulled / ONE_MIB >= TOTAL_CHUNKS ) {
706+ controller . close ( ) ;
707+ return ;
708+ }
709+ bytesPulled += chunk . length ;
710+ controller . enqueue ( chunk ) ;
711+ } ,
712+ cancel ( ) {
713+ canceled = true ;
714+ } ,
715+ } ) ,
716+ {
717+ status : 200 ,
718+ headers : { "Content-Type" : "application/json" } ,
719+ } ,
720+ ) ,
721+ release : vi . fn ( async ( ) => { } ) ,
722+ } ) ;
723+
724+ const provider = buildFalVideoGenerationProvider ( ) ;
725+ await expect (
726+ provider . generateVideo ( {
727+ provider : "fal" ,
728+ model : "fal-ai/minimax/video-01-live" ,
729+ prompt : "test" ,
730+ cfg : { } ,
731+ } ) ,
732+ ) . rejects . toThrow ( / f a l v i d e o g e n e r a t i o n r e s p o n s e m a l f o r m e d | J S O N r e s p o n s e e x c e e d s / ) ;
733+
734+ expect ( canceled ) . toBe ( true ) ;
735+ expect ( bytesPulled ) . toBeLessThan ( TOTAL_CHUNKS * ONE_MIB ) ;
736+ } ) ;
690737} ) ;
0 commit comments