Files
EpicNext-Cms/src/lib/services/captcha.test.ts
T
SimoandCursor ed7db6e048
Deploy / release (push) Skipped
Deploy / deploy (push) Successful in 2m55s
feat: public events/polls, friends graph, captcha, SSE hardening, and admin UX
Ship product gaps: register/vote pages, friend add/accept/decline/remove, email verify TTL, captcha on login/forgot, soft-fail user actions, SSE abort/shared client, Commando Centrum error toasts, admin delete for events/polls, and IT/NL i18n fills.

Co-authored-by: Cursor <[email protected]>
2026-07-21 21:08:33 +02:00

76 lines
2.2 KiB
TypeScript

import { beforeEach, describe, expect, it, vi } from "vitest";
const mockGet = vi.hoisted(() => vi.fn());
vi.mock("@/lib/services/site-settings", () => ({
siteSettings: { get: mockGet },
}));
import { captchaConfig, verifyCaptcha } from "./captcha";
beforeEach(() => {
vi.clearAllMocks();
vi.unstubAllGlobals();
});
describe("verifyCaptcha", () => {
it("allows when provider is none", async () => {
mockGet.mockImplementation(async (key: string, fallback?: string) => {
if (key === "captcha_provider") return "none";
return fallback ?? "";
});
expect(await verifyCaptcha(null)).toBe(true);
});
it("fails closed when provider set but secret missing", async () => {
mockGet.mockImplementation(async (key: string, fallback?: string) => {
if (key === "captcha_provider") return "turnstile";
if (key === "turnstile_site_key") return "site-key";
if (key === "turnstile_secret") return "";
return fallback ?? "";
});
expect(await verifyCaptcha("tok")).toBe(false);
});
it("fails closed on provider API/network errors", async () => {
mockGet.mockImplementation(async (key: string, fallback?: string) => {
if (key === "captcha_provider") return "turnstile";
if (key === "turnstile_site_key") return "site-key";
if (key === "turnstile_secret") return "secret";
return fallback ?? "";
});
vi.stubGlobal(
"fetch",
vi.fn().mockRejectedValue(new Error("network down")),
);
expect(await verifyCaptcha("tok", "1.2.3.4")).toBe(false);
});
it("accepts a successful provider response", async () => {
mockGet.mockImplementation(async (key: string, fallback?: string) => {
if (key === "captcha_provider") return "recaptcha";
if (key === "recaptcha_site_key") return "site-key";
if (key === "recaptcha_secret") return "secret";
return fallback ?? "";
});
vi.stubGlobal(
"fetch",
vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true }),
}),
);
expect(await verifyCaptcha("good-token")).toBe(true);
});
});
describe("captchaConfig", () => {
it("returns none by default", async () => {
mockGet.mockImplementation(async (_key: string, fallback?: string) => {
return fallback ?? "none";
});
const cfg = await captchaConfig();
expect(cfg.provider).toBe("none");
});
});