71 lines
2.2 KiB
TypeScript
71 lines
2.2 KiB
TypeScript
import { describe, expect, test } from "bun:test";
|
|
import { createCaptchaHttpHandlers } from "../src/http.ts";
|
|
import type { CaptchaEngine } from "../src/types.ts";
|
|
|
|
const engine: CaptchaEngine = {
|
|
provider: "self-hosted",
|
|
basePath: "/api/captcha",
|
|
async create(options) {
|
|
return {
|
|
id: "c1",
|
|
provider: "self-hosted",
|
|
type: "number",
|
|
presentation: "visual",
|
|
action: options.action,
|
|
prompt: "Enter 1",
|
|
createdAt: 1,
|
|
expiresAt: 2,
|
|
responseField: "wrn-captcha-response",
|
|
};
|
|
},
|
|
async verify(input) {
|
|
return {
|
|
success: input.answer === "1",
|
|
provider: "self-hosted",
|
|
action: input.action,
|
|
code: input.answer === "1" ? undefined : "incorrect-answer",
|
|
};
|
|
},
|
|
async verifyResponseToken(input) {
|
|
return { success: true, provider: "self-hosted", action: input.action };
|
|
},
|
|
async renderAudio() {
|
|
return { bytes: new Uint8Array([1, 2, 3]), contentType: "audio/wav" };
|
|
},
|
|
async gc() {},
|
|
};
|
|
|
|
describe("CAPTCHA HTTP handlers", () => {
|
|
test("creates and verifies same-origin challenges", async () => {
|
|
const handlers = createCaptchaHttpHandlers(engine);
|
|
const created = await handlers.handle(
|
|
new Request("https://example.test/api/captcha/challenge", {
|
|
method: "POST",
|
|
headers: { origin: "https://example.test", "content-type": "application/json" },
|
|
body: JSON.stringify({ action: "signup" }),
|
|
}),
|
|
);
|
|
expect(created?.status).toBe(201);
|
|
const verified = await handlers.handle(
|
|
new Request("https://example.test/api/captcha/verify", {
|
|
method: "POST",
|
|
headers: { origin: "https://example.test", "content-type": "application/json" },
|
|
body: JSON.stringify({ action: "signup", answer: "1" }),
|
|
}),
|
|
);
|
|
expect(verified?.status).toBe(200);
|
|
});
|
|
|
|
test("rejects cross-origin requests", async () => {
|
|
const handlers = createCaptchaHttpHandlers(engine);
|
|
const response = await handlers.create(
|
|
new Request("https://example.test/api/captcha/challenge", {
|
|
method: "POST",
|
|
headers: { origin: "https://evil.test", "content-type": "application/json" },
|
|
body: "{}",
|
|
}),
|
|
);
|
|
expect(response.status).toBe(403);
|
|
});
|
|
});
|