@@ -20,7 +20,34 @@ import { DiscreetModeFeatureProvider } from '../../features/discreet-mode';
2020import { BrowserLocalStorageBridge } from '../../features/local-storage' ;
2121import { HwDeviceStatuses } from '../../domains/Wallet' ;
2222import WalletTokenPicker from './tokens/wallet-token-picker/WalletTokenPicker' ;
23- import WalletSendForm from './WalletSendForm' ;
23+ import WalletSendForm , { FormData } from './WalletSendForm' ;
24+
25+ jest . mock (
26+ '../../containers/wallet/dialogs/send-confirmation/SendConfirmation.container' ,
27+ ( ) => {
28+ function Dialog ( {
29+ amount,
30+ formattedTotalAmount,
31+ } : {
32+ amount : number ;
33+ formattedTotalAmount : number ;
34+ } ) {
35+ return (
36+ < div >
37+ < span data-testid = "confirmation-dialog-ada-amount" > { amount } </ span >
38+ < span data-testid = "confirmation-dialog-total-amount" >
39+ { formattedTotalAmount }
40+ </ span >
41+ </ div >
42+ ) ;
43+ }
44+
45+ return {
46+ __esModule : true ,
47+ WalletSendConfirmationDialogContainer : Dialog ,
48+ } ;
49+ }
50+ ) ;
2451
2552describe ( 'wallet/Wallet Send Form' , ( ) => {
2653 beforeEach ( ( ) => addLocaleData ( [ ...en ] ) ) ;
@@ -50,11 +77,21 @@ describe('wallet/Wallet Send Form', () => {
5077 function SetupWallet ( {
5178 calculateTransactionFee,
5279 currentNumberFormat = NUMBER_OPTIONS [ 0 ] . value ,
80+ validationDebounceWait,
81+ validateAmount = jest . fn ( ) . mockResolvedValue ( true ) ,
82+ onTransactionFeeChange = jest . fn ( ) ,
5383 } : {
5484 calculateTransactionFee : ( ...args : Array < any > ) => any ;
85+ validateAmount ?: ( amount : string ) => Promise < boolean > ;
5586 currentNumberFormat ?: string ;
87+ validationDebounceWait ?: number ;
88+ onTransactionFeeChange ?: ( ) => Promise < void > ;
5689 } ) {
5790 const [ tokenPickerOpen , setTokenPickerOpen ] = useState < boolean > ( false ) ;
91+ const [ state , setState ] = useState < {
92+ isDialogOpen : boolean ;
93+ formData : FormData ;
94+ } > ( { isDialogOpen : false , formData : null } ) ;
5895
5996 return (
6097 < TestDecorator >
@@ -65,15 +102,18 @@ describe('wallet/Wallet Send Form', () => {
65102 currencyMaxFractionalDigits = { currencyMaxFractionalDigits }
66103 currencyMaxIntegerDigits = { 11 }
67104 currentNumberFormat = { currentNumberFormat }
68- validateAmount = { jest . fn ( ) . mockResolvedValue ( true ) }
105+ validateAmount = { validateAmount }
69106 validateAssetAmount = { jest . fn ( ) . mockResolvedValue ( true ) }
70107 calculateTransactionFee = { calculateTransactionFee }
71108 walletAmount = { new BigNumber ( 123 ) }
72109 assets = { assets }
73110 addressValidator = { ( ) => true }
74- onSubmit = { jest . fn ( ) }
111+ onSubmit = { ( formData ) =>
112+ setState ( { isDialogOpen : true , formData } )
113+ }
75114 isDialogOpen = { ( dialog ) =>
76- dialog === WalletTokenPicker && tokenPickerOpen
115+ ( dialog === WalletTokenPicker && tokenPickerOpen ) ||
116+ state . isDialogOpen
77117 }
78118 isRestoreActive = { false }
79119 hwDeviceStatus = { HwDeviceStatuses . READY }
@@ -88,6 +128,9 @@ describe('wallet/Wallet Send Form', () => {
88128 walletName = { faker . name . firstName ( ) }
89129 onTokenPickerDialogClose = { ( ) => setTokenPickerOpen ( false ) }
90130 onTokenPickerDialogOpen = { ( ) => setTokenPickerOpen ( true ) }
131+ confirmationDialogData = { state . formData }
132+ validationDebounceWait = { validationDebounceWait }
133+ onTransactionFeeChange = { onTransactionFeeChange }
91134 />
92135 </ MobxProvider >
93136 </ DiscreetModeFeatureProvider >
@@ -185,6 +228,18 @@ describe('wallet/Wallet Send Form', () => {
185228 ) ;
186229 }
187230
231+ function sleep ( ms ) {
232+ return new Promise ( ( resolve ) => {
233+ setTimeout ( resolve , ms ) ;
234+ } ) ;
235+ }
236+
237+ async function waitForTransactionFee ( ) {
238+ const transactionFeeSpinner = screen . getByTestId ( 'transaction-fee-spinner' ) ;
239+
240+ return waitForElementToBeRemoved ( transactionFeeSpinner ) ;
241+ }
242+
188243 test ( 'should update Ada input field to minimum required and restore to original value when tokens are removed' , async ( ) => {
189244 expect . assertions ( 4 ) ;
190245
@@ -415,4 +470,153 @@ describe('wallet/Wallet Send Form', () => {
415470 assertAdaInput ( minimumAda ) ;
416471 assertMinimumAmountNoticeMessage ( minimumAda ) ;
417472 } ) ;
473+
474+ type Cases = [
475+ Array < [ number , number ] > ,
476+ [ number , number ] ,
477+ Array < [ number , number ] > ,
478+ [ string , string , number ]
479+ ] ;
480+
481+ const cases : Cases [ ] = [
482+ [
483+ // ada inputs [delay, value]
484+ [
485+ [ 0 , 2.5 ] ,
486+ [ 0 , 1.5 ] ,
487+ ] ,
488+ // validate amount [delay]
489+ [ 50 , 5 ] ,
490+ // fee calculation [delay, value]
491+ [
492+ [ 50 , 2 ] ,
493+ [ 0 , 1 ] ,
494+ ] ,
495+ [ '1.500000' , '3.500000' , 1 ] ,
496+ ] ,
497+ [
498+ [
499+ [ 0 , 2.5 ] ,
500+ [ 0 , 1.5 ] ,
501+ ] ,
502+ [ 0 , 0 ] ,
503+ [
504+ [ 0 , 1 ] ,
505+ [ 0 , 2 ] ,
506+ ] ,
507+ [ '1.500000' , '3.500000' , 1 ] ,
508+ ] ,
509+ [
510+ [
511+ [ 50 , 2.5 ] ,
512+ [ 0 , 1.5 ] ,
513+ ] ,
514+ [ 0 , 0 ] ,
515+ [
516+ [ 0 , 1 ] ,
517+ [ 0 , 2 ] ,
518+ ] ,
519+ [ '1.500000' , '3.500000' , 2 ] ,
520+ ] ,
521+ ] ;
522+
523+ cases . forEach (
524+ (
525+ [
526+ inputs ,
527+ validateAmountParams ,
528+ feeCalculationParams ,
529+ [ expectedAdaAmount , expectedTotalAmount , expectedTimesFeeCalled ] ,
530+ ] ,
531+ idx
532+ ) => {
533+ test ( `case ${ idx } : should not allow to submit before fees are calculated` , async ( ) => {
534+ expect . assertions ( 5 ) ;
535+
536+ const validationDebounceWait = 0 ;
537+ const onTransactionFeeChangeSpy = jest . fn ( ) ;
538+
539+ const calculateTransactionFeeMock = jest . fn ( ) ;
540+
541+ feeCalculationParams . forEach ( ( [ delay , value ] ) => {
542+ calculateTransactionFeeMock . mockImplementationOnce (
543+ ( ) =>
544+ new Promise ( async ( resolve ) => {
545+ await sleep ( delay ) ;
546+ resolve ( {
547+ fee : new BigNumber ( value ) ,
548+ minimumAda : new BigNumber ( 1 ) ,
549+ } ) ;
550+ } )
551+ ) ;
552+ } ) ;
553+
554+ const validateAmountMock = jest . fn ( ) ;
555+
556+ validateAmountParams . forEach ( ( delay ) => {
557+ validateAmountMock . mockImplementationOnce (
558+ ( ) =>
559+ new Promise ( async ( resolve ) => {
560+ await sleep ( delay ) ;
561+ return resolve ( true ) ;
562+ } )
563+ ) ;
564+ } ) ;
565+
566+ render (
567+ < SetupWallet
568+ validateAmount = { validateAmountMock }
569+ calculateTransactionFee = { calculateTransactionFeeMock }
570+ validationDebounceWait = { validationDebounceWait }
571+ onTransactionFeeChange = { onTransactionFeeChangeSpy }
572+ />
573+ ) ;
574+
575+ enterReceiverAddress ( ) ;
576+
577+ const adaField = await screen . findByLabelText ( 'Ada' ) ;
578+
579+ for ( const [ delay , value ] of inputs ) {
580+ fireEvent . change ( adaField , {
581+ target : {
582+ value,
583+ } ,
584+ } ) ;
585+
586+ await sleep ( delay ) ;
587+ }
588+
589+ const sendButton : HTMLButtonElement = screen . getByText ( 'Send' ) ;
590+ expect ( sendButton ) . not . toBeEnabled ( ) ;
591+
592+ await waitForTransactionFee ( ) ;
593+
594+ expect ( sendButton ) . toBeEnabled ( ) ;
595+
596+ fireEvent . keyPress ( adaField , {
597+ key : 'Enter' ,
598+ code : 13 ,
599+ charCode : 13 ,
600+ target : adaField ,
601+ } ) ;
602+
603+ const adaAmountConfirmation = await screen . findByTestId (
604+ 'confirmation-dialog-ada-amount' ,
605+ { }
606+ ) ;
607+
608+ expect ( adaAmountConfirmation ) . toHaveTextContent ( expectedAdaAmount ) ;
609+
610+ const totalAmountConfirmation = screen . getByTestId (
611+ 'confirmation-dialog-total-amount' ,
612+ { }
613+ ) ;
614+
615+ expect ( totalAmountConfirmation ) . toHaveTextContent ( expectedTotalAmount ) ;
616+ expect ( onTransactionFeeChangeSpy ) . toHaveBeenCalledTimes (
617+ expectedTimesFeeCalled
618+ ) ;
619+ } ) ;
620+ }
621+ ) ;
418622} ) ;
0 commit comments