Skip to content

Commit

Permalink
Fix tests for newly completed transactions
Browse files Browse the repository at this point in the history
  • Loading branch information
sviderock committed Oct 15, 2024
1 parent d4fbb9b commit 5944819
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 65 deletions.
133 changes: 79 additions & 54 deletions src/transactions/feed/TransactionFeedV2.test.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { fireEvent, render, waitFor, within } from '@testing-library/react-native'
import { act, fireEvent, render, waitFor, within } from '@testing-library/react-native'
import { FetchMock } from 'jest-fetch-mock/types'
import React from 'react'
import Toast from 'react-native-simple-toast'
Expand All @@ -10,14 +10,18 @@ import { getDynamicConfigParams, getFeatureGate, getMultichainFeatures } from 's
import TransactionFeedV2 from 'src/transactions/feed/TransactionFeedV2'
import {
NetworkId,
StandbyTransaction,
TokenTransaction,
TokenTransactionTypeV2,
TransactionStatus,
} from 'src/transactions/types'
import { mockCusdAddress, mockCusdTokenId } from 'test/values'
import { mockCeloTokenId, mockCusdAddress, mockCusdTokenId, mockQRCodeRecipient } from 'test/values'

import BigNumber from 'bignumber.js'
import { Action } from 'redux-saga'
import { ApiReducersKeys } from 'src/redux/apiReducersList'
import { vibrateSuccess } from 'src/styles/hapticFeedback'
import { addStandbyTransaction, transactionConfirmed } from 'src/transactions/actions'
import { transactionFeedV2Api, type TransactionFeedV2Response } from 'src/transactions/api'
import { setupApiStore } from 'src/transactions/apiTestHelpers'
import { RecursivePartial } from 'test/utils'
Expand All @@ -29,7 +33,7 @@ jest.mock('src/styles/hapticFeedback')
const STAND_BY_TRANSACTION_SUBTITLE_KEY = 'confirmingTransaction'
const mockFetch = fetch as FetchMock

