/** * Turnstile Testing Configuration * * Use dummy sitekeys and secret keys for automated testing * to avoid hitting rate limits and ensure predictable behavior. * * Official Docs: https://developers.cloudflare.com/turnstile/troubleshooting/testing/ */ /** * Dummy Sitekeys (Client-Side) * * These can be used from any domain, including localhost. * Production secret keys will reject dummy tokens. */ export const TEST_SITEKEYS = { /** Always passes - visible widget */ ALWAYS_PASS: '1x00000000000000000000AA', /** Always blocks - visible widget */ ALWAYS_BLOCK: '2x00000000000000000000AB', /** Always passes - invisible widget */ ALWAYS_PASS_INVISIBLE: '1x00000000000000000000BB', /** Always blocks - invisible widget */ ALWAYS_BLOCK_INVISIBLE: '2x00000000000000000000BB', /** Forces an interactive challenge - visible widget */ FORCE_INTERACTIVE: '3x00000000000000000000FF', } as const /** * Dummy Secret Keys (Server-Side) * * These only accept the dummy token XXXX.DUMMY.TOKEN.XXXX * Real tokens will fail validation with these keys. */ export const TEST_SECRET_KEYS = { /** Always returns success: true */ ALWAYS_PASS: '1x0000000000000000000000000000000AA', /** Always returns success: false */ ALWAYS_FAIL: '2x0000000000000000000000000000000AA', /** Returns "token already spent" error */ TOKEN_SPENT: '3x0000000000000000000000000000000AA', } as const /** * Dummy Token * * Generated by test sitekeys. * Only valid with test secret keys. */ export const DUMMY_TOKEN = 'XXXX.DUMMY.TOKEN.XXXX' /** * Environment Detection * * Helper to determine if we're in a test environment */ export function isTestEnvironment(request: Request): boolean { // Check for test headers if (request.headers.get('x-test-environment') === 'true') { return true } // Check for localhost/test IPs const ip = request.headers.get('CF-Connecting-IP') || '' const testIPs = ['127.0.0.1', '::1', 'localhost'] if (testIPs.includes(ip)) { return true } // Check for test query parameter const url = new URL(request.url) if (url.searchParams.get('test') === 'true') { return true } return false } /** * Get Test Credentials * * Returns test or production credentials based on environment */ export function getTurnstileCredentials( request: Request, env: { TURNSTILE_SITE_KEY?: string TURNSTILE_SECRET_KEY?: string } ) { if (isTestEnvironment(request)) { return { sitekey: TEST_SITEKEYS.ALWAYS_PASS, secretKey: TEST_SECRET_KEYS.ALWAYS_PASS, } } return { sitekey: env.TURNSTILE_SITE_KEY || '', secretKey: env.TURNSTILE_SECRET_KEY || '', } } /** * Playwright Test Example */ /* // playwright.config.ts export default { use: { baseURL: 'http://localhost:5173', extraHTTPHeaders: { 'x-test-environment': 'true', }, }, } // test/turnstile.spec.ts import { test, expect } from '@playwright/test' test('form submission with Turnstile', async ({ page }) => { await page.goto('/contact') // Fill form await page.fill('input[name="email"]', 'test@example.com') await page.fill('textarea[name="message"]', 'Test message') // Turnstile auto-solves with dummy token in test mode await page.click('button[type="submit"]') // Verify success await expect(page.locator('.success-message')).toBeVisible() }) */ /** * Cypress Test Example */ /* // cypress/e2e/turnstile.cy.ts describe('Turnstile Form', () => { beforeEach(() => { // Set test header cy.intercept('**', (req) => { req.headers['x-test-environment'] = 'true' }) }) it('submits form successfully', () => { cy.visit('/contact') cy.get('input[name="email"]').type('test@example.com') cy.get('textarea[name="message"]').type('Test message') // Turnstile auto-solves in test mode cy.get('button[type="submit"]').click() cy.contains('Success').should('be.visible') }) }) */ /** * Jest Mock Example */ /* // jest.setup.ts jest.mock('@marsidev/react-turnstile', () => ({ Turnstile: ({ onSuccess }: { onSuccess: (token: string) => void }) => { // Auto-solve with dummy token React.useEffect(() => { onSuccess('XXXX.DUMMY.TOKEN.XXXX') }, [onSuccess]) return
}, })) // component.test.tsx import { render, screen, fireEvent } from '@testing-library/react' import { ContactForm } from './ContactForm' test('submits form with Turnstile', async () => { render(