import { fireEvent, render, within } from '@testing-library/react-native'
import React from 'react'
import { Provider } from 'react-redux'
import DappShortcutsRewards from 'src/dapps/DappShortcutsRewards'
import { navigate } from 'src/navigator/NavigationService'
import { Screens } from 'src/navigator/Screens'
import { Position } from 'src/positions/types'
import { NetworkId } from 'src/transactions/types'
import { createMockStore } from 'test/utils'
import { mockCusdAddress, mockCusdTokenId, mockPositions, mockShortcuts } from 'test/values'
jest.mock('src/statsig', () => ({
getFeatureGate: jest.fn(() => true),
}))
jest.mock('src/web3/networkConfig', () => {
const originalModule = jest.requireActual('src/web3/networkConfig')
return {
...originalModule,
__esModule: true,
default: {
...originalModule.default,
defaultNetworkId: 'celo-alfajores',
},
}
})
const mockCeloAddress = '0x471ece3750da237f93b8e339c536989b8978a438'
const mockUbeAddress = '0x00be915b9dcf56a3cbe739d9b9c202ca692409ec'
const mockCeloTokenId = `celo-alfajores:${mockCeloAddress}`
const mockUbeTokenId = `celo-alfajores:${mockUbeAddress}`
const getPositionWithClaimableBalance = (balance?: string): Position => ({
type: 'contract-position',
networkId: NetworkId['celo-mainnet'],
address: '0xda7f463c27ec862cfbf2369f3f74c364d050d93f',
positionId: `${NetworkId['celo-mainnet']}:0xda7f463c27ec862cfbf2369f3f74c364d050d93f`,
appId: 'ubeswap',
appName: 'Ubeswap',
displayProps: {
title: 'CELO / cUSD',
description: 'Farm',
imageUrl: '',
},
tokens: [
{
type: 'app-token',
networkId: NetworkId['celo-alfajores'],
address: '0x1e593f1fe7b61c53874b54ec0c59fd0d5eb8621e',
tokenId: `${NetworkId['celo-alfajores']}:0x1e593f1fe7b61c53874b54ec0c59fd0d5eb8621e`,
positionId: `${NetworkId['celo-alfajores']}:0x1e593f1fe7b61c53874b54ec0c59fd0d5eb8621e`,
appId: 'ubeswap',
symbol: 'ULP',
decimals: 18,
appName: 'Ubeswap',
displayProps: {
title: 'CELO / cUSD',
description: 'Pool',
imageUrl: '',
},
tokens: [
{
type: 'base-token',
networkId: NetworkId['celo-alfajores'],
address: '0x471ece3750da237f93b8e339c536989b8978a438',
tokenId: `${NetworkId['celo-alfajores']}:0x471ece3750da237f93b8e339c536989b8978a438`,
symbol: 'CELO',
decimals: 18,
priceUsd: '0.6959536890241361',
balance: balance ?? '0.950545800159603456',
category: 'claimable',
},
{
type: 'base-token',
networkId: NetworkId['celo-alfajores'],
address: '0x765de816845861e75a25fca122bb6898b8b1282a',
tokenId: `${NetworkId['celo-alfajores']}:0x765de816845861e75a25fca122bb6898b8b1282a`,
symbol: 'cUSD',
decimals: 18,
priceUsd: '1',
balance: '0.659223169268731392',
},
],
pricePerShare: ['2.827719585853931', '1.961082008754231'],
priceUsd: '3.9290438860550765',
balance: '0.336152780111169400',
supply: '42744.727037884449180591',
availableShortcutIds: [],
},
{
priceUsd: '0.00904673476946796903',
type: 'base-token',
category: 'claimable',
decimals: 18,
networkId: NetworkId['celo-alfajores'],
balance: balance ?? '0.098322815093446616',
symbol: 'UBE',
address: '0x00be915b9dcf56a3cbe739d9b9c202ca692409ec',
tokenId: `${NetworkId['celo-alfajores']}:0x00be915b9dcf56a3cbe739d9b9c202ca692409ec`,
},
],
balanceUsd: '1.3207590254762067',
availableShortcutIds: ['claim-reward'],
})
const defaultState = {
positions: {
positions: [...mockPositions.slice(0, 2), getPositionWithClaimableBalance()],
shortcuts: mockShortcuts,
},
tokens: {
tokenBalances: {
[mockCeloTokenId]: {
address: mockCeloAddress,
tokenId: mockCeloTokenId,
networkId: NetworkId['celo-alfajores'],
symbol: 'CELO',
priceUsd: '0.6959536890241361', // matches data in mockPositions
balance: '10',
priceFetchedAt: Date.now(),
isFeeCurrency: true,
},
[mockUbeTokenId]: {
address: mockUbeAddress,
tokenId: mockUbeTokenId,
networkId: NetworkId['celo-alfajores'],
symbol: 'UBE',
priceUsd: '0.00904673476946796903', // matches data in mockPositions
balance: '10',
priceFetchedAt: Date.now(),
},
[mockCusdTokenId]: {
address: mockCusdAddress,
tokenId: mockCusdTokenId,
networkId: NetworkId['celo-alfajores'],
symbol: 'cUSD',
priceUsd: '1',
balance: '10',
priceFetchedAt: Date.now(),
isFeeCurrency: true,
},
},
},
}
const mockStore = createMockStore(defaultState)
describe('DappShortcutsRewards', () => {
beforeEach(() => {
jest.clearAllMocks()
mockStore.clearActions()
})
it('should render claimable rewards correctly', () => {
const { getByText, getAllByTestId } = render(
)
expect(getByText('dappShortcuts.claimRewardsScreen.title')).toBeTruthy()
expect(getByText('dappShortcuts.claimRewardsScreen.description')).toBeTruthy()
expect(getAllByTestId('DappShortcutsRewards/Card').length).toBe(1)
const rewardCard = getAllByTestId('DappShortcutsRewards/Card')[0]
expect(within(rewardCard).getByTestId('DappShortcutsRewards/RewardAmount')).toHaveTextContent(
'0.098 UBE, 0.95 CELO'
)
expect(
within(rewardCard).getByTestId('DappShortcutsRewards/RewardAmountFiat')
).toHaveTextContent('₱0.88') // USD value $0.66, mocked exchange rate 1.33
expect(within(rewardCard).getByTestId('DappShortcutsRewards/ClaimButton')).toBeTruthy()
})
it('should dispatch the correct action on claim', async () => {
const { getAllByTestId } = render(
)
fireEvent.press(getAllByTestId('DappShortcutsRewards/ClaimButton')[0])
expect(mockStore.getActions()).toMatchInlineSnapshot(`
[
{
"payload": {
"appImage": "",
"appName": "Ubeswap",
"data": {
"address": "0x0000000000000000000000000000000000007e57",
"appId": "ubeswap",
"networkId": "celo-mainnet",
"positionAddress": "0xda7f463c27ec862cfbf2369f3f74c364d050d93f",
"positionId": "celo-mainnet:0xda7f463c27ec862cfbf2369f3f74c364d050d93f",
"shortcutId": "claim-reward",
},
"id": "claim-reward-0xda7f463c27ec862cfbf2369f3f74c364d050d93f-1.048868615253050072",
},
"type": "positions/triggerShortcut",
},
]
`)
expect(navigate).toHaveBeenCalledWith(Screens.DappShortcutTransactionRequest, {
rewardId: 'claim-reward-0xda7f463c27ec862cfbf2369f3f74c364d050d93f-1.048868615253050072',
})
})
it('should show a reward being claimed', () => {
const { getByTestId } = render(
)
expect(getByTestId('DappShortcutsRewards/ClaimButton')).toBeDisabled()
expect(getByTestId('Button/Loading')).toBeTruthy()
})
it('should show a claimed reward when it is no longer claimable in redux', () => {
const { getByTestId, getByText, queryByText, rerender } = render(
)
expect(getByTestId('DappShortcutsRewards/ClaimButton')).toBeEnabled()
expect(queryByText('dappShortcuts.claimRewardsScreen.claimedLabel')).toBeFalsy()
expect(getByText('dappShortcuts.claimRewardsScreen.claimButton')).toBeTruthy()
// simulate data refresh after a successful claim
const updatedStore = createMockStore({
...defaultState,
positions: {
...defaultState.positions,
positions: [...mockPositions.slice(0, 2), getPositionWithClaimableBalance('0')],
},
})
rerender(
)
expect(getByTestId('DappShortcutsRewards/ClaimButton')).toBeDisabled()
expect(queryByText('dappShortcuts.claimRewardsScreen.claimButton')).toBeFalsy()
expect(getByText('dappShortcuts.claimRewardsScreen.claimedLabel')).toBeTruthy()
})
it('should show a claimed, updated reward correctly', () => {
const { getByTestId, getByText, queryByText, rerender } = render(
)
expect(getByTestId('DappShortcutsRewards/ClaimButton')).toBeEnabled()
expect(queryByText('dappShortcuts.claimRewardsScreen.claimedLabel')).toBeFalsy()
expect(getByText('dappShortcuts.claimRewardsScreen.claimButton')).toBeTruthy()
// simulate data refresh after a successful claim, for a continuously claimable reward
const updatedStore = createMockStore({
...defaultState,
positions: {
...defaultState.positions,
positions: [...mockPositions.slice(0, 2), getPositionWithClaimableBalance('0.01')],
},
})
rerender(
)
expect(getByTestId('DappShortcutsRewards/ClaimButton')).toBeEnabled()
expect(queryByText('dappShortcuts.claimRewardsScreen.claimedLabel')).toBeFalsy()
expect(getByText('dappShortcuts.claimRewardsScreen.claimButton')).toBeTruthy()
})
})