Skip to content

Testing Overview

Hurum ships five test utilities, each targeting a specific layer of the architecture. They live in @hurum/core/testing and work with any test runner — Vitest, Jest, or anything else.

import { TestStore, TestExecutor, TestReducer, TestComputed, TestIntent } from '@hurum/core/testing'
UtilityWhat it testsLevel
TestStoreFull flow: Intent to Event to StateIntegration
TestExecutorExecutor side effects and emitted eventsUnit
TestReducer.on() handler pure functionsUnit
TestComputedComputed derived state calculationsUnit
TestIntentIntent command composition and execution modeUnit

Start at the bottom of the pipeline and work your way up:

1. TestReducer and TestComputed (pure functions)

Section titled “1. TestReducer and TestComputed (pure functions)”

These test the simplest parts of your store — pure functions with no dependencies. They run synchronously and never touch side effects.

const reducer = TestReducer(PurchaseStore)
const next = reducer.apply(initialState, PurchaseEvent.saved({ purchase }))
expect(next.saving).toBe(false)
const computed = TestComputed(PurchaseStore, 'totalAmount')
expect(computed.evaluate({ items: [{ amount: 100 }, { amount: 200 }] })).toBe(300)

2. TestExecutor (side effects in isolation)

Section titled “2. TestExecutor (side effects in isolation)”

Test each executor independently with mock deps. Verify it emits the right events in the right order.

const executor = TestExecutor(SaveExecutor, {
deps: { repo: mockRepo },
})
await executor.run({ id: '123' })
executor.assertEmitted([
PurchaseEvent.saveRequested({ id: '123' }),
PurchaseEvent.saved({ purchase: savedPurchase }),
])

Test the entire flow: send an intent, verify events were emitted, and check the final state.

const store = TestStore(PurchaseStore, {
deps: { repo: mockRepo },
})
await store.send.submitClicked({ id: '123' })
store.assertState({ saving: false, purchase: savedPurchase })
store.assertNoRunningExecutors()
QuestionUtility
”Does my reducer produce the right state for this event?”TestReducer
”Does my computed value calculate correctly?”TestComputed
”Does my executor emit the right events?”TestExecutor
”Does my executor handle errors correctly?”TestExecutor
”Does my intent wire up the right commands?”TestIntent
”Does the full flow produce the correct final state?”TestStore
”Are events emitted in the right order with correct intermediate states?”TestStore

All five utilities are part of @hurum/core/testing — they have no React dependency. You are testing the state management logic, not the UI.

For testing React components that use Hurum stores, use your regular React testing tools (React Testing Library, etc.) with a Provider and Store.create().