@@ -295,6 +295,86 @@ describe('set', () => {
295
295
296
296
await cleanup ( )
297
297
} )
298
+
299
+ test ( 'Accepts multiple files concurrently' , async ( ) => {
300
+ const contents = [ 'Hello from key-0' , 'Hello from key-1' , 'Hello from key-2' ]
301
+ const signedURLs = [ 'https://signed-url.aws/0' , 'https://signed-url.aws/1' , 'https://signed-url.aws/2' ]
302
+
303
+ const store = new MockFetch ( )
304
+ . put ( {
305
+ headers : { authorization : `Bearer ${ apiToken } ` } ,
306
+ response : new Response ( JSON . stringify ( { url : signedURLs [ 0 ] } ) ) ,
307
+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/key-0?context=production` ,
308
+ } )
309
+ . put ( {
310
+ body : async ( body ) => {
311
+ expect ( await streamToString ( body as unknown as NodeJS . ReadableStream ) ) . toBe ( contents [ 0 ] )
312
+ } ,
313
+ headers : {
314
+ 'cache-control' : 'max-age=0, stale-while-revalidate=60' ,
315
+ } ,
316
+ response : new Response ( null ) ,
317
+ url : signedURLs [ 0 ] ,
318
+ } )
319
+ . put ( {
320
+ headers : { authorization : `Bearer ${ apiToken } ` } ,
321
+ response : new Response ( JSON . stringify ( { url : signedURLs [ 1 ] } ) ) ,
322
+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/key-1?context=production` ,
323
+ } )
324
+ . put ( {
325
+ body : async ( body ) => {
326
+ expect ( await streamToString ( body as unknown as NodeJS . ReadableStream ) ) . toBe ( contents [ 1 ] )
327
+ } ,
328
+ headers : {
329
+ 'cache-control' : 'max-age=0, stale-while-revalidate=60' ,
330
+ } ,
331
+ response : new Response ( null ) ,
332
+ url : signedURLs [ 1 ] ,
333
+ } )
334
+ . put ( {
335
+ headers : { authorization : `Bearer ${ apiToken } ` } ,
336
+ response : new Response ( JSON . stringify ( { url : signedURLs [ 2 ] } ) ) ,
337
+ url : `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/key-2?context=production` ,
338
+ } )
339
+ . put ( {
340
+ body : async ( body ) => {
341
+ expect ( await streamToString ( body as unknown as NodeJS . ReadableStream ) ) . toBe ( contents [ 2 ] )
342
+ } ,
343
+ headers : {
344
+ 'cache-control' : 'max-age=0, stale-while-revalidate=60' ,
345
+ } ,
346
+ response : new Response ( null ) ,
347
+ url : signedURLs [ 2 ] ,
348
+ } )
349
+
350
+ const writes = await Promise . all (
351
+ contents . map ( async ( content ) => {
352
+ const { cleanup, path } = await tmp . file ( )
353
+
354
+ await writeFile ( path , content )
355
+
356
+ return { cleanup, path }
357
+ } ) ,
358
+ )
359
+ const files = writes . map ( ( { path } , idx ) => ( {
360
+ key : `key-${ idx } ` ,
361
+ path,
362
+ } ) )
363
+
364
+ const blobs = new Blobs ( {
365
+ authentication : {
366
+ token : apiToken ,
367
+ } ,
368
+ fetcher : store . fetcher ,
369
+ siteID,
370
+ } )
371
+
372
+ await blobs . setFiles ( files )
373
+
374
+ expect ( store . fulfilled ) . toBeTruthy ( )
375
+
376
+ await Promise . all ( writes . map ( ( { cleanup } ) => cleanup ( ) ) )
377
+ } )
298
378
}
299
379
300
380
test ( 'Throws when the API returns a non-200 status code' , async ( ) => {
0 commit comments