trimdown 0.1.6

Fast file compression tool for Office documents (PPTX, DOCX, XLSX), PDFs, videos, images, OpenDocument formats, and archives with streaming support
Documentation
use std::path::PathBuf;
use trimdown::{Config, TrimdownError};

#[test]
fn test_trimdown_error_messages() {
    // Test FileNotFound error
    let path = PathBuf::from("/nonexistent/file.pdf");
    let err = TrimdownError::FileNotFound(path.clone());
    assert!(err.to_string().contains("File not found"));
    assert_eq!(err.exit_code(), 2);
    assert!(!err.is_recoverable());
    assert!(err.suggestion().is_none());

    // Test UnsupportedFileType error
    let err = TrimdownError::UnsupportedFileType("txt".to_string());
    assert!(err.to_string().contains("Unsupported file type"));
    assert_eq!(err.exit_code(), 3);
    assert!(err.is_recoverable());
    assert!(err.suggestion().is_some());
    assert!(err.suggestion().unwrap().contains("PPTX"));

    // Test ExternalToolMissing error
    let err = TrimdownError::ExternalToolMissing {
        tool: "ffmpeg".to_string(),
        install_cmd: "brew install ffmpeg".to_string(),
    };
    assert!(err.to_string().contains("External tool not found"));
    assert_eq!(err.exit_code(), 5);
    assert!(err.is_recoverable());
    assert!(err.suggestion().is_some());
    assert!(err.suggestion().unwrap().contains("brew install ffmpeg"));

    // Test ConfigError error
    let err = TrimdownError::ConfigError("Invalid JSON".to_string());
    assert!(err.to_string().contains("Configuration error"));
    assert_eq!(err.exit_code(), 8);
    assert!(err.is_recoverable());
    assert!(err.suggestion().is_some());
    assert!(err.suggestion().unwrap().contains("configuration file"));
}

#[test]
fn test_config_error_handling() {
    // Test invalid JSON in config
    let invalid_json = "{ invalid json }";
    let parse_result = serde_json::from_str::<Config>(invalid_json);
    assert!(parse_result.is_err());

    // Test valid config serialization/deserialization
    let config = Config::default();
    let json_result = serde_json::to_string(&config);
    assert!(json_result.is_ok());

    let json = json_result.unwrap();
    let parsed_config: Config = serde_json::from_str(&json).unwrap();
    assert_eq!(config.quality, parsed_config.quality);
    assert_eq!(config.max_width, parsed_config.max_width);
    assert_eq!(config.video_crf, parsed_config.video_crf);
}

#[test]
fn test_error_chain_propagation() {
    // Test that errors properly propagate through the chain
    let io_err = std::io::Error::new(std::io::ErrorKind::NotFound, "File not found");
    let trimdown_err = TrimdownError::IoError(io_err);

    // This should be automatically converted to anyhow::Error
    let anyhow_err: anyhow::Error = trimdown_err.into();

    // We should be able to downcast back to TrimdownError
    assert!(anyhow_err.downcast_ref::<TrimdownError>().is_some());
}

#[test]
fn test_parallel_error() {
    let err = TrimdownError::ParallelError("Too many concurrent tasks".to_string());
    assert!(err.to_string().contains("Parallel processing error"));
    assert_eq!(err.exit_code(), 9);
    assert!(!err.is_recoverable());
    assert!(err.suggestion().is_some());
    assert!(err.suggestion().unwrap().contains("--parallel"));
}