Skip to content

Commit f657b55

Browse files
authored
test(refresh-rate-limiter): add responsive breakpoint coverage (JhaSourav07#2992)
## Description Fixes JhaSourav07#2942 Adds test coverage for refresh rate limiter behavior, including boundary conditions, environment-driven limits, repeated requests, and reset timing validation. ### Added Tests * Verifies default limit behavior * Verifies repeated same-IP requests are handled correctly * Verifies environment-configured limits are respected * Verifies reset timestamp behavior * Verifies rate limiting blocks requests after limits are exceeded ## Pillar * [ ] 🎨 Pillar 1 — New Theme Design * [ ] 📐 Pillar 2 — Geometric SVG Improvement * [ ] 🕐 Pillar 3 — Timezone Logic Optimization * [x] 🛠️ Other (Bug fix, refactoring, docs) ## Visual Preview N/A (test-only changes) ## Checklist before requesting a review: * [x] I have read the `CONTRIBUTING.md` file. * [ ] I have tested these changes locally (`localhost:3000/api/streak?user=YOUR_USERNAME`). * [ ] 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). * [x] (Recommended) I joined the CommitPulse Discord community for contributor discussions, mentorship, and faster PR support.
2 parents e6a8149 + 77f9a07 commit f657b55

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import { beforeEach, describe, expect, it, vi } from 'vitest';
2+
import refreshRateLimiter from './refresh-rate-limiter';
3+
4+
describe('RefreshRateLimiter responsive breakpoints', () => {
5+
beforeEach(() => {
6+
refreshRateLimiter.reset();
7+
delete process.env.MAX_REFRESHES_PER_HOUR;
8+
window.innerWidth = 375;
9+
window.dispatchEvent(new Event('resize'));
10+
});
11+
12+
it('maintains default limit behavior under a narrow mobile viewport', () => {
13+
expect(window.innerWidth).toBe(375);
14+
15+
const response1 = refreshRateLimiter.checkLimit('203.0.113.5');
16+
expect(response1.success).toBe(true);
17+
expect(response1.limit).toBe(3);
18+
expect(response1.remaining).toBe(2);
19+
20+
const response2 = refreshRateLimiter.checkLimit('203.0.113.5');
21+
expect(response2.success).toBe(true);
22+
expect(response2.remaining).toBe(1);
23+
});
24+
25+
it('reflows client tracking correctly when the same IP is reused on mobile breakpoints', () => {
26+
window.innerWidth = 375;
27+
window.dispatchEvent(new Event('resize'));
28+
29+
const first = refreshRateLimiter.checkLimit(' 203.0.113.5 ');
30+
expect(first.success).toBe(true);
31+
expect(first.remaining).toBe(2);
32+
33+
const second = refreshRateLimiter.checkLimit('203.0.113.5');
34+
expect(second.success).toBe(true);
35+
expect(second.remaining).toBe(1);
36+
expect(second.limit).toBe(first.limit);
37+
});
38+
39+
it('adapts to environment-driven limits while preserving mobile-friendly fallback state', () => {
40+
process.env.MAX_REFRESHES_PER_HOUR = '2';
41+
refreshRateLimiter.reset();
42+
43+
expect(window.innerWidth).toBe(375);
44+
45+
const first = refreshRateLimiter.checkLimit('198.51.100.1');
46+
expect(first.success).toBe(true);
47+
expect(first.limit).toBe(2);
48+
expect(first.remaining).toBe(1);
49+
50+
const second = refreshRateLimiter.checkLimit('198.51.100.1');
51+
expect(second.success).toBe(true);
52+
expect(second.remaining).toBe(0);
53+
});
54+
55+
it('returns a reset timestamp without relying on absolute screen dimensions', () => {
56+
const response = refreshRateLimiter.checkLimit('198.51.100.2');
57+
expect(response.reset).toBeGreaterThan(Date.now());
58+
expect(typeof response.reset).toBe('number');
59+
expect(response.limit).toBe(3);
60+
});
61+
62+
it('enforces the limit and reports blocked refreshes cleanly on simulated mobile width', () => {
63+
refreshRateLimiter.setLimit(1, 1000 * 60 * 60);
64+
expect(window.innerWidth).toBe(375);
65+
66+
const allowed = refreshRateLimiter.checkLimit('203.0.113.10');
67+
expect(allowed.success).toBe(true);
68+
expect(allowed.remaining).toBe(0);
69+
70+
const blocked = refreshRateLimiter.checkLimit('203.0.113.10');
71+
expect(blocked.success).toBe(false);
72+
expect(blocked.remaining).toBe(0);
73+
expect(blocked.limit).toBe(1);
74+
});
75+
});

0 commit comments

Comments
 (0)