SPB Git

spb/phi-conseil

Public
1.7 KB · 52 lines typescript
1import { describe, expect, it } from "vitest";2import {3  createMemoryRateLimiter,4  createDedupe,5  clientIp,6  fingerprint,7  contentSecurityPolicy,8} from "@/lib/security";910describe("limitation de débit", () => {11  it("bloque après N requêtes dans la fenêtre puis libère", () => {12    const rl = createMemoryRateLimiter(3, 60);13    const t0 = 1_000_000;14    expect(rl.check("a", t0).allowed).toBe(true);15    expect(rl.check("a", t0 + 1).allowed).toBe(true);16    expect(rl.check("a", t0 + 2).allowed).toBe(true);17    const blocked = rl.check("a", t0 + 3);18    expect(blocked.allowed).toBe(false);19    expect(blocked.retryAfterS).toBeGreaterThan(0);20    expect(rl.check("b", t0 + 3).allowed).toBe(true);21    expect(rl.check("a", t0 + 61_000).allowed).toBe(true);22  });23});2425describe("dédoublonnage", () => {26  it("signale un doublon dans la fenêtre seulement", () => {27    const d = createDedupe(10);28    expect(d.isDuplicate("k", 0)).toBe(false);29    expect(d.isDuplicate("k", 5_000)).toBe(true);30    expect(d.isDuplicate("k", 20_000)).toBe(false);31  });32});3334describe("utilitaires", () => {35  it("lit la première IP de X-Forwarded-For", () => {36    expect(clientIp(new Headers({ "x-forwarded-for": "203.0.113.5, 10.0.0.1" }))).toBe(37      "203.0.113.5",38    );39    expect(clientIp(new Headers())).toBe("unknown");40  });41  it("produit une empreinte stable non réversible", () => {42    expect(fingerprint("a")).toBe(fingerprint("a"));43    expect(fingerprint("a")).not.toBe(fingerprint("b"));44    expect(fingerprint("a")).toHaveLength(12);45  });46  it("la CSP interdit l'intégration dans une iframe et les objets", () => {47    const csp = contentSecurityPolicy();48    expect(csp).toContain("frame-ancestors 'none'");49    expect(csp).toContain("object-src 'none'");50  });51});52
Files · main
Menu

Theme