Skip to content

Commit a4eb04b

Browse files
authored
Merge pull request #1712 from curvefi/test/wagmi-connector-for-e2e-tests
test: add e2e tests for loan and lend market page
2 parents 382f22c + 4e2d442 commit a4eb04b

File tree

19 files changed

+162
-81
lines changed

19 files changed

+162
-81
lines changed
Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,35 @@
11
import { useMemo } from 'react'
22
import type { Chain } from 'viem'
3+
import { generatePrivateKey } from 'viem/accounts'
34
import { mapRecord, recordValues } from '@curvefi/prices-api/objects.util'
45
import type { NetworkMapping } from '@ui/utils'
6+
import { Chain as ChainEnum, isCypress, noCypressTestConnector } from '@ui-kit/utils'
57
import { createChainFromNetwork } from './chains'
68
import { defaultGetRpcUrls } from './rpc'
79
import { createTransportFromNetwork } from './transports'
810
import { createWagmiConfig } from './wagmi-config'
11+
import { createTestConnector } from './wagmi-test'
912

1013
export const useWagmiConfig = <T extends NetworkMapping>(networks: T | undefined) =>
11-
useMemo(
12-
() =>
13-
networks &&
14-
createWagmiConfig({
15-
chains: recordValues(networks).map((network) => createChainFromNetwork(network, defaultGetRpcUrls)) as [
16-
Chain,
17-
...Chain[],
18-
],
19-
transports: mapRecord(networks, (_, network) => createTransportFromNetwork(network, defaultGetRpcUrls)),
20-
}),
21-
[networks],
22-
)
14+
useMemo(() => {
15+
if (networks == null) return
16+
17+
const chains = recordValues(networks).map((network) => createChainFromNetwork(network, defaultGetRpcUrls)) as [
18+
Chain,
19+
...Chain[],
20+
]
21+
22+
return createWagmiConfig({
23+
chains,
24+
transports: mapRecord(networks, (_, network) => createTransportFromNetwork(network, defaultGetRpcUrls)),
25+
...(isCypress &&
26+
!noCypressTestConnector && {
27+
connectors: [
28+
createTestConnector({
29+
privateKey: generatePrivateKey(),
30+
chain: chains.find((chain) => chain.id === ChainEnum.Ethereum)!,
31+
})!,
32+
],
33+
}),
34+
})
35+
}, [networks])

tests/cypress/support/helpers/test-connector.ts renamed to packages/curve-ui-kit/src/features/connect-wallet/lib/wagmi/wagmi-test.ts

Lines changed: 33 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,65 @@
11
import {
2-
type Chain,
32
createWalletClient,
43
custom,
54
fallback,
6-
type Hex,
75
http,
8-
PrivateKeyAccount,
9-
type RpcTransactionRequest,
6+
type Address,
7+
type Chain,
8+
type CustomTransport,
9+
type Hex,
10+
type PrivateKeyAccount,
1011
} from 'viem'
1112
import { privateKeyToAccount } from 'viem/accounts'
12-
import type { TenderlyConfig } from '@cy/support/helpers/tenderly/account'
13-
import { Address } from '@ui-kit/utils'
14-
import { createConnector, type CreateConnectorFn } from '@wagmi/core'
15-
import { sendVnetTransaction } from './tenderly/vnet-transaction'
16-
17-
type Options = {
18-
/** A hexadecimal private key used to generate a test account */
19-
privateKey: Hex
20-
/** The testnet chain configuration */
21-
chain: Chain
22-
/** Tenderly configuration for the Virtual Testnet */
23-
tenderly: TenderlyConfig
24-
}
13+
import { type CreateConnectorFn, createConnector } from 'wagmi'
2514

2615
type ConnectParams<T> = { chainId?: number; isReconnecting?: boolean; withCapabilities: T }
2716
type ConnectResult<T> = { accounts: readonly T[]; chainId: number }
2817
type Account = { address: Address; capabilities: Record<string, unknown> }
2918

