use super::*;
#[test]
fn analyze_client_trait_object_compiles() {
fn _accepts_dyn(_c: &dyn AnalyzeClient) {}
}
#[test]
fn http_analyze_client_url_is_configurable() {
let client = HttpAnalyzeClient::new("http://127.0.0.1:7879").expect("TLS init should succeed");
assert_eq!(client.base_url(), "http://127.0.0.1:7879");
}
#[test]
fn http_analyze_client_strips_trailing_slash() {
let client = HttpAnalyzeClient::new("http://127.0.0.1:7879/").expect("TLS init should succeed");
assert_eq!(client.base_url(), "http://127.0.0.1:7879");
}
#[test]
fn http_analyze_client_from_config() {
let mut config = crate::config::ReviewConfig::load(None);
config.analyzer_url = "http://localhost:8888".to_string();
let client = HttpAnalyzeClient::from_config(&config).expect("TLS init should succeed");
assert_eq!(client.base_url(), "http://localhost:8888");
}
#[test]
fn analyze_health_response_is_healthy() {
let resp = AnalyzeHealthResponse {
status: "ok".to_string(),
search_reachable: true,
};
assert!(resp.is_healthy());
}
#[test]
fn analyze_health_response_not_ok() {
let resp = AnalyzeHealthResponse {
status: "starting".to_string(),
search_reachable: false,
};
assert!(!resp.is_healthy());
}
#[test]
fn analyze_health_search_not_reachable() {
let resp = AnalyzeHealthResponse {
status: "ok".to_string(),
search_reachable: false,
};
assert!(
!resp.is_healthy(),
"is_healthy must be false when search_reachable is false"
);
}
#[test]
fn analyze_health_response_deserialises() {
let json = r#"{"status":"ok","search_reachable":true}"#;
let resp: AnalyzeHealthResponse = serde_json::from_str(json).unwrap();
assert!(resp.is_healthy());
}
#[test]
fn analyze_index_info_deserialises() {
let json = r#"{"id":"main"}"#;
let info: AnalyzeIndexInfo = serde_json::from_str(json).unwrap();
assert_eq!(info.id, "main");
}
#[test]
fn hotspot_deserialises() {
let json = r#"{
"file": "src/service/mod.rs",
"function_name": "handle_webhook",
"cyclomatic": 18,
"cognitive": 22
}"#;
let h: ComplexityHotspot = serde_json::from_str(json).unwrap();
assert_eq!(h.file, "src/service/mod.rs");
assert_eq!(h.function_name.as_deref(), Some("handle_webhook"));
assert_eq!(h.cyclomatic, 18);
}
#[test]
fn smell_deserialises() {
let json = r#"{"file":"src/main.rs","category":"long_method","severity":"high","line":42}"#;
let s: Smell = serde_json::from_str(json).unwrap();
assert_eq!(s.file, "src/main.rs");
assert_eq!(s.category, "long_method");
assert_eq!(s.line, Some(42));
}
#[test]
fn analyze_error_display() {
let err = AnalyzeClientError::Transport("connection refused".to_string());
assert!(err.to_string().contains("connection refused"));
let err = AnalyzeClientError::Unavailable("timeout".to_string());
assert!(err.to_string().contains("timeout"));
}
#[test]
fn two_step_probe_never_calls_quality() {
let source = include_str!("analyze_client.rs");
let in_has_analysis: Vec<&str> = {
let mut capturing = false;
let mut brace_depth: i32 = 0;
let mut lines = Vec::new();
for line in source.lines() {
let trimmed = line.trim_start();
if !capturing && trimmed.contains("async fn has_analysis") {
capturing = true;
}
if capturing {
lines.push(line);
brace_depth += line.chars().filter(|&c| c == '{').count() as i32;
brace_depth -= line.chars().filter(|&c| c == '}').count() as i32;
if brace_depth <= 0 && lines.len() > 1 {
break;
}
}
}
lines
};
let quality_url_in_body = in_has_analysis
.iter()
.filter(|l| !l.trim_start().starts_with("//"))
.any(|l| l.contains("/quality\"") || l.contains("/quality?"));
assert!(
!quality_url_in_body,
"has_analysis must NEVER construct a URL to /quality (spec REV-441, lesson §12.3)"
);
assert!(
!in_has_analysis.is_empty(),
"could not locate has_analysis fn body in analyze_client.rs — test is broken"
);
}
#[tokio::test]
async fn two_step_probe_returns_false_on_transport_error() {
let client = HttpAnalyzeClient::new("http://127.0.0.1:1").expect("TLS init should succeed");
let result = client.has_analysis("main").await;
assert!(
!result,
"has_analysis must return false on transport error, not panic"
);
}
#[tokio::test]
async fn complexity_hotspots_transport_error_propagates() {
let client = HttpAnalyzeClient::new("http://127.0.0.1:1").expect("TLS init should succeed");
let result = client.complexity_hotspots("main", Some(5)).await;
assert!(
result.is_err(),
"transport error must surface as Err from complexity_hotspots"
);
}
#[tokio::test]
async fn smells_transport_error_propagates() {
let client = HttpAnalyzeClient::new("http://127.0.0.1:1").expect("TLS init should succeed");
let result = client.smells("main").await;
assert!(
result.is_err(),
"transport error must surface as Err from smells"
);
}