use std::process::Command;
use std::time::{Duration, Instant};
#[test]
#[ignore] fn test_red_team_shows_progress_in_tty() {
std::env::set_var("TERM", "xterm-256color");
let mut cmd = Command::new("cargo");
cmd.args([
"run",
"--bin",
"pmat",
"--",
"red-team",
"analyze",
"--message",
"feat: Test",
"--verbose",
]);
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("⠋") || stdout.contains("Extracting claims"),
"Expected progress spinner or stage message, got: {}",
stdout
);
assert!(
stdout.contains("Gathering evidence"),
"Expected 'Gathering evidence' stage"
);
}
#[test]
#[ignore] fn test_red_team_no_progress_in_quiet_mode() {
let mut cmd = Command::new("cargo");
cmd.args([
"run",
"--bin",
"pmat",
"--",
"red-team",
"analyze",
"--message",
"feat: Test",
"--quiet",
]);
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
!stdout.contains("⠋"),
"Progress spinner should not appear in quiet mode"
);
assert!(
!stdout.contains("Extracting claims"),
"Stage messages should not appear in quiet mode"
);
}
#[test]
#[ignore] fn test_red_team_progress_updates() {
use pmat::cli::progress::MultiStageProgress;
let stages = vec![
"Extracting claims".to_string(),
"Gathering evidence".to_string(),
"Analyzing results".to_string(),
];
let mut progress = MultiStageProgress::new(stages);
progress.next_stage("Extracting claims...");
assert_eq!(progress.current_stage(), "Extracting claims");
assert_eq!(progress.current_stage_index(), 0);
progress.next_stage("Gathering evidence...");
assert_eq!(progress.current_stage(), "Gathering evidence");
assert_eq!(progress.current_stage_index(), 1);
progress.next_stage("Analyzing results...");
assert_eq!(progress.current_stage(), "Analyzing results");
assert_eq!(progress.current_stage_index(), 2);
}
#[test]
#[ignore] fn test_red_team_evidence_source_progress() {
use pmat::cli::progress::MultiStageProgress;
let mut progress = MultiStageProgress::new(vec!["Gathering evidence".to_string()]);
let sources = [
"GitHistory",
"TestExecution",
"CoverageReport",
"LinkValidation",
"CargoAudit",
"BenchmarkResults",
"IssueTracker",
"CodeGrep",
];
for (idx, source) in sources.iter().enumerate() {
let percent = ((idx + 1) as f64 / sources.len() as f64) * 100.0;
progress.set_progress(idx as u64 + 1, sources.len() as u64);
let message = format!("{}: Processing... ({:.0}%)", source, percent);
assert!(message.contains(source), "Progress should show source name");
}
assert_eq!(progress.completed_items(), 8);
assert_eq!(progress.total_items(), 8);
}
#[test]
#[ignore] fn test_red_team_eta_calculation() {
use pmat::cli::progress::MultiStageProgress;
let mut progress = MultiStageProgress::new(vec!["Test stage".to_string()]);
let _start = Instant::now();
progress.set_progress(5, 10);
std::thread::sleep(Duration::from_secs(1));
let eta = progress.get_eta();
assert!(
eta.as_secs() <= 2,
"ETA calculation should be reasonable: {:?}",
eta
);
}
#[test]
#[ignore] fn test_repo_score_shows_category_progress() {
std::env::set_var("TERM", "xterm-256color");
let mut cmd = Command::new("cargo");
cmd.args([
"run",
"--bin",
"pmat",
"--",
"repo-score",
"--path",
".",
"--verbose",
]);
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("Category 1/6") || stdout.contains("Code Quality"),
"Expected category progress"
);
assert!(
stdout.contains("Category 2/6") || stdout.contains("Testing"),
"Expected multiple categories"
);
}
#[test]
#[ignore] fn test_repo_score_shows_file_progress() {
let mut cmd = Command::new("cargo");
cmd.args([
"run",
"--bin",
"pmat",
"--",
"repo-score",
"--path",
".",
"--verbose",
]);
let output = cmd.output().unwrap();
let stdout = String::from_utf8_lossy(&output.stdout);
assert!(
stdout.contains("files") || stdout.contains("["),
"Expected file count or progress bar"
);
assert!(
stdout.contains("%") || stdout.contains("complete"),
"Expected percentage or completion indicator"
);
}
#[test]
#[ignore] fn test_repo_score_category_progress() {
use pmat::cli::progress::CategoryProgress;
let categories = vec![
"Code Quality".to_string(),
"Testing".to_string(),
"Documentation".to_string(),
"Security".to_string(),
"Performance".to_string(),
"Maintainability".to_string(),
];
let mut progress = CategoryProgress::new(categories);
progress.next_category("Code Quality");
assert_eq!(progress.current_category(), "Code Quality");
assert_eq!(progress.current_category_index(), 0);
progress.set_file_progress(50, 100);
assert_eq!(progress.files_processed(), 50);
assert_eq!(progress.total_files(), 100);
assert_eq!(progress.category_percent(), 50.0);
progress.next_category("Testing");
assert_eq!(progress.current_category(), "Testing");
assert_eq!(progress.current_category_index(), 1);
}
#[test]
#[ignore] fn test_repo_score_overall_progress() {
use pmat::cli::progress::CategoryProgress;
let categories = vec![
"Category 1".to_string(),
"Category 2".to_string(),
"Category 3".to_string(),
"Category 4".to_string(),
];
let mut progress = CategoryProgress::new(categories);
progress.next_category("Category 1");
progress.set_file_progress(100, 100);
assert_eq!(progress.overall_percent(), 25.0);
progress.next_category("Category 2");
progress.set_file_progress(100, 100);
assert_eq!(progress.overall_percent(), 50.0);
progress.next_category("Category 3");
progress.set_file_progress(50, 100);
assert_eq!(progress.overall_percent(), 62.5); }
#[test]
#[ignore] fn test_repo_score_elapsed_time_display() {
use pmat::cli::progress::CategoryProgress;
let mut progress = CategoryProgress::new(vec!["Test".to_string()]);
let _start = Instant::now();
progress.next_category("Test");
std::thread::sleep(Duration::from_secs(2));
let elapsed = progress.elapsed();
assert!(
elapsed.as_secs() >= 2 && elapsed.as_secs() <= 3,
"Elapsed time should be approximately 2 seconds: {:?}",
elapsed
);
}
#[test]
#[ignore] fn test_progress_respects_ci_environment() {
std::env::set_var("CI", "true");
use pmat::cli::progress::ProgressIndicator;
let progress = ProgressIndicator::new("Testing");
assert!(!progress.is_enabled(), "Progress should be disabled in CI");
}
#[test]
#[ignore] fn test_progress_respects_no_color() {
std::env::set_var("NO_COLOR", "1");
use pmat::cli::progress::ProgressIndicator;
let progress = ProgressIndicator::new("Testing");
assert!(!progress.uses_color(), "Progress should respect NO_COLOR");
}
#[test]
#[ignore] fn test_progress_tty_detection() {
use pmat::cli::progress::ProgressIndicator;
let _progress = ProgressIndicator::new("Testing");
assert!(
!ProgressIndicator::is_tty(),
"Test environment should not be TTY"
);
}
#[test]
#[ignore] fn test_progress_bar_formatting() {
use pmat::cli::progress::MultiStageProgress;
let mut progress = MultiStageProgress::new(vec!["Test".to_string()]);
progress.set_progress(0, 100);
assert_eq!(progress.completed_items(), 0);
assert_eq!(progress.total_items(), 100);
progress.set_progress(50, 100);
assert_eq!(progress.completed_items(), 50);
assert_eq!(progress.total_items(), 100);
progress.set_progress(100, 100);
assert_eq!(progress.completed_items(), 100);
}
#[test]
#[ignore] fn test_progress_spinner_animation() {
use pmat::cli::progress::Spinner;
let mut spinner = Spinner::new();
let frames = vec!['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
for (idx, expected_frame) in frames.iter().enumerate() {
spinner.tick();
let current = spinner.current_frame();
assert_eq!(
current, *expected_frame,
"Frame {} should be {}, got {}",
idx, expected_frame, current
);
}
spinner.tick();
assert_eq!(spinner.current_frame(), frames[0]);
}