1+ import { render , screen , fireEvent } from '@testing-library/react' ;
2+ import { PayoutUI } from '../PayoutUI' ;
3+ import { useEscrowPayout } from '@/hooks/useEscrowPayout' ;
4+
5+ // Mock the useEscrowPayout hook
6+ jest . mock ( '@/hooks/useEscrowPayout' ) ;
7+ const mockedUseEscrowPayout = useEscrowPayout as jest . Mock ;
8+
9+ describe ( 'PayoutUI' , ( ) => {
10+ const mockEscrowId = 'escrow-123' ;
11+ const mockReleaseFunds = jest . fn ( ) ;
12+
13+ beforeEach ( ( ) => {
14+ // Reset mock before each test
15+ mockedUseEscrowPayout . mockClear ( ) ;
16+ mockReleaseFunds . mockClear ( ) ;
17+ } ) ;
18+
19+ it ( 'should render loading state' , ( ) => {
20+ mockedUseEscrowPayout . mockReturnValue ( {
21+ isLoading : true ,
22+ error : null ,
23+ requiredSignatures : 0 ,
24+ currentSignatures : 0 ,
25+ canRelease : false ,
26+ releaseFunds : mockReleaseFunds ,
27+ } ) ;
28+
29+ render ( < PayoutUI escrowId = { mockEscrowId } /> ) ;
30+ expect ( screen . getByLabelText ( 'Loading payout UI' ) ) . toBeInTheDocument ( ) ;
31+ } ) ;
32+
33+ it ( 'should render error state' , ( ) => {
34+ mockedUseEscrowPayout . mockReturnValue ( {
35+ isLoading : false ,
36+ error : 'Failed to fetch escrow details' ,
37+ requiredSignatures : 0 ,
38+ currentSignatures : 0 ,
39+ canRelease : false ,
40+ releaseFunds : mockReleaseFunds ,
41+ } ) ;
42+
43+ render ( < PayoutUI escrowId = { mockEscrowId } /> ) ;
44+ expect ( screen . getByRole ( 'alert' ) ) . toHaveTextContent (
45+ 'Error: Failed to fetch escrow details' ,
46+ ) ;
47+ } ) ;
48+
49+ it ( 'should disable the "Release Funds" button when signatures are below threshold (1 of 2)' , ( ) => {
50+ mockedUseEscrowPayout . mockReturnValue ( {
51+ isLoading : false ,
52+ error : null ,
53+ requiredSignatures : 2 ,
54+ currentSignatures : 1 ,
55+ canRelease : false ,
56+ releaseFunds : mockReleaseFunds ,
57+ } ) ;
58+
59+ render ( < PayoutUI escrowId = { mockEscrowId } /> ) ;
60+
61+ const releaseButton = screen . getByRole ( 'button' , { name : 'Release Funds' } ) ;
62+ expect ( releaseButton ) . toBeDisabled ( ) ;
63+ expect ( screen . getByText ( 'Signatures: 1 / 2' ) ) . toBeInTheDocument ( ) ;
64+
65+ // Assert that clicking the disabled button throws no exceptions and does not call releaseFunds
66+ fireEvent . click ( releaseButton ) ;
67+ expect ( mockReleaseFunds ) . not . toHaveBeenCalled ( ) ;
68+ } ) ;
69+
70+ it ( 'should enable the "Release Funds" button when signatures meet the threshold (2 of 2)' , ( ) => {
71+ mockedUseEscrowPayout . mockReturnValue ( {
72+ isLoading : false ,
73+ error : null ,
74+ requiredSignatures : 2 ,
75+ currentSignatures : 2 ,
76+ canRelease : true ,
77+ releaseFunds : mockReleaseFunds ,
78+ } ) ;
79+
80+ render ( < PayoutUI escrowId = { mockEscrowId } /> ) ;
81+
82+ const releaseButton = screen . getByRole ( 'button' , { name : 'Release Funds' } ) ;
83+ expect ( releaseButton ) . not . toBeDisabled ( ) ;
84+ expect ( screen . getByText ( 'Signatures: 2 / 2' ) ) . toBeInTheDocument ( ) ;
85+
86+ fireEvent . click ( releaseButton ) ;
87+ expect ( mockReleaseFunds ) . toHaveBeenCalledTimes ( 1 ) ;
88+ } ) ;
89+ } ) ;
0 commit comments