use prodigy::cook::interaction::display::{ProgressDisplay, ProgressDisplayImpl, VerbosityLevel};
use prodigy::cook::interaction::{DefaultUserInteraction, UserInteraction};
use std::time::Duration;
#[test]
fn test_display_message_type_coverage() {
let display = ProgressDisplayImpl::new(VerbosityLevel::Normal);
display.info("Test info message");
display.warning("Test warning message");
display.error("Test error message");
display.progress("Test progress message");
display.success("Test success message");
display.action("Test action message");
display.metric("Test metric", "value");
display.status("Test status message");
}
#[test]
fn test_verbosity_level_filtering() {
let quiet_display = ProgressDisplayImpl::new(VerbosityLevel::Quiet);
assert_eq!(quiet_display.verbosity(), VerbosityLevel::Quiet);
let normal_display = ProgressDisplayImpl::new(VerbosityLevel::Normal);
assert_eq!(normal_display.verbosity(), VerbosityLevel::Normal);
let verbose_display = ProgressDisplayImpl::new(VerbosityLevel::Verbose);
assert_eq!(verbose_display.verbosity(), VerbosityLevel::Verbose);
let debug_display = ProgressDisplayImpl::new(VerbosityLevel::Debug);
assert_eq!(debug_display.verbosity(), VerbosityLevel::Debug);
let trace_display = ProgressDisplayImpl::new(VerbosityLevel::Trace);
assert_eq!(trace_display.verbosity(), VerbosityLevel::Trace);
}
#[test]
fn test_user_interaction_formatting() {
let interaction = DefaultUserInteraction::new();
interaction.display_info("Information without embedded icons");
interaction.display_warning("Warning without embedded icons");
interaction.display_error("Error without embedded icons");
interaction.display_progress("Progress without embedded icons");
interaction.display_success("Success without embedded icons");
interaction.display_action("Action without embedded icons");
interaction.display_metric("Metric", "100");
interaction.display_status("Status without embedded icons");
interaction.iteration_start(1, 10);
interaction.iteration_end(1, Duration::from_secs(5), true);
interaction.step_start(1, 5, "Test step");
interaction.step_end(1, true);
}
#[test]
fn test_spinner_lifecycle() {
let interaction = DefaultUserInteraction::new();
let mut success_spinner = interaction.start_spinner("Processing...");
success_spinner.update_message("Still processing...");
success_spinner.success("Completed successfully");
let mut fail_spinner = interaction.start_spinner("Another task...");
fail_spinner.fail("Task failed");
}
#[test]
fn test_no_embedded_icons_in_source() {
let test_message = "Executing command: test";
assert!(!test_message.contains("🚀"));
assert!(!test_message.contains("❌"));
assert!(!test_message.contains("⚠️"));
assert!(!test_message.contains("🎉"));
let display = ProgressDisplayImpl::new(VerbosityLevel::Normal);
display.action(test_message);
display.error("Failed to execute");
display.warning("Warning message");
display.success("Operation completed");
}
#[test]
fn test_orchestrator_output_formatting() {
let interaction = DefaultUserInteraction::new();
interaction.display_action("Executing command: cargo test");
interaction.display_error("Failed to find output 'result': not found");
interaction.display_success("Processed all 10 inputs successfully!");
interaction.display_warning("No files matched pattern: *.txt");
interaction.display_error("Error processing pattern 'src/**/*.rs': permission denied");
interaction.display_action("Executing MapReduce workflow: test-workflow");
interaction.display_warning("Command 'test' failed for input 'data.txt', continuing...");
}
#[test]
fn test_workflow_executor_output_formatting() {
let interaction = DefaultUserInteraction::new();
interaction.display_error("Shell command failed after 3 attempts");
interaction.display_error("Tests failed after 2 attempts");
let error_msg = "Workflow stopped: No changes were committed by step 1";
assert!(!error_msg.contains("❌"));
}
#[test]
fn test_command_output_respects_verbosity() {
let quiet = DefaultUserInteraction::with_verbosity(VerbosityLevel::Quiet);
let normal = DefaultUserInteraction::with_verbosity(VerbosityLevel::Normal);
let verbose = DefaultUserInteraction::with_verbosity(VerbosityLevel::Verbose);
quiet.command_output("Test output", VerbosityLevel::Normal);
normal.command_output("Test output", VerbosityLevel::Normal);
verbose.command_output("Test output", VerbosityLevel::Verbose);
quiet.debug_output("Debug info", VerbosityLevel::Debug);
verbose.debug_output("Debug info", VerbosityLevel::Verbose);
}
#[test]
fn test_duration_formatting() {
let interaction = DefaultUserInteraction::new();
interaction.iteration_end(1, Duration::from_millis(500), true);
interaction.iteration_end(2, Duration::from_secs(5), true);
interaction.iteration_end(3, Duration::from_secs(65), false);
interaction.iteration_end(4, Duration::from_secs(3661), true);
}
#[test]
fn test_unicode_vs_ascii_box_drawing() {
let display = ProgressDisplayImpl::new(VerbosityLevel::Normal);
display.iteration_start(1, 5);
display.iteration_end(1, Duration::from_secs(10), true);
}
#[test]
fn test_parallel_display_safety() {
use std::sync::Arc;
use std::thread;
let interaction = Arc::new(DefaultUserInteraction::new());
let handles: Vec<_> = (0..5)
.map(|i| {
let interaction = Arc::clone(&interaction);
thread::spawn(move || {
interaction.display_info(&format!("Thread {} info", i));
interaction.display_warning(&format!("Thread {} warning", i));
interaction.display_error(&format!("Thread {} error", i));
})
})
.collect();
for handle in handles {
handle.join().unwrap();
}
}