ouroborai maintains 419 TypeScript tests (38 files) and 115 Rust tests across
the four Stylus contracts. This page documents the testing conventions and
patterns used throughout the codebase.
TypeScript (Vitest)
The project uses Vitest v3 with globals enabled. All tests run through the
workspace Vitest configuration.
Running Tests
Do NOT use bun test or npx vitest — version mismatches between Bun’s
bundled test runner and the project’s Vitest installation cause failures.
Always use ./node_modules/.bin/vitest run.
vi.hoisted for Mock Variables
When mock variables need to be referenced inside vi.mock() factory
functions, use vi.hoisted() to ensure they are initialized before the
mock factory runs:
vi.hoisted() lifts the callback above all vi.mock() calls in the module
scope. Without it, mock variables would be undefined when the factory
runs.
vi.clearAllMocks vs vi.restoreAllMocks
Use vi.clearAllMocks() in beforeEach — not vi.restoreAllMocks():
restoreAllMocks() removes mockImplementation callbacks, which breaks
tests that rely on them. clearAllMocks() resets call counts and return
values while preserving the mock structure.
Mocking with vi.mock
Factory-based mocking for module dependencies:
Globals Enabled
The Vitest config has globals: true, so describe, it, expect,
beforeEach, vi, etc. are available without imports:
Testing Hono Routes
Use Hono’s built-in app.request() for route testing:
Rust (Stylus Contracts)
Stylus contracts use cargo test with the stylus-test feature flag for
testing utilities.
Running Tests
TestVM Setup Pattern
Every test creates a TestVM and instantiates the contract from it:
Setting Sender
Use vm.set_sender() to simulate calls from different addresses:
Mocking External Calls
Use mock_call for state-changing calls and mock_static_call for view
calls:
mock_static_call in stylus-test 0.10.0 always returns the LAST
registered mock’s data when multiple mocks target the same contract.
Register losing mocks first, winning mock last.
Required Imports
Stylus tests require specific imports that differ from the main code:
Verifying Events
Check emitted events via vm.get_emitted_logs():
Private Helpers
Private helper functions that take &mut parameters must live in a separate
impl block (not #[public]). The Stylus SDK requires ABI-compatible types
in all #[public] methods: