@@ -234,6 +234,101 @@ describe('rate-limit', () => {
234234
235235 expect ( shouldSkip ) . toHaveBeenCalled ( )
236236 } )
237+
238+ it ( 'should support max as an async function' , async ( ) => {
239+ const maxFn = vi . fn ( async ( ) => 2 )
240+
241+ const app = createAppWith (
242+ rateLimit ( {
243+ max : maxFn
244+ } )
245+ )
246+
247+ await makeFetch ( app ) ( '/' ) . expect ( 200 )
248+ await makeFetch ( app ) ( '/' ) . expect ( 200 )
249+ await makeFetch ( app ) ( '/' ) . expect ( 429 )
250+
251+ expect ( maxFn ) . toHaveBeenCalled ( )
252+ } )
253+
254+ it ( 'should not decrement on successful requests when skipFailedRequests is true' , async ( ) => {
255+ const store = new MockStore ( )
256+ const app = createAppWith (
257+ rateLimit ( {
258+ skipFailedRequests : true ,
259+ store : store
260+ } )
261+ )
262+
263+ await makeFetch ( app ) ( '/' ) . expect ( 200 )
264+ // decrement should NOT be called for successful requests with skipFailedRequests
265+ expect ( store . decrement_was_called ) . toBeFalsy ( )
266+ } )
267+
268+ it ( 'should not decrement on failed requests when skipSuccessfulRequests is true' , async ( ) => {
269+ const store = new MockStore ( )
270+ const app = createAppWith (
271+ rateLimit ( {
272+ skipSuccessfulRequests : true ,
273+ store : store
274+ } )
275+ )
276+
277+ await makeFetch ( app ) ( '/errorPage' ) . expect ( 404 )
278+ // decrement should NOT be called for failed requests with skipSuccessfulRequests
279+ expect ( store . decrement_was_called ) . toBeFalsy ( )
280+ } )
281+
282+ it ( 'should call onLimitReached when limit is first reached' , async ( ) => {
283+ const onLimitReached = vi . fn ( )
284+
285+ const app = createAppWith (
286+ rateLimit ( {
287+ max : 1 ,
288+ onLimitReached
289+ } )
290+ )
291+
292+ await makeFetch ( app ) ( '/' ) . expect ( 200 )
293+ expect ( onLimitReached ) . not . toHaveBeenCalled ( )
294+
295+ await makeFetch ( app ) ( '/' ) . expect ( 429 )
296+ expect ( onLimitReached ) . toHaveBeenCalledTimes ( 1 )
297+
298+ // Should not call again on subsequent requests
299+ await makeFetch ( app ) ( '/' ) . expect ( 429 )
300+ expect ( onLimitReached ) . toHaveBeenCalledTimes ( 1 )
301+ } )
302+
303+ it ( 'should handle store error in incr callback' , async ( ) => {
304+ const errorStore = {
305+ incr : ( _ , cb ) => {
306+ cb ( new Error ( 'Store error' ) , 0 , new Date ( ) )
307+ } ,
308+ resetKey : ( ) => { } ,
309+ decrement : ( ) => { } ,
310+ resetAll : ( ) => { }
311+ }
312+
313+ const app = createAppWith (
314+ rateLimit ( {
315+ store : errorStore
316+ } )
317+ )
318+
319+ await makeFetch ( app ) ( '/' ) . expect ( 500 )
320+ } )
321+
322+ it ( 'should not send headers when headers option is false and rate limited' , async ( ) => {
323+ const app = new App ( )
324+ app . use ( rateLimit ( { max : 1 , headers : false } ) )
325+ app . get ( '/' , ( _ , res ) => res . send ( 'response!' ) )
326+ const server = app . listen ( )
327+
328+ await makeFetch ( server ) ( '/' ) . expect ( 200 )
329+ const response = await makeFetch ( server ) ( '/' ) . expect ( 429 )
330+ expect ( response . headers . get ( 'retry-after' ) ) . toBeNull ( )
331+ } )
237332 } )
238333} )
239334
0 commit comments