Skip to content

Commit 6ede310

Browse files
authored
test: add sliding-window expiry test for utility (JhaSourav07#1619)
## Description Added a test case for the sliding-window expiry utility to verify that keys expire exactly at the window boundary. This ensures the low-level time helper handles edge cases correctly and guarantees expiry precision for time-range inputs. Fixes JhaSourav07#1581 ## Pillar - [ ] 🎨 Pillar 1 — New Theme Design - [ ] 📐 Pillar 2 — Geometric SVG Improvement - [x] 🕐 Pillar 3 — Timezone Logic Optimization - [ ] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview ## Checklist before requesting a review: - [x] I have read the `CONTRIBUTING.md` file. - [x] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). - [x] I have run `npm run format` and `npm run lint` locally and resolved all errors (CI will fail otherwise). - [x] My commits follow the Conventional Commits format (e.g., `feat(themes): ...`, `fix(calculate): ...`). - [ ] I have updated `README.md` if I added a new theme or URL parameter. - [x] I have started 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 (no raw elements, smooth animations, correct fonts). - [ ] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents 79e10e6 + 94247ce commit 6ede310

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

lib/rate-limit.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,38 @@ describe('rateLimit', () => {
108108
});
109109
});
110110

111+
it('keys expire exactly at the window limit with sliding time advances', async () => {
112+
vi.useFakeTimers();
113+
const ip = '9.9.9.9';
114+
const windowMs = 1000;
115+
const limit = 5;
116+
117+
// First request: creates the tracker with 1s TTL
118+
let res = await rateLimit(ip, limit, windowMs);
119+
expect(res.success).toBe(true);
120+
expect(res.remaining).toBe(limit - 1);
121+
122+
// Advance half the window and make another request
123+
vi.advanceTimersByTime(500);
124+
res = await rateLimit(ip, limit, windowMs);
125+
expect(res.success).toBe(true);
126+
127+
// Advance to exactly the original window boundary (total = 1000ms)
128+
vi.advanceTimersByTime(500);
129+
130+
// At the exact boundary the entry should still be considered valid
131+
res = await rateLimit(ip, limit, windowMs);
132+
expect(res.success).toBe(true);
133+
134+
// Move just past the window expiry
135+
vi.advanceTimersByTime(1);
136+
137+
// Now the key must have expired and a fresh window starts
138+
res = await rateLimit(ip, limit, windowMs);
139+
expect(res.success).toBe(true);
140+
expect(res.remaining).toBe(limit - 1);
141+
});
142+
111143
it('allows requests after many expired IP entries', async () => {
112144
const windowMs = 1000;
113145

0 commit comments

Comments
 (0)