Initial commit
This commit is contained in:
175
skills/cli-testing-patterns/templates/jest-cli-test.ts
Normal file
175
skills/cli-testing-patterns/templates/jest-cli-test.ts
Normal file
@@ -0,0 +1,175 @@
|
||||
/**
|
||||
* Jest CLI Test Template
|
||||
*
|
||||
* Complete test suite for CLI tools using Jest and child_process.execSync
|
||||
* Tests command execution, exit codes, stdout/stderr output
|
||||
*/
|
||||
|
||||
import { execSync } from 'child_process';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
|
||||
describe('CLI Tool Tests', () => {
|
||||
const CLI_PATH = path.join(__dirname, '../bin/mycli');
|
||||
|
||||
/**
|
||||
* Helper function to execute CLI commands and capture output
|
||||
* @param args - Command line arguments as string
|
||||
* @returns Object with stdout, stderr, and exit code
|
||||
*/
|
||||
function runCLI(args: string): {
|
||||
stdout: string;
|
||||
stderr: string;
|
||||
code: number;
|
||||
} {
|
||||
try {
|
||||
const stdout = execSync(`${CLI_PATH} ${args}`, {
|
||||
encoding: 'utf8',
|
||||
stdio: 'pipe',
|
||||
});
|
||||
return { stdout, stderr: '', code: 0 };
|
||||
} catch (error: any) {
|
||||
return {
|
||||
stdout: error.stdout || '',
|
||||
stderr: error.stderr || '',
|
||||
code: error.status || 1,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Version Testing
|
||||
describe('version command', () => {
|
||||
test('should display version with --version', () => {
|
||||
const { stdout, code } = runCLI('--version');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('1.0.0');
|
||||
});
|
||||
|
||||
test('should display version with -v', () => {
|
||||
const { stdout, code } = runCLI('-v');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toMatch(/\d+\.\d+\.\d+/);
|
||||
});
|
||||
});
|
||||
|
||||
// Help Testing
|
||||
describe('help command', () => {
|
||||
test('should display help with --help', () => {
|
||||
const { stdout, code } = runCLI('--help');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Usage:');
|
||||
expect(stdout).toContain('Commands:');
|
||||
expect(stdout).toContain('Options:');
|
||||
});
|
||||
|
||||
test('should display help with -h', () => {
|
||||
const { stdout, code } = runCLI('-h');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Usage:');
|
||||
});
|
||||
});
|
||||
|
||||
// Error Handling
|
||||
describe('error handling', () => {
|
||||
test('should handle unknown command', () => {
|
||||
const { stderr, code } = runCLI('unknown-command');
|
||||
expect(code).toBe(1);
|
||||
expect(stderr).toContain('unknown command');
|
||||
});
|
||||
|
||||
test('should handle invalid options', () => {
|
||||
const { stderr, code } = runCLI('--invalid-option');
|
||||
expect(code).toBe(1);
|
||||
expect(stderr).toContain('unknown option');
|
||||
});
|
||||
|
||||
test('should validate required arguments', () => {
|
||||
const { stderr, code } = runCLI('deploy');
|
||||
expect(code).toBe(1);
|
||||
expect(stderr).toContain('missing required argument');
|
||||
});
|
||||
});
|
||||
|
||||
// Command Execution
|
||||
describe('command execution', () => {
|
||||
test('should execute deploy command', () => {
|
||||
const { stdout, code } = runCLI('deploy production --force');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Deploying to production');
|
||||
expect(stdout).toContain('Force mode enabled');
|
||||
});
|
||||
|
||||
test('should execute with flags', () => {
|
||||
const { stdout, code } = runCLI('build --verbose --output dist');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Building project');
|
||||
expect(stdout).toContain('Output: dist');
|
||||
});
|
||||
});
|
||||
|
||||
// Configuration Testing
|
||||
describe('configuration', () => {
|
||||
test('should set configuration value', () => {
|
||||
const { stdout, code } = runCLI('config set key value');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Configuration updated');
|
||||
});
|
||||
|
||||
test('should get configuration value', () => {
|
||||
runCLI('config set api_key your_key_here');
|
||||
const { stdout, code } = runCLI('config get api_key');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('your_key_here');
|
||||
});
|
||||
|
||||
test('should list all configuration', () => {
|
||||
const { stdout, code } = runCLI('config list');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain('Configuration:');
|
||||
});
|
||||
});
|
||||
|
||||
// Exit Code Validation
|
||||
describe('exit codes', () => {
|
||||
test('should return 0 on success', () => {
|
||||
const { code } = runCLI('status');
|
||||
expect(code).toBe(0);
|
||||
});
|
||||
|
||||
test('should return 1 on general error', () => {
|
||||
const { code } = runCLI('invalid-command');
|
||||
expect(code).toBe(1);
|
||||
});
|
||||
|
||||
test('should return 2 on invalid arguments', () => {
|
||||
const { code } = runCLI('deploy --invalid-flag');
|
||||
expect(code).toBe(2);
|
||||
});
|
||||
});
|
||||
|
||||
// Output Format Testing
|
||||
describe('output formatting', () => {
|
||||
test('should output JSON when requested', () => {
|
||||
const { stdout, code } = runCLI('status --format json');
|
||||
expect(code).toBe(0);
|
||||
expect(() => JSON.parse(stdout)).not.toThrow();
|
||||
});
|
||||
|
||||
test('should output YAML when requested', () => {
|
||||
const { stdout, code } = runCLI('status --format yaml');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toContain(':');
|
||||
});
|
||||
|
||||
test('should output table by default', () => {
|
||||
const { stdout, code } = runCLI('status');
|
||||
expect(code).toBe(0);
|
||||
expect(stdout).toMatch(/[─┼│]/); // Table characters
|
||||
});
|
||||
});
|
||||
|
||||
// Cleanup
|
||||
afterAll(() => {
|
||||
// Clean up any test artifacts
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user