@orchestr8/testkit
v2.2.1
Published
A comprehensive testing toolkit for the @orchestr8 monorepo with modular imports and optional dependencies.
Readme
@orchestr8/testkit
A comprehensive testing toolkit for the @orchestr8 monorepo with modular imports and optional dependencies.
Installation
npm install @orchestr8/testkit
# or
pnpm add @orchestr8/testkit
# or
yarn add @orchestr8/testkitCore Features
- Lean Core: Main export includes only essential utilities with no optional dependencies
- Modular Imports: Use only what you need via sub-exports
- Optional Dependencies: Advanced features require optional peer dependencies
- TypeScript Support: Full type safety and IntelliSense support
- Vitest Integration: Optimized for Vitest testing framework
Quick Start
Basic Usage (No Optional Dependencies)
import {
delay,
retry,
getTestEnvironment,
createTempDirectory,
} from '@orchestr8/testkit'
// Use core utilities without installing optional dependencies
const env = getTestEnvironment()
const tempDir = createTempDirectory()
await delay(1000)Advanced Usage (With Optional Dependencies)
// Import specific modules as needed
import { setupMSW } from '@orchestr8/testkit/msw' // requires msw
import { createMemoryUrl, createSQLitePool } from '@orchestr8/testkit/sqlite' // requires better-sqlite3
import { createPostgresContext } from '@orchestr8/testkit/containers' // requires testcontainersDependency Requirements Matrix
| Feature | Import | Required Dependencies | Optional Dependencies |
| ------------------- | ------------------------------- | ----------------------------------------- | ---------------------------- |
| Core Utils | @orchestr8/testkit | vitest@^3.2.0 | None |
| MSW Testing | @orchestr8/testkit/msw | vitest@^3.2.0, msw@^2.0.0 | happy-dom@^18.0.0 |
| Test Containers | @orchestr8/testkit/containers | vitest@^3.2.0, testcontainers@^10.0.0 | mysql2@^3.0.0, pg@^8.0.0 |
| SQLite Testing | @orchestr8/testkit/sqlite | vitest@^3.2.0, better-sqlite3@^12.0.0 | None |
| Convex Testing | @orchestr8/testkit/convex | vitest@^3.2.0, convex-test@^0.0.38 | None |
| CLI Utilities | @orchestr8/testkit/cli | vitest@^3.2.0 | None |
| Environment | @orchestr8/testkit/env | vitest@^3.2.0 | None |
| File System | @orchestr8/testkit/fs | vitest@^3.2.0 | None |
| Config | @orchestr8/testkit/config | None | None |
| Register | @orchestr8/testkit/register | vitest@^3.2.0 | None |
Available Exports
Main Export (@orchestr8/testkit)
All utilities that only require vitest as a dependency:
// Utility functions
export { delay, retry, withTimeout, createMockFn } from '@orchestr8/testkit'
// Environment utilities (from /env sub-export)
export {
getTestEnvironment,
setupTestEnv,
getTestTimeouts,
} from '@orchestr8/testkit'
// File system utilities (from /fs sub-export)
export {
createTempDirectory,
createNamedTempDirectory,
} from '@orchestr8/testkit'
// Vitest configuration
export { createVitestConfig } from '@orchestr8/testkit'
// Types
export type { TestConfig, TestEnvironment, TestKit } from '@orchestr8/testkit'Additional utilities available via sub-exports:
// Advanced environment utilities (requires vitest)
import {
useFakeTimers,
createSeedContext,
DeterministicGenerator,
createSystemTimeContext,
createTimezoneContext,
} from '@orchestr8/testkit/env'
// Advanced file system utilities (requires vitest)
import {
useTempDirectory,
createManagedTempDirectory,
createTempDirectoryWithResourceManager,
withTempDirectoryScope,
} from '@orchestr8/testkit/fs'Sub-Exports
MSW Testing (@orchestr8/testkit/msw)
Requires: msw@^2.0.0
Note: MSW v2 introduces breaking changes from v1. Use
http.getinstead ofrest.get,http.postinstead ofrest.post, etc.
import {
setupMSW,
createMSWServer,
createAuthHandlers,
http,
HttpResponse,
} from '@orchestr8/testkit/msw'SQLite Testing (@orchestr8/testkit/sqlite)
Requires: better-sqlite3@^12.0.0
import {
createMemoryUrl,
createFileDatabase,
createSQLitePool,
withTransaction,
seedWithSql,
seedWithFiles,
seedWithBatch,
} from '@orchestr8/testkit/sqlite'Container Testing (@orchestr8/testkit/containers)
Requires: testcontainers@^10.0.0
import {
createPostgresContext,
createMySQLContext,
PostgresContainer,
MySQLContainer,
setupPostgresTest,
setupMySQLTest,
} from '@orchestr8/testkit/containers'Convex Testing (@orchestr8/testkit/convex)
Requires: convex-test@^0.0.38
import {
createConvexTestHarness,
} from '@orchestr8/testkit/convex'Installation Options
Option 1: Core Install (All Non-Optional Features)
npm install @orchestr8/testkit @vitest/ui vitestProvides access to all core utilities, environment management, file system utilities, and vitest configuration without optional external dependencies.
Option 2: Selective Install (Pick Your Features)
# Core + MSW
npm install @orchestr8/testkit @vitest/ui vitest msw happy-dom
# Core + SQLite
npm install @orchestr8/testkit @vitest/ui vitest better-sqlite3
# Core + Containers
npm install @orchestr8/testkit @vitest/ui vitest testcontainers
# Core + All Optional Features
npm install @orchestr8/testkit @vitest/ui vitest \
msw happy-dom better-sqlite3 convex-test testcontainers mysql2 pgUsage Examples
Basic Testing Utilities
import { delay, retry, withTimeout } from '@orchestr8/testkit'
test('async operations', async () => {
// Wait for a condition
await delay(100)
// Retry flaky operations
const result = await retry(
async () => {
const response = await fetch('/api/data')
if (!response.ok) throw new Error('Failed')
return response.json()
},
3,
1000,
)
// Add timeouts to prevent hanging tests
const data = await withTimeout(fetchLargeDataset(), 5000)
})Environment Detection
import { test } from 'vitest'
import { getTestEnvironment, setupTestEnv } from '@orchestr8/testkit'
test('environment-specific behavior', () => {
const env = getTestEnvironment()
// env contains: { isCI, isWallaby, isVitest, isJest, nodeEnv }
if (env.isCI) {
// Increase timeout for this test in CI
test.setTimeout(30000)
}
if (env.isWallaby) {
// Skip slow tests in Wallaby
return
}
})
test('with custom environment', () => {
const envRestore = setupTestEnv({
NODE_ENV: 'production',
API_URL: 'https://staging.example.com',
})
// Test with custom environment
// ...
envRestore.restore()
})Temporary File Management
import { createTempDirectory } from '@orchestr8/testkit'
test('file operations', async () => {
const tempDir = createTempDirectory()
// Use temp directory for test
await fs.writeFile(path.join(tempDir.path, 'test.txt'), 'content')
// Automatic cleanup when test completes
})MSW Mock Server (Optional)
MSW v2 Migration Note: This package uses MSW v2. If you're migrating from v1:
- Replace
rest.*withhttp.*(e.g.,rest.get→http.get)- Import
httpinstead ofrestfrom the MSW module- See MSW v2 migration guide for more details
import {
setupMSW,
createAuthHandlers,
http,
HttpResponse,
} from '@orchestr8/testkit/msw'
const server = setupMSW([
...createAuthHandlers(),
http.get('/api/users', () => {
return HttpResponse.json([
{ id: 1, name: 'John' },
{ id: 2, name: 'Jane' },
])
}),
])
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())SQLite Database Testing (Optional)
import {
createMemoryUrl,
createSQLitePool,
withTransaction,
seedWithSql,
} from '@orchestr8/testkit/sqlite'
import { betterSqliteAdapter } from '@orchestr8/testkit/sqlite/adapters'
import Database from 'better-sqlite3'
test('database operations', async () => {
// Create a connection pool with an in-memory database
const pool = createSQLitePool({ url: createMemoryUrl('raw') })
const db = await pool.getConnection()
// Set up the schema
db.exec('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
// Seed data
await seedWithSql(db, `INSERT INTO users (name) VALUES ('John')`)
// Use transactions for safe database operations with adapter
await withTransaction(db, betterSqliteAdapter, async (tx) => {
tx.run('INSERT INTO users (name) VALUES (?)', 'Alice')
const user = tx.get('SELECT * FROM users WHERE name = ?', 'Alice')
expect(user.name).toBe('Alice')
})
// Cleanup
await pool.close()
})Container Testing (Optional)
import { createPostgresContext } from '@orchestr8/testkit/containers'
test('integration with PostgreSQL', async () => {
// Create a context with a real PostgreSQL container
const context = await createPostgresContext({
database: 'testdb',
username: 'testuser',
password: 'testpass',
})
// Use the database connection directly from the context
const result = await context.db.query('SELECT 1')
expect(result.rows).toHaveLength(1)
// Cleanup stops the container and removes it
await context.cleanup()
}, 60000) // Containers need longer timeoutNew Features in v2.0.0
Security Validation
Built-in security validation to prevent common vulnerabilities:
- Command Injection Prevention: Validates and sanitizes shell commands
- Path Traversal Protection: Prevents directory traversal attacks
- SQL Injection Prevention: Sanitizes SQL identifiers
- Shell Argument Escaping: Properly escapes shell arguments
Advanced Resource Management
Comprehensive resource cleanup system:
- Automatic Resource Tracking: Tracks database connections, file descriptors, processes, timers
- Priority-Based Cleanup: Critical resources cleaned up first
- Leak Detection: Identifies potential resource leaks
- Event-Driven Monitoring: Real-time resource lifecycle events
Concurrency Control
Built-in concurrency limits to prevent resource exhaustion:
- Operation-Specific Limits: Different limits for database, file, network operations
- Batch Processing: Process arrays with concurrency limits
- Predefined Managers: Ready-to-use managers for common scenarios
- Custom Concurrency: Create custom concurrency managers
SQLite Connection Pooling
Advanced SQLite testing with connection pooling:
- Connection Pooling: Manage multiple SQLite connections efficiently
- Transaction Management: Enhanced transaction support with adapters
- Migration Support: Run database migrations in tests
- Environment Probing: Verify SQLite capabilities and configuration
Enhanced Environment Control
Expanded environment testing capabilities:
- Comprehensive Detection: Detect CI, Wallaby, Jest, Node test runners
- Advanced Time Control: Fake timers with timezone support
- Randomness Control: Deterministic random number generation and crypto mocking
- Environment Scoping: Isolated environment changes with automatic restore
API Naming Conventions
The testkit follows consistent naming patterns to provide an intuitive developer experience:
Function Naming Standards
create*- Factory functions that return new instancescreateTempDirectory() // Creates and returns a temp directory createMSWServer() // Creates a new MSW server instance createConvexTestHarness() // Creates a test harnesssetup*- One-time initialization functions with side effectssetupMSW() // Initializes MSW globally setupCryptoControl() // Sets up crypto mocking setupTestEnv() // Configures test environmentuse*- Hook-style functions for test lifecycle managementuseTempDirectory() // Returns a cleanup function (from @orchestr8/testkit/fs) useFakeTimers() // Returns timer context (from @orchestr8/testkit/env) usePrismaTestDatabase() // Returns database context (from @orchestr8/testkit/sqlite)with*- Scoped operations with automatic cleanupwithTempDirectoryScope() // Executes function with temp dir withFakeTimers() // Executes with fake time withTransaction() // Executes within database transactionget*- Pure getter functions without side effectsgetTestEnvironment() // Returns current test env getMSWServer() // Returns existing server instance getResourceStats() // Returns resource statistics
Deprecation Policy
When function names are standardized, the old names are kept with deprecation warnings:
// New standardized name
createTempDirectoryWithResourceManager()
// Old name still available but deprecated
useTempDirectoryWithResourceManager() // Shows deprecation warningVitest Configuration
The testkit provides pre-configured Vitest setups:
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import { createVitestConfig } from '@orchestr8/testkit/config'
export default defineConfig(
createVitestConfig({
test: {
globals: true,
environment: 'happy-dom', // requires happy-dom
setupFiles: ['@orchestr8/testkit/register'],
},
}),
)TypeScript Support
Full TypeScript definitions are included:
import type {
TestConfig,
TestEnvironment,
} from '@orchestr8/testkit'
// Types from sub-exports
import type { TempDirectory } from '@orchestr8/testkit/fs'
import type { FakeTimerOptions } from '@orchestr8/testkit/env'Error Handling
The package is designed with graceful error handling:
- Missing optional dependencies: Sub-exports will fail with clear error messages
- Vitest context issues: Core utilities work outside of test contexts
- Environment detection: Safe fallbacks for all environment checks
Contributing
This package is part of the @orchestr8 monorepo. See the main repository for contribution guidelines.
License
MIT
