Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(TokenEnterAmount): Add new Enter Amount component #6242

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

sviderock
Copy link
Contributor

@sviderock sviderock commented Nov 18, 2024

Description

1/5 PR for new Enter Amount component. This PR implements a new component but doesn't use it anywhere. The tests are absent as this component will be covered with its usages in the follow-up PRs.

This is only done to reduce amount of lines to review per PR as at the end this whole feature is about 1k new lines and -1k of removed lines.

Test plan

Omit tests for now but in the follow-up PRs the following test files will be testing this component:

  • EnterAmount.test.tsx
  • EarnEnterAmount.test.tsx
  • SwapScreen.test.tsx

There will also be some test files that are gonna be fixed alongside. Please, see the follow-up PRs for more details.

Related issues

Backwards compatibility

Yes

Network scalability

If a new NetworkId and/or Network are added in the future, the changes in this PR will:

  • Continue to work without code changes, OR trigger a compilation error (guaranteeing we find it when a new network is added)

Copy link

codecov bot commented Nov 19, 2024

Codecov Report

Attention: Patch coverage is 90.12346% with 8 lines in your changes missing coverage. Please review.

Project coverage is 88.93%. Comparing base (66bd6d0) to head (0d64a5b).
Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/components/TokenEnterAmount.tsx 90.12% 8 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #6242      +/-   ##
==========================================
+ Coverage   88.92%   88.93%   +0.01%     
==========================================
  Files         737      738       +1     
  Lines       31431    31513      +82     
  Branches     5837     5864      +27     
==========================================
+ Hits        27950    28027      +77     
+ Misses       3437     3287     -150     
- Partials       44      199     +155     
Files with missing lines Coverage Δ
src/components/TokenEnterAmount.tsx 90.12% <90.12%> (ø)

... and 69 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 66bd6d0...0d64a5b. Read the comment docs.

---- 🚨 Try these New Features:

@sviderock sviderock marked this pull request as ready for review November 19, 2024 08:24
Comment on lines +78 to +84
const formattedInputValue = useMemo(() => {
const number = groupNumber(inputValue)
.replaceAll('.', decimalSeparator)
.replaceAll('group', groupingSeparator)
if (amountType === 'token') return number
return number !== '' ? `${localCurrencySymbol}${number}` : ''
}, [inputValue, amountType, localCurrencySymbol])
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured its easier to add currency sign before whatever is typed in the amount field rather than trying to parse it while having that sign and manage all the use-cases when it whether includes the sign (when typing in fiat) or not (when typing in crypto).

}
}

return (
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kudos to @kathaypacific for implementing 95% of this component 🚀

Copy link
Collaborator

@kathaypacific kathaypacific left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💥 looking great!! i had just a few small questions and suggestions for tests :)

inputValue: '1',
tokenAmount: '1',
localAmount: '$0.1',
amountType: 'token' as AmountEnteredIn,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
amountType: 'token' as AmountEnteredIn,
amountType: 'token' as const,

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kathaypacific considering this is more for the intellisense purpose I would keep it as is!

toggleAmountType: mockToggleAmountType,
onOpenTokenPicker: mockOnOpenTokenPicker,
editable: true,
testID: 'tokenEnterAmount',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

super nit: i think the pattern is to use TitleCase for test id's

Suggested change
testID: 'tokenEnterAmount',
testID: 'TokenEnterAmount',

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kathaypacific Sorry, this was the part generated by Chat GPT so I just kept it unchanged 🤦
Will change!

testID: 'tokenEnterAmount',
}

it('renders without crashing', () => {
Copy link
Collaborator

@kathaypacific kathaypacific Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: i think that this test is unnecessary, the scenario is already covered by the following tests (since the input to the render method is the same, and asserting on elements already ensures that the component has successfully rendered without errors)

<TokenEnterAmount {...defaultProps} />
</Provider>
)
expect(getByTestId('tokenEnterAmount/TokenName')).toBeTruthy()
Copy link
Collaborator

@kathaypacific kathaypacific Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(getByTestId('tokenEnterAmount/TokenName')).toBeTruthy()
expect(getByTestId('tokenEnterAmount/TokenName')).toHaveTextContent('CELO on Celo Alfajores')

expect(getByTestId('tokenEnterAmount/TokenSelect')).toBeTruthy()
expect(getByTestId('tokenEnterAmount/TokenBalance')).toBeTruthy()
expect(getByTestId('tokenEnterAmount/TokenBalance').props.children.props.i18nKey).toBe(
'tokenEnterAmount.availableBalance'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it's possible we should avoid digging into props since then we test implementation details rather than user outcomes...could instead consider doing something like

expect(getByTestId('tokenEnterAmount/TokenBalance')).toHaveTextContent(
      'tokenEnterAmount.availableBalance'
    )
    expect(getByTestId('tokenEnterAmount/TokenBalance')).toHaveTextContent('5.00 CELO')

?

Copy link
Contributor Author

@sviderock sviderock Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kathaypacific This makes sense! I've tried initially with getByText but for some reason for this particular test it couldn't find an element with that text (probably, cause it was including multiple nested Text tags so it wasn't able to match it). But your suggestion might work! Will try it out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works!

const input = getByTestId('tokenEnterAmount/TokenAmountInput')
const converted = getByTestId('tokenEnterAmount/ExchangeAmount')
expect(input.props.value).toBe('1')
expect(converted.props.children).toBe(`${APPROX_SYMBOL} $0.1`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(converted.props.children).toBe(`${APPROX_SYMBOL} $0.1`)
expect(converted).toHaveTextContent(`${APPROX_SYMBOL} $0.1`)

)
const input = getByTestId('tokenEnterAmount/TokenAmountInput')

expect(input.props.editable).toBe(false)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(input.props.editable).toBe(false)
expect(input).toBeDisabled()

</Provider>
)
const exchangeAmount = getByTestId('tokenEnterAmount/ExchangeAmount')
expect(exchangeAmount.props.children).toBe(`${APPROX_SYMBOL} $0.1`)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
expect(exchangeAmount.props.children).toBe(`${APPROX_SYMBOL} $0.1`)
expect(exchangeAmount).toHaveTextContent(`${APPROX_SYMBOL} $0.1`)

const BORDER_RADIUS = 12

function groupNumber(value: string) {
return value.replace(/\B(?=(\d{3})+(?!\d))(?<!\.\d*)/g, 'group')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please add a comment about what this regex does? 🙈 i would definitely benefit from this, i don't speak regex fluently

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kathaypacific I've refactored this function a bit in the next PR and added comments explaining how it works!

const formattedInputValue = useMemo(() => {
const number = groupNumber(inputValue)
.replaceAll('.', decimalSeparator)
.replaceAll('group', groupingSeparator)
Copy link
Collaborator

@kathaypacific kathaypacific Nov 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could we add a couple of tests around the expected outcome of this formatting function? i think i may be missing something, but i'm surprised that we can freely use '.' here - if the inputValue is 1.234.567,888, would this function still work? (unsure if this is a real scenario and if consumers of this component will pass in formatted values, but this formatting convention is real)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kathaypacific you're right! It was a bug that I've revealed once I was working on a useEnterAmount hook in the next PR. I've refactored this part as well so it should be resolved there!

In order to not keep these issues in the codebase - I would wait for the next PR to also get approved and will merge them both in a batch!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants