@@ -46,17 +46,19 @@ describe('retryResponseErrorHandler', () => {
4646 await retryResponseErrorHandler ( error , config , client ) ;
4747 fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
4848 } catch ( err ) {
49- expect ( err ) . toEqual ( expect . objectContaining ( {
50- code : 'ECONNABORTED' ,
51- config : expect . objectContaining ( { retryOnError : false } ) ,
52- } ) ) ;
49+ expect ( err ) . toEqual (
50+ expect . objectContaining ( {
51+ code : 'ECONNABORTED' ,
52+ config : expect . objectContaining ( { retryOnError : false } ) ,
53+ } )
54+ ) ;
5355 }
5456 } ) ;
5557 it ( 'should reject the promise if retryOnError is true' , async ( ) => {
5658 const error = { config : { retryOnError : true } } ;
5759 const config = { retryLimit : 5 } ;
5860 const client = axios . create ( ) ;
59-
61+
6062 try {
6163 await retryResponseErrorHandler ( error , config , client ) ;
6264 fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
@@ -73,121 +75,212 @@ describe('retryResponseErrorHandler', () => {
7375 await retryResponseErrorHandler ( error , config , client ) ;
7476 fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
7577 } catch ( err ) {
76- expect ( err ) . toEqual ( expect . objectContaining ( {
77- error_code : 408 ,
78- error_message : `Timeout of ${ config . timeout } ms exceeded` ,
79- errors : null
80- } ) ) ;
81- }
78+ expect ( err ) . toEqual (
79+ expect . objectContaining ( {
80+ error_code : 408 ,
81+ error_message : `Timeout of ${ config . timeout } ms exceeded` ,
82+ errors : null ,
83+ } )
84+ ) ;
85+ }
8286 } ) ;
8387 it ( 'should reject the promise if response status is 429 and retryCount exceeds retryLimit' , async ( ) => {
8488 const error = {
8589 config : { retryOnError : true , retryCount : 5 } ,
86- response : { status : 429 , statusText : 'timeout of 1000ms exceeded' } ,
90+ response : {
91+ status : 429 ,
92+ statusText : 'timeout of 1000ms exceeded' ,
93+ headers : { } ,
94+ data : {
95+ error_message : 'Rate limit exceeded' ,
96+ error_code : 429 ,
97+ errors : null ,
98+ } ,
99+ } ,
87100 } ;
88101 const config = { retryLimit : 5 , timeout : 1000 } ;
89102 const client = axios . create ( ) ;
90103
91- await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toBe ( error ) ;
104+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
92105 } ) ;
93106 it ( 'should reject the promise if response status is 401 and retryCount exceeds retryLimit' , async ( ) => {
94107 const error = {
95108 config : { retryOnError : true , retryCount : 5 } ,
96- response : { status : 401 , statusText : 'timeout of 1000ms exceeded' } ,
109+ response : {
110+ status : 401 ,
111+ statusText : 'timeout of 1000ms exceeded' ,
112+ headers : { } ,
113+ data : {
114+ error_message : 'Unauthorized' ,
115+ error_code : 401 ,
116+ errors : null ,
117+ } ,
118+ } ,
97119 } ;
98120 const config = { retryLimit : 5 , timeout : 1000 } ;
99121 const client = axios . create ( ) ;
100122
101- await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toBe ( error ) ;
123+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
102124 } ) ;
103125 it ( 'should reject the promise if response status is 429 or 401 and retryCount is within limit' , async ( ) => {
104126 const error = {
105127 config : { retryOnError : true , retryCount : 4 } ,
106- response : { status : 429 , statusText : 'timeout of 1000ms exceeded' } ,
128+ response : {
129+ status : 429 ,
130+ statusText : 'timeout of 1000ms exceeded' ,
131+ headers : { } ,
132+ data : {
133+ error_message : 'Rate limit exceeded' ,
134+ error_code : 429 ,
135+ errors : null ,
136+ } ,
137+ } ,
107138 request : {
108139 method : 'post' ,
109140 url : '/retryURL' ,
110141 data : { key : 'value' } ,
111142 headers : { 'Content-Type' : 'application/json' } ,
112143 } ,
113144 } ;
114- const config = { retryLimit : 5 , timeout : 1000 } ;
145+ const config = { retryLimit : 4 , timeout : 1000 } ;
115146 const client = axios . create ( ) ;
116147
117- const finalResponseObj = {
118- config : { retryOnError : true , retryCount : 4 } ,
119- response : { status : 429 , statusText : 'timeout of 1000ms exceeded' } ,
120- } ;
121-
122- mock . onPost ( '/retryURL' ) . reply ( 200 , finalResponseObj ) ;
123-
124- try {
125- await retryResponseErrorHandler ( error , config , client ) ;
126- throw new Error ( 'Expected retryResponseErrorHandler to throw an error' ) ;
127- } catch ( err : any ) {
128- expect ( err . response . status ) . toBe ( 429 ) ;
129- expect ( err . response . statusText ) . toBe ( error . response . statusText ) ;
130- expect ( err . config . retryCount ) . toBe ( error . config . retryCount ) ;
131- }
132-
148+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
133149 } ) ;
134150 it ( 'should call the retry function if retryCondition is passed' , async ( ) => {
135151 const error = {
136152 config : { retryOnError : true , retryCount : 4 } ,
137- response : { status : 200 , statusText : 'Success Response but retry needed' } ,
153+ response : {
154+ status : 200 ,
155+ statusText : 'Success Response but retry needed' ,
156+ headers : { } ,
157+ data : {
158+ error_message : 'Retry needed' ,
159+ error_code : 200 ,
160+ errors : null ,
161+ } ,
162+ } ,
138163 request : {
139164 method : 'post' ,
140165 url : '/retryURL' ,
141166 data : { key : 'value' } ,
142167 headers : { 'Content-Type' : 'application/json' } ,
143168 } ,
144169 } ;
145- // eslint-disable-next-line @typescript-eslint/no-shadow
146- const retryCondition = ( error : any ) => true ;
147- const config = { retryLimit : 5 , timeout : 1000 , retryCondition : retryCondition } ;
170+ const retryCondition = ( ) => true ;
171+ const config = { retryLimit : 5 , timeout : 1000 , retryCondition } ;
148172 const client = axios . create ( ) ;
149173
150- const finalResponseObj = {
151- config : { retryOnError : true , retryCount : 5 } ,
152- response : { status : 429 , statusText : 'timeout of 1000ms exceeded' } ,
153- } ;
154-
155- mock . onPost ( '/retryURL' ) . reply ( 200 , finalResponseObj ) ;
174+ mock . onPost ( '/retryURL' ) . reply ( 200 , { success : true } ) ;
156175
157- const finalResponse : any = await retryResponseErrorHandler ( error , config , client ) ;
158-
159- expect ( finalResponse . data ) . toEqual ( finalResponseObj ) ;
176+ const response = ( await retryResponseErrorHandler ( error , config , client ) ) as AxiosResponse ;
177+ expect ( response . status ) . toBe ( 200 ) ;
160178 } ) ;
161179 it ( 'should reject to error when retryCondition is passed but retryLimit is exceeded' , async ( ) => {
162180 const error = {
163181 config : { retryOnError : true , retryCount : 5 } ,
164- response : { status : 200 , statusText : 'Success Response but retry needed' } ,
182+ response : {
183+ status : 200 ,
184+ statusText : 'Success Response but retry needed' ,
185+ headers : { } ,
186+ data : {
187+ error_message : 'Retry needed' ,
188+ error_code : 200 ,
189+ errors : null ,
190+ } ,
191+ } ,
165192 request : {
166193 method : 'post' ,
167194 url : '/retryURL' ,
168195 data : { key : 'value' } ,
169196 headers : { 'Content-Type' : 'application/json' } ,
170197 } ,
171198 } ;
172- // eslint-disable-next-line @typescript-eslint/no-shadow
173199 const retryCondition = ( error : any ) => true ;
174- const config = { retryLimit : 5 , timeout : 1000 , retryCondition : retryCondition } ;
200+ const config = { retryLimit : 5 , timeout : 1000 , retryCondition } ;
175201 const client = axios . create ( ) ;
176202
177- const finalResponseObj = {
178- config : { retryOnError : true , retryCount : 5 } ,
179- response : { status : 429 , statusText : 'timeout of 1000ms exceeded' } ,
203+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error ) ;
204+ } ) ;
205+
206+ it ( 'should retry when response status is 429 and retryCount is less than retryLimit' , async ( ) => {
207+ const error = {
208+ config : { retryOnError : true , retryCount : 1 } ,
209+ response : {
210+ status : 429 ,
211+ statusText : 'Rate limit exceeded' ,
212+ headers : { } ,
213+ data : {
214+ error_message : 'Rate limit exceeded' ,
215+ error_code : 429 ,
216+ errors : null ,
217+ } ,
218+ } ,
219+ } ;
220+ const config = { retryLimit : 3 } ;
221+ const client = axios . create ( ) ;
222+
223+ mock . onAny ( ) . reply ( 200 , { success : true } ) ;
224+
225+ const response = ( await retryResponseErrorHandler ( error , config , client ) ) as AxiosResponse ;
226+ expect ( response . status ) . toBe ( 200 ) ;
227+ } ) ;
228+
229+ it ( 'should retry when retryCondition is true' , async ( ) => {
230+ const error = {
231+ config : { retryOnError : true , retryCount : 1 } ,
232+ response : {
233+ status : 500 ,
234+ statusText : 'Internal Server Error' ,
235+ headers : { } ,
236+ data : {
237+ error_message : 'Internal Server Error' ,
238+ error_code : 500 ,
239+ errors : null ,
240+ } ,
241+ } ,
180242 } ;
243+ const retryCondition = jest . fn ( ) . mockReturnValue ( true ) ;
244+ const config = { retryLimit : 3 , retryCondition, retryDelay : 100 } ;
245+ const client = axios . create ( ) ;
181246
182- mock . onPost ( '/retryURL' ) . reply ( 200 , finalResponseObj ) ;
247+ mock . onAny ( ) . reply ( 200 , { success : true } ) ;
183248
184- await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toBe ( error ) ;
249+ const response = ( await retryResponseErrorHandler ( error , config , client ) ) as AxiosResponse ;
250+ expect ( response . status ) . toBe ( 200 ) ;
251+ expect ( retryCondition ) . toHaveBeenCalledWith ( error ) ;
185252 } ) ;
186253
187- it ( 'should retry when response status is 429 and retryCount is less than retryLimit ' , async ( ) => {
254+ it ( 'should reject with rate limit error when x-ratelimit-remaining is 0 ' , async ( ) => {
188255 const error = {
189256 config : { retryOnError : true , retryCount : 1 } ,
190- response : { status : 429 , statusText : 'Rate limit exceeded' } ,
257+ response : {
258+ status : 429 ,
259+ headers : {
260+ 'x-ratelimit-remaining' : '0' ,
261+ } ,
262+ data : {
263+ error_message : 'Rate limit exceeded' ,
264+ error_code : 429 ,
265+ errors : null ,
266+ } ,
267+ } ,
268+ } ;
269+ const config = { retryLimit : 3 } ;
270+ const client = axios . create ( ) ;
271+
272+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
273+ } ) ;
274+
275+ it ( 'should retry when x-ratelimit-remaining is greater than 0' , async ( ) => {
276+ const error = {
277+ config : { retryOnError : true , retryCount : 1 } ,
278+ response : {
279+ status : 429 ,
280+ headers : {
281+ 'x-ratelimit-remaining' : '5' ,
282+ } ,
283+ } ,
191284 } ;
192285 const config = { retryLimit : 3 } ;
193286 const client = axios . create ( ) ;
@@ -198,19 +291,20 @@ describe('retryResponseErrorHandler', () => {
198291 expect ( response . status ) . toBe ( 200 ) ;
199292 } ) ;
200293
201- it ( 'should retry when retryCondition is true ' , async ( ) => {
294+ it ( 'should retry when x-ratelimit-remaining header is not present ' , async ( ) => {
202295 const error = {
203296 config : { retryOnError : true , retryCount : 1 } ,
204- response : { status : 500 , statusText : 'Internal Server Error' } ,
297+ response : {
298+ status : 429 ,
299+ headers : { } ,
300+ } ,
205301 } ;
206- const retryCondition = jest . fn ( ) . mockReturnValue ( true ) ;
207- const config = { retryLimit : 3 , retryCondition, retryDelay : 100 } ;
302+ const config = { retryLimit : 3 } ;
208303 const client = axios . create ( ) ;
209304
210305 mock . onAny ( ) . reply ( 200 ) ;
211306
212307 const response : any = await retryResponseErrorHandler ( error , config , client ) ;
213308 expect ( response . status ) . toBe ( 200 ) ;
214- expect ( retryCondition ) . toHaveBeenCalledWith ( error ) ;
215309 } ) ;
216310} ) ;
0 commit comments