diff --git a/components/groups/modals/__tests__/voteDetailsModal.test.tsx b/components/groups/modals/__tests__/voteDetailsModal.test.tsx new file mode 100644 index 00000000..3035299c --- /dev/null +++ b/components/groups/modals/__tests__/voteDetailsModal.test.tsx @@ -0,0 +1,115 @@ +import { describe, test, expect, jest, mock, afterEach } from 'bun:test'; +import React from 'react'; +import { screen, fireEvent, cleanup, waitFor } from '@testing-library/react'; +import VoteDetailsModal from '../voteDetailsModal'; +import { + ProposalSDKType, + MemberSDKType, + VoteSDKType, + ProposalStatus, + ProposalExecutorResult, +} from '@liftedinit/manifestjs/dist/codegen/cosmos/group/v1/types'; +import { QueryTallyResultResponseSDKType } from '@liftedinit/manifestjs/dist/codegen/cosmos/group/v1/query'; +import matchers from '@testing-library/jest-dom/matchers'; +import { renderWithChainProvider } from '@/tests/render'; +import { + manifestAddr1, + mockGroupFormData, + mockMembers, + mockProposals, + mockTally, + mockVotes, +} from '@/tests/mock'; + +expect.extend(matchers); + +mock.module('react-apexcharts', () => ({ + default: jest.fn(), +})); + +mock.module('@cosmos-kit/react', () => ({ + useChain: jest.fn().mockReturnValue({ + address: mockProposals['test_policy_address'][0].proposers[0], + chain: { fees: null }, + }), +})); + +const mockProposal = mockProposals['test_policy_address'][0]; + +describe('VoteDetailsModal', () => { + const defaultProps = { + tallies: mockTally, + votes: mockVotes, + members: mockMembers, + proposal: mockProposal, + onClose: jest.fn(), + modalId: 'voteDetailsModal', + refetchVotes: jest.fn(), + refetchTally: jest.fn(), + refetchProposals: jest.fn(), + }; + + afterEach(() => { + mock.restore(); + cleanup(); + }); + + test('renders the component with provided props', () => { + renderWithChainProvider(); + expect(screen.getByText(`#${mockProposal.id.toString()}`)).toBeInTheDocument(); + expect(screen.getByText(mockProposal.title)).toBeInTheDocument(); + expect(screen.getByText('SUMMARY')).toBeInTheDocument(); + expect(screen.getByText(mockProposal.summary)).toBeInTheDocument(); + }); + + test('renders the tally chart', () => { + renderWithChainProvider(); + expect(screen.getByLabelText('chart-tally')).toBeInTheDocument(); + }); + + test('renders voting countdown timer', () => { + renderWithChainProvider(); + expect(screen.getByLabelText('voting-countdown-1')).toBeInTheDocument(); + expect(screen.getByLabelText('voting-countdown-2')).toBeInTheDocument(); + }); + + test('renders messages section with correct data', () => { + renderWithChainProvider(); + expect(screen.getByText('MESSAGES')).toBeInTheDocument(); + expect(screen.getByText('Send')).toBeInTheDocument(); + expect(screen.getByText('from_address:')).toBeInTheDocument(); + expect(screen.getByText('to_address:')).toBeInTheDocument(); + }); + + test('conditionally renders execute button when proposal is accepted', () => { + const props = { + ...defaultProps, + proposal: { + ...mockProposal, + status: 'PROPOSAL_STATUS_ACCEPTED', + executor_result: 'PROPOSAL_EXECUTOR_RESULT_NOT_RUN', + }, + }; + renderWithChainProvider(); + expect(screen.getByText('Execute')).toBeInTheDocument(); + }); + + test('conditionally renders vote button when proposal is open and user has not voted', () => { + renderWithChainProvider(); + expect(screen.getByText('Vote')).toBeInTheDocument(); + }); + + test('does not render vote button when user has already voted', () => { + const props = { ...defaultProps, votes: [{ ...mockVotes[0], voter: 'proposer1' }] }; + renderWithChainProvider(); + const btn = screen.getByLabelText('action-btn'); + expect(btn.textContent).not.toBe('Vote'); + }); + + test('handles vote button click and opens voting modal', async () => { + renderWithChainProvider(); + const voteButton = screen.getByText('Vote'); + fireEvent.click(voteButton); + await waitFor(() => expect(screen.getByLabelText('vote-modal')).toBeInTheDocument()); + }); +}); diff --git a/components/groups/modals/voteDetailsModal.tsx b/components/groups/modals/voteDetailsModal.tsx index e6aa8d76..5c9f6025 100644 --- a/components/groups/modals/voteDetailsModal.tsx +++ b/components/groups/modals/voteDetailsModal.tsx @@ -497,7 +497,7 @@ function VoteDetailsModal({ })} -
+

VOTING COUNTDOWN

@@ -508,7 +508,7 @@ function VoteDetailsModal({

TALLY

-
+
@@ -556,7 +556,7 @@ function VoteDetailsModal({
-
+

VOTING COUNTDOWN

@@ -565,6 +565,7 @@ function VoteDetailsModal({
{getButtonState.action && (