testing
SKILL.md
Testing Midnight Contracts
Test Compact smart contracts using simulators and test frameworks.
Quick Start
import { ContractSimulator } from '@midnight-ntwrk/compact-simulator';
// Create simulator
const simulator = new ContractSimulator(compiledContract);
// Call circuit
const result = await simulator.call('increment', {});
// Check state
expect(simulator.ledger.counter).toBe(1n);
Reference Files
| Topic | Resource |
|---|---|
| Simulator Setup | references/simulator-setup.md |
| Test Patterns | references/test-patterns.md |
| Debugging | references/debugging.md |
Test Environment
┌──────────────────────────────────────────────┐
│ Test Environment │
├──────────────────────────────────────────────┤
│ ┌────────────────┐ ┌────────────────┐ │
│ │ Contract │ │ Contract │ │
│ │ Simulator │ │ Artifacts │ │
│ └────────────────┘ └────────────────┘ │
│ │ │ │
│ └────────┬─────────┘ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Test Suite │ │
│ │ (Jest/Vitest)│ │
│ └────────────────┘ │
└──────────────────────────────────────────────┘
Installation
npm install -D @midnight-ntwrk/compact-simulator vitest
Basic Test Structure
import { describe, it, expect, beforeEach } from 'vitest';
import { ContractSimulator } from '@midnight-ntwrk/compact-simulator';
import { setNetworkId, NetworkId } from '@midnight-ntwrk/midnight-js-network-id';
describe('MyContract', () => {
let simulator: ContractSimulator;
beforeEach(() => {
setNetworkId(NetworkId.Undeployed);
simulator = new ContractSimulator(compiledContract);
});
it('should initialize with zero', async () => {
expect(simulator.ledger.counter).toBe(0n);
});
it('should increment counter', async () => {
await simulator.call('increment', {});
expect(simulator.ledger.counter).toBe(1n);
});
});
Testing Patterns
State Verification
it('should update ledger state', async () => {
// Initial state
expect(simulator.ledger.message).toBe('');
// Call circuit
await simulator.call('setMessage', { input: 'Hello' });
// Verify state
expect(simulator.ledger.message).toBe('Hello');
});
Error Testing
it('should reject invalid input', async () => {
await expect(simulator.call('withdraw', { amount: 1000n })).rejects.toThrow('Assertion failed');
});
Privacy Testing
it('should not reveal private inputs', async () => {
const result = await simulator.call('checkBalance', {
balance: 1000n,
required: 500n,
});
// Result is boolean, not actual balance
expect(result).toBe(true);
// Ledger should not contain balance
expect(simulator.ledger.balance).toBeUndefined();
});
Best Practices
- ✅ Test each circuit function independently
- ✅ Verify state changes after each call
- ✅ Test error conditions and edge cases
- ✅ Mock witnesses for privacy testing
- ✅ Use
NetworkId.Undeployedfor testing - ❌ Don't test proof generation (use simulator)
- ❌ Don't rely on network in unit tests
Test Categories
| Category | Tests |
|---|---|
| Unit | Individual circuit functions |
| Integration | Multi-circuit workflows |
| State | Ledger state transitions |
| Error | Assertion failures |
| Privacy | Data not leaked |
Running Tests
# Run all tests
npm test
# Run with coverage
npm test -- --coverage
# Run specific test file
npm test -- counter.test.ts
# Watch mode
npm test -- --watch
Weekly Installs
3
Repository
fractionestate/…v-skillsFirst Seen
Jan 31, 2026
Security Audits
Installed on
gemini-cli3
opencode2
replit2
antigravity2
claude-code2
github-copilot2