use super::*;
mod tests {
use super::*;
use crate::cli::commands::ServeTransport;
use crate::cli::{
AnalyzeCommands, Commands, ComplexityOutputFormat, DagType, DeadCodeOutputFormat,
OutputFormat, SatdOutputFormat,
};
use crate::cli::{
DeepContextCacheStrategy, DeepContextDagType, DeepContextOutputFormat, DemoProtocol,
};
use crate::models::churn::ChurnOutputFormat;
use crate::unified_protocol::{HeaderMap, StatusCode, Uuid};
use serde_json::{json, Value};
use std::path::PathBuf;
#[test]
fn test_cli_input_creation() {
let params = vec![
(
"project_name".to_string(),
Value::String("test".to_string()),
),
("version".to_string(), Value::String("1.0.0".to_string())),
];
let command = Commands::Generate {
category: "makefile".to_string(),
template: "rust/cli".to_string(),
params,
output: Some(PathBuf::from("Makefile")),
create_dirs: true,
};
let input = CliInput::from_commands(command);
assert_eq!(input.command_name, "generate");
}
#[tokio::test]
async fn test_cli_adapter_decode_generate() {
let adapter = CliAdapter::new();
let params = vec![(
"project_name".to_string(),
Value::String("test".to_string()),
)];
let command = Commands::Generate {
category: "makefile".to_string(),
template: "rust/cli".to_string(),
params,
output: None,
create_dirs: false,
};
let input = CliInput::from_commands(command);
let unified_request = adapter.decode(input).await.unwrap();
assert_eq!(unified_request.method, Method::POST);
assert_eq!(unified_request.path, "/api/v1/generate");
assert_eq!(
unified_request.get_extension::<Protocol>("protocol"),
Some(Protocol::Cli)
);
let cli_context: CliContext = unified_request.get_extension("cli_context").unwrap();
assert_eq!(cli_context.command, "generate");
}
#[tokio::test]
async fn test_cli_adapter_decode_list() {
let adapter = CliAdapter::new();
let command = Commands::List {
toolchain: Some("rust".to_string()),
category: None,
format: OutputFormat::Json,
};
let input = CliInput::from_commands(command);
let unified_request = adapter.decode(input).await.unwrap();
assert_eq!(unified_request.method, Method::GET);
assert!(unified_request.path.starts_with("/api/v1/templates"));
assert!(unified_request.path.contains("toolchain=rust"));
}
#[tokio::test]
async fn test_cli_adapter_decode_analyze_complexity() {
let adapter = CliAdapter::new();
let command = Commands::Analyze(AnalyzeCommands::Complexity {
path: PathBuf::from("."),
project_path: None,
file: None,
files: vec![],
toolchain: Some("rust".to_string()),
format: ComplexityOutputFormat::Json,
output: None,
max_cyclomatic: Some(10),
max_cognitive: Some(15),
include: vec!["**/*.rs".to_string()],
watch: false,
top_files: 0,
fail_on_violation: false,
timeout: 60,
ml: false,
});
let input = CliInput::from_commands(command);
let unified_request = adapter.decode(input).await.unwrap();
assert_eq!(unified_request.method, Method::POST);
assert_eq!(unified_request.path, "/api/v1/analyze/complexity");
let body_bytes = axum::body::to_bytes(unified_request.body, usize::MAX)
.await
.unwrap();
let body_json: Value = serde_json::from_slice(&body_bytes).unwrap();
assert_eq!(body_json["toolchain"], "rust");
assert_eq!(body_json["max_cyclomatic"], 10);
assert_eq!(body_json["max_cognitive"], 15);
}
#[tokio::test]
async fn test_cli_adapter_encode_success() {
let adapter = CliAdapter::new();
let response = UnifiedResponse::ok()
.with_json(&json!({"message": "success"}))
.unwrap();
let output = adapter.encode(response).await.unwrap();
match output {
CliOutput::Success { content, exit_code } => {
assert_eq!(exit_code, 0);
assert!(content.contains("success"));
}
_ => panic!("Expected success output"),
}
}
#[tokio::test]
async fn test_cli_adapter_encode_error() {
let adapter = CliAdapter::new();
let response = UnifiedResponse::new(axum::http::StatusCode::BAD_REQUEST)
.with_json(&json!({"error": "Invalid request"}))
.unwrap();
let output = adapter.encode(response).await.unwrap();
match output {
CliOutput::Error { message, exit_code } => {
assert_eq!(exit_code, 1);
assert!(message.contains("Invalid request"));
}
_ => panic!("Expected error output"),
}
}
#[test]
fn test_format_conversions() {
assert_eq!(format_to_string(&ContextFormat::Markdown), "markdown");
assert_eq!(format_to_string(&ContextFormat::Json), "json");
assert_eq!(
churn_format_to_string(&ChurnOutputFormat::Summary),
"summary"
);
assert_eq!(churn_format_to_string(&ChurnOutputFormat::Json), "json");
assert_eq!(
complexity_format_to_string(&ComplexityOutputFormat::Sarif),
"sarif"
);
assert_eq!(dag_type_to_string(&DagType::CallGraph), "call-graph");
assert_eq!(
dag_type_to_string(&DagType::FullDependency),
"full-dependency"
);
}
#[test]
fn test_cli_output_methods() {
let success = CliOutput::Success {
content: "test content".to_string(),
exit_code: 0,
};
assert_eq!(success.exit_code(), 0);
assert_eq!(success.content(), "test content");
let error = CliOutput::Error {
message: "test error".to_string(),
exit_code: 1,
};
assert_eq!(error.exit_code(), 1);
assert_eq!(error.content(), "test error");
}
#[test]
fn test_cli_adapter_new() {
let _ = CliAdapter::new();
}
#[test]
fn test_cli_adapter_default() {
let _ = CliAdapter;
}
#[tokio::test]
async fn test_decode_scaffold_project() {
let adapter = CliAdapter::new();
let params = vec![(
"project_name".to_string(),
Value::String("test_project".to_string()),
)];
let command = Commands::Scaffold {
command: ScaffoldCommands::Project {
toolchain: "rust".to_string(),
templates: vec!["cli".to_string()],
params,
parallel: 4,
},
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/scaffold");
}
#[tokio::test]
async fn test_decode_search() {
let adapter = CliAdapter::new();
let command = Commands::Search {
query: "rust cli".to_string(),
toolchain: Some("rust".to_string()),
limit: 10,
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/search");
}
#[tokio::test]
async fn test_decode_validate() {
let adapter = CliAdapter::new();
let params = vec![("key".to_string(), Value::String("value".to_string()))];
let command = Commands::Validate {
uri: "template://rust/cli".to_string(),
params,
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/validate");
}
#[tokio::test]
async fn test_decode_context() {
let adapter = CliAdapter::new();
let command = Commands::Context {
toolchain: Some("rust".to_string()),
project_path: PathBuf::from("/test/project"),
output: Some(PathBuf::from("context.md")),
format: ContextFormat::Markdown,
include_large_files: false,
skip_expensive_metrics: true,
language: None,
languages: None,
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/analyze/context");
}
#[tokio::test]
async fn test_decode_analyze_churn() {
let adapter = CliAdapter::new();
let command = Commands::Analyze(AnalyzeCommands::Churn {
project_path: PathBuf::from("."),
days: 30,
format: ChurnOutputFormat::Json,
output: None,
top_files: 10,
include: vec![],
exclude: vec![],
});
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/analyze/churn");
}
#[tokio::test]
async fn test_decode_analyze_dag() {
let adapter = CliAdapter::new();
let command = Commands::Analyze(AnalyzeCommands::Dag {
dag_type: DagType::FullDependency,
project_path: PathBuf::from("."),
output: None,
max_depth: Some(5),
target_nodes: None,
filter_external: false,
show_complexity: false,
include_duplicates: false,
enhanced: false,
include_dead_code: false,
});
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/analyze/dag");
}
#[tokio::test]
async fn test_decode_analyze_dead_code() {
let adapter = CliAdapter::new();
let command = Commands::Analyze(AnalyzeCommands::DeadCode {
path: PathBuf::from("."),
format: DeadCodeOutputFormat::Json,
top_files: Some(10),
include_unreachable: true,
min_dead_lines: 10,
include_tests: false,
output: None,
fail_on_violation: false,
max_percentage: 15.0,
timeout: 60,
include: vec![],
exclude: vec![],
max_depth: 8,
});
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/analyze/dead-code");
}
#[tokio::test]
async fn test_decode_analyze_satd() {
let adapter = CliAdapter::new();
let command = Commands::Analyze(AnalyzeCommands::Satd {
path: PathBuf::from("."),
format: SatdOutputFormat::Json,
severity: None,
critical_only: false,
include_tests: false,
strict: false,
evolution: false,
days: 30,
metrics: false,
output: None,
top_files: 10,
fail_on_violation: false,
timeout: 60,
include: vec![],
exclude: vec![],
});
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/analyze/satd");
}
#[tokio::test]
async fn test_decode_demo() {
let adapter = CliAdapter::new();
let command = Commands::Demo {
path: Some(PathBuf::from(".")),
url: None,
repo: None,
format: OutputFormat::Table,
protocol: DemoProtocol::Http,
show_api: false,
no_browser: false,
port: Some(8080),
cli: true,
target_nodes: 100,
centrality_threshold: 0.5,
merge_threshold: 3,
debug: false,
debug_output: None,
skip_vendor: true,
no_skip_vendor: false,
max_line_length: None,
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;
assert!(result.is_ok());
let request = result.unwrap();
assert_eq!(request.method, Method::POST);
assert_eq!(request.path, "/api/v1/demo");
}
#[tokio::test]
async fn test_decode_serve() {
let adapter = CliAdapter::new();
let command = Commands::Serve {
host: "127.0.0.1".to_string(),
port: 3000,
cors: true,
transport: ServeTransport::Http,
};
let input = CliInput::from_commands(command);
let result = adapter.decode(input).await;