@@ -46,17 +46,19 @@ describe('retryResponseErrorHandler', () => {
46
46
await retryResponseErrorHandler ( error , config , client ) ;
47
47
fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
48
48
} 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
+ ) ;
53
55
}
54
56
} ) ;
55
57
it ( 'should reject the promise if retryOnError is true' , async ( ) => {
56
58
const error = { config : { retryOnError : true } } ;
57
59
const config = { retryLimit : 5 } ;
58
60
const client = axios . create ( ) ;
59
-
61
+
60
62
try {
61
63
await retryResponseErrorHandler ( error , config , client ) ;
62
64
fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
@@ -73,121 +75,212 @@ describe('retryResponseErrorHandler', () => {
73
75
await retryResponseErrorHandler ( error , config , client ) ;
74
76
fail ( 'Expected retryResponseErrorHandler to throw an error' ) ;
75
77
} 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
+ }
82
86
} ) ;
83
87
it ( 'should reject the promise if response status is 429 and retryCount exceeds retryLimit' , async ( ) => {
84
88
const error = {
85
89
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
+ } ,
87
100
} ;
88
101
const config = { retryLimit : 5 , timeout : 1000 } ;
89
102
const client = axios . create ( ) ;
90
103
91
- await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toBe ( error ) ;
104
+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
92
105
} ) ;
93
106
it ( 'should reject the promise if response status is 401 and retryCount exceeds retryLimit' , async ( ) => {
94
107
const error = {
95
108
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
+ } ,
97
119
} ;
98
120
const config = { retryLimit : 5 , timeout : 1000 } ;
99
121
const client = axios . create ( ) ;
100
122
101
- await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toBe ( error ) ;
123
+ await expect ( retryResponseErrorHandler ( error , config , client ) ) . rejects . toEqual ( error . response . data ) ;
102
124
} ) ;
103
125
it ( 'should reject the promise if response status is 429 or 401 and retryCount is within limit' , async ( ) => {
104
126
const error = {
105
127
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
+ } ,
107
138
request : {
108
139
method : 'post' ,
109
140
url : '/retryURL' ,
110
141
data : { key : 'value' } ,
111
142
headers : { 'Content-Type' : 'application/json' } ,
112
143
} ,
113
144
} ;
114
- const config = { retryLimit : 5 , timeout : 1000 } ;
145
+ const config = { retryLimit : 4 , timeout : 1000 } ;
115
146
const client = axios . create ( ) ;
116
147
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 ) ;
133
149
} ) ;
134
150
it ( 'should call the retry function if retryCondition is passed' , async ( ) => {
135
151
const error = {
136
152
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
+ } ,
138
163
request : {
139
164
method : 'post' ,
140
165
url : '/retryURL' ,
141
166
data : { key : 'value' } ,
142
167
headers : { 'Content-Type' : 'application/json' } ,
143
168
} ,
144
169
} ;
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 } ;
148
172
const client = axios . create ( ) ;
149
173
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 } ) ;
156
175
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 ) ;
160
178
} ) ;
161
179
it ( 'should reject to error when retryCondition is passed but retryLimit is exceeded' , async ( ) => {
162
180
const error = {
163
181
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
+ } ,
165
192
request : {
166
193
method : 'post' ,
167
194
url : '/retryURL' ,
168
195
data : { key : 'value' } ,
169
196
headers : { 'Content-Type' : 'application/json' } ,
170
197
} ,
171
198
} ;
172
- // eslint-disable-next-line @typescript-eslint/no-shadow
173
199
const retryCondition = ( error : any ) => true ;
174
- const config = { retryLimit : 5 , timeout : 1000 , retryCondition : retryCondition } ;
200
+ const config = { retryLimit : 5 , timeout : 1000 , retryCondition } ;
175
201
const client = axios . create ( ) ;
176
202
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
+ } ,
180
242
} ;
243
+ const retryCondition = jest . fn ( ) . mockReturnValue ( true ) ;
244
+ const config = { retryLimit : 3 , retryCondition, retryDelay : 100 } ;
245
+ const client = axios . create ( ) ;
181
246
182
- mock . onPost ( '/retryURL' ) . reply ( 200 , finalResponseObj ) ;
247
+ mock . onAny ( ) . reply ( 200 , { success : true } ) ;
183
248
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 ) ;
185
252
} ) ;
186
253
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 ( ) => {
188
255
const error = {
189
256
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
+ } ,
191
284
} ;
192
285
const config = { retryLimit : 3 } ;
193
286
const client = axios . create ( ) ;
@@ -198,19 +291,20 @@ describe('retryResponseErrorHandler', () => {
198
291
expect ( response . status ) . toBe ( 200 ) ;
199
292
} ) ;
200
293
201
- it ( 'should retry when retryCondition is true ' , async ( ) => {
294
+ it ( 'should retry when x-ratelimit-remaining header is not present ' , async ( ) => {
202
295
const error = {
203
296
config : { retryOnError : true , retryCount : 1 } ,
204
- response : { status : 500 , statusText : 'Internal Server Error' } ,
297
+ response : {
298
+ status : 429 ,
299
+ headers : { } ,
300
+ } ,
205
301
} ;
206
- const retryCondition = jest . fn ( ) . mockReturnValue ( true ) ;
207
- const config = { retryLimit : 3 , retryCondition, retryDelay : 100 } ;
302
+ const config = { retryLimit : 3 } ;
208
303
const client = axios . create ( ) ;
209
304
210
305
mock . onAny ( ) . reply ( 200 ) ;
211
306
212
307
const response : any = await retryResponseErrorHandler ( error , config , client ) ;
213
308
expect ( response . status ) . toBe ( 200 ) ;
214
- expect ( retryCondition ) . toHaveBeenCalledWith ( error ) ;
215
309
} ) ;
216
310
} ) ;
0 commit comments