diff --git a/src/lib/cloudflare-api.test.ts b/src/lib/cloudflare-api.test.ts index 65d52d10..94fd1006 100644 --- a/src/lib/cloudflare-api.test.ts +++ b/src/lib/cloudflare-api.test.ts @@ -10,6 +10,58 @@ import { verifyCloudflareConnection, } from "./cloudflare-api"; +// The coordination state must be deterministic in CI too (where REDIS_URL is +// set), so the unit test drives a small in-memory Redis fake. +const state = vi.hoisted(() => ({ map: new Map() })); + +vi.mock("@/lib/redis", () => ({ + redis: { + get: async (key: string) => state.map.get(key) ?? null, + set: async ( + key: string, + value: string, + _mode?: string, + _seconds?: number, + nx?: string, + ) => { + if (nx === "NX" && state.map.has(key)) return null; + state.map.set(key, value); + return "OK"; + }, + del: async (...keys: string[]) => { + for (const key of keys) state.map.delete(key); + return keys.length; + }, + incr: async (key: string) => { + const next = (Number(state.map.get(key)) || 0) + 1; + state.map.set(key, String(next)); + return next; + }, + pexpire: async () => 1, + pttl: async () => 60_000, + sadd: async (key: string, member: string) => { + const members = new Set( + (state.map.get(key) ?? "").split("\u0001").filter(Boolean), + ); + members.add(member); + state.map.set(key, [...members].join("\u0001")); + return 1; + }, + srem: async (key: string, member: string) => { + const members = new Set( + (state.map.get(key) ?? "").split("\u0001").filter(Boolean), + ); + const before = members.size; + members.delete(member); + state.map.set(key, [...members].join("\u0001")); + return before - members.size; + }, + smembers: async (key: string) => + (state.map.get(key) ?? "").split("\u0001").filter(Boolean), + }, + __esModule: true, +})); + function jsonResponse(body: unknown, status = 200): Response { return new Response(JSON.stringify(body), { status, @@ -28,6 +80,7 @@ describe("cloudflare-api", () => { beforeEach(() => { vi.unstubAllGlobals(); vi.unstubAllEnvs(); + state.map.clear(); resetCloudflareAutoBlockCache(); fetchMock = vi.fn(); vi.stubGlobal("fetch", fetchMock); @@ -36,6 +89,7 @@ describe("cloudflare-api", () => { afterEach(() => { vi.unstubAllGlobals(); vi.unstubAllEnvs(); + state.map.clear(); resetCloudflareAutoBlockCache(); });