import { describe, expect, test } from "bun:test"; import { existsSync, readFileSync } from "node:fs"; import { join } from "node:path"; const showcaseRoot = join(import.meta.dir, ".."); const repositoryRoot = join(showcaseRoot, "..", ".."); const packageComponentPath = join( repositoryRoot, "packages", "captcha", "components", "Captcha.wrn", ); function path(relativePath: string): string { return join(showcaseRoot, relativePath); } function read(relativePath: string): string { return readFileSync(path(relativePath), "utf8"); } describe("CAPTCHA showcase structure", () => { test("ships the required pages, routes, middleware, and component", () => { const requiredFiles = [ "app/pages/index.wrn", "app/pages/captcha.wrn", "app/pages/protected.wrn", "app/pages/styles.wrn", "app/api/contact.ts", "app/api/page-grant.ts", "app/schemas/contact.ts", "app/lib/captcha.ts", "app/middleware/captcha-page-gate.ts", "app/styles/global.css", "wrnexus.config.ts", ]; for (const relativePath of requiredFiles) { expect(existsSync(path(relativePath))).toBe(true); } }); test("configures Tailwind and Lucide Iconify utilities", () => { const packageJson = read("package.json"); const styles = read("app/styles/global.css"); expect(packageJson).toContain('"@iconify-json/lucide"'); expect(packageJson).toContain('"@iconify/tailwind4"'); expect(styles).toContain('@plugin "@iconify/tailwind4";'); expect(styles).not.toContain("packages/captcha/components"); expect(read("wrnexus.config.ts")).not.toContain("includePackageSources: false"); }); test("documents every bundled challenge mode", () => { const source = read("app/pages/index.wrn"); const expectedExamples = [ 'type="number"', 'type="alpha"', 'type="alphanumeric"', 'type="calculation"', 'type="image"', 'type="timing"', 'type="not-robot"', 'presentation="audio"', 'presentation="invisible"', ]; for (const example of expectedExamples) { expect(source).toContain(example); } expect(source.match(/ { const source = read("app/pages/styles.wrn"); const styles = [ "classic", "collision", "snow", "corrosion", "spiderweb", "cross-shadow", "split", "split2", "cut", "darts", "distortion", "stitch", "striped", "wave", "grid-noise", "scribble", "pixel", "broken-lines", ]; for (const style of styles) { expect(source).toContain(`imageStyle="${style}"`); } expect(source).toContain('imageStyle="random"'); expect(source).toContain('allowedStyles="classic,snow,distortion,wave"'); expect(source).toContain('excludedStyles="collision,split,split2,broken-lines"'); expect(source).toContain('difficulty="easy"'); expect(source).toContain('difficulty="normal"'); expect(source).toContain('difficulty="hard"'); expect(source.match(/ { const source = read("app/pages/index.wrn"); expect(source).toContain('action="/api/contact"'); expect(source).toContain('data-schema="contact"'); expect(source).toContain('action="contact-submit"'); expect(source).toContain('data-error="email"'); expect(source).toContain('data-error="message"'); expect(source).toContain('provider="turnstile"'); expect(source).toContain('provider="recaptcha"'); expect(source).toContain('provider="hcaptcha"'); }); }); describe("CAPTCHA showcase integration", () => { test("configures the self-hosted engine and HTTP handlers", () => { const source = read("app/lib/captcha.ts"); expect(source).toContain("createCaptchaEngine"); expect(source).toContain("createCaptchaHttpHandlers"); expect(source).toContain('basePath: "/api/captcha"'); expect(source).toContain("challengeTtlMs: 2 * 60_000"); expect(source).toContain("responseTokenTtlMs: 5 * 60_000"); expect(source).toContain("maxAttempts: 3"); }); test("protects the contact form with a server-side guard", () => { const source = read("app/api/contact.ts"); expect(source).toContain("captchaGuard"); expect(source).toContain('action: "contact-submit"'); expect(source).toContain('responseField: "wrn-captcha-response"'); expect(source).toContain("bindHostname: true"); expect(source).toContain("bindSession: true"); expect(source).toContain("parseBody"); expect(source).toContain("contactSchema"); expect(source).toContain("ctx.req.clone()"); }); test("protects the page route with a session grant", () => { const middleware = read("app/middleware/captcha-page-gate.ts"); const challengePage = read("app/pages/captcha.wrn"); expect(middleware).toContain("captchaPageGate"); expect(middleware).toContain('action: "protected-page-access"'); expect(middleware).toContain('mode: "session"'); expect(middleware).toContain("verifiedForMs: 15 * 60_000"); expect(middleware).toContain('routeGroups: ["/protected"]'); expect(middleware).toContain('ctx.url.pathname === "/api/page-grant"'); expect(challengePage).toContain('action="protected-page-access"'); expect(challengePage).toContain('action="/api/page-grant"'); expect(challengePage).toContain('name="returnTo"'); expect(challengePage).toContain("value='{returnTo}'"); const grantRoute = read("app/api/page-grant.ts"); expect(grantRoute).toContain("safeReturnPath"); expect(grantRoute).toContain('form.get("returnTo")'); expect(grantRoute).toContain("Response.redirect"); }); test("auto-discovers the CAPTCHA package without manual plugin or script wiring", () => { const config = read("wrnexus.config.ts"); const packageJson = read("package.json"); const component = readFileSync(packageComponentPath, "utf8"); expect(packageJson).toContain('"@wrnexus/captcha": "workspace:*"'); expect(existsSync(path("app/components/Captcha.wrn"))).toBe(false); expect(existsSync(packageComponentPath)).toBe(true); expect(config).not.toContain("captchaPlugin"); expect(config).not.toContain("plugins:"); expect(component).toContain('data-wrnexus-runtime="captcha"'); expect(component).not.toContain(" { const source = readFileSync(packageComponentPath, "utf8"); const expectedEvents = [ "ready", "challenge", "input", "verify", "success", "failure", "expired", "refresh", "audioStart", "audioEnd", "error", ]; expect(source).toContain('name = "wrn-captcha-response"'); expect(source).toContain('responseField = "wrn-captcha-response"'); expect(source).toContain("disturbance = 50"); expect(source).toContain('size = "normal"'); expect(source).toContain("showListen = true"); expect(source).toContain('imageStyle = "random"'); expect(source).toContain('allowedStyles = ""'); expect(source).toContain('excludedStyles = ""'); expect(source).toContain("randomizeStyle = false"); expect(source).toContain("data-captcha-not-robot-button"); for (const eventName of expectedEvents) { expect(source).toContain(`@event ${eventName} = function`); } }); });