citty-test-utils
Version:
Unified testing framework for CLI applications with auto-detecting local/cleanroom execution, vitest config integration, and simplified scenario DSL.
209 lines (195 loc) • 5.45 kB
JavaScript
#!/usr/bin/env node
// src/cli.mjs - Test CLI for citty-test-utils integration testing
import { defineCommand, runMain } from 'citty'
const testCli = defineCommand({
meta: {
name: 'test-cli',
version: '1.0.0',
description: 'Test CLI for citty-test-utils integration testing',
},
subCommands: {
greet: defineCommand({
meta: {
name: 'greet',
description: 'Greet someone',
},
args: {
name: {
type: 'positional',
description: 'Name to greet',
default: 'World',
},
verbose: {
type: 'boolean',
description: 'Enable verbose output',
default: false,
},
count: {
type: 'number',
description: 'Number of times to repeat',
default: 1,
},
},
run: async (ctx) => {
const { name, verbose, count } = ctx.args
if (ctx.args.json) {
console.log(
JSON.stringify({
message: `Hello, ${name}!`,
count,
verbose,
})
)
} else {
if (verbose) {
console.log('Verbose mode enabled')
}
for (let i = 0; i < count; i++) {
console.log(`Hello, ${name}! (${i + 1}/${count})`)
}
}
},
}),
math: defineCommand({
meta: {
name: 'math',
description: 'Perform mathematical operations',
},
subCommands: {
add: defineCommand({
meta: {
name: 'add',
description: 'Add two numbers',
},
args: {
a: {
type: 'positional',
description: 'First number',
required: true,
},
b: {
type: 'positional',
description: 'Second number',
required: true,
},
},
run: async (ctx) => {
const { a, b } = ctx.args
const result = Number(a) + Number(b)
if (ctx.args.json) {
console.log(
JSON.stringify({
operation: 'add',
a: Number(a),
b: Number(b),
result,
})
)
} else {
console.log(`${a} + ${b} = ${result}`)
}
},
}),
multiply: defineCommand({
meta: {
name: 'multiply',
description: 'Multiply two numbers',
},
args: {
a: {
type: 'positional',
description: 'First number',
required: true,
},
b: {
type: 'positional',
description: 'Second number',
required: true,
},
},
run: async (ctx) => {
const { a, b } = ctx.args
const result = Number(a) * Number(b)
if (ctx.args.json) {
console.log(
JSON.stringify({
operation: 'multiply',
a: Number(a),
b: Number(b),
result,
})
)
} else {
console.log(`${a} × ${b} = ${result}`)
}
},
}),
},
}),
error: defineCommand({
meta: {
name: 'error',
description: 'Simulate different types of errors',
},
args: {
type: {
type: 'positional',
description: 'Type of error to simulate',
default: 'generic',
},
},
run: async (ctx) => {
const { type } = ctx.args
switch (type) {
case 'generic':
throw new Error('Generic error occurred')
case 'validation':
throw new Error('Validation error: Invalid input')
case 'timeout':
await new Promise((resolve) => setTimeout(resolve, 10000))
break
case 'exit':
process.exit(1)
default:
console.log(`Unknown error type: ${type}`)
}
},
}),
info: defineCommand({
meta: {
name: 'info',
description: 'Show test CLI information',
},
run: async (ctx) => {
const info = {
name: 'citty-test-utils-test-cli',
version: '1.0.0',
description: 'Test CLI for citty-test-utils integration testing',
commands: ['greet', 'math', 'error', 'info'],
features: [
'Basic command execution',
'Subcommands',
'JSON output support',
'Error simulation',
'Argument parsing',
],
}
if (ctx.args.json) {
console.log(JSON.stringify(info, null, 2))
} else {
console.log('Test CLI Information:')
console.log(`Name: ${info.name}`)
console.log(`Version: ${info.version}`)
console.log(`Description: ${info.description}`)
console.log(`Commands: ${info.commands.join(', ')}`)
console.log('Features:')
info.features.forEach((feature) => console.log(` - ${feature}`))
}
},
}),
},
})
// Only run the CLI when this script is executed directly
if (import.meta.url === `file://${process.argv[1]}`) {
runMain(testCli)
}