test: cover captcha env fallback, cache TTLs and public e2e flows
CI / check (push) Successful in 39s
CI / tests-imaging-browsers (push) Successful in 1m46s
CI / tests-unit (push) Successful in 2m16s
CI / tests-integration (push) Successful in 2m12s
CI / tests-ui (push) Failing after 3m45s
CI / preflight (push) Skipped
CI / deploy (push) Skipped

- unit: captcha env fallback/precedence (DB wins, explicit "none") and
  perf-ttls defaults, overrides and invalid values
- e2e: public page render + image health, register form and Turnstile
  widget consistency, anonymous auth-guard redirects, plus warm latency
  budgets and cache-control contracts
This commit is contained in:
openhands committed 2026-10-15 16:00:08 +02:00
1 parent 9f024dc6ac
commit 62de3e3a8b
7 files changed
+401

No files matched your search

+61
View File
@@ -12,6 +12,7 @@ import { captchaConfig, verifyCaptcha } from "./captcha";
beforeEach(() => {
vi.clearAllMocks();
vi.unstubAllGlobals();
vi.unstubAllEnvs();
});
describe("verifyCaptcha", () => {
@@ -74,3 +75,63 @@ describe("captchaConfig", () => {
expect(cfg.provider).toBe("none");
});
});
describe("env fallback", () => {
it("enables Turnstile from env when the DB is unconfigured", async () => {
mockGet.mockResolvedValue("");
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
const cfg = await captchaConfig();
expect(cfg.provider).toBe("turnstile");
expect(cfg.siteKey).toBe("env-site-key");
expect(cfg.field).toBe("cf-turnstile-response");
});
it("lets an explicit DB value — including none — win over env", async () => {
mockGet.mockImplementation(async (key: string) => {
if (key === "captcha_provider") return "none";
return "";
});
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
const cfg = await captchaConfig();
expect(cfg.provider).toBe("none");
});
it("prefers the DB site key over the env one", async () => {
mockGet.mockImplementation(async (key: string) => {
if (key === "captcha_provider") return "turnstile";
if (key === "turnstile_site_key") return "db-site-key";
return "";
});
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
const cfg = await captchaConfig();
expect(cfg.siteKey).toBe("db-site-key");
});
it("verifies against the env secret when the DB secret is unset", async () => {
mockGet.mockResolvedValue("");
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
vi.stubEnv("TURNSTILE_SECRET_KEY", "env-secret");
const fetchMock = vi.fn().mockResolvedValue({
ok: true,
json: async () => ({ success: true }),
});
vi.stubGlobal("fetch", fetchMock);
expect(await verifyCaptcha("tok", "1.2.3.4")).toBe(true);
expect(fetchMock).toHaveBeenCalledOnce();
const [, init] = fetchMock.mock.calls[0];
expect((init.body as URLSearchParams).get("secret")).toBe("env-secret");
expect(fetchMock.mock.calls[0][0]).toBe(
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
);
});
it("fails closed when the provider comes from env but no secret exists", async () => {
mockGet.mockResolvedValue("");
vi.stubEnv("CAPTCHA_PROVIDER", "turnstile");
vi.stubEnv("TURNSTILE_SITE_KEY", "env-site-key");
expect(await verifyCaptcha("tok")).toBe(false);
});
});