import assert from "node:assert/strict"; import { test } from "node:test"; import { verifyTurnstileToken } from "../lib/turnstile/server"; const request = new Request("https://anouma.org/api/test", { headers: { "x-forwarded-for": "203.0.113.10" }, }); test("Turnstile verification fails closed for missing configuration or token", async () => { const originalFetch = globalThis.fetch; let called = false; globalThis.fetch = async () => { called = true; throw new Error("fetch must not run"); }; try { delete process.env.TURNSTILE_SECRET_KEY; process.env.TURNSTILE_HOSTNAMES = "anouma.org"; assert.equal(await verifyTurnstileToken("token", "contact", request), false); process.env.TURNSTILE_SECRET_KEY = "test-secret"; assert.equal(await verifyTurnstileToken(undefined, "contact", request), false); assert.equal(called, false); } finally { globalThis.fetch = originalFetch; delete process.env.TURNSTILE_SECRET_KEY; delete process.env.TURNSTILE_HOSTNAMES; } }); test("Turnstile verification accepts the expected action and hostname", async () => { const originalFetch = globalThis.fetch; let receivedBody = ""; globalThis.fetch = async (_input, init) => { receivedBody = String(init?.body ?? ""); return new Response(JSON.stringify({ success: true, action: "contact", hostname: "anouma.org" }), { status: 200 }); }; try { process.env.TURNSTILE_SECRET_KEY = "test-secret"; process.env.TURNSTILE_HOSTNAMES = "anouma.org"; assert.equal(await verifyTurnstileToken("fresh-token", "contact", request), true); const params = new URLSearchParams(receivedBody); assert.equal(params.get("response"), "fresh-token"); assert.equal(params.get("secret"), "test-secret"); assert.equal(params.get("remoteip"), "203.0.113.10"); } finally { globalThis.fetch = originalFetch; delete process.env.TURNSTILE_SECRET_KEY; delete process.env.TURNSTILE_HOSTNAMES; } }); test("Turnstile verification rejects action, hostname, and upstream failures", async () => { const originalFetch = globalThis.fetch; process.env.TURNSTILE_SECRET_KEY = "test-secret"; process.env.TURNSTILE_HOSTNAMES = "anouma.org"; try { globalThis.fetch = async () => new Response(JSON.stringify({ success: true, action: "login", hostname: "anouma.org" }), { status: 200 }); assert.equal(await verifyTurnstileToken("token", "contact", request), false); globalThis.fetch = async () => new Response(JSON.stringify({ success: true, action: "contact", hostname: "evil.example" }), { status: 200 }); assert.equal(await verifyTurnstileToken("token", "contact", request), false); globalThis.fetch = async () => new Response("upstream error", { status: 503 }); assert.equal(await verifyTurnstileToken("token", "contact", request), false); } finally { globalThis.fetch = originalFetch; delete process.env.TURNSTILE_SECRET_KEY; delete process.env.TURNSTILE_HOSTNAMES; } });