midnight-dapp:testing-patterns
Use when writing unit tests for Midnight contract interaction code, integration testing without ZK proofs, E2E testing with Playwright or Cypress, or setting up CI/CD pipelines for Midnight DApps.
Best use case
midnight-dapp:testing-patterns is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Use when writing unit tests for Midnight contract interaction code, integration testing without ZK proofs, E2E testing with Playwright or Cypress, or setting up CI/CD pipelines for Midnight DApps.
Teams using midnight-dapp:testing-patterns should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/midnight-dapp-testing-patterns/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How midnight-dapp:testing-patterns Compares
| Feature / Agent | midnight-dapp:testing-patterns | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Use when writing unit tests for Midnight contract interaction code, integration testing without ZK proofs, E2E testing with Playwright or Cypress, or setting up CI/CD pipelines for Midnight DApps.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
SKILL.md Source
# Testing Patterns
Test Midnight DApps efficiently using mocked providers, simulated wallets, and testnet integration strategies.
## When to Use
- Writing unit tests for contract interaction code
- Integration testing without real ZK proof generation
- E2E testing with Playwright or Cypress
- Setting up CI/CD pipelines for Midnight DApps
- Testing wallet connection flows without browser extension
- Validating transaction flows before testnet deployment
## Key Concepts
### The Testing Challenge
Midnight DApps face unique testing challenges:
| Challenge | Why It Matters | Solution |
|-----------|----------------|----------|
| **Proof generation takes seconds** | Tests would be too slow | Mock proof providers |
| **Wallet requires browser extension** | Can't run in CI/CD | Mock wallet provider |
| **Private state is local only** | Hard to verify in tests | Controlled test state |
| **Testnet requires real infrastructure** | Flaky in automation | Mock for unit tests, testnet for E2E |
### Testing Pyramid for Midnight DApps
```
E2E (Testnet)
/ \
/ Real proofs \
/ Real wallet \
/ Slow (~min) \
/____________________\
|
Integration (Mocked)
/ \
/ Mock proof provider \
/ Mock wallet provider \
/ Fast (~seconds) \
/______________________________\
|
Unit Tests
/ \
/ Pure logic \
/ No providers \
/ Fast (~ms) \
/____________________\
```
### Mock vs Real: When to Use Each
| Test Type | Proof Provider | Wallet Provider | Use Case |
|-----------|---------------|-----------------|----------|
| **Unit** | N/A | N/A | Pure business logic |
| **Component** | Mock | Mock | UI components |
| **Integration** | Mock | Mock | Contract interactions |
| **E2E (local)** | Mock | Mock | Full user flows |
| **E2E (testnet)** | Real | Real (Lace) | Pre-deployment validation |
## References
| Document | Description |
|----------|-------------|
| [mocking-proofs.md](references/mocking-proofs.md) | Mock proof provider for fast tests |
| [mock-wallet-provider.md](references/mock-wallet-provider.md) | Simulating Lace wallet in tests |
| [testnet-workflows.md](references/testnet-workflows.md) | E2E testing against testnet |
| [web3-comparison.md](references/web3-comparison.md) | Hardhat/Foundry testing vs Midnight |
## Examples
| Example | Description |
|---------|-------------|
| [mock-proof-context/](examples/mock-proof-context/) | Mock proof provider and test utilities |
| [mock-wallet/](examples/mock-wallet/) | Fake wallet implementation for tests |
| [e2e-testnet/](examples/e2e-testnet/) | Playwright E2E test against testnet |
## Quick Start
### 1. Install Test Dependencies
```bash
pnpm add -D vitest @testing-library/react @playwright/test msw
```
### 2. Create Mock Proof Provider
```typescript
import { createMockProofProvider } from "./mockProofProvider";
// Returns dummy proofs instantly (no ZK computation)
const mockProofProvider = createMockProofProvider({
latencyMs: 10, // Simulate realistic timing
});
```
### 3. Create Mock Wallet
```typescript
import { MockWallet } from "./MockWallet";
const mockWallet = new MockWallet({
address: "addr_test1qz_mock_address_for_testing_purposes_xyz",
balance: 1000000n,
network: "testnet",
});
// Inject into window for components that check window.midnight
globalThis.window = {
midnight: { mnLace: mockWallet.connector },
};
```
### 4. Write a Test
```typescript
import { describe, it, expect, beforeEach } from "vitest";
import { render, screen, fireEvent } from "@testing-library/react";
import { MockWallet } from "./MockWallet";
import { createMockProofProvider } from "./mockProofProvider";
import { TransferButton } from "../TransferButton";
describe("TransferButton", () => {
let mockWallet: MockWallet;
let mockProofProvider: MockProofProvider;
beforeEach(() => {
mockWallet = new MockWallet({ balance: 1000n });
mockProofProvider = createMockProofProvider();
});
it("should complete transfer with mocked providers", async () => {
render(
<TransferButton
wallet={mockWallet.api}
proofProvider={mockProofProvider}
recipient="addr_test1..."
amount={100n}
/>
);
fireEvent.click(screen.getByText("Transfer"));
// No actual proof generation - instant!
await screen.findByText("Transfer Complete");
expect(mockWallet.getBalance()).toBe(900n);
});
});
```
## Common Patterns
### Testing Contract State Reads
```typescript
import { describe, it, expect } from "vitest";
import { createMockContract } from "./testUtils";
describe("Contract State", () => {
it("should read balance from contract state", async () => {
const contract = createMockContract({
state: {
balances: new Map([["addr_test1...", 500n]]),
totalSupply: 10000n,
},
});
const balance = await contract.state.balances.get("addr_test1...");
expect(balance).toBe(500n);
});
});
```
### Testing Witness Execution
```typescript
import { describe, it, expect } from "vitest";
import { witnesses, createInitialPrivateState } from "../witnesses";
describe("Witnesses", () => {
it("should return balance from private state", () => {
const privateState = createInitialPrivateState(new Uint8Array(32));
privateState.balance = 1000n;
const context = { privateState, setPrivateState: () => {} };
const balance = witnesses.get_balance(context);
expect(balance).toBe(1000n);
});
it("should throw for expired credential", () => {
const privateState = createInitialPrivateState(new Uint8Array(32));
privateState.credentials.set("abc123", {
expiry: BigInt(Date.now() / 1000 - 3600), // Expired 1 hour ago
data: new Uint8Array(32),
});
const context = { privateState, setPrivateState: () => {} };
expect(() =>
witnesses.get_credential(context, hexToBytes("abc123"))
).toThrow("expired");
});
});
```
### Testing Error Handling
```typescript
import { describe, it, expect, vi } from "vitest";
import { MockWallet } from "./MockWallet";
describe("Error Handling", () => {
it("should handle user rejection", async () => {
const wallet = new MockWallet();
wallet.rejectNextTransaction("User rejected");
await expect(
wallet.api.submitTransaction(mockTx)
).rejects.toThrow("User rejected");
});
it("should handle proof server unavailable", async () => {
const proofProvider = createMockProofProvider({
shouldFail: true,
errorMessage: "Proof server unavailable",
});
await expect(
proofProvider.generateProof(mockCircuit, mockWitness)
).rejects.toThrow("Proof server unavailable");
});
});
```
### Snapshot Testing for Disclosures
```typescript
import { describe, it, expect } from "vitest";
import { render } from "@testing-library/react";
import { DisclosureModal } from "../DisclosureModal";
describe("DisclosureModal", () => {
it("should render disclosure summary correctly", () => {
const disclosures = [
{ field: "age", label: "Your Age", value: "25" },
{ field: "country", label: "Country", value: "US" },
];
const { container } = render(
<DisclosureModal disclosures={disclosures} onConfirm={() => {}} />
);
expect(container).toMatchSnapshot();
});
});
```
## CI/CD Integration
### GitHub Actions Example
```yaml
name: Test Midnight DApp
on: [push, pull_request]
jobs:
unit-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- run: pnpm install
- run: pnpm test:unit
- run: pnpm test:integration
e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
with:
node-version: "20"
cache: "pnpm"
- run: pnpm install
- run: pnpm exec playwright install --with-deps
# E2E with mocks - fast, reliable
- run: pnpm test:e2e:mock
# Optional: E2E with testnet (slower, requires secrets)
# - run: pnpm test:e2e:testnet
# env:
# TESTNET_FAUCET_KEY: ${{ secrets.TESTNET_FAUCET_KEY }}
```
## Related Skills
- `proof-handling` - Understanding what to mock in proof generation
- `wallet-integration` - Understanding Lace wallet API to mock
- `error-handling` - Testing error scenarios
- `state-management` - Testing state synchronization
## Related Commands
- `/dapp-check` - Validates test configuration
- `/dapp-debug tests` - Diagnose test failuresRelated Skills
qa-testing
Ensure data integrity, stability, and basic security for a personal productivity app. Focus on preventing data loss, memory leaks, and sync failures during daily 8-hour usage sessions. Skip enterprise-grade testing. Use when testing, verifying, validating, checking features, running tests, or before claiming anything is "done" or "fixed".
qa-testing-strategy
Risk-based quality engineering test strategy across unit, integration, contract, E2E, performance, and security testing with shift-left gates, flake control, CI economics, and observability-first debugging.
qa-testing-playwright
End-to-end web application testing with Playwright: scope control, stable selectors, parallelization/sharding, flake control, network mocking vs real services, visual testing tradeoffs, and CI/CD integration.
qa-testing-ios
iOS testing with XCTest/XCUITest on simulators and devices: layered strategy, determinism/flake control, device matrix selection, CI ergonomics, and repeatable simulator automation.
Property Testing
Property-based testing with fast-check for business logic validation
Playwright E2E Testing
Comprehensive Playwright end-to-end testing patterns with Page Object Model, fixtures, and best practices
OWASP Security Testing
OWASP Top 10 security testing patterns and vulnerability scanning
mobile-testing
Executes automated tests on mobile apps via MCP. Use when testing iOS/Android apps, verifying UI states, automating interactions, or performing end-to-end validation. Not for web testing, API validation, or desktop applications.
moai-workflow-testing
AI-powered enterprise web application testing orchestrator with Context7 integration, intelligent test generation, visual regression testing, cross-browser coordination, and automated QA workflows for modern web applications
implementing-e2e-testing
Master end-to-end testing with Playwright and Cypress to build reliable test suites that catch bugs, improve confidence, and enable fast deployment. Use when implementing E2E tests, debugging flaky tests, or establishing testing standards.
idor-testing
This skill should be used when the user asks to "test for insecure direct object references," "find IDOR vulnerabilities," "exploit broken access control," "enumerate user IDs or obje...
File Path Traversal Testing
This skill should be used when the user asks to "test for directory traversal", "exploit path traversal vulnerabilities", "read arbitrary files through web applications", "find LFI vulnerabilities", or "access files outside web root". It provides comprehensive file path traversal attack and testing methodologies.