import { describe, it, expect } from "vitest"; import { rateLimit } from "@/lib/rate-limit"; describe("rateLimit", () => { it("allows up to limit calls in window", () => { const key = "test:" + Math.random(); for (let i = 0; i < 5; i++) { const r = rateLimit({ key, windowMs: 60_000, limit: 5 }); expect(r.ok).toBe(true); } }); it("blocks the (limit+1)th call with retryAfter > 0", () => { const key = "test:" + Math.random(); for (let i = 0; i < 3; i++) { rateLimit({ key, windowMs: 60_000, limit: 3 }); } const r = rateLimit({ key, windowMs: 60_000, limit: 3 }); expect(r.ok).toBe(false); expect(r.retryAfter).toBeGreaterThan(0); expect(r.remaining).toBe(0); }); it("isolates different keys", () => { const k1 = "test:" + Math.random(); const k2 = "test:" + Math.random(); for (let i = 0; i < 5; i++) { rateLimit({ key: k1, windowMs: 60_000, limit: 5 }); } const r = rateLimit({ key: k2, windowMs: 60_000, limit: 5 }); expect(r.ok).toBe(true); }); it("resets after window expires", async () => { const key = "test:" + Math.random(); rateLimit({ key, windowMs: 10, limit: 1 }); const blocked = rateLimit({ key, windowMs: 10, limit: 1 }); expect(blocked.ok).toBe(false); await new Promise((r) => setTimeout(r, 15)); const after = rateLimit({ key, windowMs: 10, limit: 1 }); expect(after.ok).toBe(true); }); });