@@ -418,6 +418,59 @@ describe('set', () => {
418418 `The blob store is unavailable because it's missing required configuration properties` ,
419419 )
420420 } )
421+
422+ test ( 'Retries failed operations' , async ( ) => {
423+ let attempts = 0
424+
425+ const fetcher = async ( ...args : Parameters < typeof globalThis . fetch > ) => {
426+ const [ url , options ] = args
427+ const headers = options ?. headers as Record < string , string >
428+
429+ expect ( options ?. method ) . toBe ( 'put' )
430+
431+ if ( url === `https://api.netlify.com/api/v1/sites/${ siteID } /blobs/${ key } ?context=production` ) {
432+ const data = JSON . stringify ( { url : signedURL } )
433+
434+ expect ( headers . authorization ) . toBe ( `Bearer ${ apiToken } ` )
435+
436+ return new Response ( data )
437+ }
438+
439+ if ( url === signedURL ) {
440+ attempts += 1
441+
442+ expect ( options ?. body ) . toBe ( value )
443+
444+ if ( attempts === 1 ) {
445+ return new Response ( null , { status : 500 } )
446+ }
447+
448+ if ( attempts === 2 ) {
449+ throw new Error ( 'Some network problem' )
450+ }
451+
452+ if ( attempts === 3 ) {
453+ return new Response ( null , { headers : { 'X-RateLimit-Reset' : '10' } , status : 429 } )
454+ }
455+
456+ return new Response ( value )
457+ }
458+
459+ throw new Error ( `Unexpected fetch call: ${ url } ` )
460+ }
461+
462+ const blobs = new Blobs ( {
463+ authentication : {
464+ token : apiToken ,
465+ } ,
466+ fetcher,
467+ siteID,
468+ } )
469+
470+ await blobs . set ( key , value )
471+
472+ expect ( attempts ) . toBe ( 4 )
473+ } )
421474} )
422475
423476describe ( 'setJSON' , ( ) => {
0 commit comments