function mockTransaction(data?: Partial<TokenTransaction>): TokenTransaction {
function mockTransaction(data?: Partial<TokenTransaction | StandbyTransaction>): TokenTransaction {
return {
__typename: 'TokenTransferV3',
networkId: NetworkId['celo-alfajores'],
Expand Down Expand Up @@ -434,65 +438,86 @@ describe('TransactionFeedV2', () => {
await waitFor(() => expect(tree.queryByTestId('TransactionList/loading')).toBeFalsy())
await waitFor(() => expect(Toast.showWithGravity).toBeCalledTimes(0))
})
})

it('should vibrate when there are new completed transactions', async () => {
mockFetch.mockResponse(typedResponse({ transactions: [mockTransaction()] }))
const { store } = renderScreen({ transactions: { standbyTransactions: [mockTransaction()] } })

await waitFor(() => expect(store.getState().transactions.standbyTransactions.length).toBe(0))
expect(vibrateSuccess).toHaveBeenCalledTimes(1)
})

it('should vibrate when there are pending transactions that turned into completed', async () => {
const standByTransactionHash = '0x02' as string
mockFetch
.mockResponseOnce(
typedResponse({ transactions: [mockTransaction({ transactionHash: '0x01' })] })
)
.mockResponseOnce(
it('should vibrate when there is a pending transaction that turned into completed', async () => {
const standByTransactionHash = '0x02' as string
mockFetch.mockResponseOnce(typedResponse({ transactions: [] })).mockResponseOnce(
typedResponse({
transactions: [
mockTransaction({ transactionHash: '0x01' }),
mockTransaction({ transactionHash: standByTransactionHash }),
],
transactions: [mockTransaction({ transactionHash: standByTransactionHash })],
})
)

const { store, rerender, ...tree } = renderScreen({
transactions: {
standbyTransactions: [
mockTransaction({
transactionHash: standByTransactionHash,
status: TransactionStatus.Pending,
}),
],
},
})
const { store, ...tree } = renderScreen({
transactions: {
standbyTransactions: [
mockTransaction({
context: { id: standByTransactionHash },
transactionHash: standByTransactionHash,
status: TransactionStatus.Pending,
}),
],
},
})

await waitFor(() => expect(tree.getByTestId('TransactionList').props.data.length).toBe(2))
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(1)
expect(tree.getByTestId('TransactionList').props.data[1].data.length).toBe(1)
const updatedStore = getInitialStore({
transactions: {
standbyTransactions: [
mockTransaction({
transactionHash: standByTransactionHash,
status: TransactionStatus.Complete,
}),
],
},
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(1)

// imitate changing of pending stand by transaction to confirmed
await act(() => {
const changePendingToConfirmed = transactionConfirmed(
standByTransactionHash,
{ status: TransactionStatus.Complete, transactionHash: standByTransactionHash, block: '' },
mockTransaction().timestamp
) as Action
store.dispatch(changePendingToConfirmed)
})

await waitFor(() => {
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(1)
})
expect(vibrateSuccess).toHaveBeenCalledTimes(1)
})

rerender(
<Provider store={updatedStore}>
<TransactionFeedV2 />
</Provider>
)
it('should not vibrate when there is a new pending transaction', async () => {
const pendingStandByTransactionHash1 = '0x01' as string
const pendingStandByTransactionHash2 = '0x02' as string
const { store, rerender, ...tree } = renderScreen({
transactions: {
standbyTransactions: [
mockTransaction({
context: { id: pendingStandByTransactionHash1 },
transactionHash: pendingStandByTransactionHash1,
status: TransactionStatus.Pending,
}),
],
},
})

await waitFor(() => expect(tree.getByTestId('TransactionList').props.data.length).toBe(1))
await waitFor(() => {
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(2)
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(1)

await act(() => {
const newPendingTransaction = addStandbyTransaction({
__typename: 'TokenTransferV3',
context: { id: pendingStandByTransactionHash2 },
type: TokenTransactionTypeV2.Sent,
networkId: NetworkId['celo-alfajores'],
amount: {
value: BigNumber(10).negated().toString(),
tokenAddress: mockCusdAddress,
tokenId: mockCusdTokenId,
},
address: mockQRCodeRecipient.address,
metadata: {},
feeCurrencyId: mockCeloTokenId,
transactionHash: pendingStandByTransactionHash2,
}) as Action
store.dispatch(newPendingTransaction)
})

await waitFor(() => {
expect(tree.getByTestId('TransactionList').props.data[0].data.length).toBe(2)
})
expect(vibrateSuccess).not.toHaveBeenCalled()
})
await waitFor(() => expect(vibrateSuccess).toBeCalled())

// it('should vibrate when there are new completed transactions', () => {})

Check failure on line 522 in src/transactions/feed/TransactionFeedV2.test.tsx

View workflow job for this annotation

GitHub Actions / Lint

Some tests seem to be commented
})
23 changes: 12 additions & 11 deletions src/transactions/feed/TransactionFeedV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -192,15 +192,15 @@ function useStandByTransactions() {
function useNewlyCompletedTransactions(
standByTransactions: ReturnType<typeof useStandByTransactions>
) {
const [prevStandBy, setPrevStandBy] = useState({
const [previousStandBy, setPreviousStandBy] = useState({
pending: [] as string[],
confirmed: [] as string[],
hasNewlyCompletedTransactions: false,
})

useEffect(
function updatePrevStandBy() {
setPrevStandBy((prev) => {
setPreviousStandBy((prev) => {
const pendingHashes = standByTransactions.pending.map((tx) => tx.transactionHash)
const confirmedHashes = standByTransactions.confirmed.map((tx) => tx.transactionHash)
const hasNewlyCompletedTransactions = prev.pending.some((hash) => {
Expand All @@ -217,7 +217,7 @@ function useNewlyCompletedTransactions(
[standByTransactions]
)

return prevStandBy.hasNewlyCompletedTransactions
return previousStandBy.hasNewlyCompletedTransactions
}

function renderItem({ item: tx }: { item: TokenTransaction }) {
Expand Down Expand Up @@ -350,14 +350,15 @@ export default function TransactionFeedV2() {
[data?.transactions]
)

useEffect(() => {
if (originalArgs?.endCursor === undefined) return

const isFirstPage = originalArgs.endCursor === FIRST_PAGE_TIMESTAMP
if (isFirstPage && newlyCompletedTransactions) {
vibrateSuccess()
}
}, [newlyCompletedTransactions, originalArgs])
useEffect(
function vibrateForNewCompletedTransactions() {
const isFirstPage = originalArgs?.endCursor === FIRST_PAGE_TIMESTAMP
if (isFirstPage && newlyCompletedTransactions) {
vibrateSuccess()
}
},
[newlyCompletedTransactions, originalArgs]
)

const confirmedTransactions = useMemo(() => {
const flattenedPages = Object.values(paginatedData).flat()
Expand Down

0 comments on commit 5944819

Please sign in to comment.