citty-test-utils
Version:
A comprehensive testing framework for CLI applications built with Citty, featuring Docker cleanroom support, fluent assertions, advanced scenario DSL, and noun-verb CLI structure with template generation.
290 lines (229 loc) ⢠7.53 kB
Markdown
for `citty-test-utils` - the testing utilities for GitVan CLI applications.
- [**Getting Started Guide**](guides/getting-started.md) - Quick start and basic usage
- [**Installation**](guides/getting-started.md
- [**First Test**](guides/getting-started.md
- [**Complete API Reference**](api/README.md) - Full API documentation
- [**Core Functions**](api/README.md
- [**Fluent Assertions**](api/README.md
- [**Scenario DSL**](api/README.md
- [**TypeScript Types**](api/README.md
- [**Cookbooks**](cookbooks/README.md) - Ready-to-use testing patterns
- [**Basic CLI Testing**](cookbooks/README.md
- [**Error Handling Tests**](cookbooks/README.md
- [**Performance Testing**](cookbooks/README.md
- [**Cross-Environment Testing**](cookbooks/README.md
- [**Advanced Examples**](examples/README.md) - Complex testing scenarios
- [**Enterprise Patterns**](examples/README.md
- [**Custom Frameworks**](examples/README.md
- [**Performance Benchmarking**](examples/README.md
- [**Security Testing**](examples/README.md
- [**Troubleshooting**](guides/troubleshooting.md) - Common issues and solutions
- [**Migration Guide**](guides/migration.md) - Migrating from other testing approaches
- [**Best Practices**](guides/best-practices.md) - Recommended testing patterns
```javascript
import { runLocalCitty } from 'citty-test-utils'
// Test GitVan CLI locally
const result = await runLocalCitty(['--help'])
result.expectSuccess().expectOutput('USAGE').expectNoStderr()
```
```mermaid
graph TB
A[Test Code] --> B[citty-test-utils]
B --> C[Local Runner]
B --> D[Cleanroom Runner]
B --> E[Scenario DSL]
B --> F[Fluent Assertions]
C --> G[GitVan CLI]
D --> H[Docker Container]
E --> I[Multi-step Workflows]
F --> J[Chainable Expectations]
G --> K[Local Environment]
H --> L[Isolated Environment]
I --> M[Complex Test Scenarios]
J --> N[Detailed Error Messages]
```
- Automatically finds GitVan project root
- Validates CLI path and configuration
- Works from any subdirectory
- Execute CLI commands locally
- Timeout and environment support
- Safe JSON parsing with fallback
- Isolated testing environment
- Consistent results across systems
- Automatic container management
- Chainable expectation API
- Detailed error messages
- 15+ assertion methods
- Multi-step test workflows
- Custom actions and expectations
- Pre-built scenario templates
- Retry logic for flaky tests
- Temporary file management
- Wait conditions and timeouts
```javascript
// Test help and version commands
const helpResult = await runLocalCitty(['--help'])
helpResult.expectSuccess().expectOutput('USAGE')
const versionResult = await runLocalCitty(['--version'])
versionResult.expectSuccess().expectOutput(/\d+\.\d+\.\d+/)
```
```javascript
// Test invalid commands
const errorResult = await runLocalCitty(['invalid-command'])
errorResult.expectFailure().expectStderr(/Unknown command/)
```
```javascript
// Multi-step scenario
const result = await scenario('Project Setup')
.step('Initialize project')
.run('init', 'my-project')
.expectSuccess()
.step('Check status')
.run('status')
.expectSuccess()
.execute('local')
```
```javascript
// Test in both local and cleanroom
await setupCleanroom({ rootDir: '.' })
const localResult = await runLocalCitty(['--help'])
const cleanroomResult = await runCitty(['--help'])
// Compare results
expect(localResult.result.stdout).toBe(cleanroomResult.result.stdout)
await teardownCleanroom()
```
```json
{
"name": "gitvan",
"type": "module",
"scripts": {
"test": "vitest",
"test:cli": "vitest tests/cli-tests.mjs"
},
"devDependencies": {
"citty-test-utils": "^0.2.1",
"vitest": "^1.0.0"
}
}
```
```javascript
// vitest.config.mjs
export default {
test: {
environment: 'node',
timeout: 60000
}
}
```
```javascript
import { describe, it } from 'vitest'
import { runLocalCitty } from 'citty-test-utils'
describe('CLI Commands', () => {
it('should show help', async () => {
const result = await runLocalCitty(['--help'])
result.expectSuccess().expectOutput('USAGE')
})
})
```
```javascript
import { scenario } from 'citty-test-utils'
const result = await scenario('Integration Test')
.step('Setup')
.run('init', 'test-project')
.expectSuccess()
.step('Verify')
.run('status')
.expectSuccess()
.execute('local')
```
```javascript
import { setupCleanroom, runCitty, teardownCleanroom } from 'citty-test-utils'
await setupCleanroom({ rootDir: '.' })
const result = await runCitty(['--help'])
result.expectSuccess().expectOutput('USAGE')
await teardownCleanroom()
```
```bash
your-project/
āāā src/cli.mjs
āāā package.json
```
```bash
docker --version
docker ps
```
```bash
chmod +x src/cli.mjs
```
- **Local Runner**: ~50ms per command
- **Cleanroom Setup**: ~2-5 seconds
- **Command Execution**: ~100-500ms
- **Memory Usage**: ~50MB per test
- Use local runner for simple tests
- Reuse cleanroom containers
- Run tests in parallel
- Set appropriate timeouts
```bash
git clone https://github.com/gitvan/gitvan.git
cd vendors/citty-test-utils
npm install
npm test
```
```bash
npm run test:unit
npm run test:integration
npm test
```
MIT License - see [LICENSE](../LICENSE) for details.
- **NPM Package**: [citty-test-utils](https://www.npmjs.com/package/citty-test-utils)
- **GitHub Repository**: [seanchatmangpt/gitvan](https://github.com/seanchatmangpt/gitvan)
- **Issues**: [GitHub Issues](https://github.com/seanchatmangpt/gitvan/issues)
- **Discussions**: [GitHub Discussions](https://github.com/seanchatmangpt/gitvan/discussions)
---
**Need help?** Check out the [Troubleshooting Guide](guides/troubleshooting.md) or [open an issue](https://github.com/seanchatmangpt/gitvan/issues).
Welcome to the comprehensive documentation