Skip to content

Commit 0ec4b46

Browse files
authored
test(RateLimiter): add unit tests for RateLimiter class (JhaSourav07#1216)
## Description Fixes JhaSourav07#1022 ## Pillar - [ ] 🎨 Pillar 1 β€” New Theme Design - [ ] πŸ“ Pillar 2 β€” Geometric SVG Improvement - [ ] πŸ• Pillar 3 β€” Timezone Logic Optimization - [x] πŸ› οΈ Other (Bug fix, refactoring, docs) ## Changes Added 4 unit tests for the `RateLimiter` class in `lib/rate-limit.test.ts`: - `check(ip)` returns `true` when within limit - `check(ip)` returns `false` after exceeding limit - Multiple IPs are tracked independently - `check(ip)` returns `true` again after window reset ## Visual Preview N/A β€” no visual changes. ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`npm run test` β€” 8/8 tests pass). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors. - [x] My commits follow the Conventional Commits format. - [ ] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have starred the repo. - [x] I have made sure that I have only one commit to merge in this PR. - [ ] The SVG output matches the CommitPulse "premium quality" aesthetic standard. - [ ] (Recommended) I joined the CommitPulse Discord community.
2 parents d8c470b + bb9d3e4 commit 0ec4b46

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

β€Žlib/rate-limit.test.tsβ€Ž

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { describe, it, expect, beforeEach, vi } from 'vitest';
22
import { rateLimit } from './rate-limit';
3+
import { RateLimiter } from './rate-limit';
34

45
describe('rateLimit', () => {
56
beforeEach(() => {
@@ -60,3 +61,48 @@ describe('rateLimit', () => {
6061
expect(rateLimit(ip2, 60, 60000).success).toBe(true);
6162
});
6263
});
64+
65+
describe('RateLimiter', () => {
66+
beforeEach(() => {
67+
vi.useFakeTimers();
68+
});
69+
70+
it('allows requests within the limit', () => {
71+
// Each check() within the limit should return true
72+
const limiter = new RateLimiter(3, 60000);
73+
expect(limiter.check('1.1.1.1')).toBe(true);
74+
expect(limiter.check('1.1.1.1')).toBe(true);
75+
expect(limiter.check('1.1.1.1')).toBe(true);
76+
});
77+
78+
it('blocks requests after exceeding the limit', () => {
79+
// 4th request should be denied when limit is 3
80+
const limiter = new RateLimiter(3, 60000);
81+
limiter.check('2.2.2.2');
82+
limiter.check('2.2.2.2');
83+
limiter.check('2.2.2.2');
84+
expect(limiter.check('2.2.2.2')).toBe(false);
85+
});
86+
87+
it('tracks multiple IPs independently', () => {
88+
// Exhausting one IP's limit should not affect another IP
89+
const limiter = new RateLimiter(2, 60000);
90+
limiter.check('3.3.3.3');
91+
limiter.check('3.3.3.3');
92+
expect(limiter.check('3.3.3.3')).toBe(false);
93+
expect(limiter.check('4.4.4.4')).toBe(true);
94+
});
95+
96+
it('allows requests again after the window resets', () => {
97+
// TTL expiry should clear the count, allowing the IP through again
98+
const windowMs = 60000;
99+
const limiter = new RateLimiter(2, windowMs);
100+
limiter.check('5.5.5.5');
101+
limiter.check('5.5.5.5');
102+
expect(limiter.check('5.5.5.5')).toBe(false);
103+
104+
vi.advanceTimersByTime(windowMs + 1);
105+
106+
expect(limiter.check('5.5.5.5')).toBe(true);
107+
});
108+
});

0 commit comments

Comments
Β (0)