Skip to main content

Testing

Preact provides testing utilities in the preact/test-utils package to make testing components easier. These utilities help you control the rendering lifecycle, flush effects synchronously, and write reliable tests.

Installation

The test utilities are included in the preact package:
You’ll also want a test runner and assertion library:

Importing Test Utils

Source: test-utils/src/index.js

setupRerender()

Sets up a function to flush pending renders synchronously. By default, Preact batches renders asynchronously. In tests, you want renders to happen immediately.
How it works:
Source: test-utils/src/index.js:7-11 It replaces options.debounceRendering to capture the render callback, then returns a function to execute it synchronously.

act()

Runs a function and flushes all effects and rerenders. This is similar to React’s act() helper.
Key features:
  1. Flushes all pending renders
  2. Executes all pending effects (useEffect, useLayoutEffect)
  3. Works with both sync and async callbacks
  4. Returns a Promise
Source: test-utils/src/index.js:27-112

Async Callbacks

act() works with asynchronous callbacks:
Source: test-utils/src/index.js:37-46, test-utils/src/index.js:97-101

Nested act() Calls

Nested act() calls are supported:
Source: test-utils/src/index.js:28-54

teardown()

Cleans up test utilities and resets Preact’s internal state. Call this after each test:
What it does:
  1. Flushes any pending updates
  2. Restores original debounceRendering
  3. Cleans up internal test state
Source: test-utils/src/index.js:117-130
Always call teardown() after tests to prevent state leaking between tests.

Testing Patterns

Basic Component Test

Testing State Changes

Testing Effects

Testing Async Operations

Testing Custom Hooks

Testing Context

Testing Error Boundaries

Integration with Testing Library

Preact works seamlessly with @testing-library/preact:

Vitest Configuration

Example Vitest setup for Preact:
Source: vitest.config.mjs in Preact repo

Jest Configuration

Example Jest setup for Preact:

Snapshot Testing

Best Practices

  1. Always use act(): Wrap state updates and side effects in act() to ensure all updates are flushed:
  1. Call teardown(): Always clean up after tests:
  1. Test user behavior: Focus on how users interact with your components:
  1. Use Testing Library queries: Prefer accessible queries:
  1. Mock external dependencies: Mock API calls, timers, etc.:
  1. Test edge cases: Don’t just test the happy path:

Debugging Tests

Using debug()

Log render count

Use preact/debug in tests for better error messages and validation.

Common Pitfalls

Forgetting to await act()

Not cleaning up

Testing implementation details