Skip to content

Commit 34c5dcc

Browse files
v1rtlclaude
andcommitted
test(rate-limit): add tests to improve coverage
Add tests covering: - max as an async function - Successful requests with skipFailedRequests (no decrement) - Failed requests with skipSuccessfulRequests (no decrement) - onLimitReached callback when limit is first reached - Store error in incr callback - headers: false option when rate limited Improves rate-limit.ts coverage: - Statements: 95% -> 97% - Branches: 83% -> 94% Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 59fbb13 commit 34c5dcc

1 file changed

Lines changed: 95 additions & 0 deletions

File tree

tests/wares/rate-limit/rate-limit.test.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)