import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { describe, expect, it, vi, beforeEach } from "vitest"; import { createRoutesStub } from "react-router"; import { useState } from "react"; import { InformationRequestForm, RequestType, } from "#/components/features/onboarding/information-request-form"; import { EnterpriseFormData } from "#/utils/local-storage"; vi.mock("#/hooks/use-client-analytics", () => ({ useClientAnalytics: () => ({ trackSaasSelfhostedInquiry: vi.fn(), trackEnterpriseLeadFormSubmitted: vi.fn(), }), })); const mockOnBack = vi.fn(); // Wrapper to manage form state (needed since component is controlled) function StatefulForm({ requestType }: { requestType: RequestType }) { const [formData, setFormData] = useState({ name: "", company: "", email: "", message: "" }); return ; } describe("InformationRequestForm", () => { const defaultProps = { requestType: "saas" as RequestType, }; beforeEach(() => { vi.clearAllMocks(); mockOnBack.mockClear(); }); const renderWithRouter = (props = defaultProps) => { const Stub = createRoutesStub([ { path: "/", Component: () => , }, { path: "/login", Component: () =>
, }, { path: "/information-request", Component: () =>
, }, ]); return render(); }; it("should render the form", () => { renderWithRouter(); expect(screen.getByTestId("information-request-form")).toBeInTheDocument(); }); it("should render the logo", () => { renderWithRouter(); const logo = screen.getByTestId("information-request-form").querySelector("svg"); expect(logo).toBeInTheDocument(); }); it("should render all form fields", () => { renderWithRouter(); expect(screen.getByTestId("form-input-name")).toBeInTheDocument(); expect(screen.getByTestId("form-input-company")).toBeInTheDocument(); expect(screen.getByTestId("form-input-email")).toBeInTheDocument(); expect(screen.getByTestId("form-input-message")).toBeInTheDocument(); }); it("should render SaaS-specific title when requestType is saas", () => { renderWithRouter({ ...defaultProps, requestType: "saas" }); expect(screen.getByText("ENTERPRISE$FORM_SAAS_TITLE")).toBeInTheDocument(); }); it("should render Self-hosted-specific title when requestType is self-hosted", () => { renderWithRouter({ ...defaultProps, requestType: "self-hosted" }); expect(screen.getByText("ENTERPRISE$FORM_SELF_HOSTED_TITLE")).toBeInTheDocument(); }); it("should render cloud icon for SaaS request type", () => { renderWithRouter({ ...defaultProps, requestType: "saas" }); // The card should contain the cloud icon const card = screen.getByText("ENTERPRISE$SAAS_TITLE").closest("div"); expect(card).toBeInTheDocument(); }); it("should render stacked icon for self-hosted request type", () => { renderWithRouter({ ...defaultProps, requestType: "self-hosted" }); // The card should contain the stacked icon const card = screen.getByText("ENTERPRISE$SELF_HOSTED_TITLE").closest("div"); expect(card).toBeInTheDocument(); }); it("should call onBack when back button is clicked", async () => { const user = userEvent.setup(); renderWithRouter(); const backButton = screen.getByRole("button", { name: "COMMON$BACK" }); await user.click(backButton); expect(mockOnBack).toHaveBeenCalledTimes(1); }); it("should update form fields when user types", async () => { const user = userEvent.setup(); renderWithRouter(); const nameInput = screen.getByTestId("form-input-name"); await user.type(nameInput, "John Doe"); expect(nameInput).toHaveValue("John Doe"); }); it("should update email field when user types", async () => { const user = userEvent.setup(); renderWithRouter(); const emailInput = screen.getByTestId("form-input-email"); await user.type(emailInput, "john@example.com"); expect(emailInput).toHaveValue("john@example.com"); }); it("should render message as textarea", () => { renderWithRouter(); const messageInput = screen.getByTestId("form-input-message"); expect(messageInput.tagName).toBe("TEXTAREA"); }); it("should have all fields marked as required", () => { renderWithRouter(); expect(screen.getByTestId("form-input-name")).toBeRequired(); expect(screen.getByTestId("form-input-company")).toBeRequired(); expect(screen.getByTestId("form-input-email")).toBeRequired(); expect(screen.getByTestId("form-input-message")).toBeRequired(); }); it("should render submit button", () => { renderWithRouter(); const submitButton = screen.getByRole("button", { name: "ENTERPRISE$FORM_SUBMIT" }); expect(submitButton).toBeInTheDocument(); expect(submitButton).toHaveAttribute("type", "submit"); }); it("should render back button", () => { renderWithRouter(); const backButton = screen.getByRole("button", { name: "COMMON$BACK" }); expect(backButton).toBeInTheDocument(); expect(backButton).toHaveAttribute("type", "button"); }); it("should have button group with role and aria-label", () => { renderWithRouter(); const buttonGroup = screen.getByRole("group", { name: "Form actions" }); expect(buttonGroup).toBeInTheDocument(); }); it("should display SaaS card description for saas request type", () => { renderWithRouter({ ...defaultProps, requestType: "saas" }); expect(screen.getByText("ENTERPRISE$SAAS_DESCRIPTION")).toBeInTheDocument(); }); it("should display Self-hosted card description for self-hosted request type", () => { renderWithRouter({ ...defaultProps, requestType: "self-hosted" }); expect(screen.getByText("ENTERPRISE$SELF_HOSTED_DESCRIPTION")).toBeInTheDocument(); }); describe("form validation", () => { it("should not show error state before form submission", () => { renderWithRouter(); const nameInput = screen.getByTestId("form-input-name"); const companyInput = screen.getByTestId("form-input-company"); const emailInput = screen.getByTestId("form-input-email"); const messageInput = screen.getByTestId("form-input-message"); expect(nameInput).toHaveAttribute("aria-invalid", "false"); expect(companyInput).toHaveAttribute("aria-invalid", "false"); expect(emailInput).toHaveAttribute("aria-invalid", "false"); expect(messageInput).toHaveAttribute("aria-invalid", "false"); }); it("should not navigate when form is submitted with empty fields", async () => { const user = userEvent.setup(); renderWithRouter(); const submitButton = screen.getByRole("button", { name: "ENTERPRISE$FORM_SUBMIT", }); await user.click(submitButton); // Should stay on form page, not navigate to login expect(screen.getByTestId("information-request-form")).toBeInTheDocument(); expect(screen.queryByTestId("login-page")).not.toBeInTheDocument(); }); it("should navigate to login page when form is submitted with all fields filled", async () => { const user = userEvent.setup(); renderWithRouter(); await user.type(screen.getByTestId("form-input-name"), "John Doe"); await user.type(screen.getByTestId("form-input-company"), "Acme Inc"); await user.type(screen.getByTestId("form-input-email"), "john@example.com"); await user.type(screen.getByTestId("form-input-message"), "Hello world"); const submitButton = screen.getByRole("button", { name: "ENTERPRISE$FORM_SUBMIT", }); await user.click(submitButton); // Should navigate to login page expect(screen.getByTestId("login-page")).toBeInTheDocument(); }); it("should have valid aria-invalid state when field has value", async () => { const user = userEvent.setup(); renderWithRouter(); const nameInput = screen.getByTestId("form-input-name"); await user.type(nameInput, "John Doe"); // Field with value should not be invalid expect(nameInput).toHaveAttribute("aria-invalid", "false"); }); it("should not navigate when email is invalid", async () => { const user = userEvent.setup(); renderWithRouter(); await user.type(screen.getByTestId("form-input-name"), "John Doe"); await user.type(screen.getByTestId("form-input-company"), "Acme Inc"); await user.type(screen.getByTestId("form-input-email"), "invalid-email"); await user.type(screen.getByTestId("form-input-message"), "Hello world"); const submitButton = screen.getByRole("button", { name: "ENTERPRISE$FORM_SUBMIT", }); await user.click(submitButton); // Should stay on form page, not navigate to login expect(screen.getByTestId("information-request-form")).toBeInTheDocument(); expect(screen.queryByTestId("login-page")).not.toBeInTheDocument(); }); }); describe("loading state", () => { it("should prevent double submission", async () => { const user = userEvent.setup(); renderWithRouter(); await user.type(screen.getByTestId("form-input-name"), "John Doe"); await user.type(screen.getByTestId("form-input-company"), "Acme Inc"); await user.type(screen.getByTestId("form-input-email"), "john@example.com"); await user.type(screen.getByTestId("form-input-message"), "Hello world"); const submitButton = screen.getByRole("button", { name: "ENTERPRISE$FORM_SUBMIT", }); // Click multiple times rapidly await user.click(submitButton); await user.click(submitButton); await user.click(submitButton); // Should navigate to login page expect(screen.getByTestId("login-page")).toBeInTheDocument(); }); }); });