import { fireEvent, render } from '@testing-library/react-native'
import * as React from 'react'
import { Provider } from 'react-redux'
import AppAnalytics from 'src/analytics/AppAnalytics'
import { DappExplorerEvents } from 'src/analytics/Events'
import { dappSelected, fetchDappsList } from 'src/dapps/slice'
import { DappCategory, DappSection } from 'src/dapps/types'
import TabDiscover from 'src/dappsExplorer/TabDiscover'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { getFeatureGate } from 'src/statsig'
import { StatsigFeatureGates } from 'src/statsig/types'
import { NetworkId } from 'src/transactions/types'
import MockedNavigator from 'test/MockedNavigator'
import { createMockStore } from 'test/utils'
import {
mockAaveArbUsdcAddress,
mockAaveArbUsdcTokenId,
mockDappListWithCategoryNames,
mockEarnPositions,
} from 'test/values'
jest.mock('src/analytics/AppAnalytics')
jest.mock('src/statsig', () => ({
getExperimentParams: jest.fn(() => ({
dappsFilterEnabled: true,
dappsSearchEnabled: true,
})),
getFeatureGate: jest.fn(),
}))
const dappsList = [
...mockDappListWithCategoryNames,
{
name: 'Dapp 4',
id: 'dapp4',
categories: ['1'],
categoryNames: ['Swap'],
description: 'Some dapp thing',
iconUrl: 'https://raw.githubusercontent.com/app-list/main/assets/dapp4.png',
dappUrl: 'https://app.dapp4.org/',
},
{
name: 'Dapp 5',
id: 'dapp5',
categories: ['1'],
categoryNames: ['Swap'],
description: 'Some dapp thing',
iconUrl: 'https://raw.githubusercontent.com/app-list/main/assets/dapp5.png',
dappUrl: 'https://app.dapp5.org/',
},
{
name: 'Dapp 6',
id: 'dapp6',
categories: ['1'],
categoryNames: ['Swap'],
description: 'Some dapp thing',
iconUrl: 'https://raw.githubusercontent.com/app-list/main/assets/dapp6.png',
dappUrl: 'https://app.dapp6.org/',
},
]
const dappsCategories: DappCategory[] = [
{
id: '1',
name: 'Swap',
backgroundColor: '#DEF8EA',
fontColor: '#1AB775',
},
{
id: '2',
name: 'Lend, Borrow & Earn',
backgroundColor: '#DEF8F7',
fontColor: '#07A0AE',
},
]
const mostPopularDappIds = ['dapp1', 'dapp2', 'dapp3', 'dapp4', 'dapp5']
const defaultExpectedDappOpenProps = {
categories: ['1'],
dappId: 'dapp1',
dappName: 'Dapp 1',
position: 1,
section: 'favorites dapp screen',
fromScreen: 'TabDiscover',
}
const defaultStore = createMockStore({
dapps: { dappListApiUrl: 'http://url.com', dappsList, dappsCategories },
})
describe('TabDiscover', () => {
beforeEach(() => {
defaultStore.clearActions()
jest.clearAllMocks()
jest.mocked(getFeatureGate).mockReturnValue(false)
})
it('renders correctly when there are no favorite dapps', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: [],
},
})
const { queryByTestId, getByTestId, getAllByTestId } = render(
)
expect(getByTestId('DiscoverDappsCard')).toBeTruthy()
const mostPopularSectionResults = getAllByTestId(
'DiscoverDappsCard/MostPopularSection/DappCard'
)
expect(mostPopularSectionResults.length).toBe(5)
expect(mostPopularSectionResults[0]).toHaveTextContent(dappsList[0].name)
expect(mostPopularSectionResults[0]).toHaveTextContent(dappsList[0].description)
expect(mostPopularSectionResults[1]).toHaveTextContent(dappsList[1].name)
expect(mostPopularSectionResults[1]).toHaveTextContent(dappsList[1].description)
expect(mostPopularSectionResults[2]).toHaveTextContent(dappsList[2].name)
expect(mostPopularSectionResults[2]).toHaveTextContent(dappsList[2].description)
expect(mostPopularSectionResults[3]).toHaveTextContent(dappsList[3].name)
expect(mostPopularSectionResults[3]).toHaveTextContent(dappsList[3].description)
expect(mostPopularSectionResults[4]).toHaveTextContent(dappsList[4].name)
expect(mostPopularSectionResults[4]).toHaveTextContent(dappsList[4].description)
expect(queryByTestId('DiscoverDappsCard/FavoritesSection/Title')).toBeFalsy()
})
it('renders correctly when there are <=2 favorite dapps', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp3'],
},
})
const { getByTestId, getAllByTestId } = render(
)
expect(getByTestId('DiscoverDappsCard')).toBeTruthy()
const mostPopularSectionResults = getAllByTestId(
'DiscoverDappsCard/MostPopularSection/DappCard'
)
expect(mostPopularSectionResults.length).toBe(3)
expect(mostPopularSectionResults[0]).toHaveTextContent(dappsList[1].name)
expect(mostPopularSectionResults[0]).toHaveTextContent(dappsList[1].description)
expect(mostPopularSectionResults[1]).toHaveTextContent(dappsList[3].name)
expect(mostPopularSectionResults[1]).toHaveTextContent(dappsList[3].description)
expect(mostPopularSectionResults[2]).toHaveTextContent(dappsList[4].name)
expect(mostPopularSectionResults[2]).toHaveTextContent(dappsList[4].description)
const favoritesSectionResults = getAllByTestId('DiscoverDappsCard/FavoritesSection/DappCard')
expect(favoritesSectionResults.length).toBe(2)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].name)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].description)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[2].name)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[2].description)
})
it('renders correctly when there are >2 favorite dapps', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp3', 'dapp4'],
},
})
const { queryByTestId, getByTestId, getAllByTestId } = render(
)
expect(getByTestId('DiscoverDappsCard')).toBeTruthy()
expect(queryByTestId('DiscoverDappsCard/MostPopularSection/Title')).toBeFalsy()
const favoritesSectionResults = getAllByTestId('DiscoverDappsCard/FavoritesSection/DappCard')
expect(favoritesSectionResults.length).toBe(3)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].name)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].description)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[2].name)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[2].description)
expect(favoritesSectionResults[2]).toHaveTextContent(dappsList[3].name)
expect(favoritesSectionResults[2]).toHaveTextContent(dappsList[3].description)
})
it('renders correctly when there are >5 favorite dapps', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp2', 'dapp3', 'dapp4', 'dapp5', 'dapp6'],
},
})
const { queryByTestId, getByTestId, getAllByTestId } = render(
)
expect(getByTestId('DiscoverDappsCard')).toBeTruthy()
expect(queryByTestId('DiscoverDappsCard/MostPopularSection/Title')).toBeFalsy()
const favoritesSectionResults = getAllByTestId('DiscoverDappsCard/FavoritesSection/DappCard')
expect(favoritesSectionResults.length).toBe(5)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].name)
expect(favoritesSectionResults[0]).toHaveTextContent(dappsList[0].description)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[1].name)
expect(favoritesSectionResults[1]).toHaveTextContent(dappsList[1].description)
expect(favoritesSectionResults[2]).toHaveTextContent(dappsList[2].name)
expect(favoritesSectionResults[2]).toHaveTextContent(dappsList[2].description)
expect(favoritesSectionResults[3]).toHaveTextContent(dappsList[3].name)
expect(favoritesSectionResults[3]).toHaveTextContent(dappsList[3].description)
expect(favoritesSectionResults[4]).toHaveTextContent(dappsList[4].name)
expect(favoritesSectionResults[4]).toHaveTextContent(dappsList[4].description)
})
it('fires event on favorite dapp press', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp3'],
},
})
const { getByText } = render(
)
fireEvent.press(getByText('Dapp 1'))
expect(store.getActions()).toEqual(
expect.arrayContaining([
fetchDappsList(),
dappSelected({ dapp: { ...dappsList[0], openedFrom: DappSection.FavoritesDappScreen } }),
])
)
expect(AppAnalytics.track).toHaveBeenCalledWith(
DappExplorerEvents.dapp_open,
defaultExpectedDappOpenProps
)
})
it('fires event on popular dapp press', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp3'],
},
})
const { getByText } = render(
)
fireEvent.press(getByText('Dapp 2'))
expect(store.getActions()).toEqual(
expect.arrayContaining([
fetchDappsList(),
dappSelected({ dapp: { ...dappsList[1], openedFrom: DappSection.MostPopular } }),
])
)
expect(AppAnalytics.track).toHaveBeenCalledWith(DappExplorerEvents.dapp_open, {
...defaultExpectedDappOpenProps,
categories: ['2'],
dappId: 'dapp2',
dappName: 'Dapp 2',
section: 'mostPopular',
})
})
it('navigates to dapp screen on button press and fires event', () => {
const store = createMockStore({
dapps: {
dappListApiUrl: 'http://url.com',
dappsList,
dappsCategories,
mostPopularDappIds,
favoriteDappIds: ['dapp1', 'dapp3'],
},
})
const { getByText } = render(
)
fireEvent.press(getByText('dappsScreen.exploreAll'))
expect(AppAnalytics.track).toHaveBeenCalledWith(DappExplorerEvents.dapp_explore_all)
expect(navigate).toHaveBeenCalledWith(Screens.DappsScreen)
})
describe('earn', () => {
it('does not display earn cta or active pool if feature gate is false', () => {
const { queryByTestId } = render(
)
expect(queryByTestId('EarnCta')).toBeFalsy()
expect(queryByTestId('EarnActivePool')).toBeFalsy()
})
it('displays EarnEntrypoint', () => {
jest
.mocked(getFeatureGate)
.mockImplementation(
(featureGateName) => featureGateName === StatsigFeatureGates.SHOW_POSITIONS
)
const store = createMockStore({
dapps: { dappListApiUrl: 'http://url.com', dappsList, dappsCategories },
tokens: {
tokenBalances: {
[mockAaveArbUsdcTokenId]: {
networkId: NetworkId['arbitrum-sepolia'],
address: mockAaveArbUsdcAddress,
tokenId: mockAaveArbUsdcTokenId,
symbol: 'aArbSepUSDC',
priceUsd: '1',
balance: '10',
priceFetchedAt: Date.now(),
},
},
},
positions: {
positions: [{ ...mockEarnPositions[0], balance: '10' }],
earnPositionIds: ['arbitrum-sepolia:0x460b97bd498e1157530aeb3086301d5225b91216'],
},
})
const { getByTestId } = render(
)
expect(getByTestId('EarnEntrypoint')).toBeTruthy()
})
})
})