/** * Shared test utilities for the form-component tests. Each form needs an * `` + `` wrap with controllable seams, * inside a `` so `useTranslation()` resolves. */ import { createI18n } from "@suaveplan/i18n/plugin"; import { TranslationProvider } from "@suaveplan/react-i18n"; import { lightTheme, ThemeProvider } from "@suaveplan/react-ui/theme"; import type { ReactNode } from "react"; import { AuthProvider } from "../../src/context/auth-context.js"; import { BrandingProvider } from "../../src/context/branding-context.js"; import type { AuthConfig, TenantBranding, } from "../../src/types/branding.types.js"; export interface FormFetchCall { url: string; init?: RequestInit; } export function makeFetch( handler: (call: FormFetchCall) => Response | Promise ): { fetch: ( input: string | URL | Request, init?: RequestInit ) => Promise; calls: FormFetchCall[]; } { const calls: FormFetchCall[] = []; return { calls, fetch: async (input, init) => { const url = typeof input === "string" ? input : input.toString(); calls.push({ url, init }); return handler({ url, init }); }, }; } export function jsonResponse(body: unknown, status = 200): Response { return new Response(JSON.stringify(body), { status, headers: { "Content-Type": "application/json" }, }); } export const FORM_TEST_BRANDING: TenantBranding = { tenantId: "test", name: "Test Co", primaryColor: "#3B82F6", secondaryColor: "#10B981", logo: "https://cdn/logo.svg", logoLight: "https://cdn/logo-light.svg", }; export interface FormWrapperOptions { authConfig?: Partial | undefined; navigated?: string[] | undefined; } const sharedI18n = createI18n({ defaultLocale: "en-GB", messages: { "en-GB": {} }, }); export function FormWrapper({ children, options = {}, }: { children: ReactNode; options?: FormWrapperOptions; }): ReactNode { const fetchImpl = options.authConfig?.fetch ?? makeFetch(() => jsonResponse({})).fetch; const navigate = options.authConfig?.navigate ?? ((url: string): void => { options.navigated?.push(url); }); const config: AuthConfig = { authUrl: "https://auth.example.com", ...options.authConfig, fetch: fetchImpl, navigate, }; return ( {children} ); }