Documentation Index
Fetch the complete documentation index at: https://mintlify.com/visible/cruel/llms.txt
Use this file to discover all available pages before exploring further.
Cruel provides custom test matchers for Vitest, Jest, and Bun to make testing chaos behaviors easier.
Setup
import { setupMatchers } from 'cruel/matchers'
import { beforeAll } from 'bun:test'
beforeAll(() => {
setupMatchers()
})
Matchers
toThrowCruelError
Check if function throws any Cruel error:
import { cruel, matchers } from 'cruel/matchers'
import { expect, test } from 'bun:test'
test('throws cruel error', () => {
const fn = () => {
throw new CruelError('test')
}
expect(fn).toThrowCruelError()
})
toThrowTimeout
Check if function throws a timeout error:
test('throws timeout', async () => {
const fn = cruel.timeout(async () => 'data', 1)
await expect(fn()).toEventuallyThrow(CruelTimeoutError)
})
Returns: MatcherResult
toThrowNetworkError
Check if function throws a network error, optionally with specific type:
test('throws network error', () => {
const fn = () => {
throw new CruelNetworkError('disconnect')
}
expect(fn).toThrowNetworkError()
expect(fn).toThrowNetworkError('disconnect')
})
Expected network error type (disconnect, packet_loss, dns_failure, offline)
Returns: MatcherResult
toThrowHttpError
Check if function throws an HTTP error, optionally with specific status:
test('throws http error', () => {
const fn = () => {
throw new CruelHttpError(500)
}
expect(fn).toThrowHttpError()
expect(fn).toThrowHttpError(500)
})
Expected HTTP status code
Returns: MatcherResult
toThrowRateLimit
Check if function throws a rate limit error:
test('throws rate limit', () => {
const fn = () => {
throw new CruelRateLimitError(60)
}
expect(fn).toThrowRateLimit()
})
Returns: MatcherResult
toThrowAIError
Check if function throws an AI error, optionally with specific type:
test('throws AI error', () => {
const fn = () => {
throw new CruelAIError('rate_limit')
}
expect(fn).toThrowAIError()
expect(fn).toThrowAIError('rate_limit')
})
Expected AI error type (rate_limit, overloaded, context_length, content_filter, model_unavailable, stream_cut)
Returns: MatcherResult
toEventuallyThrow
Check if async function throws an error:
test('eventually throws', async () => {
const fn = async () => {
throw new Error('failed')
}
await expect(fn()).toEventuallyThrow()
await expect(fn()).toEventuallyThrow(Error)
})
received
() => Promise<unknown>
required
Async function to test
Returns: Promise<MatcherResult>
toCompleteWithin
Check if async function completes within time limit:
test('completes quickly', async () => {
const fn = async () => {
await new Promise(r => setTimeout(r, 100))
return 'done'
}
await expect(fn()).toCompleteWithin(200)
})
received
() => Promise<unknown>
required
Async function to test
Maximum allowed duration in milliseconds
Returns: Promise<MatcherResult>
toTakeLongerThan
Check if async function takes at least specified time:
test('takes time', async () => {
const fn = cruel.slow(async () => 'data', 500)
await expect(fn()).toTakeLongerThan(400)
})
received
() => Promise<unknown>
required
Async function to test
Minimum expected duration in milliseconds
Returns: Promise<MatcherResult>
Usage with testing frameworks
Bun
import { setupMatchers } from 'cruel/matchers'
import { beforeAll, test, expect } from 'bun:test'
beforeAll(() => {
setupMatchers()
})
test('uses matchers', async () => {
const fn = cruel.fail(async () => 'data', 1)
await expect(fn()).toEventuallyThrow()
})
Vitest
import { setupMatchers } from 'cruel/matchers'
import { beforeAll, test, expect } from 'vitest'
beforeAll(() => {
setupMatchers()
})
test('uses matchers', async () => {
const fn = cruel.fail(async () => 'data', 1)
await expect(fn()).toEventuallyThrow()
})
Jest
import { setupMatchers } from 'cruel/matchers'
import { beforeAll, test, expect } from '@jest/globals'
beforeAll(() => {
setupMatchers()
})
test('uses matchers', async () => {
const fn = cruel.fail(async () => 'data', 1)
await expect(fn()).resolves.toEventuallyThrow()
})
Type definitions
interface MatcherResult {
pass: boolean
message: () => string
}
declare global {
namespace jest {
interface Matchers<R> {
toThrowCruelError(): R
toThrowTimeout(): R
toThrowNetworkError(type?: string): R
toThrowHttpError(status?: number): R
toThrowRateLimit(): R
toThrowAIError(type?: string): R
toEventuallyThrow(errorType?: new () => Error): Promise<R>
toCompleteWithin(ms: number): Promise<R>
toTakeLongerThan(ms: number): Promise<R>
}
}
}
Matchers are automatically extended to expect when you call setupMatchers().
Call setupMatchers() once in your test setup (beforeAll or setupFiles) to enable all matchers globally.