FastAPI + Celery + Next.js + Postgres/Redis app with company monitoring, source collection, LLM-based change analysis, enrichment, and account security (Turnstile, escalating lockout, email verification).
56 lines
1.9 KiB
TypeScript
56 lines
1.9 KiB
TypeScript
import { act, render } from "@testing-library/react";
|
|
import { createRef } from "react";
|
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
import { TurnstileWidget, type TurnstileWidgetHandle } from "@/components/ui/turnstile-widget";
|
|
|
|
afterEach(() => {
|
|
delete (window as unknown as { turnstile?: unknown }).turnstile;
|
|
});
|
|
|
|
describe("TurnstileWidget", () => {
|
|
it("renders nothing when no site key is configured", () => {
|
|
const { container } = render(<TurnstileWidget siteKey={null} onToken={() => {}} />);
|
|
expect(container).toBeEmptyDOMElement();
|
|
});
|
|
|
|
it("renders via window.turnstile once the script loads, reports tokens, and resets", () => {
|
|
let capturedCallback: ((token: string) => void) | undefined;
|
|
const renderMock = vi.fn(
|
|
(_container: HTMLElement, options: { callback: (t: string) => void }) => {
|
|
capturedCallback = options.callback;
|
|
return "widget-1";
|
|
},
|
|
);
|
|
const resetMock = vi.fn();
|
|
const removeMock = vi.fn();
|
|
window.turnstile = { render: renderMock, reset: resetMock, remove: removeMock };
|
|
|
|
const onToken = vi.fn();
|
|
const ref = createRef<TurnstileWidgetHandle>();
|
|
|
|
render(<TurnstileWidget ref={ref} siteKey="test-site-key" onToken={onToken} />);
|
|
|
|
// jsdom never actually executes the remote Cloudflare script - simulate
|
|
// next/script's load detection by firing "load" on the tag it inserted.
|
|
const scriptEl = document.querySelector('script[src*="turnstile"]');
|
|
expect(scriptEl).not.toBeNull();
|
|
act(() => {
|
|
scriptEl?.dispatchEvent(new Event("load"));
|
|
});
|
|
|
|
expect(renderMock).toHaveBeenCalledTimes(1);
|
|
expect(renderMock.mock.calls[0]?.[1]).toMatchObject({
|
|
sitekey: "test-site-key",
|
|
action: "turnstile-spin-v2",
|
|
});
|
|
|
|
capturedCallback?.("fake-token");
|
|
expect(onToken).toHaveBeenCalledWith("fake-token");
|
|
|
|
act(() => {
|
|
ref.current?.reset();
|
|
});
|
|
expect(resetMock).toHaveBeenCalledWith("widget-1");
|
|
});
|
|
});
|