feat: split validation for amount so we can render conditionally based on type

This commit is contained in:
Matthew Russell
2023-02-22 14:18:07 -08:00
parent 28111881b3
commit 948db1880e
2 changed files with 63 additions and 27 deletions
+17 -9
View File
@@ -11,7 +11,7 @@ const formFieldError = 'input-error-text';
const ASSET_EURO = 1;
describe('deposit form validation', { tags: '@smoke' }, () => {
before(() => {
function openDepositForm() {
cy.mockWeb3Provider();
cy.mockSubscription();
cy.mockTradingPage();
@@ -22,10 +22,14 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
cy.getByTestId('deposit-button').click();
cy.wait('@Assets');
connectEthereumWallet('MetaMask');
cy.getByTestId('deposit-submit').click();
}
before(() => {
openDepositForm();
});
it('handles empty fields', () => {
cy.getByTestId('deposit-submit').click();
cy.getByTestId(formFieldError).should('contain.text', 'Required');
cy.getByTestId(formFieldError).should('have.length', 2);
});
@@ -48,7 +52,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
it('invalid amount', () => {
mockWeb3DepositCalls({
allowance: '1000',
depositLifetimeLimit: '600',
depositLifetimeLimit: '1000',
balance: '800',
deposited: '0',
dps: 5,
@@ -67,7 +71,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
it('insufficient funds', () => {
mockWeb3DepositCalls({
allowance: '1000',
depositLifetimeLimit: '600',
depositLifetimeLimit: '1000',
balance: '800',
deposited: '0',
dps: 5,
@@ -80,6 +84,8 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
});
it('above deposit limit', () => {
// reload form with new web3 mocks
openDepositForm();
mockWeb3DepositCalls({
allowance: '1000',
depositLifetimeLimit: '600',
@@ -87,11 +93,13 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
deposited: '0',
dps: 5,
});
cy.get(amountField)
.clear()
.type('650')
.next(`[data-testid="${formFieldError}"]`)
.should('have.text', 'Amount is above deposit limit');
selectAsset(ASSET_EURO);
cy.get(amountField).clear().type('650');
cy.getByTestId('deposit-submit').click();
cy.get(`[data-testid="${formFieldError}"]`).should(
'have.text',
'Amount is above deposit limit'
);
});
});
+46 -18
View File
@@ -25,7 +25,8 @@ import { useWeb3React } from '@web3-react/core';
import BigNumber from 'bignumber.js';
import type { ButtonHTMLAttributes } from 'react';
import { useMemo } from 'react';
import { Controller, useForm, useWatch } from 'react-hook-form';
import type { FieldError } from 'react-hook-form';
import { Controller, useForm } from 'react-hook-form';
import { DepositLimits } from './deposit-limits';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import {
@@ -106,8 +107,6 @@ export const DepositForm = ({
}
};
const amount = useWatch({ name: 'amount', control });
const maxAmount = useMemo(() => {
const maxApproved = allowance ? allowance : new BigNumber(0);
const maxAvailable = balance ? balance : new BigNumber(0);
@@ -138,13 +137,7 @@ export const DepositForm = ({
return minViableAmount;
}, [selectedAsset]);
const approved =
allowance &&
allowance.isGreaterThan(0) &&
new BigNumber(amount || 0).isLessThan(allowance)
? true
: false;
const approved = allowance && allowance.isGreaterThan(0) ? true : false;
const formState = getFormState(selectedAsset, isActive, approved);
return (
@@ -304,24 +297,35 @@ export const DepositForm = ({
validate: {
required,
minSafe: (value) => minSafe(new BigNumber(min))(value),
maxSafe: (v) => {
approved: (v) => {
const value = new BigNumber(v);
if (value.isGreaterThan(maxAmount.approved)) {
return t('Amount is above approved amount');
}
return true;
},
limit: (v) => {
const value = new BigNumber(v);
if (value.isGreaterThan(maxAmount.limit)) {
return t('Amount is above deposit limit');
}
return true;
},
balance: (v) => {
const value = new BigNumber(v);
if (value.isGreaterThan(maxAmount.available)) {
return t('Insufficient amount in Ethereum wallet');
} else if (value.isGreaterThan(maxAmount.limit)) {
return t('Amount is above deposit limit');
} else if (value.isGreaterThan(maxAmount.approved)) {
return t('Amount is above approved amount');
}
return true;
},
maxSafe: (v) => {
return maxSafe(maxAmount.amount)(v);
},
},
})}
/>
{errors.amount?.message && (
<InputError intent="danger" forInput="amount">
{errors.amount.message}
</InputError>
<AmountError error={errors.amount} submitApprove={submitApprove} />
)}
{selectedAsset && balance && (
<UseButton
@@ -340,6 +344,30 @@ export const DepositForm = ({
);
};
const AmountError = ({
error,
submitApprove,
}: {
error: FieldError;
submitApprove: () => void;
}) => {
if (error.type === 'approved') {
return (
<InputError intent="danger" forInput="amount">
{error.message}.
<button onClick={submitApprove} className="underline ml-2">
{t('Update approve amount')}
</button>
</InputError>
);
}
return (
<InputError intent="danger" forInput="amount">
{error.message}
</InputError>
);
};
interface FormButtonProps {
selectedAsset?: Asset;
formState: ReturnType<typeof getFormState>;