← back to Govarbitrage
src/lib/rate-limit.test.ts
33 lines
import { describe, expect, it, beforeEach } from "vitest";
import { rateLimit, __resetRateLimit } from "./rate-limit";
beforeEach(() => __resetRateLimit());
describe("rateLimit (sliding window)", () => {
it("allows up to the limit, then blocks", () => {
const t0 = 1_000_000;
for (let i = 1; i <= 5; i++) {
expect(rateLimit("ip:a", 5, 60_000, t0).allowed).toBe(true);
}
const sixth = rateLimit("ip:a", 5, 60_000, t0);
expect(sixth.allowed).toBe(false);
expect(sixth.remaining).toBe(0);
expect(sixth.retryAfterSec).toBeGreaterThan(0);
});
it("resets after the window elapses", () => {
const t0 = 2_000_000;
for (let i = 0; i < 5; i++) rateLimit("ip:b", 5, 60_000, t0);
expect(rateLimit("ip:b", 5, 60_000, t0).allowed).toBe(false);
// A moment past the window: fresh bucket.
expect(rateLimit("ip:b", 5, 60_000, t0 + 60_001).allowed).toBe(true);
});
it("isolates buckets by key", () => {
const t0 = 3_000_000;
for (let i = 0; i < 5; i++) rateLimit("ip:c", 5, 60_000, t0);
expect(rateLimit("ip:c", 5, 60_000, t0).allowed).toBe(false);
expect(rateLimit("ip:d", 5, 60_000, t0).allowed).toBe(true);
});
});