profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
rate-limit.test.ts 1,365 bytes
1 import { describe, expect, it } from 'vitest';
2 import { rateLimit } from './rate-limit';
3
4 describe('rateLimit', () => {
5 it('allows up to the limit, then blocks', () => {
6 const key = 'test-block';
7 const window = 60_000;
8 expect(rateLimit(key, 3, window).allowed).toBe(true);
9 expect(rateLimit(key, 3, window).allowed).toBe(true);
10 expect(rateLimit(key, 3, window).allowed).toBe(true);
11 const blocked = rateLimit(key, 3, window);
12 expect(blocked.allowed).toBe(false);
13 expect(blocked.remaining).toBe(0);
14 expect(blocked.resetMs).toBeGreaterThan(0);
15 });
16
17 it('reports decreasing remaining budget', () => {
18 const key = 'test-remaining';
19 expect(rateLimit(key, 5, 60_000).remaining).toBe(4);
20 expect(rateLimit(key, 5, 60_000).remaining).toBe(3);
21 });
22
23 it('tracks keys independently', () => {
24 const window = 60_000;
25 rateLimit('user-a', 1, window);
26 expect(rateLimit('user-a', 1, window).allowed).toBe(false);
27 // A different key still has its full budget.
28 expect(rateLimit('user-b', 1, window).allowed).toBe(true);
29 });
30
31 it('lets requests through again once the window has passed', () => {
32 const key = 'test-window';
33 // Zero-length window: the previous hit is always outside it.
34 expect(rateLimit(key, 1, 0).allowed).toBe(true);
35 expect(rateLimit(key, 1, 0).allowed).toBe(true);
36 });
37 });
38