cli_testing_specialist/cli/
commands.rs

1use clap::{Parser, Subcommand, ValueEnum};
2use clap_complete::Shell;
3use std::path::PathBuf;
4
5/// CLI Testing Specialist - Comprehensive testing framework for CLI tools
6#[derive(Parser, Debug)]
7#[command(
8    name = "cli-test",
9    version,
10    about = "Comprehensive CLI testing framework",
11    long_about = "Analyzes CLI tools, generates BATS test suites, and produces detailed security reports"
12)]
13pub struct Cli {
14    /// Subcommand to execute
15    #[command(subcommand)]
16    pub command: Commands,
17
18    /// Enable verbose output
19    #[arg(short, long, global = true)]
20    pub verbose: bool,
21}
22
23/// Available subcommands
24#[derive(Subcommand, Debug)]
25pub enum Commands {
26    /// Analyze a CLI tool and extract its structure
27    #[command(about = "Analyze CLI tool structure and options")]
28    Analyze {
29        /// Path to the CLI binary to analyze
30        #[arg(value_name = "BINARY")]
31        binary: PathBuf,
32
33        /// Output JSON file path
34        #[arg(short, long, default_value = "cli-analysis.json")]
35        output: PathBuf,
36
37        /// Maximum recursion depth for subcommands
38        #[arg(short, long, default_value = "3")]
39        depth: u8,
40
41        /// Enable parallel processing
42        #[arg(long)]
43        parallel: bool,
44    },
45
46    /// Generate test cases from analysis results
47    #[command(about = "Generate test suites from analysis (BATS, assert_cmd, or snapbox)")]
48    Generate {
49        /// Analysis JSON file path
50        #[arg(value_name = "ANALYSIS")]
51        analysis: PathBuf,
52
53        /// Output directory for test files
54        #[arg(short, long, default_value = "test-output")]
55        output: PathBuf,
56
57        /// Test categories to generate (comma-separated or "all")
58        #[arg(short, long, default_value = "all")]
59        categories: String,
60
61        /// Test framework format (bats, assert_cmd, snapbox)
62        #[arg(short, long, default_value = "bats")]
63        format: TestFormat,
64
65        /// Include resource-intensive tests (directory-traversal, large-scale performance)
66        /// These tests may require significant /tmp space and memory
67        #[arg(long)]
68        include_intensive: bool,
69    },
70
71    /// Run BATS tests and generate reports
72    #[command(about = "Execute BATS tests and generate reports")]
73    Run {
74        /// Test directory containing BATS files
75        #[arg(value_name = "TEST_DIR")]
76        test_dir: PathBuf,
77
78        /// Report format to generate
79        #[arg(short, long, default_value = "markdown")]
80        format: ReportFormat,
81
82        /// Output directory for reports
83        #[arg(short, long, default_value = "reports")]
84        output: PathBuf,
85
86        /// Timeout per test suite in seconds (default: 300)
87        #[arg(short = 't', long, default_value = "300")]
88        timeout: u64,
89
90        /// Skip specific test categories (comma-separated)
91        #[arg(short = 's', long)]
92        skip: Option<String>,
93    },
94
95    /// Validate analysis JSON file
96    #[command(about = "Validate analysis JSON file structure")]
97    Validate {
98        /// Analysis JSON file to validate
99        #[arg(value_name = "FILE")]
100        file: PathBuf,
101    },
102
103    /// Generate shell completion scripts
104    #[command(about = "Generate shell completion scripts")]
105    Completion {
106        /// Shell type to generate completion for
107        #[arg(value_name = "SHELL")]
108        shell: Shell,
109    },
110}
111
112/// Report output format
113#[derive(ValueEnum, Clone, Debug)]
114pub enum ReportFormat {
115    /// Markdown format
116    Markdown,
117
118    /// JSON format
119    Json,
120
121    /// HTML format
122    Html,
123
124    /// JUnit XML format
125    Junit,
126
127    /// All formats
128    All,
129}
130
131impl ReportFormat {
132    /// Get file extension for this format
133    pub fn extension(&self) -> &'static str {
134        match self {
135            Self::Markdown => "md",
136            Self::Json => "json",
137            Self::Html => "html",
138            Self::Junit => "xml",
139            Self::All => "all",
140        }
141    }
142}
143
144/// Test framework format
145#[derive(ValueEnum, Clone, Debug)]
146pub enum TestFormat {
147    /// BATS (Bash Automated Testing System)
148    Bats,
149
150    /// assert_cmd (Rust testing framework)
151    #[value(name = "assert_cmd")]
152    AssertCmd,
153
154    /// snapbox (Rust snapshot testing)
155    Snapbox,
156}
157
158impl TestFormat {
159    /// Get file extension for this format
160    pub fn extension(&self) -> &'static str {
161        match self {
162            Self::Bats => "bats",
163            Self::AssertCmd => "rs",
164            Self::Snapbox => "rs",
165        }
166    }
167
168    /// Get format name as string
169    pub fn as_str(&self) -> &'static str {
170        match self {
171            Self::Bats => "bats",
172            Self::AssertCmd => "assert_cmd",
173            Self::Snapbox => "snapbox",
174        }
175    }
176}
177
178#[cfg(test)]
179mod tests {
180    use super::*;
181
182    #[test]
183    fn test_report_format_extension() {
184        assert_eq!(ReportFormat::Markdown.extension(), "md");
185        assert_eq!(ReportFormat::Json.extension(), "json");
186        assert_eq!(ReportFormat::Html.extension(), "html");
187        assert_eq!(ReportFormat::Junit.extension(), "xml");
188    }
189}