Files
WRNexusJS/services/managed-captcha/test/service.test.ts
2026-07-27 12:42:18 +05:30

102 lines
3.2 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import {
createCaptchaEngine,
MemoryCaptchaStore,
type CaptchaChallengeGenerator,
} from "@wrnexus/captcha/server";
import { ManagedCaptchaService } from "../src/service.ts";
let seed = 11;
function randomBytes(length: number): Uint8Array {
const output = new Uint8Array(length);
for (let index = 0; index < length; index += 1) {
seed = (seed * 1103515245 + 12345) >>> 0;
output[index] = seed & 255;
}
return output;
}
const generator: CaptchaChallengeGenerator = {
type: "number",
generate: () => ({
type: "number",
presentation: "visual",
prompt: "Enter 7",
answer: "7",
answerKind: "text",
inputMode: "numeric",
}),
};
describe("managed CAPTCHA service", () => {
test("creates a project and completes the public-to-server flow", async () => {
const service = new ManagedCaptchaService({
adminToken: "a-long-admin-token-for-managed-captcha-tests",
baseUrl: "https://captcha.test",
randomBytes,
engineFactory: (project) =>
createCaptchaEngine({
secret: project.engineSecret,
store: new MemoryCaptchaStore(),
generators: [generator],
defaultType: "number",
minCompletionMs: 0,
randomBytes,
}),
});
const project = await service.createProject({ name: "Test", allowedHostnames: ["app.test"] });
const created = await service.handle(
new Request("https://captcha.test/v1/challenges", {
method: "POST",
headers: { origin: "https://app.test", "content-type": "application/json" },
body: JSON.stringify({ siteKey: project.siteKey, action: "signup", type: "number" }),
}),
);
expect(created.status).toBe(201);
const challenge = (await created.json()) as { id: string; provider: string };
expect(challenge.provider).toBe("wrnexus-managed");
const solved = await service.handle(
new Request("https://captcha.test/v1/solve", {
method: "POST",
headers: { origin: "https://app.test", "content-type": "application/json" },
body: JSON.stringify({ challengeId: challenge.id, action: "signup", answer: "7" }),
}),
);
expect(solved.status).toBe(200);
const solution = (await solved.json()) as { responseToken: string };
const verified = await service.handle(
new Request("https://captcha.test/v1/verify", {
method: "POST",
headers: {
authorization: `Bearer ${project.secretKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
responseToken: solution.responseToken,
action: "signup",
hostname: "app.test",
}),
}),
);
expect(verified.status).toBe(200);
const replay = await service.handle(
new Request("https://captcha.test/v1/verify", {
method: "POST",
headers: {
authorization: `Bearer ${project.secretKey}`,
"content-type": "application/json",
},
body: JSON.stringify({
responseToken: solution.responseToken,
action: "signup",
hostname: "app.test",
}),
}),
);
expect(replay.status).toBe(400);
});
});