-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b12fade
commit 6d0be56
Showing
9 changed files
with
390 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { createConfig, http } from '@wagmi/core' | ||
import { mock } from '@wagmi/core/internal' | ||
import { base as viem_base } from 'viem/chains' | ||
import { accounts } from './constants.js' | ||
import { getRpcUrls } from './utils.js' | ||
|
||
const base = { | ||
...getRpcUrls({ port: 8547 }), | ||
...viem_base, | ||
fork: { | ||
blockNumber: process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER | ||
? BigInt(Number(process.env.VITE_OPTIMISM_FORK_BLOCK_NUMBER)) | ||
: 5940037n, | ||
url: process.env.VITE_OPTIMISM_FORK_URL ?? 'https://mainnet.base.org', | ||
}, | ||
} | ||
|
||
export const config = createConfig({ | ||
chains: [base], | ||
connectors: [mock({ accounts })], | ||
pollingInterval: 100, | ||
storage: null, | ||
transports: { | ||
[base.id]: http(), | ||
}, | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* The id of the current test worker. | ||
* | ||
* This is used by the anvil proxy to route requests to the correct anvil instance. | ||
*/ | ||
export const pool = Number(process.env.VITEST_POOL_ID ?? 1) | ||
|
||
// Test accounts | ||
export const accounts = ['0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266'] as const | ||
|
||
const messages = new Map() | ||
function warn(message: string) { | ||
if (!messages.has(message)) { | ||
messages.set(message, true) | ||
console.warn(message) | ||
} | ||
} | ||
|
||
export let forkBlockNumber: bigint | ||
if (process.env.VITE_ANVIL_BLOCK_NUMBER) { | ||
forkBlockNumber = BigInt(Number(process.env.VITE_ANVIL_BLOCK_NUMBER)) | ||
} else { | ||
forkBlockNumber = 18136086n | ||
warn( | ||
`\`VITE_ANVIL_BLOCK_NUMBER\` not found. Falling back to \`${forkBlockNumber}\`.`, | ||
) | ||
} | ||
|
||
export let forkUrl: string | ||
if (process.env.VITE_ANVIL_FORK_URL) { | ||
forkUrl = process.env.VITE_ANVIL_FORK_URL | ||
} else { | ||
forkUrl = 'https://cloudflare-eth.com' | ||
warn(`\`VITE_ANVIL_FORK_URL\` not found. Falling back to \`${forkUrl}\`.`) | ||
} | ||
|
||
export let blockTime: number | ||
if (process.env.VITE_ANVIL_BLOCK_TIME) { | ||
blockTime = Number(process.env.VITE_ANVIL_BLOCK_TIME) | ||
} else { | ||
blockTime = 1 | ||
warn(`\`VITE_ANVIL_BLOCK_TIME\` not found. Falling back to \`${blockTime}\`.`) | ||
} | ||
|
||
export let rollupForkBlockNumber: bigint | ||
if (process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER) { | ||
rollupForkBlockNumber = BigInt( | ||
Number(process.env.VITE_ANVIL_ROLLUP_BLOCK_NUMBER), | ||
) | ||
} else { | ||
rollupForkBlockNumber = 3709321n | ||
warn( | ||
`\`VITE_ANVIL_ROLLUP_BLOCK_NUMBER\` not found. Falling back to \`${rollupForkBlockNumber}\`.`, | ||
) | ||
} | ||
|
||
export let rollupForkUrl: string | ||
if (process.env.VITE_ANVIL_ROLLUP_FORK_URL) { | ||
rollupForkUrl = process.env.VITE_ANVIL_ROLLUP_FORK_URL | ||
} else { | ||
rollupForkUrl = 'https://mainnet.base.org' | ||
warn( | ||
`\`VITE_ANVIL_ROLLUP_FORK_URL\` not found. Falling back to \`${rollupForkUrl}\`.`, | ||
) | ||
} | ||
|
||
export let rollupBlockTime: number | ||
if (process.env.VITE_ANVIL_ROLLUP_BLOCK_TIME) { | ||
rollupBlockTime = Number(process.env.VITE_ANVIL_ROLLUP_BLOCK_TIME) | ||
} else { | ||
rollupBlockTime = 1 | ||
warn( | ||
`\`VITE_ANVIL_ROLLUP_BLOCK_TIME\` not found. Falling back to \`${rollupBlockTime}\`.`, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
// from https://github.com/wagmi-dev/viem/blob/main/src/_test/globalSetup.ts | ||
import { startProxy } from '@viem/anvil' | ||
|
||
import { | ||
blockTime, | ||
forkBlockNumber, | ||
forkUrl, | ||
rollupBlockTime, | ||
rollupForkBlockNumber, | ||
rollupForkUrl, | ||
} from './constants.js' | ||
|
||
export default async function() { | ||
if (process.env.SKIP_GLOBAL_SETUP) { | ||
return | ||
} | ||
|
||
// Using this proxy, we can parallelize our test suite by spawning multiple "on demand" anvil | ||
// instances and proxying requests to them. Especially for local development, this is much faster | ||
// than running the tests serially. | ||
// | ||
// In vitest, each thread is assigned a unique, numerical id (`process.env.VITEST_POOL_ID`). We | ||
// append this id to the local rpc url (e.g. `http://127.0.0.1:8545/<ID>`). | ||
// | ||
// Whenever a request hits the proxy server at this url, it spawns (or reuses) an anvil instance | ||
// at a randomly assigned port and proxies the request to it. The anvil instance is added to a | ||
// [id:port] mapping for future request and is kept alive until the test suite finishes. | ||
// | ||
// Since each thread processes one test file after the other, we don't have to worry about | ||
// non-deterministic behavior caused by multiple tests hitting the same anvil instance concurrently | ||
// as long as we avoid `test.concurrent()`. | ||
// | ||
// We still need to remember to reset the anvil instance between test files. This is generally | ||
// handled in `setup.ts` but may require additional resetting (e.g. via `afterAll`), in case of | ||
// any custom per-test adjustments that persist beyond `anvil_reset`. | ||
await startProxy({ | ||
port: 8555, | ||
options: { | ||
forkUrl: rollupForkUrl, | ||
forkBlockNumber: rollupForkBlockNumber, | ||
blockTime: rollupBlockTime, | ||
}, | ||
}) | ||
return await startProxy({ | ||
options: { | ||
forkUrl, | ||
forkBlockNumber, | ||
blockTime, | ||
}, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query' | ||
import { | ||
renderHook as rtl_renderHook, | ||
type RenderHookOptions, | ||
type RenderHookResult, | ||
waitFor as rtl_waitFor, | ||
type waitForOptions, | ||
} from '@testing-library/react' | ||
import { createElement } from 'react' | ||
import { WagmiProvider } from 'wagmi' | ||
export { act, cleanup } from '@testing-library/react' | ||
|
||
import { config } from './config.js' | ||
|
||
export const queryClient = new QueryClient() | ||
|
||
export function createWrapper<TComponent extends React.FunctionComponent<any>>( | ||
Wrapper: TComponent, | ||
props: Parameters<TComponent>[0], | ||
) { | ||
type Props = { children?: React.ReactNode | undefined } | ||
return function CreatedWrapper({ children }: Props) { | ||
return createElement( | ||
Wrapper, | ||
props, | ||
createElement(QueryClientProvider, { client: queryClient }, children), | ||
) | ||
} | ||
} | ||
|
||
export function renderHook<Result, Props>( | ||
render: (props: Props) => Result, | ||
options?: RenderHookOptions<Props> | undefined, | ||
): RenderHookResult<Result, Props> { | ||
queryClient.clear() | ||
return rtl_renderHook(render, { | ||
wrapper: createWrapper(WagmiProvider, { config, reconnectOnMount: false }), | ||
...options, | ||
}) | ||
} | ||
|
||
export function waitFor<T>( | ||
callback: () => Promise<T> | T, | ||
options?: waitForOptions | undefined, | ||
): Promise<T> { | ||
return rtl_waitFor(callback, { timeout: 10_000, ...options }) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import { vi } from 'vitest' | ||
|
||
// Make dates stable across runs | ||
Date.now = vi.fn(() => new Date(Date.UTC(2023, 10, 20)).valueOf()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { pool } from './constants.js' | ||
|
||
export function getRpcUrls({ port }: { port: number }) { | ||
return { | ||
port, | ||
rpcUrls: { | ||
// These rpc urls are automatically used in the transports. | ||
default: { | ||
// Note how we append the worker id to the local rpc urls. | ||
http: [`http://127.0.0.1:${port}/${pool}`], | ||
webSocket: [`ws://127.0.0.1:${port}/${pool}`], | ||
}, | ||
public: { | ||
// Note how we append the worker id to the local rpc urls. | ||
http: [`http://127.0.0.1:${port}/${pool}`], | ||
webSocket: [`ws://127.0.0.1:${port}/${pool}`], | ||
}, | ||
}, | ||
} as const | ||
} | ||
|
||
export async function wait(time: number) { | ||
return new Promise((res) => setTimeout(res, time)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
import { connect, disconnect } from '@wagmi/core' | ||
import { expect, test } from 'vitest' | ||
import { config } from '../../_test/config.js' | ||
import { accounts } from '../../_test/constants.js' | ||
import { renderHook, waitFor } from '../../_test/react.js' | ||
import { useSimulateDepositETH } from './useSimulateDepositETH.js' | ||
|
||
const connector = config.connectors[0]! | ||
const portal = '0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA' | ||
|
||
test('default', async () => { | ||
await connect(config, { connector }) | ||
|
||
const { result } = renderHook(() => | ||
useSimulateDepositETH({ | ||
args: { | ||
to: accounts[0], | ||
gasLimit: 100000, | ||
}, | ||
portal, | ||
value: BigInt(1), | ||
dataSuffix: '0x1234', | ||
}) | ||
) | ||
|
||
await waitFor(() => expect(result.current.isSuccess).toBeTruthy()) | ||
|
||
expect(result.current).toMatchInlineSnapshot(` | ||
{ | ||
"data": { | ||
"request": { | ||
"abi": [ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "_to", | ||
"type": "address", | ||
}, | ||
{ | ||
"internalType": "uint256", | ||
"name": "_value", | ||
"type": "uint256", | ||
}, | ||
{ | ||
"internalType": "uint64", | ||
"name": "_gasLimit", | ||
"type": "uint64", | ||
}, | ||
{ | ||
"internalType": "bool", | ||
"name": "_isCreation", | ||
"type": "bool", | ||
}, | ||
{ | ||
"internalType": "bytes", | ||
"name": "_data", | ||
"type": "bytes", | ||
}, | ||
], | ||
"name": "depositTransaction", | ||
"outputs": [], | ||
"stateMutability": "payable", | ||
"type": "function", | ||
}, | ||
], | ||
"account": { | ||
"address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", | ||
"type": "json-rpc", | ||
}, | ||
"address": "0xe93c8cD0D409341205A592f8c4Ac1A5fe5585cfA", | ||
"args": [ | ||
"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", | ||
1n, | ||
100000, | ||
false, | ||
"0x", | ||
], | ||
"dataSuffix": "0x1234", | ||
"functionName": "depositTransaction", | ||
"value": 1n, | ||
}, | ||
"result": undefined, | ||
}, | ||
"dataUpdatedAt": 1700438400000, | ||
"error": null, | ||
"errorUpdateCount": 0, | ||
"errorUpdatedAt": 0, | ||
"failureCount": 0, | ||
"failureReason": null, | ||
"fetchStatus": "idle", | ||
"isError": false, | ||
"isFetched": true, | ||
"isFetchedAfterMount": true, | ||
"isFetching": false, | ||
"isInitialLoading": false, | ||
"isLoading": false, | ||
"isLoadingError": false, | ||
"isPaused": false, | ||
"isPending": false, | ||
"isPlaceholderData": false, | ||
"isRefetchError": false, | ||
"isRefetching": false, | ||
"isStale": true, | ||
"isSuccess": true, | ||
"queryKey": [ | ||
"simulateContract", | ||
{ | ||
"account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", | ||
"blockNumber": undefined, | ||
"chainId": 8453, | ||
"dataSuffix": "0x1234", | ||
"gasLimit": 100000, | ||
"gasPrice": undefined, | ||
"to": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", | ||
"type": undefined, | ||
"value": undefined, | ||
}, | ||
], | ||
"refetch": [Function], | ||
"status": "success", | ||
} | ||
`) | ||
|
||
await disconnect(config, { connector }) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
export const poolId = Number(process.env.VITEST_POOL_ID ?? 1) | ||
export const localHttpUrl = `http://127.0.0.1:8545/${poolId}` | ||
export const localWsUrl = `ws://127.0.0.1:8545/${poolId}` | ||
export const localRollupHttpUrl = `http://127.0.0.1:8555/${poolId}` | ||
export const localRollupWsUrl = `ws://127.0.0.1:8555/${poolId}` | ||
import { defineConfig } from 'vitest/config' | ||
|
||
export default defineConfig({ | ||
test: { | ||
benchmark: { | ||
outputFile: './bench/report.json', | ||
reporters: process.env.CI ? ['json'] : ['verbose'], | ||
}, | ||
// if you are using the default rpc you will need these to not get rate limited | ||
// maxConcurrency: 1, | ||
// maxThreads: 1, | ||
// minThreads: 1, | ||
coverage: { | ||
lines: 95, | ||
statements: 95, | ||
functions: 90, | ||
branches: 93.82, | ||
thresholdAutoUpdate: true, | ||
reporter: ['text', 'json-summary', 'json'], | ||
exclude: [ | ||
'**/errors/utils.ts', | ||
'**/dist/**', | ||
'**/*.test.ts', | ||
'**/_test/**', | ||
], | ||
}, | ||
environment: 'happy-dom', | ||
globalSetup: ['./src/_test/globalSetup.ts'], | ||
setupFiles: ['./src/_test/setup.ts'], | ||
testTimeout: 100_000, | ||
}, | ||
}) |