From 81fbed46d90124a622a8272367e825334cf50a88 Mon Sep 17 00:00:00 2001 From: Tom McGuire Date: Fri, 14 Jun 2024 16:24:54 -0700 Subject: [PATCH] fix(max): respect local decimal separator when setting max (#5551) ### Description Discovered with `EarnEnterAmount.tsx`, but also present in `EnterAmount.tsx` when pressing max the local decimilar separator was not set correctly preventing users from being able to delete characters from the input amount. ### Test plan - [x] Tested locally on iOS - [x] Tested locally on Android - [x] Unit tests updated ### Related issues N/A ### Backwards compatibility Yes ### Network scalability N/A --- src/earn/EarnEnterAmount.test.tsx | 57 +++++++++++++++++++++++++++++++ src/earn/EarnEnterAmount.tsx | 2 +- src/send/EnterAmount.test.tsx | 20 +++++++++++ src/send/EnterAmount.tsx | 2 +- 4 files changed, 79 insertions(+), 2 deletions(-) diff --git a/src/earn/EarnEnterAmount.test.tsx b/src/earn/EarnEnterAmount.test.tsx index 13f08839519..c7687da9c3f 100644 --- a/src/earn/EarnEnterAmount.test.tsx +++ b/src/earn/EarnEnterAmount.test.tsx @@ -1,6 +1,7 @@ import { fireEvent, render, waitFor } from '@testing-library/react-native' import BigNumber from 'bignumber.js' import React from 'react' +import { getNumberFormatSettings } from 'react-native-localize' import { Provider } from 'react-redux' import { EarnEvents } from 'src/analytics/Events' import ValoraAnalytics from 'src/analytics/ValoraAnalytics' @@ -17,6 +18,7 @@ import { mockAccount, mockArbEthTokenId, mockTokenBalances } from 'test/values' jest.mock('src/earn/prepareTransactions') jest.mock('src/earn/poolInfo') +jest.mock('react-native-localize') const mockPreparedTransaction: PreparedTransactionsPossible = { type: 'possible' as const, @@ -97,6 +99,9 @@ describe('EarnEnterAmount', () => { beforeEach(() => { jest.clearAllMocks() jest.mocked(fetchAavePoolInfo).mockResolvedValue({ apy: 0.1 }) + jest + .mocked(getNumberFormatSettings) + .mockReturnValue({ decimalSeparator: '.', groupingSeparator: ',' }) }) it('should render APY and EarnUpTo', async () => { @@ -242,4 +247,56 @@ describe('EarnEnterAmount', () => { ) expect(getByTestId('EarnEnterAmount/Continue')).toBeDisabled() }) + + describe.each([ + { decimal: '.', group: ',' }, + { decimal: ',', group: '.' }, + ])('with decimal separator "$decimal" and group separator "$group"', ({ decimal, group }) => { + const replaceSeparators = (value: string) => + value.replace(/\./g, '|').replace(/,/g, group).replace(/\|/g, decimal) + + beforeEach(() => { + jest + .mocked(getNumberFormatSettings) + .mockReturnValue({ decimalSeparator: decimal, groupingSeparator: group }) + BigNumber.config({ + FORMAT: { + decimalSeparator: decimal, + groupSeparator: group, + groupSize: 3, + }, + }) + }) + + const mockStore = createMockStore({ + tokens: { + tokenBalances: { + [networkConfig.arbUsdcTokenId]: { + tokenId: networkConfig.arbUsdcTokenId, + symbol: 'USDC', + priceUsd: '1', + priceFetchedAt: priceFetchedAt, + networkId: NetworkId['arbitrum-sepolia'], + balance: '100000.42', + }, + }, + }, + }) + + it('entering MAX token applies correct decimal separator', async () => { + const { getByTestId } = render( + + + + ) + + fireEvent.press(getByTestId('EarnEnterAmount/Max')) + expect(getByTestId('EarnEnterAmount/TokenAmountInput').props.value).toBe( + replaceSeparators('100000.42') + ) + expect(getByTestId('EarnEnterAmount/LocalAmountInput').props.value).toBe( + replaceSeparators('₱133,000.56') + ) + }) + }) }) diff --git a/src/earn/EarnEnterAmount.tsx b/src/earn/EarnEnterAmount.tsx index c8e82ff8a96..13bb8d0b4af 100644 --- a/src/earn/EarnEnterAmount.tsx +++ b/src/earn/EarnEnterAmount.tsx @@ -242,7 +242,7 @@ function EarnEnterAmount({ route }: Props) { // eventually we may want to do something smarter here, like subtracting gas fees from the max amount if // this is a gas-paying token. for now, we are just showing a warning to the user prompting them to lower the amount // if there is not enough for gas - setTokenAmountInput(token.balance.toString()) + setTokenAmountInput(token.balance.toFormat({ decimalSeparator })) setEnteredIn('token') tokenAmountInputRef.current?.blur() localAmountInputRef.current?.blur() diff --git a/src/send/EnterAmount.test.tsx b/src/send/EnterAmount.test.tsx index b51c4a0ccbe..2eb2b9c9501 100644 --- a/src/send/EnterAmount.test.tsx +++ b/src/send/EnterAmount.test.tsx @@ -320,6 +320,26 @@ describe('EnterAmount', () => { expect(tokenAmountInput.props.value).toBe(replaceSeparators('1000')) expect(localAmountInput.props.value).toBe(replaceSeparators('₱133')) }) + + it('entering MAX token applies correct decimal separator', async () => { + const store = createMockStore(mockStore) + const tokenBalances = mockStoreBalancesToTokenBalances([ + { ...mockStoreTokenBalances[mockCeloTokenId], balance: '100000.42' }, + ]) + const { getByTestId } = render( + + + + ) + + fireEvent.press(getByTestId('SendEnterAmount/Max')) + expect(getByTestId('SendEnterAmount/TokenAmountInput').props.value).toBe( + replaceSeparators('100000.42') + ) + expect(getByTestId('SendEnterAmount/LocalAmountInput').props.value).toBe( + replaceSeparators('₱66,500.28') + ) + }) }) it.each([ diff --git a/src/send/EnterAmount.tsx b/src/send/EnterAmount.tsx index 3ec7e83d7a6..de1d4e5e939 100644 --- a/src/send/EnterAmount.tsx +++ b/src/send/EnterAmount.tsx @@ -183,7 +183,7 @@ function EnterAmount({ // eventually we may want to do something smarter here, like subtracting gas fees from the max amount if // this is a gas-paying token. for now, we are just showing a warning to the user prompting them to lower the amount // if there is not enough for gas - setTokenAmountInput(token.balance.toString()) + setTokenAmountInput(token.balance.toFormat({ decimalSeparator })) setEnteredIn('token') tokenAmountInputRef.current?.blur() localAmountInputRef.current?.blur()