Commit 4888fe23 authored by Zach Pomerantz's avatar Zach Pomerantz Committed by GitHub

test: add jest.asMock (#6310)

* test: add jest.asMock

* test: use mocked instead

* test: split test-utils to prevent interaction

* test: whoops missed one

* Merge but actually this time
parent ef9ecd9c
......@@ -10,7 +10,7 @@ import {
TransactionDetails,
TransactionType,
} from 'state/transactions/types'
import { renderHook } from 'test-utils'
import { renderHook } from 'test-utils/render'
import { parseLocalActivity, useLocalActivities } from './parseLocal'
......
......@@ -2,13 +2,13 @@ import { BigNumber } from '@ethersproject/bignumber'
import { SupportedChainId, WETH9 } from '@uniswap/sdk-core'
import { FeeAmount, Pool, Position } from '@uniswap/v3-sdk'
import { USDC_MAINNET } from 'constants/tokens'
import { render } from 'test-utils'
import { mocked } from 'test-utils/mocked'
import { render } from 'test-utils/render'
import Pools from '.'
import useMultiChainPositions from './useMultiChainPositions'
jest.mock('./useMultiChainPositions')
const mockUseMultiChainPositions = useMultiChainPositions as jest.MockedFunction<typeof useMultiChainPositions>
const owner = '0xf5b6bb25f5beaea03dd014c6ef9fa9f3926bf36c'
......@@ -58,7 +58,7 @@ const useMultiChainPositionsReturnValue = {
}
beforeEach(() => {
mockUseMultiChainPositions.mockReturnValue(useMultiChainPositionsReturnValue)
mocked(useMultiChainPositions).mockReturnValue(useMultiChainPositionsReturnValue)
})
test('Pools should render LP positions', () => {
const props = { account: owner }
......
import { SupportedChainId } from '@uniswap/sdk-core'
import { DAI_ARBITRUM } from '@uniswap/smart-order-router'
import { DAI, USDC_ARBITRUM, USDC_MAINNET } from 'constants/tokens'
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import { PortfolioLogo } from './PortfolioLogo'
......
import { getConnections } from 'connection'
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import StatusIcon from './StatusIcon'
......
......@@ -5,19 +5,17 @@ import { USDC_MAINNET } from 'constants/tokens'
import { useToken } from 'hooks/Tokens'
import { usePool } from 'hooks/usePools'
import { PoolState } from 'hooks/usePools'
import { render } from 'test-utils'
import { mocked } from 'test-utils/mocked'
import { render } from 'test-utils/render'
import { unwrappedToken } from 'utils/unwrappedToken'
import PositionListItem from '.'
jest.mock('utils/unwrappedToken')
const mockUnwrappedToken = unwrappedToken as jest.MockedFunction<typeof unwrappedToken>
jest.mock('hooks/usePools')
const mockUsePool = usePool as jest.MockedFunction<typeof usePool>
jest.mock('hooks/Tokens')
const mockUseToken = useToken as jest.MockedFunction<typeof useToken>
// eslint-disable-next-line react/display-name
jest.mock('components/DoubleLogo', () => () => <div />)
......@@ -36,16 +34,16 @@ const susToken0Address = '0x39AA39c021dfbaE8faC545936693aC917d5E7563'
beforeEach(() => {
const susToken0 = new Token(1, susToken0Address, 8, 'https://www.example.com', 'example.com coin')
mockUseToken.mockImplementation((tokenAddress?: string | null | undefined) => {
mocked(useToken).mockImplementation((tokenAddress?: string | null | undefined) => {
if (!tokenAddress) return null
if (tokenAddress === susToken0.address) return susToken0
return new Token(1, tokenAddress, 8, 'symbol', 'name')
})
mockUsePool.mockReturnValue([
mocked(usePool).mockReturnValue([
PoolState.EXISTS,
new Pool(susToken0, USDC_MAINNET, FeeAmount.HIGH, '2437312313659959819381354528', '10272714736694327408', -69633),
])
mockUnwrappedToken.mockReturnValue(susToken0)
mocked(unwrappedToken).mockReturnValue(susToken0)
})
test('PositionListItem should not render when token0 symbol contains a url', () => {
......
......@@ -3,7 +3,7 @@ import { Currency, Percent } from '@uniswap/sdk-core'
import { FeeAmount } from '@uniswap/v3-sdk'
import { RoutingDiagramEntry } from 'components/swap/SwapRoute'
import { DAI, USDC_MAINNET, WBTC } from 'constants/tokens'
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import RoutingDiagram from './RoutingDiagram'
......
......@@ -2,7 +2,7 @@ import { screen } from '@testing-library/react'
import { Currency, CurrencyAmount as mockCurrencyAmount, Token as mockToken } from '@uniswap/sdk-core'
import { DAI, USDC_MAINNET, WBTC } from 'constants/tokens'
import * as mockJSBI from 'jsbi'
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import CurrencyList from '.'
......
import { fireEvent, render, screen } from 'test-utils'
import { fireEvent, render, screen } from 'test-utils/render'
import { ResizingTextArea, TextInput } from './'
......
import userEvent from '@testing-library/user-event'
import { useWeb3React } from '@web3-react/core'
import { useAccountDrawer } from 'components/AccountDrawer'
import { fireEvent, render, screen } from 'test-utils'
import { fireEvent, render, screen } from 'test-utils/render'
import { useFiatOnrampAvailability, useOpenModal } from '../../state/application/hooks'
import SwapBuyFiatButton, { MOONPAY_REGION_AVAILABILITY_ARTICLE } from './SwapBuyFiatButton'
......
import INJECTED_DARK_ICON from 'assets/svg/browser-wallet-dark.svg'
import INJECTED_LIGHT_ICON from 'assets/svg/browser-wallet-light.svg'
import { ConnectionType, getConnections, useGetConnection } from 'connection'
import { renderHook } from 'test-utils'
import { renderHook } from 'test-utils/render'
beforeEach(() => {
jest.resetModules()
......
......@@ -4,6 +4,7 @@ import { DAI, USDC_MAINNET } from 'constants/tokens'
import { RouterPreference } from 'state/routing/slice'
import { TradeState } from 'state/routing/types'
import { useClientSideRouter } from 'state/user/hooks'
import { mocked } from 'test-utils/mocked'
import { useRoutingAPITrade } from '../state/routing/useRoutingAPITrade'
import useAutoRouterSupported from './useAutoRouterSupported'
......@@ -29,53 +30,45 @@ jest.mock('./useIsWindowVisible')
jest.mock('state/routing/useRoutingAPITrade')
jest.mock('state/user/hooks')
const mockUseDebounce = useDebounce as jest.MockedFunction<typeof useDebounce>
const mockUseAutoRouterSupported = useAutoRouterSupported as jest.MockedFunction<typeof useAutoRouterSupported>
const mockUseIsWindowVisible = useIsWindowVisible as jest.MockedFunction<typeof useIsWindowVisible>
const mockUseRoutingAPITrade = useRoutingAPITrade as jest.MockedFunction<typeof useRoutingAPITrade>
const mockUseClientSideRouter = useClientSideRouter as jest.MockedFunction<typeof useClientSideRouter>
const mockUseClientSideV3Trade = useClientSideV3Trade as jest.MockedFunction<typeof useClientSideV3Trade>
// helpers to set mock expectations
const expectRouterMock = (state: TradeState) => {
mockUseRoutingAPITrade.mockReturnValue({ state, trade: undefined })
mocked(useRoutingAPITrade).mockReturnValue({ state, trade: undefined })
}
const expectClientSideMock = (state: TradeState) => {
mockUseClientSideV3Trade.mockReturnValue({ state, trade: undefined })
mocked(useClientSideV3Trade).mockReturnValue({ state, trade: undefined })
}
beforeEach(() => {
// ignore debounced value
mockUseDebounce.mockImplementation((value) => value)
mocked(useDebounce).mockImplementation((value) => value)
mockUseIsWindowVisible.mockReturnValue(true)
mockUseAutoRouterSupported.mockReturnValue(true)
mockUseClientSideRouter.mockReturnValue([true, () => undefined])
mocked(useIsWindowVisible).mockReturnValue(true)
mocked(useAutoRouterSupported).mockReturnValue(true)
mocked(useClientSideRouter).mockReturnValue([true, () => undefined])
})
describe('#useBestV3Trade ExactIn', () => {
it('does not compute routing api trade when routing API is not supported', async () => {
mockUseAutoRouterSupported.mockReturnValue(false)
mocked(useAutoRouterSupported).mockReturnValue(false)
expectRouterMock(TradeState.INVALID)
expectClientSideMock(TradeState.VALID)
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseRoutingAPITrade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, DAI, RouterPreference.CLIENT)
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, USDCAmount, DAI)
expect(useRoutingAPITrade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, DAI, RouterPreference.CLIENT)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, USDCAmount, DAI)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
it('does not compute routing api trade when window is not focused', async () => {
mockUseIsWindowVisible.mockReturnValue(false)
mocked(useIsWindowVisible).mockReturnValue(false)
expectRouterMock(TradeState.NO_ROUTE_FOUND)
expectClientSideMock(TradeState.VALID)
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseRoutingAPITrade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, DAI, RouterPreference.CLIENT)
expect(useRoutingAPITrade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, DAI, RouterPreference.CLIENT)
expect(result.current).toEqual({ state: TradeState.NO_ROUTE_FOUND, trade: undefined })
})
......@@ -85,7 +78,7 @@ describe('#useBestV3Trade ExactIn', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.LOADING, trade: undefined })
})
......@@ -94,7 +87,7 @@ describe('#useBestV3Trade ExactIn', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
......@@ -103,7 +96,7 @@ describe('#useBestV3Trade ExactIn', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.SYNCING, trade: undefined })
})
})
......@@ -115,7 +108,7 @@ describe('#useBestV3Trade ExactIn', () => {
renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, undefined, undefined)
})
it('computes client side v3 trade if routing api is NO_ROUTE_FOUND', () => {
......@@ -124,7 +117,7 @@ describe('#useBestV3Trade ExactIn', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_INPUT, USDCAmount, DAI))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, USDCAmount, DAI)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_INPUT, USDCAmount, DAI)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
})
......@@ -132,30 +125,30 @@ describe('#useBestV3Trade ExactIn', () => {
describe('#useBestV3Trade ExactOut', () => {
it('does not compute routing api trade when routing API is not supported', () => {
mockUseAutoRouterSupported.mockReturnValue(false)
mocked(useAutoRouterSupported).mockReturnValue(false)
expectRouterMock(TradeState.INVALID)
expectClientSideMock(TradeState.VALID)
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseRoutingAPITrade).toHaveBeenCalledWith(
expect(useRoutingAPITrade).toHaveBeenCalledWith(
TradeType.EXACT_OUTPUT,
undefined,
USDC_MAINNET,
RouterPreference.CLIENT
)
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
it('does not compute routing api trade when window is not focused', () => {
mockUseIsWindowVisible.mockReturnValue(false)
mocked(useIsWindowVisible).mockReturnValue(false)
expectRouterMock(TradeState.NO_ROUTE_FOUND)
expectClientSideMock(TradeState.VALID)
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseRoutingAPITrade).toHaveBeenCalledWith(
expect(useRoutingAPITrade).toHaveBeenCalledWith(
TradeType.EXACT_OUTPUT,
undefined,
USDC_MAINNET,
......@@ -169,7 +162,7 @@ describe('#useBestV3Trade ExactOut', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.LOADING, trade: undefined })
})
......@@ -178,7 +171,7 @@ describe('#useBestV3Trade ExactOut', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
......@@ -187,7 +180,7 @@ describe('#useBestV3Trade ExactOut', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(result.current).toEqual({ state: TradeState.SYNCING, trade: undefined })
})
})
......@@ -199,7 +192,7 @@ describe('#useBestV3Trade ExactOut', () => {
renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, undefined, undefined)
})
it('computes client side v3 trade if routing api is NO_ROUTE_FOUND', () => {
......@@ -208,7 +201,7 @@ describe('#useBestV3Trade ExactOut', () => {
const { result } = renderHook(() => useBestTrade(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET))
expect(mockUseClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET)
expect(useClientSideV3Trade).toHaveBeenCalledWith(TradeType.EXACT_OUTPUT, DAIAmount, USDC_MAINNET)
expect(result.current).toEqual({ state: TradeState.VALID, trade: undefined })
})
})
......
import { WARNING_LEVEL } from 'constants/tokenSafety'
import { renderHook } from 'test-utils'
import { renderHook } from 'test-utils/render'
import { lightTheme } from 'theme/colors'
import { useTokenWarningColor, useTokenWarningTextColor } from './useTokenWarningColor'
......
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import Bag from './Bag'
......
import { Markets } from 'nft/types'
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import { MarketplaceContainer } from './icons'
......
import { render } from 'test-utils'
import { render } from 'test-utils/render'
import { EmptyWalletModule } from './EmptyWalletContent'
......
import * as useV3Positions from 'hooks/useV3Positions'
import { render, screen } from 'test-utils'
import { render, screen } from 'test-utils/render'
import CTACards from './CTACards'
......
import * as chains from 'constants/chains'
import * as useV3Positions from 'hooks/useV3Positions'
import { render, screen } from 'test-utils'
import { render, screen } from 'test-utils/render'
import Pool from '.'
......
import { act, renderHook } from 'test-utils'
import { act, renderHook } from 'test-utils/render'
import { useConnectedWallets } from './hooks'
import { Wallet } from './types'
......
/**
* Casts the passed function as a jest.Mock.
* Use this in combination with jest.mock() to safely access functions from mocked modules.
*
* @example
*
* import { useExample } from 'example'
* jest.mock('example', () => ({ useExample: jest.fn() }))
* beforeEach(() => {
* asMock(useExample).mockImplementation(() => ...)
* })
*/
// jest expects mocks to be coerced (eg fn as jest.MockedFunction<T>), but this is not ergonomic when using ASI.
// Instead, we use this utility function to improve readability and add a check to ensure the function is a mock.
export function mocked<T extends (...args: any) => any>(fn: T) {
if (!jest.isMockFunction(fn)) throw new Error('fn is not a mock')
return fn as jest.MockedFunction<T>
}
......@@ -5,6 +5,7 @@ import { render, renderHook } from '@testing-library/react'
import Web3Provider from 'components/Web3Provider'
import { DEFAULT_LOCALE } from 'constants/locales'
import { BlockNumberProvider } from 'lib/hooks/useBlockNumber'
import catalog from 'locales/en-US'
import { en } from 'make-plural/plurals'
import { ReactElement, ReactNode } from 'react'
import { QueryClient, QueryClientProvider } from 'react-query'
......@@ -13,8 +14,6 @@ import { HashRouter } from 'react-router-dom'
import store from 'state'
import ThemeProvider from 'theme'
import catalog from './locales/en-US'
i18n.load({
[DEFAULT_LOCALE]: catalog.messages,
})
......
......@@ -3,6 +3,7 @@ import '@sentry/tracing' // required to populate Sentry.startTransaction, which
import * as Sentry from '@sentry/react'
import { Transaction } from '@sentry/tracing'
import assert from 'assert'
import { mocked } from 'test-utils/mocked'
import { trace } from './trace'
......@@ -11,10 +12,9 @@ jest.mock('@sentry/react', () => {
startTransaction: jest.fn(),
}
})
const startTransaction = Sentry.startTransaction as jest.Mock
function getTransaction(index = 0): Transaction {
const transactions = startTransaction.mock.results.map(({ value }) => value)
const transactions = mocked(Sentry.startTransaction).mock.results.map(({ value }) => value)
expect(transactions).toHaveLength(index + 1)
const transaction = transactions[index]
expect(transaction).toBeDefined()
......@@ -23,12 +23,13 @@ function getTransaction(index = 0): Transaction {
describe('trace', () => {
beforeEach(() => {
const Sentry = jest.requireActual('@sentry/react')
startTransaction.mockReset().mockImplementation((context) => {
const transaction: Transaction = Sentry.startTransaction(context)
transaction.initSpanRecorder()
return transaction
})
mocked(Sentry.startTransaction)
.mockReset()
.mockImplementation((context) => {
const transaction: Transaction = jest.requireActual('@sentry/react').startTransaction(context)
transaction.initSpanRecorder()
return transaction
})
})
it('propagates callback', async () => {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment