cli_testing_specialist/cli/
commands.rs1use clap::{Parser, Subcommand, ValueEnum};
2use clap_complete::Shell;
3use std::path::PathBuf;
4
5#[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 #[command(subcommand)]
16 pub command: Commands,
17
18 #[arg(short, long, global = true)]
20 pub verbose: bool,
21}
22
23#[derive(Subcommand, Debug)]
25pub enum Commands {
26 #[command(about = "Analyze CLI tool structure and options")]
28 Analyze {
29 #[arg(value_name = "BINARY")]
31 binary: PathBuf,
32
33 #[arg(short, long, default_value = "cli-analysis.json")]
35 output: PathBuf,
36
37 #[arg(short, long, default_value = "3")]
39 depth: u8,
40
41 #[arg(long)]
43 parallel: bool,
44 },
45
46 #[command(about = "Generate test suites from analysis (BATS, assert_cmd, or snapbox)")]
48 Generate {
49 #[arg(value_name = "ANALYSIS")]
51 analysis: PathBuf,
52
53 #[arg(short, long, default_value = "test-output")]
55 output: PathBuf,
56
57 #[arg(short, long, default_value = "all")]
59 categories: String,
60
61 #[arg(short, long, default_value = "bats")]
63 format: TestFormat,
64
65 #[arg(long)]
68 include_intensive: bool,
69 },
70
71 #[command(about = "Execute BATS tests and generate reports")]
73 Run {
74 #[arg(value_name = "TEST_DIR")]
76 test_dir: PathBuf,
77
78 #[arg(short, long, default_value = "markdown")]
80 format: ReportFormat,
81
82 #[arg(short, long, default_value = "reports")]
84 output: PathBuf,
85
86 #[arg(short = 't', long, default_value = "300")]
88 timeout: u64,
89
90 #[arg(short = 's', long)]
92 skip: Option<String>,
93 },
94
95 #[command(about = "Validate analysis JSON file structure")]
97 Validate {
98 #[arg(value_name = "FILE")]
100 file: PathBuf,
101 },
102
103 #[command(about = "Generate shell completion scripts")]
105 Completion {
106 #[arg(value_name = "SHELL")]
108 shell: Shell,
109 },
110}
111
112#[derive(ValueEnum, Clone, Debug)]
114pub enum ReportFormat {
115 Markdown,
117
118 Json,
120
121 Html,
123
124 Junit,
126
127 All,
129}
130
131impl ReportFormat {
132 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#[derive(ValueEnum, Clone, Debug)]
146pub enum TestFormat {
147 Bats,
149
150 #[value(name = "assert_cmd")]
152 AssertCmd,
153
154 Snapbox,
156}
157
158impl TestFormat {
159 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 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}