11import { describe , it , expect , vi , beforeEach } from 'vitest' ;
2- import { render , screen , waitFor } from '@testing-library/react' ;
2+ import { act , render , screen , waitFor } from '@testing-library/react' ;
33import {
44 StreamFiProvider ,
55 useCancelStream ,
@@ -25,6 +25,12 @@ vi.mock('@conduit-protocol/sdk', () => ({
2525 ConduitClient : vi . fn ( function ( ) {
2626 return {
2727 streams : {
28+ get : vi . fn ( ) . mockResolvedValue ( {
29+ ratePerSecond : 5n ,
30+ startTime : 0 ,
31+ endTime : 100 ,
32+ withdrawn : 1n ,
33+ } ) ,
2834 withdraw : mockWithdraw ,
2935 cancel : mockCancel ,
3036 pause : mockPause ,
@@ -36,20 +42,23 @@ vi.mock('@conduit-protocol/sdk', () => ({
3642 } ) ,
3743} ) ) ;
3844
39- function LifecycleActions ( ) {
45+ function LifecycleActions ( { tokenBalance } : { tokenBalance ?: bigint | string } ) {
4046 const withdraw = useWithdrawStream ( 7n ) ;
4147 const cancel = useCancelStream ( 7n ) ;
4248 const pause = usePauseStream ( 7n ) ;
4349 const resume = useResumeStream ( 7n ) ;
44- const topUp = useTopUpStream ( 7n ) ;
50+ const topUp = useTopUpStream ( 7n , { tokenBalance } ) ;
4551
4652 return (
4753 < div >
4854 < button data-testid = "withdraw" onClick = { ( ) => withdraw . withdraw ( ) . catch ( ( ) => { } ) } > withdraw</ button >
4955 < button data-testid = "cancel" onClick = { ( ) => cancel . cancel ( ) . catch ( ( ) => { } ) } > cancel</ button >
56+ < button data-testid = "confirm-cancel" onClick = { ( ) => cancel . confirmCancel ( ) . catch ( ( ) => { } ) } > confirm cancel</ button >
5057 < button data-testid = "pause" onClick = { ( ) => pause . pause ( ) . catch ( ( ) => { } ) } > pause</ button >
5158 < button data-testid = "resume" onClick = { ( ) => resume . resume ( ) . catch ( ( ) => { } ) } > resume</ button >
5259 < button data-testid = "top-up" onClick = { ( ) => topUp . topUp ( '25' ) . catch ( ( ) => { } ) } > top up</ button >
60+ < div data-testid = "cancel-confirming" > { String ( cancel . isConfirming ) } </ div >
61+ < div data-testid = "cancel-settlement" > { String ( Boolean ( cancel . settlement ) ) } </ div >
5362 < div data-testid = "withdraw-hash" > { withdraw . txHash ?? '' } </ div >
5463 < div data-testid = "cancel-hash" > { cancel . txHash ?? '' } </ div >
5564 < div data-testid = "pause-hash" > { pause . txHash ?? '' } </ div >
@@ -101,26 +110,50 @@ describe('stream lifecycle hooks', () => {
101110 it ( 'wraps withdraw, cancel, pause, resume, and top up stream actions' , async ( ) => {
102111 render (
103112 < StreamFiProvider config = { { network : 'testnet' as const } } >
104- < LifecycleActions />
113+ < LifecycleActions tokenBalance = { 100n } />
105114 </ StreamFiProvider > ,
106115 ) ;
107116
108- screen . getByTestId ( 'withdraw' ) . click ( ) ;
109- screen . getByTestId ( 'cancel' ) . click ( ) ;
110- screen . getByTestId ( 'pause' ) . click ( ) ;
111- screen . getByTestId ( 'resume' ) . click ( ) ;
112- screen . getByTestId ( 'top-up' ) . click ( ) ;
117+ await act ( async ( ) => {
118+ screen . getByTestId ( 'withdraw' ) . click ( ) ;
119+ screen . getByTestId ( 'cancel' ) . click ( ) ;
120+ } ) ;
121+
122+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'cancel-confirming' ) ) . toHaveTextContent ( 'true' ) ) ;
123+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'cancel-settlement' ) ) . toHaveTextContent ( 'true' ) ) ;
124+
125+ await act ( async ( ) => {
126+ screen . getByTestId ( 'confirm-cancel' ) . click ( ) ;
127+ screen . getByTestId ( 'pause' ) . click ( ) ;
128+ screen . getByTestId ( 'resume' ) . click ( ) ;
129+ screen . getByTestId ( 'top-up' ) . click ( ) ;
130+ } ) ;
113131
114- await waitFor ( ( ) => expect ( screen . getByTestId ( 'withdraw-hash' ) ) . toHaveTextContent ( 'withdraw-tx' ) ) ;
115- expect ( screen . getByTestId ( 'cancel-hash' ) ) . toHaveTextContent ( 'cancel-tx' ) ;
116- expect ( screen . getByTestId ( 'pause-hash' ) ) . toHaveTextContent ( 'pause-tx' ) ;
117- expect ( screen . getByTestId ( 'resume-hash' ) ) . toHaveTextContent ( 'resume-tx' ) ;
118- expect ( screen . getByTestId ( 'top-up-hash' ) ) . toHaveTextContent ( 'top-up-tx' ) ;
132+ await waitFor ( ( ) => {
133+ expect ( screen . getByTestId ( 'withdraw-hash' ) ) . toHaveTextContent ( 'withdraw-tx' ) ;
134+ expect ( screen . getByTestId ( 'cancel-hash' ) ) . toHaveTextContent ( 'cancel-tx' ) ;
135+ expect ( screen . getByTestId ( 'pause-hash' ) ) . toHaveTextContent ( 'pause-tx' ) ;
136+ expect ( screen . getByTestId ( 'resume-hash' ) ) . toHaveTextContent ( 'resume-tx' ) ;
137+ expect ( screen . getByTestId ( 'top-up-hash' ) ) . toHaveTextContent ( 'top-up-tx' ) ;
138+ } ) ;
119139
120140 expect ( mockWithdraw ) . toHaveBeenCalledWith ( 7n , undefined ) ;
121141 expect ( mockCancel ) . toHaveBeenCalledWith ( 7n ) ;
122142 expect ( mockPause ) . toHaveBeenCalledWith ( 7n ) ;
123143 expect ( mockResume ) . toHaveBeenCalledWith ( 7n ) ;
124144 expect ( mockTopUp ) . toHaveBeenCalledWith ( 7n , 25n ) ;
125145 } ) ;
146+
147+ it ( 'throws before wallet submission when the top-up exceeds the available token balance' , async ( ) => {
148+ render (
149+ < StreamFiProvider config = { { network : 'testnet' as const } } >
150+ < LifecycleActions tokenBalance = { 10n } />
151+ </ StreamFiProvider > ,
152+ ) ;
153+
154+ screen . getByTestId ( 'top-up' ) . click ( ) ;
155+
156+ await waitFor ( ( ) => expect ( screen . getByTestId ( 'top-up-hash' ) ) . toHaveTextContent ( '' ) ) ;
157+ expect ( mockTopUp ) . not . toHaveBeenCalled ( ) ;
158+ } ) ;
126159} ) ;
0 commit comments