Skip to content
LogoLogo

Getting started

Requirements

  • Node 24 or later. All three packages declare "engines": { "node": ">=24" }.
  • Vitest 4. The matchers register themselves through expect.extend and augment Vitest's Assertion interface.
  • viem 2. viem is a peer dependency of @tevm/test-matchers.

Install

The published package names are @tevm/test-matchers, @tevm/test-node, and @tevm/test-utils. They are versioned together with Tevm core and are currently on the 1.0.0-rc line:

Install only what you need — the three packages are independent. @tevm/test-matchers and @tevm/test-node need Tevm itself at runtime, declared as a tevm >= 1.0.0 peer dependency:

pnpm add tevm@^1.0.0-rc.151

Register the matchers

@tevm/test-matchers has no named entry point to call: importing it for side effects registers every matcher on Vitest's expect and declares the types. Create a setup file:

vitest.setup.ts
import '@tevm/test-matchers'

Then point Vitest at it:

vitest.config.ts
import { defineConfig } from 'vitest/config'
 
export default defineConfig({
	test: {
		environment: 'node',
		setupFiles: ['./vitest.setup.ts'],
		// EVM tests deploy contracts and mine blocks; the default 5s is often tight.
		testTimeout: 120_000,
	},
})

That's it — every test file now sees toEmit, toBeReverted, toChangeBalance, and the rest, fully typed.

Your first test

This is a complete, runnable file. It deploys the SimpleContract fixture from @tevm/test-utils into an in-memory Tevm node and asserts on the event it emits.

simpleContract.spec.ts
import { createMemoryClient } from '@tevm/memory-client'
import { SimpleContract } from '@tevm/test-utils'
import type { Address } from 'viem'
import { assert, beforeEach, describe, expect, it } from 'vitest'
 
const client = createMemoryClient()
 
describe('SimpleContract', () => {
	let contract: ReturnType<typeof SimpleContract.withAddress>
 
	beforeEach(async () => {
		const { createdAddress } = await client.tevmDeploy({
			...SimpleContract.deploy(0n),
			addToBlockchain: true,
		})
		assert(createdAddress, 'contract was not deployed')
		contract = SimpleContract.withAddress(createdAddress as Address)
	})
 
	it('emits ValueSet with the new value', async () => {
		await expect(client.tevmContract(contract.write.set(100n)))
			.toEmit(contract, 'ValueSet')
			.withEventArgs(100n)
	})
 
	it('stores the new value', async () => {
		await client.tevmContract({ ...contract.write.set(42n), addToBlockchain: true })
		const { data } = await client.tevmContract(contract.read.get())
		expect(data).toBe(42n)
	})
})

Run it with vitest run. There is no node to start, no fork, and no network access.