30-
/**
31-
* Creates a custom transport that intercepts JSON-RPC requests to handle account retrieval and
32-
* transaction sending via Tenderly Virtual Testnet Admin API.
33-
*
34-
* This is necessary because our code under test uses a BrowserProvider with http transport,
35-
* which relies on RPC methods to retrieve accounts and send transactions.
36-
*/
37-
const customTransport = (account: PrivateKeyAccount, tenderly: TenderlyConfig) =>
19+
/** Default custom transport for Cypress E2E tests, read-only */
20+
const cypressTransport = (account: PrivateKeyAccount) =>
3821
custom({
39-
request: async ({ method, params: [param] }): Promise<any> => {
22+
request: async ({ method }): Promise<any> => {
4023
if (method === 'eth_accounts') {
4124
return [account.address]
4225
}
43-
if (method === 'eth_sendTransaction') {
44-
return await sendVnetTransaction({ tenderly, tx: param as RpcTransactionRequest }).catch((err) => {
45-
console.error(`Tenderly failed for ${method}(${JSON.stringify(param)}). Error: ${err}`)
46-
throw err
47-
})
48-
}
4926
throw new Error(`Unsupported method: ${method}, http fallback is used`)
5027
},
5128
})
5229

30+
export type CreateTestConnectorOptions = {
31+
/** A hexadecimal private key used to generate a test account */
32+
privateKey: Hex
33+
/** The testnet chain configuration */
34+
chain: Chain
35+
/**
36+
* Creates a custom transport that intercepts JSON-RPC requests to handle account retrieval and such.
37+
*
38+
* This is necessary because our code under test uses a BrowserProvider with http transport,
39+
* which relies on RPC methods not always available to retrieve accounts and send transactions.
40+
*
41+
* Defaults to a read-only custom transport for Cypress.
42+
*/
43+
transport?: (account: PrivateKeyAccount) => CustomTransport
44+
}
45+
5346
/**
54-
* Cypress test connector for Wagmi.
47+
* Creates a wagmi test connector for Cypress.
5548
*
56-
* This connector is designed for use in test environments (e.g., Cypress) with a testnet chain.
57-
* It creates a wallet using a custom seed (private key) to allow testing contract write calls
49+
* This connector is designed for use in test environments (e.g., Cypress) with optionally a testnet chain.
50+
* It creates a wallet using a custom seed (private key) to allow testing contract read and write calls
5851
* without relying on third-party browser extensions like MetaMask.
5952
*/
60-
export function createTestConnector({ privateKey, chain, tenderly }: Options): CreateConnectorFn {
53+
export function createTestConnector({ privateKey, chain, transport }: CreateTestConnectorOptions): CreateConnectorFn {
6154
const account = privateKeyToAccount(privateKey)
6255

6356
const client = createWalletClient({
6457
account,
6558
chain,
66-
transport: fallback([customTransport(account, tenderly), ...chain.rpcUrls.default.http.map((url) => http(url))]),
59+
transport: fallback([
60+
(transport ?? cypressTransport)(account),
61+
...chain.rpcUrls.default.http.map((url) => http(url)),
62+
]),
6763
})
6864

6965
// A connect function with overloads to satisfy Wagmi's conditional return type

packages/curve-ui-kit/src/utils/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export enum ReleaseChannel {
1818
}
1919

2020
export const isCypress = Boolean((window as { Cypress?: unknown }).Cypress)
21+
export const noCypressTestConnector = Boolean((window as { CypressNoTestConnector?: unknown }).CypressNoTestConnector)
2122

2223
const isDefaultBeta =
2324
process.env.NODE_ENV === 'development' ||

tests/cypress/component/llamalend/borrow-tab-contents.rpc.cy.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useMemo } from 'react'
1+
import { useMemo } from 'react'
22
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts'
33
import { prefetchMarkets } from '@/lend/entities/chain/chain-query'
44
import { CreateLoanForm } from '@/llamalend/features/borrow/components/CreateLoanForm'
@@ -7,7 +7,7 @@ import type { CreateLoanOptions } from '@/llamalend/mutations/create-loan.mutati
77
import networks from '@/loan/networks'
88
import { oneBool, oneValueOf } from '@cy/support/generators'
99
import { ComponentTestWrapper } from '@cy/support/helpers/ComponentTestWrapper'
10-
import { createTestWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
10+
import { createTenderlyWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
1111
import { getRpcUrls } from '@cy/support/helpers/tenderly/vnet'
1212
import { fundErc20, fundEth } from '@cy/support/helpers/tenderly/vnet-fund'
1313
import { LOAD_TIMEOUT } from '@cy/support/ui'
@@ -80,7 +80,10 @@ describe('BorrowTabContents Component Tests', () => {
8080
})
8181

8282
const BorrowTabTestWrapper = (props: BorrowTabTestProps) => (
83-
<ComponentTestWrapper config={createTestWagmiConfigFromVNet({ vnet: getVirtualNetwork(), privateKey })} autoConnect>
83+
<ComponentTestWrapper
84+
config={createTenderlyWagmiConfigFromVNet({ vnet: getVirtualNetwork(), privateKey })}
85+
autoConnect
86+
>
8487
<ConnectionProvider
8588
app="llamalend"
8689
network={networks[chainId]}

tests/cypress/component/llamalend/manage-soft-liq.rpc.cy.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { prefetchMarkets } from '@/lend/entities/chain/chain-query'
33
import { ManageSoftLiquidation } from '@/llamalend/features/manage-soft-liquidation'
44
import networks from '@/loan/networks'
55
import { ComponentTestWrapper } from '@cy/support/helpers/ComponentTestWrapper'
6-
import { createTestWagmiConfigFromVNet, forkVirtualTestnet } from '@cy/support/helpers/tenderly'
6+
import { createTenderlyWagmiConfigFromVNet, forkVirtualTestnet } from '@cy/support/helpers/tenderly'
77
import Skeleton from '@mui/material/Skeleton'
88
import { ConnectionProvider, useConnection } from '@ui-kit/features/connect-wallet'
99
import { Chain } from '@ui-kit/utils'
@@ -29,7 +29,10 @@ describe('Manage soft liquidation', () => {
2929
}
3030

3131
const TestComponentWrapper = () => (
32-
<ComponentTestWrapper config={createTestWagmiConfigFromVNet({ vnet: getVirtualNetwork(), privateKey })} autoConnect>
32+
<ComponentTestWrapper
33+
config={createTenderlyWagmiConfigFromVNet({ vnet: getVirtualNetwork(), privateKey })}
34+
autoConnect
35+
>
3336
<ConnectionProvider
3437
app="llamalend"
3538
network={network}

tests/cypress/component/loan/peg-stability-reserve.rpc.cy.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { PegKeeper } from '@/loan/components/PagePegKeepers/components/PegKeeper'
22
import { PEG_KEEPERS } from '@/loan/components/PagePegKeepers/constants'
33
import { ComponentTestWrapper, type Config } from '@cy/support/helpers/ComponentTestWrapper'
4-
import { createTestWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
4+
import { createTenderlyWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
55

66
const getVirtualNetwork = createVirtualTestnet((uuid) => ({
77
slug: `pegkeepers-${uuid}`,
@@ -25,7 +25,7 @@ describe('Peg stability reserve', () => {
2525
return
2626
}
2727

28-
const config = createTestWagmiConfigFromVNet({ vnet })
28+
const config = createTenderlyWagmiConfigFromVNet({ vnet })
2929
cy.mount(<TestComponent config={config} />)
3030

3131
// Initial data when not connected

tests/cypress/component/root-layout.rpc.cy.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import React from 'react'
21
import { useNetworksQuery } from '@/dex/entities/networks'
32
import { ComponentTestWrapper } from '@cy/support/helpers/ComponentTestWrapper'
4-
import { createTestWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
3+
import { createTenderlyWagmiConfigFromVNet, createVirtualTestnet } from '@cy/support/helpers/tenderly'
54
import Box from '@mui/material/Box'
65
import { ConnectionProvider } from '@ui-kit/features/connect-wallet/lib/ConnectionProvider'
76
import { usePathname } from '@ui-kit/hooks/router'
@@ -34,7 +33,7 @@ describe('RootLayout RPC Tests', () => {
3433

3534
it(`redirects to arbitrum when the wallet is connected to it`, () => {
3635
cy.mount(
37-
<ComponentTestWrapper config={createTestWagmiConfigFromVNet({ vnet: getVirtualNetwork() })} autoConnect>
36+
<ComponentTestWrapper config={createTenderlyWagmiConfigFromVNet({ vnet: getVirtualNetwork() })} autoConnect>
3837
<Test />
3938
</ComponentTestWrapper>,
4039
)

tests/cypress/e2e/all/header.cy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ describe('Header', () => {
2727
viewport = oneDesktopViewport()
2828
cy.viewport(...viewport)
2929
route = oneAppRoute()
30-
cy.visit(`/${route}`)
30+
cy.visitWithoutTestConnector(route)
3131
waitIsLoaded(route)
3232
})
3333

@@ -89,7 +89,7 @@ describe('Header', () => {
8989
viewport = oneMobileOrTabletViewport()
9090
cy.viewport(...viewport)
9191
route = oneAppRoute()
92-
cy.visit(`/${route}`)
92+
cy.visitWithoutTestConnector(route)
9393
waitIsLoaded(route)
9494
})
9595

tests/cypress/e2e/lend/basic.cy.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,9 @@ describe('Basic Access Test', () => {
1616
cy.url(LOAD_TIMEOUT).should('match', /http:\/\/localhost:\d+\/lend\/ethereum\/legal\/?\?tab=disclaimers$/)
1717
cy.title().should('equal', 'Legal - Curve Lend')
1818
})
19+
20+
it('should open a lend market page succesfully', () => {
21+
cy.visit('/lend/ethereum/markets/0x23F5a668A9590130940eF55964ead9787976f2CC') // some WETH lend market on ethereum
22+
cy.get('[data-testid^="detail-page-stack"]', LOAD_TIMEOUT).should('be.visible')
23+
})
1924
})

tests/cypress/e2e/loan/basic.cy.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,9 @@ describe('Basic Access Test', () => {
1111
cy.title(LOAD_TIMEOUT).should('equal', 'Savings crvUSD - Curve')
1212
cy.url().should('match', /http:\/\/localhost:\d+\/crvusd\/ethereum\/scrvUSD\/?$/)
1313
})
14+
15+
it('should open a loan market page succesfully', () => {
16+
cy.visit('/crvusd/ethereum/markets/WBTC') // some WBTC mint market on ethereum
17+
cy.get('[data-testid^="detail-page-stack"]', LOAD_TIMEOUT).should('be.visible')
18+
})
1419
})

0 commit comments

Comments
 (0)