use debtmap::io::writers::MarkdownWriter;
use debtmap::io::writers::markdown::EnhancedMarkdownWriter;
use debtmap::priority::{
CallGraph, DebtType, FunctionRole, FunctionVisibility, ImpactMetrics, UnifiedAnalysis,
UnifiedAnalysisUtils,
unified_scorer::{Location, UnifiedDebtItem, UnifiedScore},
};
use std::io::Cursor;
use std::path::PathBuf;
fn create_sample_unified_item() -> UnifiedDebtItem {
UnifiedDebtItem {
location: Location {
file: PathBuf::from("src/main.rs"),
function: "process_data".to_string(),
line: 42,
},
debt_type: DebtType::TestingGap {
coverage: 0.3,
cyclomatic: 15,
cognitive: 20,
},
unified_score: UnifiedScore {
complexity_factor: 7.5,
coverage_factor: 8.0,
dependency_factor: 4.0,
role_multiplier: 1.2,
final_score: 7.8,
base_score: None,
exponential_factor: None,
risk_boost: None,
pre_adjustment_score: None,
adjustment_applied: None,
purity_factor: None,
refactorability_factor: None,
pattern_factor: None,
debt_adjustment: None,
pre_normalization_score: None,
structural_multiplier: Some(1.0),
has_coverage_data: false,
contextual_risk_multiplier: None,
pre_contextual_score: None,
debt_type_multiplier: None,
},
function_role: FunctionRole::PureLogic,
recommendation: debtmap::priority::ActionableRecommendation {
primary_action: "Add unit tests".to_string(),
rationale: "High complexity with low coverage".to_string(),
implementation_steps: vec![],
related_items: vec![],
steps: None,
estimated_effort_hours: None,
},
expected_impact: ImpactMetrics {
coverage_improvement: 30.0,
lines_reduction: 0,
complexity_reduction: 0.0,
risk_reduction: 25.0,
},
transitive_coverage: None,
file_context: None,
upstream_dependencies: 3,
downstream_dependencies: 5,
upstream_callers: vec![],
downstream_callees: vec![],
upstream_production_callers: vec![],
upstream_test_callers: vec![],
production_blast_radius: 0,
nesting_depth: 3,
function_length: 50,
cyclomatic_complexity: 15,
cognitive_complexity: 20,
is_pure: None,
purity_confidence: None,
purity_level: None,
god_object_indicators: None,
tier: None,
function_context: None,
context_confidence: None,
contextual_recommendation: None,
pattern_analysis: None,
context_multiplier: None,
context_type: None,
language_specific: None, detected_pattern: None,
contextual_risk: None, file_line_count: None,
responsibility_category: None,
error_swallowing_count: None,
error_swallowing_patterns: None,
entropy_analysis: None,
context_suggestion: None,
}
}
#[test]
fn test_enhanced_markdown_priority_section() {
let call_graph = CallGraph::new();
let mut analysis = UnifiedAnalysis::new(call_graph);
let item = create_sample_unified_item();
analysis.add_item(item);
analysis.sort_by_priority();
let mut output = Vec::new();
let mut writer = MarkdownWriter::new(Cursor::new(&mut output));
writer.write_priority_section(&analysis).unwrap();
let markdown = String::from_utf8(output).unwrap();
if !markdown.contains("process_data") {
println!("Markdown output:\n{}", markdown);
}
assert!(markdown.contains("## Priority Technical Debt"));
if !markdown.contains("_No priority items found._") {
assert!(markdown.contains("### Top"));
assert!(markdown.contains("| Rank | Score | Function | Type | Issue |"));
assert!(markdown.contains("src/main.rs:42")); assert!(markdown.contains("Testing Gap"));
}
}
#[test]
fn test_enhanced_markdown_dead_code_section() {
let call_graph = CallGraph::new();
let mut analysis = UnifiedAnalysis::new(call_graph);
let mut item = create_sample_unified_item();
item.debt_type = DebtType::DeadCode {
visibility: FunctionVisibility::Private,
cyclomatic: 10,
cognitive: 15,
usage_hints: vec![],
};
analysis.add_item(item);
let mut output = Vec::new();
let mut writer = MarkdownWriter::new(Cursor::new(&mut output));
writer.write_dead_code_section(&analysis).unwrap();
let markdown = String::from_utf8(output).unwrap();
assert!(markdown.contains("## Dead Code Detection"));
assert!(markdown.contains("### Unused Functions"));
assert!(markdown.contains("| Function | Visibility | Complexity | Recommendation |"));
assert!(markdown.contains("process_data"));
assert!(markdown.contains("private"));
}
#[test]
fn test_enhanced_markdown_testing_recommendations() {
let call_graph = CallGraph::new();
let mut analysis = UnifiedAnalysis::new(call_graph);
let item = create_sample_unified_item();
analysis.add_item(item);
let mut output = Vec::new();
let mut writer = MarkdownWriter::new(Cursor::new(&mut output));
writer.write_testing_recommendations(&analysis).unwrap();
let markdown = String::from_utf8(output).unwrap();
assert!(markdown.contains("## Testing Recommendations"));
assert!(markdown.contains("### ROI-Based Testing Priorities"));
assert!(markdown.contains("| Function | ROI | Complexity | Coverage | Risk Reduction |"));
assert!(markdown.contains("process_data"));
assert!(markdown.contains("30%")); }
#[test]
fn test_enhanced_markdown_with_verbosity() {
let call_graph = CallGraph::new();
let mut analysis = UnifiedAnalysis::new(call_graph);
for i in 0..3 {
let mut item = create_sample_unified_item();
item.location.function = format!("function_{}", i);
item.unified_score.final_score = 10.0 - i as f64;
analysis.add_item(item);
}
analysis.sort_by_priority();
let mut output = Vec::new();
let mut writer = MarkdownWriter::with_verbosity(Cursor::new(&mut output), 2);
writer.write_unified_analysis(&analysis).unwrap();
let markdown = String::from_utf8(output).unwrap();
assert!(markdown.contains("<details>"));
assert!(markdown.contains("Score Breakdown"));
assert!(markdown.contains("## Call Graph Analysis"));
assert!(markdown.contains("### Module Statistics"));
}
#[test]
fn test_enhanced_markdown_full_report() {
let call_graph = CallGraph::new();
let mut analysis = UnifiedAnalysis::new(call_graph);
let mut item1 = create_sample_unified_item();
item1.location.function = "untested_function".to_string();
analysis.add_item(item1);
let mut item2 = create_sample_unified_item();
item2.location.function = "dead_function".to_string();
item2.debt_type = DebtType::DeadCode {
visibility: FunctionVisibility::Public,
cyclomatic: 5,
cognitive: 8,
usage_hints: vec!["Consider removing".to_string()],
};
analysis.add_item(item2);
let mut item3 = create_sample_unified_item();
item3.location.function = "complex_function".to_string();
item3.debt_type = DebtType::ComplexityHotspot {
cyclomatic: 25,
cognitive: 30,
};
analysis.add_item(item3);
analysis.sort_by_priority();
let mut output = Vec::new();
let mut writer = MarkdownWriter::with_verbosity(Cursor::new(&mut output), 1);
writer.write_unified_analysis(&analysis).unwrap();
let markdown = String::from_utf8(output).unwrap();
assert!(markdown.contains("## Priority Technical Debt"));
assert!(markdown.contains("## Dead Code Detection"));
assert!(markdown.contains("## Testing Recommendations"));
assert!(markdown.contains("Top 3 Priority Items"));
assert!(markdown.contains("untested_function"));
assert!(markdown.contains("dead_function"));
assert!(markdown.contains("complex_function"));
}