46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { RateLimiter } from "../src/auth/rate-limit";
|
|
|
|
const T0 = new Date("2026-01-01T00:00:00Z");
|
|
const at = (ms: number) => new Date(T0.getTime() + ms);
|
|
|
|
describe("RateLimiter (fenêtre glissante)", () => {
|
|
it("autorise jusqu'à maxHits puis bloque", () => {
|
|
const rl = new RateLimiter(3, 60_000);
|
|
expect(rl.hit("a", T0)).toBe(true);
|
|
expect(rl.hit("a", at(1000))).toBe(true);
|
|
expect(rl.hit("a", at(2000))).toBe(true);
|
|
expect(rl.hit("a", at(3000))).toBe(false);
|
|
});
|
|
|
|
it("les hits anciens sortent de la fenêtre", () => {
|
|
const rl = new RateLimiter(2, 60_000);
|
|
expect(rl.hit("a", T0)).toBe(true);
|
|
expect(rl.hit("a", at(30_000))).toBe(true);
|
|
expect(rl.hit("a", at(31_000))).toBe(false);
|
|
// Le hit de T0 a expiré de la fenêtre (60 s).
|
|
expect(rl.hit("a", at(61_001))).toBe(true);
|
|
});
|
|
|
|
it("reset vide la clé", () => {
|
|
const rl = new RateLimiter(1, 60_000);
|
|
expect(rl.hit("a", T0)).toBe(true);
|
|
expect(rl.hit("a", at(1000))).toBe(false);
|
|
rl.reset("a");
|
|
expect(rl.hit("a", at(2000))).toBe(true);
|
|
});
|
|
|
|
it("remaining reflète les tentatives restantes", () => {
|
|
const rl = new RateLimiter(2, 60_000);
|
|
expect(rl.remaining("a", T0)).toBe(2);
|
|
rl.hit("a", T0);
|
|
expect(rl.remaining("a", at(1000))).toBe(1);
|
|
});
|
|
|
|
it("les clés sont isolées", () => {
|
|
const rl = new RateLimiter(1, 60_000);
|
|
expect(rl.hit("a", T0)).toBe(true);
|
|
expect(rl.hit("b", T0)).toBe(true);
|
|
});
|
|
});
|