import { fireEvent, render, within } from '@testing-library/react-native' import React from 'react' import { Provider } from 'react-redux' import FiatExchangeCurrencyBottomSheet from 'src/fiatExchanges/FiatExchangeCurrencyBottomSheet' import { FiatExchangeFlow } from 'src/fiatExchanges/types' import { getDynamicConfigParams, getFeatureGate, getMultichainFeatures } from 'src/statsig' import { DynamicConfigs } from 'src/statsig/constants' import { StatsigDynamicConfigs, StatsigFeatureGates, StatsigMultiNetworkDynamicConfig, } from 'src/statsig/types' import { NetworkId } from 'src/transactions/types' import MockedNavigator from 'test/MockedNavigator' import { createMockStore } from 'test/utils' import { mockCeloTokenId, mockCeurTokenId, mockCrealTokenId, mockCusdTokenId, mockEthTokenId, mockTokenBalances, } from 'test/values' const MOCK_STORE_DATA = { tokens: { tokenBalances: { ...mockTokenBalances, }, }, } jest.mock('src/web3/networkConfig', () => { const originalModule = jest.requireActual('src/web3/networkConfig') return { ...originalModule, __esModule: true, default: { ...originalModule.default, defaultNetworkId: 'celo-alfajores', spendTokenIds: [ 'celo-alfajores:0x874069Fa1Eb16D44d622F2e0Ca25eeA172369bC1'.toLowerCase(), 'celo-alfajores:0x10c892A6EC43a53E45D0B916B4b7D383B1b78C0F'.toLowerCase(), ], }, } }) jest.mock('src/statsig') describe(FiatExchangeCurrencyBottomSheet, () => { const mockStore = createMockStore(MOCK_STORE_DATA) beforeEach(() => { jest.clearAllMocks() jest.mocked(getFeatureGate).mockReturnValue(false) jest.mocked(getMultichainFeatures).mockReturnValue({ ...DynamicConfigs[StatsigMultiNetworkDynamicConfig.MULTI_CHAIN_FEATURES].defaultValues, showCico: [NetworkId['celo-alfajores'], NetworkId['ethereum-sepolia']], }) jest.mocked(getDynamicConfigParams).mockImplementation(({ configName, defaultValues }) => { switch (configName) { case StatsigDynamicConfigs.CICO_TOKEN_INFO: return { tokenInfo: { [mockEthTokenId]: { cicoOrder: 1 }, [mockCeloTokenId]: { cicoOrder: 2 }, [mockCusdTokenId]: { cicoOrder: 3 }, [mockCeurTokenId]: { cicoOrder: 4 }, [mockCrealTokenId]: { cicoOrder: 5 }, }, } case StatsigDynamicConfigs.SWAP_CONFIG: return { popularTokenIds: [mockEthTokenId, mockCeloTokenId], } default: return defaultValues } }) }) it('shows the correct tokens for cash in', () => { const { getAllByTestId } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) ;['ETH', 'CELO', 'cUSD', 'cEUR', 'cREAL', 'USDC'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('shows the correct tokens for cash out', () => { const { getAllByTestId } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(2) ;['CELO', 'cUSD'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('shows the correct tokens for cash spend', () => { const { getAllByTestId } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(2) ;['cUSD', 'cEUR'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('shows the correct order when cicoOrder missing/same value', () => { jest.mocked(getDynamicConfigParams).mockImplementation(({ configName, defaultValues }) => { switch (configName) { case StatsigDynamicConfigs.CICO_TOKEN_INFO: return { tokenInfo: { [mockCusdTokenId]: { cicoOrder: 1 }, [mockCrealTokenId]: { cicoOrder: 1 }, }, } default: return defaultValues } }) const { getAllByTestId } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) ;['cUSD', 'cREAL', 'cEUR', 'CELO', 'ETH', 'USDC'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it.each([{ flow: FiatExchangeFlow.CashOut }, { flow: FiatExchangeFlow.Spend }])( `does not show filters for $flow`, ({ flow }) => { const { queryByTestId } = render( ) expect(queryByTestId('FilterChipsCarousel')).toBeFalsy() } ) it('shows filters for cash in', () => { const { getByTestId, getByText } = render( ) expect(getByTestId('FilterChipsCarousel')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.popular')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.stablecoins')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.gasTokens')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.selectNetwork')).toBeTruthy() }) it('hides the popular filter for UK compliance', () => { jest .mocked(getFeatureGate) .mockImplementation((feature) => feature === StatsigFeatureGates.SHOW_UK_COMPLIANT_VARIANT) const { queryByText, getByText } = render( ) expect(queryByText('tokenBottomSheet.filters.popular')).toBeFalsy() expect(getByText('tokenBottomSheet.filters.stablecoins')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.gasTokens')).toBeTruthy() expect(getByText('tokenBottomSheet.filters.selectNetwork')).toBeTruthy() }) it('popular filter filters correctly', () => { const { getAllByTestId, getByText } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) fireEvent.press(getByText('tokenBottomSheet.filters.popular')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(2) ;['ETH', 'CELO'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('stablecoin filter filters correctly', () => { const { getAllByTestId, getByText } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) fireEvent.press(getByText('tokenBottomSheet.filters.stablecoins')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(4) ;['cUSD', 'cEUR', 'cREAL', 'USDC'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('gas tokens filter filters correctly', () => { const { getAllByTestId, getByText } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) fireEvent.press(getByText('tokenBottomSheet.filters.gasTokens')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(5) ;['ETH', 'CELO', 'cUSD', 'cEUR', 'cREAL'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('network filter filters correctly', () => { const { getAllByTestId, getByText } = render( ) const networkMultiSelect = getAllByTestId('MultiSelectBottomSheet')[0] expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) fireEvent.press(getByText('tokenBottomSheet.filters.selectNetwork')) // select celo filter fireEvent.press(within(networkMultiSelect).getByTestId('Celo Alfajores-icon')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(4) ;['CELO', 'cUSD', 'cEUR', 'cREAL'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) // select eth filter fireEvent.press(within(networkMultiSelect).getByTestId('Ethereum Sepolia-icon')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(2) ;['ETH', 'USDC'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) }) it('allows a network to be pre-selected', () => { const { getAllByTestId } = render( ) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(4) ;['CELO', 'cUSD', 'cEUR', 'cREAL'].forEach((token, index) => { expect(getAllByTestId('TokenBalanceItem')[index]).toHaveTextContent(token) }) // unselect filter, to prove that the pre-selection yielded different results const networkMultiSelect = getAllByTestId('MultiSelectBottomSheet')[0] fireEvent.press(within(networkMultiSelect).getByTestId('multiSelect.allNetworks-icon')) expect(getAllByTestId('TokenBalanceItem')).toHaveLength(6) }) })