import { fireEvent, render } from '@testing-library/react-native'
import BigNumber from 'bignumber.js'
import React from 'react'
import { Provider } from 'react-redux'
import BeforeDepositBottomSheet from 'src/earn/poolInfoScreen/BeforeDepositBottomSheet'
import { CICOFlow } from 'src/fiatExchanges/types'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import { createMockStore } from 'test/utils'
import { mockEarnPositions, mockTokenBalances } from 'test/values'
const mockPoolTokenId = mockEarnPositions[0].dataProps.depositTokenId
const mockToken = {
...mockTokenBalances[mockPoolTokenId],
balance: new BigNumber(1),
priceUsd: new BigNumber(1),
lastKnownPriceUsd: new BigNumber(1),
}
jest.mock('src/statsig')
describe('BeforeDepositBottomSheet', () => {
beforeEach(() => {
jest.clearAllMocks()
jest
.mocked(getFeatureGate)
.mockImplementation((gate) => gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS)
})
it.each`
scenario | expectedActions | hasDepositToken | hasTokensOnSameNetwork | hasTokensOnOtherNetworks | canAdd | poolCannotSwapAndDeposit | allowCrossChainSwaps
${'does not have any tokens'} | ${['Add', 'Transfer']} | ${false} | ${false} | ${false} | ${true} | ${false} | ${true}
${'does not have any tokens, cannot buy'} | ${['Transfer']} | ${false} | ${false} | ${false} | ${false} | ${false} | ${true}
${'only has deposit token'} | ${['Deposit', 'AddMore']} | ${true} | ${false} | ${false} | ${true} | ${false} | ${true}
${'only has deposit token, cannot buy'} | ${['Deposit', 'Transfer']} | ${true} | ${false} | ${false} | ${false} | ${false} | ${true}
${'only has other tokens on same chain'} | ${['SwapAndDeposit', 'Add']} | ${false} | ${true} | ${false} | ${true} | ${false} | ${true}
${'only has other tokens on same chain, cannot buy'} | ${['SwapAndDeposit', 'Transfer']} | ${false} | ${true} | ${false} | ${false} | ${false} | ${true}
${'only has other tokens on same chain, pool cannot swap and deposit'} | ${['Swap', 'Add']} | ${false} | ${true} | ${false} | ${true} | ${true} | ${true}
${'only has other tokens on same chain, pool cannot swap and deposit, cannot buy'} | ${['Swap', 'Transfer']} | ${false} | ${true} | ${false} | ${false} | ${true} | ${true}
${'only has tokens on different chain'} | ${['Swap', 'Add']} | ${false} | ${false} | ${true} | ${true} | ${false} | ${true}
${'only has tokens on different chain, cannot buy'} | ${['Swap', 'Transfer']} | ${false} | ${false} | ${true} | ${false} | ${false} | ${true}
${'only has tokens on different chain, cross chain swap disabled'} | ${['Add', 'Transfer']} | ${false} | ${false} | ${true} | ${true} | ${false} | ${false}
${'has deposit token and other tokens on same chain'} | ${['Deposit', 'SwapAndDeposit', 'AddMore']} | ${true} | ${true} | ${false} | ${true} | ${false} | ${true}
${'has deposit token and other tokens on same chain, cannot buy'} | ${['Deposit', 'SwapAndDeposit', 'Transfer']} | ${true} | ${true} | ${false} | ${false} | ${false} | ${true}
${'has deposit token and other tokens on same chain, pool cannot swap and deposit'} | ${['Deposit', 'Swap', 'AddMore']} | ${true} | ${true} | ${false} | ${true} | ${true} | ${true}
${'has deposit token and tokens on different chain, cross chain swap disabled'} | ${['Deposit', 'AddMore']} | ${true} | ${false} | ${true} | ${true} | ${false} | ${false}
${'has deposit token and tokens on different chain'} | ${['Deposit', 'Swap', 'AddMore']} | ${true} | ${false} | ${true} | ${true} | ${false} | ${true}
${'has deposit token and tokens on different chain, cannot buy'} | ${['Deposit', 'Swap', 'Transfer']} | ${true} | ${false} | ${true} | ${false} | ${false} | ${true}
${'has other tokens on same and different chain'} | ${['SwapAndDeposit', 'CrossChainSwap', 'Add']} | ${false} | ${true} | ${true} | ${true} | ${false} | ${true}
${'has other tokens on same and different chain, pool cannot swap and deposit'} | ${['Swap', 'Add']} | ${false} | ${true} | ${true} | ${true} | ${true} | ${true}
${'has other tokens on same and different chain, cross chain swap disabled'} | ${['SwapAndDeposit', 'Add']} | ${false} | ${true} | ${true} | ${true} | ${false} | ${false}
${'has all types of tokens'} | ${['Deposit', 'SwapAndDeposit', 'CrossChainSwap']} | ${true} | ${true} | ${true} | ${true} | ${false} | ${true}
${'has all types of tokens, pool cannot swap and deposit'} | ${['Deposit', 'Swap']} | ${true} | ${true} | ${true} | ${true} | ${true} | ${true}
${'has all types of tokens, cross chain swap disabled'} | ${['Deposit', 'SwapAndDeposit', 'AddMore']} | ${true} | ${true} | ${true} | ${true} | ${false} | ${false}
${'has all types of tokens, cross chain swap disabled, cannot buy'} | ${['Deposit', 'SwapAndDeposit', 'Transfer']} | ${true} | ${true} | ${true} | ${false} | ${false} | ${false}
${'has all types of tokens, cannot buy'} | ${['Deposit', 'SwapAndDeposit', 'CrossChainSwap']} | ${true} | ${true} | ${true} | ${false} | ${false} | ${true}
`(
'shows correct title and actions when cross chain swap and deposit is disabled and user $scenario',
({
hasDepositToken,
hasTokensOnSameNetwork,
hasTokensOnOtherNetworks,
canAdd,
expectedActions,
poolCannotSwapAndDeposit,
allowCrossChainSwaps,
}: {
hasDepositToken: boolean
hasTokensOnSameNetwork: boolean
hasTokensOnOtherNetworks: boolean
canAdd: boolean
expectedActions: string[]
poolCannotSwapAndDeposit: boolean
allowCrossChainSwaps: boolean
}) => {
jest
.mocked(getFeatureGate)
.mockImplementation(
(gate) => gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS && allowCrossChainSwaps
)
const { getAllByTestId, getByText, queryByTestId, queryByText } = render(
)
expect(getAllByTestId(/^Earn\/ActionCard/).map((element) => element.props.testID)).toEqual(
expectedActions.map((action) => `Earn/ActionCard/${action}`)
)
const canDeposit =
expectedActions.includes('Deposit') || expectedActions.includes('SwapAndDeposit')
expect(
getByText(
`earnFlow.beforeDepositBottomSheet.${canDeposit ? 'depositTitle' : 'beforeYouCanDepositTitle'}`
)
).toBeTruthy()
expect(!!queryByTestId('Earn/BeforeDepositBottomSheet/AlternativeDescription')).toBe(
canDeposit
)
expect(
!!queryByText(
'earnFlow.beforeDepositBottomSheet.crossChainAlternativeDescription, {"tokenNetwork":"Arbitrum Sepolia"}'
)
).toBe(canDeposit)
}
)
// The has other tokens case either sets hasTokensOnSameNetwork or
// hasTokensOnOtherNetworks to true, we don't need to test every combination individually
it.each`
scenario | expectedActions | hasDepositToken | hasTokensOnSameNetwork | hasTokensOnOtherNetworks | canAdd | poolCannotSwapAndDeposit
${'does not have any tokens'} | ${['Add', 'Transfer']} | ${false} | ${false} | ${false} | ${true} | ${false}
${'does not have any tokens, cannot buy'} | ${['Transfer']} | ${false} | ${false} | ${false} | ${false} | ${false}
${'only has deposit token'} | ${['Deposit', 'AddMore']} | ${true} | ${false} | ${false} | ${true} | ${false}
${'only has deposit token, cannot buy'} | ${['Deposit', 'Transfer']} | ${true} | ${false} | ${false} | ${false} | ${false}
${'only has other tokens'} | ${['SwapAndDeposit', 'Add']} | ${false} | ${true} | ${false} | ${true} | ${false}
${'only has other tokens, cannot buy'} | ${['SwapAndDeposit', 'Transfer']} | ${false} | ${false} | ${true} | ${false} | ${false}
${'only has other tokens, pool cannot swap and deposit'} | ${['Swap', 'Add']} | ${false} | ${true} | ${false} | ${true} | ${true}
${'only has other tokens, pool cannot swap and deposit, cannot buy'} | ${['Swap', 'Transfer']} | ${false} | ${true} | ${true} | ${false} | ${true}
${'has deposit token and other tokens'} | ${['Deposit', 'SwapAndDeposit', 'AddMore']} | ${true} | ${false} | ${true} | ${true} | ${false}
${'has deposit token and other tokens, cannot buy'} | ${['Deposit', 'SwapAndDeposit', 'Transfer']} | ${true} | ${true} | ${false} | ${false} | ${false}
${'has deposit token and other tokens, pool cannot swap and deposit'} | ${['Deposit', 'Swap', 'AddMore']} | ${true} | ${true} | ${true} | ${true} | ${true}
${'has deposit token and other tokens, pool cannot swap and deposit, cannot buy'} | ${['Deposit', 'Swap', 'Transfer']} | ${true} | ${true} | ${true} | ${false} | ${true}
`(
'shows correct title and actions when cross chain swap and deposit is enabled and user $scenario',
({
hasDepositToken,
hasTokensOnSameNetwork,
hasTokensOnOtherNetworks,
canAdd,
expectedActions,
poolCannotSwapAndDeposit,
}: {
hasDepositToken: boolean
hasTokensOnSameNetwork: boolean
hasTokensOnOtherNetworks: boolean
canAdd: boolean
expectedActions: string[]
poolCannotSwapAndDeposit: boolean
}) => {
jest
.mocked(getFeatureGate)
.mockImplementation(
(gate) =>
gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAP_AND_DEPOSIT ||
gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS
)
const { getAllByTestId, getByText, queryByTestId, queryByText } = render(
)
expect(getAllByTestId(/^Earn\/ActionCard/).map((element) => element.props.testID)).toEqual(
expectedActions.map((action) => `Earn/ActionCard/${action}`)
)
const canDeposit =
expectedActions.includes('Deposit') || expectedActions.includes('SwapAndDeposit')
expect(
getByText(
`earnFlow.beforeDepositBottomSheet.${canDeposit ? 'depositTitle' : 'beforeYouCanDepositTitle'}`
)
).toBeTruthy()
expect(!!queryByTestId('Earn/BeforeDepositBottomSheet/AlternativeDescription')).toBe(
canDeposit
)
expect(!!queryByText('earnFlow.beforeDepositBottomSheet.alternativeDescription')).toBe(
canDeposit
)
}
)
it('shows correct swap and deposit action description when cross chain swap and deposit is disabled', () => {
const { getByTestId, getByText } = render(
)
expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toContainElement(
getByText(
'earnFlow.beforeDepositBottomSheet.action.swapAndDepositDescription, {"tokenNetwork":"Arbitrum Sepolia"}'
)
)
})
it('shows correct swap and deposit action description when cross chain swap and deposit is enabled', () => {
jest
.mocked(getFeatureGate)
.mockImplementation(
(gate) =>
gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAP_AND_DEPOSIT ||
gate === StatsigFeatureGates.ALLOW_CROSS_CHAIN_SWAPS
)
const { getByTestId, getByText } = render(
)
expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toContainElement(
getByText('earnFlow.beforeDepositBottomSheet.action.swapAndDepositAllTokensDescription')
)
})
it('navigates correctly when deposit action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/Deposit')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/Deposit'))
expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
pool: mockEarnPositions[0],
})
})
it('navigates correctly when swap and deposit action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/SwapAndDeposit')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/SwapAndDeposit'))
expect(navigate).toHaveBeenCalledWith(Screens.EarnEnterAmount, {
pool: mockEarnPositions[0],
mode: 'swap-deposit',
})
})
it('navigates correctly when cross chain swap action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/CrossChainSwap')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/CrossChainSwap'))
expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
})
})
it('navigates correctly when add more action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/AddMore')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/AddMore'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
tokenId: mockEarnPositions[0].dataProps.depositTokenId,
flow: CICOFlow.CashIn,
tokenSymbol: 'USDC',
})
})
it('navigates correctly when add action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/Add')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/Add'))
expect(navigate).toHaveBeenCalledWith(Screens.FiatExchangeAmount, {
tokenId: mockEarnPositions[0].dataProps.depositTokenId,
flow: CICOFlow.CashIn,
tokenSymbol: 'USDC',
})
})
it('navigates correctly when swap action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/Swap')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/Swap'))
expect(navigate).toHaveBeenCalledWith(Screens.SwapScreenWithBack, {
toTokenId: mockEarnPositions[0].dataProps.depositTokenId,
})
})
it('navigates correctly when transfer action item is tapped', () => {
const { getByTestId } = render(
)
expect(getByTestId('Earn/ActionCard/Transfer')).toBeTruthy()
fireEvent.press(getByTestId('Earn/ActionCard/Transfer'))
expect(navigate).toHaveBeenCalledWith(Screens.ExchangeQR, {
flow: CICOFlow.CashIn,
exchanges: [],
})
})
})