use ai_code_buddy::core::review::{CommitStatus, Issue, Review};
use ai_code_buddy::widget_states::analysis::AnalysisWidgetState;
use ai_code_buddy::widget_states::overview::{OverviewComponent, OverviewWidgetState};
use ai_code_buddy::widget_states::reports::ReportsWidgetState;
use ratatui::{
backend::TestBackend,
buffer::Buffer,
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Style},
widgets::{Block, Borders, Clear, Gauge, List, ListItem, Paragraph, Wrap},
Terminal,
};
#[test]
fn legacy_integration_placeholder() {
assert!(true);
}
#[test]
fn test_analysis_widget_empty_state() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend).unwrap();
let state = AnalysisWidgetState::default();
terminal
.draw(|f| {
let area = f.area();
let block = Block::default().title("🔍 Analysis").borders(Borders::ALL);
if state.is_analyzing {
let gauge = Gauge::default()
.block(block)
.gauge_style(Style::default().fg(Color::Blue))
.percent((state.progress * 100.0) as u16)
.label(format!("Analyzing: {}", state.current_file));
f.render_widget(gauge, area);
} else {
let paragraph = Paragraph::new("Press Enter to start analysis")
.block(block)
.wrap(Wrap { trim: true });
f.render_widget(paragraph, area);
}
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "Analysis"));
assert!(buffer_contains_text(
buffer,
"Press Enter to start analysis"
));
}
#[test]
fn test_analysis_widget_analyzing_state() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend).unwrap();
let mut state = AnalysisWidgetState::default();
state.start_analysis();
state.update_progress(0.5, "src/main.rs".to_string());
terminal
.draw(|f| {
let area = f.area();
let block = Block::default().title("🔍 Analysis").borders(Borders::ALL);
let gauge = Gauge::default()
.block(block)
.gauge_style(Style::default().fg(Color::Blue))
.percent((state.progress * 100.0) as u16)
.label(format!("Analyzing: {}", state.current_file));
f.render_widget(gauge, area);
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "Analysis"));
assert!(buffer_contains_text(buffer, "Analyzing: src/main.rs"));
}
#[test]
fn test_overview_widget_menu_rendering() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend).unwrap();
let _state = OverviewWidgetState::default();
terminal
.draw(|f| {
let area = f.area();
let menu_items = vec![
ListItem::new("🚀 Start Analysis"),
ListItem::new("📊 View Reports"),
ListItem::new("⚙️ Settings"),
ListItem::new("❓ Help"),
ListItem::new("🚪 Exit"),
];
let list = List::new(menu_items)
.block(
Block::default()
.title("🤖 AI Code Buddy")
.borders(Borders::ALL),
)
.highlight_style(Style::default().fg(Color::Yellow))
.highlight_symbol("► ");
f.render_widget(list, area);
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "AI Code Buddy"));
assert!(buffer_contains_text(buffer, "Start Analysis"));
assert!(buffer_contains_text(buffer, "View Reports"));
assert!(buffer_contains_text(buffer, "Settings"));
assert!(buffer_contains_text(buffer, "Help"));
assert!(buffer_contains_text(buffer, "Exit"));
}
#[test]
fn test_reports_widget_with_data() {
let backend = TestBackend::new(100, 30);
let mut terminal = Terminal::new(backend).unwrap();
let mut state = ReportsWidgetState::default();
let review = Review {
files_count: 5,
issues_count: 3,
critical_issues: 1,
high_issues: 1,
medium_issues: 1,
low_issues: 0,
issues: vec![Issue {
file: "src/auth.rs".to_string(),
line: 42,
severity: "Critical".to_string(),
category: "Security".to_string(),
description: "Hardcoded password detected".to_string(),
commit_status: CommitStatus::Modified,
}],
};
state.set_review(review);
let report_content = state.generate_report().unwrap();
terminal
.draw(|f| {
let area = f.area();
let block = Block::default().title("📊 Reports").borders(Borders::ALL);
let paragraph = Paragraph::new(report_content.as_str())
.block(block)
.wrap(Wrap { trim: true });
f.render_widget(paragraph, area);
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "Reports"));
assert!(buffer_contains_text(buffer, "AI Code Review Summary"));
assert!(buffer_contains_text(buffer, "Files analyzed: 5"));
assert!(buffer_contains_text(buffer, "Total issues found: 3"));
}
#[test]
fn test_multi_widget_layout() {
let backend = TestBackend::new(120, 40);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
let area = f.area();
let chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(30), Constraint::Percentage(70)])
.split(area);
let overview_block = Block::default().title("🤖 Overview").borders(Borders::ALL);
f.render_widget(overview_block, chunks[0]);
let right_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Percentage(60), Constraint::Percentage(40)])
.split(chunks[1]);
let analysis_block = Block::default().title("🔍 Analysis").borders(Borders::ALL);
f.render_widget(analysis_block, right_chunks[0]);
let reports_block = Block::default().title("📊 Reports").borders(Borders::ALL);
f.render_widget(reports_block, right_chunks[1]);
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "Overview"));
assert!(buffer_contains_text(buffer, "Analysis"));
assert!(buffer_contains_text(buffer, "Reports"));
}
#[test]
fn test_popup_overlay() {
let backend = TestBackend::new(80, 24);
let mut terminal = Terminal::new(backend).unwrap();
terminal
.draw(|f| {
let area = f.area();
let background = Block::default().title("Background").borders(Borders::ALL);
f.render_widget(background, area);
let popup_area = centered_rect(50, 50, area);
f.render_widget(Clear, popup_area);
let popup = Block::default()
.title("🆘 Help")
.borders(Borders::ALL)
.style(Style::default().fg(Color::Yellow));
f.render_widget(popup, popup_area);
let help_text =
Paragraph::new("Press Esc to close this help dialog").wrap(Wrap { trim: true });
let inner = Rect::new(
popup_area.x + 1,
popup_area.y + 1,
popup_area.width.saturating_sub(2),
popup_area.height.saturating_sub(2),
);
f.render_widget(help_text, inner);
})
.unwrap();
let buffer = terminal.backend().buffer();
assert!(buffer_contains_text(buffer, "Background"));
assert!(buffer_contains_text(buffer, "Help"));
assert!(buffer_contains_text(buffer, "Press Esc to close"));
}
#[test]
fn test_widget_state_interactions() {
let mut analysis_state = AnalysisWidgetState::default();
let overview_state = OverviewWidgetState::default();
let mut reports_state = ReportsWidgetState::default();
assert_eq!(
overview_state.selected_component,
OverviewComponent::StartAnalysis
);
analysis_state.start_analysis();
assert!(analysis_state.is_analyzing);
analysis_state.update_progress(0.3, "src/lib.rs".to_string());
assert_eq!(analysis_state.progress, 0.3);
assert_eq!(analysis_state.current_file, "src/lib.rs");
let review = Review {
files_count: 3,
issues_count: 2,
critical_issues: 0,
high_issues: 1,
medium_issues: 1,
low_issues: 0,
issues: vec![],
};
analysis_state.complete_analysis(review.clone());
assert!(!analysis_state.is_analyzing);
assert!(analysis_state.review.is_some());
reports_state.set_review(review);
assert!(reports_state.review.is_some());
let report = reports_state.generate_report();
assert!(report.is_some());
assert!(reports_state.generated_report.is_some());
}
fn buffer_contains_text(buffer: &Buffer, text: &str) -> bool {
for y in 0..buffer.area.height {
for x in 0..buffer.area.width {
let cell = &buffer[(x, y)];
if cell.symbol().contains(text) {
return true;
}
}
}
let buffer_content = (0..buffer.area.height)
.map(|y| {
(0..buffer.area.width)
.map(|x| buffer[(x, y)].symbol())
.collect::<String>()
})
.collect::<Vec<String>>()
.join("\n");
buffer_content.contains(text)
}
fn centered_rect(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
let popup_layout = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Percentage((100 - percent_y) / 2),
Constraint::Percentage(percent_y),
Constraint::Percentage((100 - percent_y) / 2),
])
.split(r);
Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Percentage((100 - percent_x) / 2),
Constraint::Percentage(percent_x),
Constraint::Percentage((100 - percent_x) / 2),
])
.split(popup_layout[1])[1]
}