import "@testing-library/jest-dom"; import { fireEvent, render, screen, within } from "@testing-library/react"; import React from "react"; import { describe, expect, it, vi } from "vitest"; import { RegisterForm } from "./RegisterForm"; const routerState = vi.hoisted(() => ({ searchParams: new URLSearchParams(), })); vi.mock("react-router", async (importOriginal) => { const actual = await importOriginal(); return { ...actual, Form: ({ children, ...props }: React.FormHTMLAttributes) =>
{children}
, useLocation: () => ({ pathname: "/register" }), useMatches: () => [], useNavigation: () => ({ state: "idle" }), useSearchParams: () => [routerState.searchParams], }; }); vi.mock("react-i18next", () => ({ useTranslation: () => ({ i18n: { exists: () => true }, t: (key: string) => key, }), })); vi.mock("~/utils/data/useRootData", () => ({ useRootData: () => ({ csrf: "csrf-token", appConfiguration: { auth: { requireEmailVerification: false, requireName: false, requireOrganization: false, authMethods: { emailPassword: { enabled: true }, }, captcha: { enabled: false, instanceUrl: undefined, loginSiteKey: undefined, }, }, }, }), })); describe("RegisterForm", () => { it("posts redirectTo from inside the email-password form", () => { routerState.searchParams = new URLSearchParams({ redirect: "/app/acme/dashboard" }); render(); const form = document.querySelector('[data-ui-id="ui.auth.register.form"]'); expect(form).toBeInTheDocument(); expect(form?.querySelector('input[name="redirectTo"]')).toHaveValue("/app/acme/dashboard"); }); it("renders registration copy and localized password requirement labels", () => { routerState.searchParams = new URLSearchParams(); render( ); expect(document.querySelector('[data-ui-id="ui.auth.register.form"]')).toBeInTheDocument(); expect(screen.getByRole("button", { name: "account.register.prompts.register.title" })).toBeInTheDocument(); expect(screen.getByText("account.register.bySigningUp", { exact: false })).toBeInTheDocument(); expect(screen.getByRole("link", { name: "account.register.termsAndConditions" })).toHaveAttribute("href", "/terms-and-conditions"); expect(screen.getByRole("link", { name: "account.register.privacyPolicy" })).toHaveAttribute("href", "/privacy-policy"); const requirements = screen.getByRole("list"); expect(requirements).toHaveAccessibleName("account.register.passwordRequirements.label"); const items = within(requirements).getAllByRole("listitem"); expect(items.map((item) => item.textContent)).toEqual([ "[ ] account.register.passwordRequirements.minLength", "[ ] account.register.passwordRequirements.upper", "[ ] account.register.passwordRequirements.lower", "[ ] account.register.passwordRequirements.digit", "[ ] account.register.passwordRequirements.special", ]); expect(items[0]).toHaveAccessibleName("account.register.passwordRequirements.notMet: account.register.passwordRequirements.minLength"); fireEvent.change(screen.getByLabelText(/account\.shared\.password/), { target: { value: "Abcdef1!" } }); expect(items.map((item) => item.textContent)).toEqual([ "[x] account.register.passwordRequirements.minLength", "[x] account.register.passwordRequirements.upper", "[x] account.register.passwordRequirements.lower", "[x] account.register.passwordRequirements.digit", "[x] account.register.passwordRequirements.special", ]); expect(items[0]).toHaveAccessibleName("account.register.passwordRequirements.met: account.register.passwordRequirements.minLength"); }); it("keeps lead-conversion email locked while preserving hidden conversion fields", () => { routerState.searchParams = new URLSearchParams(); render( ); expect(screen.getByLabelText(/account\.shared\.email/)).toHaveAttribute("readonly"); expect(screen.getByLabelText(/account\.shared\.email/)).toHaveAttribute("type", "email"); expect(document.querySelector('input[name="leadId"]')).toHaveValue("lead_123"); expect(document.querySelector('input[name="leadToken"]')).toHaveValue("signed-token"); expect(document.querySelector('input[name="leadPlanId"]')).toHaveValue("plan_pro"); }); });