Skip to content
Back to skills

Voltaire Effect Testing

ASecurity

This skill should be used when the user asks about "voltaire-effect testing", "CryptoTest", "TestTransport", "mock provider", "test layers", "layer swap testing", "Effect test patterns", "deterministic crypto", or needs to understand how to test programs built with voltaire-effect.

  • 9 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 10, 2026
testingtypescripttesting

Security analysis

A100/100

Scanned September 10, 2026

npx -y skills add cyotee/indexedex --skill voltaire-effect-testing --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Voltaire Effect Testing?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Voltaire Effect Testing
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/cyotee-voltaire-effect-testing/badge)](https://www.skillsdirectory.com/skills/cyotee-voltaire-effect-testing)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: Voltaire Effect Testing
description: This skill should be used when the user asks about "voltaire-effect testing", "CryptoTest", "TestTransport", "mock provider", "test layers", "layer swap testing", "Effect test patterns", "deterministic crypto", or needs to understand how to test programs built with voltaire-effect.
version: 0.1.0
---

# Voltaire Effect Testing

## Overview

voltaire-effect's service model makes testing straightforward - swap production layers with test layers at program boundaries without changing application code. Test layers provide deterministic outputs and mock responses.

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                         TESTING STRATEGY                                     │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                              │
│  Same application code:                                                      │
│  ┌────────────────────────────────────────────────────────┐                 │
│  │  const program = Effect.gen(function* () {             │                 │
│  │    const balance = yield* getBalance(addr)             │                 │
│  │    const hash = yield* keccak.hash(data)               │                 │
│  │    return { balance, hash }                            │                 │
│  │  })                                                    │                 │
│  └────────────────────────────────────────────────────────┘                 │
│                                                                              │
│  Production:                          Testing:                              │
│  ┌──────────────────────┐            ┌──────────────────────┐              │
│  │ Effect.provide(       │            │ Effect.provide(       │              │
│  │   Layer.mergeAll(     │            │   Layer.mergeAll(     │              │
│  │     ProviderLive,     │            │     TestTransport,    │              │
│  │     CryptoLive        │            │     CryptoTest        │              │
│  │   )                   │            │   )                   │              │
│  │ )                     │            │ )                     │              │
│  └──────────────────────┘            └──────────────────────┘              │
│   ↓ Real HTTP, real crypto            ↓ Mock responses, deterministic      │
│                                                                              │
└─────────────────────────────────────────────────────────────────────────────┘
```

## Schema Testing

Schema decode is pure - test directly without services:

```typescript
import * as Address from 'voltaire-effect/primitives/Address'
import * as S from 'effect/Schema'

// Valid input
test('decodes valid address', () => {
  const addr = S.decodeSync(Address.Hex)('0x742d35Cc6634C0532925a3b844Bc9e7595f251e3')
  expect(addr).toBeInstanceOf(Uint8Array)
  expect(addr.length).toBe(20)
})

// Invalid input (throws synchronously)
test('rejects invalid address', () => {
  expect(() => S.decodeSync(Address.Hex)('not-an-address')).toThrow()
})

// Using Either for non-throwing tests
test('returns Left for invalid input', () => {
  const result = S.decodeEither(Address.Hex)('bad')
  expect(Either.isLeft(result)).toBe(true)
})
```

## TestTransport

Mock JSON-RPC responses by method name:

```typescript
import { TestTransport } from 'voltaire-effect'

const MockTransport = TestTransport({
  eth_blockNumber: '0x10',
  eth_getBalance: '0xde0b6b3a7640000',  // 1 ETH
  eth_call: '0x0000000000000000000000000000000000000000000000000000000005f5e100'
})

const TestProvider = Provider.pipe(Layer.provide(MockTransport))
```

### Mocking Errors

```typescript
import { TransportError } from 'voltaire-effect'

const ErrorTransport = TestTransport({
  eth_getBalance: new TransportError({
    code: -32000,
    message: 'execution reverted'
  })
})
```

## CryptoTest

Deterministic crypto outputs for reproducible tests:

```typescript
import { CryptoTest } from 'voltaire-effect/crypto'

// CryptoTest provides all crypto services with deterministic output
// No actual cryptographic computation - fast and predictable
const TestLayer = Layer.mergeAll(TestProvider, CryptoTest)

const result = await Effect.runPromise(
  program.pipe(Effect.provide(TestLayer))
)
```

## Composing Test Layers

```typescript
// Minimal test environment
const UnitTestLayer = Layer.mergeAll(
  TestTransport({ eth_blockNumber: '0x1' }),
  CryptoTest
)

// Full test environment with provider
const IntegrationTestLayer = Layer.mergeAll(
  Provider.pipe(Layer.provide(
    TestTransport({
      eth_blockNumber: '0x10',
      eth_getBalance: '0xde0b6b3a7640000'
    })
  )),
  CryptoTest
)
```

## Testing Error Handling

Verify error branches are handled:

```typescript
test('handles transport errors gracefully', async () => {
  const ErrorLayer = Provider.pipe(
    Layer.provide(TestTransport({
      eth_getBalance: new TransportError({ code: -32000, message: 'reverted' })
    }))
  )

  const program = getBalance(addr).pipe(
    Effect.catchTag('TransportError', () => Effect.succeed(0n))
  )

  const result = await Effect.runPromise(program.pipe(Effect.provide(ErrorLayer)))
  expect(result).toBe(0n)
})
```

## Integration Testing

For end-to-end validation against live networks:

```typescript
const LiveLayer = Provider.pipe(
  Layer.provide(HttpTransport('https://eth.llamarpc.com'))
)

test('reads real block number', async () => {
  const blockNumber = await Effect.runPromise(
    getBlockNumber().pipe(Effect.provide(LiveLayer))
  )
  expect(blockNumber).toBeGreaterThan(0n)
})
```

## Service Mocking Pattern

Create custom mock services for fine-grained control:

```typescript
const MockProvider = Layer.succeed(ProviderService, {
  request: (method, params) => {
    switch (method) {
      case 'eth_blockNumber':
        return Effect.succeed('0x10')
      case 'eth_getBalance':
        return Effect.succeed('0xde0b6b3a7640000')
      default:
        return Effect.fail(new ProviderResponseError({ message: `Unexpected: ${method}` }))
    }
  }
})
```

## Testing Best Practices

1. **Schema tests** - Test decode/encode directly with `decodeSync` or `decodeEither`
2. **Service tests** - Use `TestTransport` + `CryptoTest` for fast, deterministic unit tests
3. **Error tests** - Mock failures with `TransportError` and verify `catchTag` handling
4. **Integration tests** - Use `HttpTransport` to a live RPC for end-to-end validation
5. **No code changes** - Same program code works with both production and test layers

## Reference

- Testing docs: https://voltaire-effect.tevm.sh/testing
- Effect testing guide: https://effect.website/docs/testing

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…