41 lines
1.4 KiB
TypeScript
41 lines
1.4 KiB
TypeScript
import { describe, it, expect, beforeEach } from 'vitest';
|
|
import { rateLimit, _clearRateLimits } from './v2-rate-limit';
|
|
|
|
describe('rateLimit', () => {
|
|
beforeEach(() => {
|
|
_clearRateLimits();
|
|
});
|
|
|
|
it('allows requests up to the limit', () => {
|
|
for (let i = 0; i < 3; i++) {
|
|
const r = rateLimit({ key: 'k', limit: 3, windowMs: 60_000, now: 1000 });
|
|
expect(r.ok).toBe(true);
|
|
}
|
|
});
|
|
|
|
it('rejects once the limit is exceeded and reports Retry-After', () => {
|
|
for (let i = 0; i < 3; i++) {
|
|
rateLimit({ key: 'k', limit: 3, windowMs: 60_000, now: 1000 });
|
|
}
|
|
const r = rateLimit({ key: 'k', limit: 3, windowMs: 60_000, now: 1000 });
|
|
expect(r.ok).toBe(false);
|
|
expect(r.retryAfterMs).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('treats keys independently', () => {
|
|
rateLimit({ key: 'a', limit: 1, windowMs: 60_000, now: 1000 });
|
|
expect(rateLimit({ key: 'a', limit: 1, windowMs: 60_000, now: 1000 }).ok).toBe(false);
|
|
expect(rateLimit({ key: 'b', limit: 1, windowMs: 60_000, now: 1000 }).ok).toBe(true);
|
|
});
|
|
|
|
it('lets the window expire before allowing again', () => {
|
|
for (let i = 0; i < 2; i++) {
|
|
rateLimit({ key: 'k', limit: 2, windowMs: 10_000, now: 1000 });
|
|
}
|
|
expect(rateLimit({ key: 'k', limit: 2, windowMs: 10_000, now: 1000 }).ok).toBe(false);
|
|
expect(rateLimit({ key: 'k', limit: 2, windowMs: 10_000, now: 1000 + 10_000 + 1 }).ok).toBe(
|
|
true
|
|
);
|
|
});
|
|
});
|