/** * InitiateConnectionDialog Component Tests * Following TDD - write tests first! */ import { describe, it, expect, vi } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import { InitiateConnectionDialog } from "./InitiateConnectionDialog"; describe("InitiateConnectionDialog", (): void => { const mockOnInitiate = vi.fn(); const mockOnCancel = vi.fn(); it("should render when open is true", (): void => { render( ); expect(screen.getByText(/connect to remote instance/i)).toBeInTheDocument(); }); it("should not render when open is false", (): void => { const { container } = render( ); expect(container.firstChild).toBeNull(); }); it("should render PDA-friendly title", (): void => { render( ); expect(screen.getByText(/connect to remote instance/i)).toBeInTheDocument(); }); it("should render PDA-friendly description", (): void => { render( ); expect(screen.getByText(/enter the url/i)).toBeInTheDocument(); }); it("should render URL input field", (): void => { render( ); expect(screen.getByLabelText(/instance url/i)).toBeInTheDocument(); }); it("should render Connect button", (): void => { render( ); expect(screen.getByRole("button", { name: /connect/i })).toBeInTheDocument(); }); it("should render Cancel button", (): void => { render( ); expect(screen.getByRole("button", { name: /cancel/i })).toBeInTheDocument(); }); it("should call onCancel when cancel button clicked", async (): Promise => { const user = userEvent.setup(); render( ); const cancelButton = screen.getByRole("button", { name: /cancel/i }); await user.click(cancelButton); expect(mockOnCancel).toHaveBeenCalledTimes(1); }); it("should call onInitiate with URL when connect button clicked", async (): Promise => { const user = userEvent.setup(); render( ); const urlInput = screen.getByLabelText(/instance url/i); await user.type(urlInput, "https://mosaic.example.com"); const connectButton = screen.getByRole("button", { name: /connect/i }); await user.click(connectButton); expect(mockOnInitiate).toHaveBeenCalledWith("https://mosaic.example.com"); }); it("should disable connect button when URL is empty", (): void => { render( ); const connectButton = screen.getByRole("button", { name: /connect/i }); expect(connectButton).toBeDisabled(); }); it("should enable connect button when URL is entered", async (): Promise => { const user = userEvent.setup(); render( ); const urlInput = screen.getByLabelText(/instance url/i); await user.type(urlInput, "https://mosaic.example.com"); const connectButton = screen.getByRole("button", { name: /connect/i }); expect(connectButton).not.toBeDisabled(); }); it("should show validation error for invalid URL", async (): Promise => { const user = userEvent.setup(); render( ); const urlInput = screen.getByLabelText(/instance url/i); await user.type(urlInput, "not-a-valid-url"); const connectButton = screen.getByRole("button", { name: /connect/i }); await user.click(connectButton); expect(screen.getByText(/please enter a valid url/i)).toBeInTheDocument(); }); it("should clear input when dialog is closed", async (): Promise => { const user = userEvent.setup(); const { rerender } = render( ); const urlInput = screen.getByLabelText(/instance url/i); await user.type(urlInput, "https://mosaic.example.com"); // Close dialog rerender( ); // Reopen dialog rerender( ); const newUrlInput = screen.getByLabelText(/instance url/i); expect(newUrlInput).toHaveValue(""); }); it("should show loading state when isLoading is true", (): void => { render( ); expect(screen.getByText(/connecting/i)).toBeInTheDocument(); }); it("should disable buttons when isLoading is true", (): void => { render( ); const connectButton = screen.getByRole("button", { name: /connecting/i }); const cancelButton = screen.getByRole("button", { name: /cancel/i }); expect(connectButton).toBeDisabled(); expect(cancelButton).toBeDisabled(); }); it("should display error message when error prop is provided", (): void => { render( ); expect(screen.getByText("Unable to connect to remote instance")).toBeInTheDocument(); }); });