diff --git a/__tests__/dispute-raise-modal.test.tsx b/__tests__/dispute-raise-modal.test.tsx new file mode 100644 index 0000000..24c25bf --- /dev/null +++ b/__tests__/dispute-raise-modal.test.tsx @@ -0,0 +1,924 @@ +/** + * Unit tests for DisputeRaiseModal + * + * Covers (issue #339): + * 1. Node rendering — modal open/closed guard + * 2. Empty-state node rendering (#333) — null milestoneIndex + * 3. Empty-state layout / design-token classes (#333) + * 4. Confirmation body — valid milestoneIndex + * 5. Milestone label helper (milestoneLabel) + * 6. ARIA attribute compliance (#330) + * - role="dialog", aria-modal, aria-labelledby, aria-describedby + * - role="alert" on warning banner + * - aria-label on action buttons + * - aria-disabled mirroring HTML disabled + * - aria-live="polite" on empty state + * - Escape key closes the modal + * - Backdrop click closes the modal + * 7. Interactive states / Tailwind classes (#331) + * - hover, focus-visible, disabled class presence + * - active:scale-[0.97] on action buttons + * - disabled:opacity-40, disabled:cursor-not-allowed + * 8. Action button behaviour + * - onConfirm / onClose callbacks + * - isPending disables both buttons and shows spinner label + * - no-handler (null milestoneIndex) disables confirm + * 9. Amount display + * 10. TxStatusBanner visibility + */ + +import { fireEvent, render, screen } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; +import DisputeRaiseModal, { + milestoneLabel, +} from "@/app/components/DisputeRaiseModal"; + +// --------------------------------------------------------------------------- +// Mocks — TxStatusBanner and ButtonSpinner are simple presentational +// components; we stub them to keep tests focused on DisputeRaiseModal logic. +// --------------------------------------------------------------------------- + +vi.mock("@/app/components/TxStatusBanner", () => ({ + default: ({ state, successMessage }: { state: { phase: string }; successMessage?: string }) => + state.phase !== "idle" ? ( +
+ {successMessage} +
+ ) : null, +})); + +vi.mock("@/app/components/ButtonSpinner", () => ({ + default: () =>