Skip to content

Commit b49577d

Browse files
committed
test(github): verify rate limiter edge cases and missing parameter fallbacks
1 parent 0783fae commit b49577d

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// @vitest-environment node
2+
3+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
4+
import { refreshRateLimiter } from './refresh-rate-limiter';
5+
6+
const FIXED_NOW = new Date('2026-06-02T00:00:00.000Z').valueOf();
7+
8+
describe('RefreshRateLimiter Empty Fallback Verification', () => {
9+
beforeEach(() => {
10+
vi.useFakeTimers();
11+
vi.setSystemTime(FIXED_NOW);
12+
vi.stubEnv('MAX_REFRESHES_PER_HOUR', 'not-a-number');
13+
refreshRateLimiter.reset();
14+
});
15+
16+
afterEach(() => {
17+
refreshRateLimiter.reset();
18+
vi.clearAllTimers();
19+
vi.useRealTimers();
20+
vi.unstubAllEnvs();
21+
vi.restoreAllMocks();
22+
});
23+
24+
it('throws for empty object and empty array runtime payloads', () => {
25+
expect(() => Reflect.apply(refreshRateLimiter.checkLimit, refreshRateLimiter, [{}])).toThrow(
26+
TypeError
27+
);
28+
expect(() => Reflect.apply(refreshRateLimiter.checkLimit, refreshRateLimiter, [[]])).toThrow(
29+
TypeError
30+
);
31+
});
32+
33+
it('throws for null and numeric runtime payloads', () => {
34+
expect(() => Reflect.apply(refreshRateLimiter.checkLimit, refreshRateLimiter, [null])).toThrow(
35+
TypeError
36+
);
37+
expect(() => Reflect.apply(refreshRateLimiter.checkLimit, refreshRateLimiter, [0])).toThrow(
38+
TypeError
39+
);
40+
});
41+
42+
it('accepts whitespace strings and still returns the default limiter structure', () => {
43+
const result = refreshRateLimiter.checkLimit(' ');
44+
45+
expect(result.success).toBe(true);
46+
expect(result.limit).toBe(3);
47+
expect(result.remaining).toBe(2);
48+
expect(result.reset).toBe(FIXED_NOW + 60 * 60 * 1000);
49+
});
50+
51+
it('honors a stubbed hourly limit for repeated checks', () => {
52+
vi.stubEnv('MAX_REFRESHES_PER_HOUR', '2');
53+
refreshRateLimiter.reset();
54+
55+
const first = refreshRateLimiter.checkLimit('203.0.113.5');
56+
const second = refreshRateLimiter.checkLimit('203.0.113.5');
57+
const third = refreshRateLimiter.checkLimit('203.0.113.5');
58+
59+
expect(first.success).toBe(true);
60+
expect(first.limit).toBe(2);
61+
expect(first.remaining).toBe(1);
62+
63+
expect(second.success).toBe(true);
64+
expect(second.limit).toBe(2);
65+
expect(second.remaining).toBe(0);
66+
67+
expect(third.success).toBe(false);
68+
expect(third.limit).toBe(2);
69+
expect(third.remaining).toBe(0);
70+
});
71+
72+
it('resets back to production defaults after a custom limit has been applied', () => {
73+
refreshRateLimiter.setLimit(1);
74+
75+
const allowed = refreshRateLimiter.checkLimit('198.51.100.1');
76+
const blocked = refreshRateLimiter.checkLimit('198.51.100.1');
77+
78+
expect(allowed.success).toBe(true);
79+
expect(allowed.limit).toBe(1);
80+
expect(allowed.remaining).toBe(0);
81+
82+
expect(blocked.success).toBe(false);
83+
expect(blocked.limit).toBe(1);
84+
expect(blocked.remaining).toBe(0);
85+
86+
refreshRateLimiter.reset();
87+
88+
const resetResult = refreshRateLimiter.checkLimit('198.51.100.1');
89+
90+
expect(resetResult.success).toBe(true);
91+
expect(resetResult.limit).toBe(3);
92+
expect(resetResult.remaining).toBe(2);
93+
});
94+
});

0 commit comments

Comments
 (0)