use anyhow::Result;
use console::style;
use std::path::Path;
use crate::analyzer;
pub fn cmd_compare(before: &str, after: &str) -> Result<()> {
cmd_compare_impl(before, after, true)
}
fn cmd_compare_impl(before: &str, after: &str, check_twiggy: bool) -> Result<()> {
let before_path = Path::new(before);
let after_path = Path::new(after);
if !before_path.exists() {
anyhow::bail!(
"Baseline file not found: {}. Run a build first to create a baseline.",
before
);
}
if !after_path.exists() {
anyhow::bail!("Comparison file not found: {}", after);
}
if check_twiggy && !analyzer::TwiggyAnalyzer::check_installation()? {
eprintln!(
"{}",
style(analyzer::TwiggyAnalyzer::installation_instructions()).yellow()
);
anyhow::bail!("twiggy not installed");
}
println!("📊 {} WASM Build Comparison", style("wasm-slim").bold());
println!();
use crate::infra::{RealCommandExecutor, RealFileSystem};
let results = analyzer::TwiggyAnalyzer::compare(
before_path,
after_path,
&RealFileSystem,
&RealCommandExecutor,
)?;
analyzer::print_comparison_report(&results);
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
use tempfile::TempDir;
#[test]
fn test_compare_with_missing_baseline_file() {
let temp_dir = TempDir::new().unwrap();
let baseline = temp_dir.path().join("nonexistent_baseline.wasm");
let after = temp_dir.path().join("after.wasm");
fs::write(&after, b"dummy wasm content").unwrap();
let result = cmd_compare_impl(baseline.to_str().unwrap(), after.to_str().unwrap(), false);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Baseline file not found"));
assert!(err_msg.contains("nonexistent_baseline.wasm"));
}
#[test]
fn test_compare_with_missing_comparison_file() {
let temp_dir = TempDir::new().unwrap();
let baseline = temp_dir.path().join("baseline.wasm");
let after = temp_dir.path().join("nonexistent_after.wasm");
fs::write(&baseline, b"dummy wasm content").unwrap();
let result = cmd_compare_impl(baseline.to_str().unwrap(), after.to_str().unwrap(), false);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Comparison file not found"));
assert!(err_msg.contains("nonexistent_after.wasm"));
}
#[test]
fn test_compare_with_both_files_missing() {
let temp_dir = TempDir::new().unwrap();
let baseline = temp_dir.path().join("nonexistent1.wasm");
let after = temp_dir.path().join("nonexistent2.wasm");
let result = cmd_compare_impl(baseline.to_str().unwrap(), after.to_str().unwrap(), false);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Baseline file not found"));
}
#[test]
fn test_compare_validates_baseline_before_comparison() {
let temp_dir = TempDir::new().unwrap();
let baseline = temp_dir.path().join("missing_baseline.wasm");
let after = temp_dir.path().join("missing_after.wasm");
let result = cmd_compare_impl(baseline.to_str().unwrap(), after.to_str().unwrap(), false);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains("Baseline"));
assert!(!err_msg.contains("Comparison file not found"));
}
#[test]
fn test_compare_error_message_includes_file_path() {
let baseline_path = "/some/path/to/baseline.wasm";
let after_path = "/some/path/to/after.wasm";
let result = cmd_compare_impl(baseline_path, after_path, false);
assert!(result.is_err());
let err_msg = result.unwrap_err().to_string();
assert!(err_msg.contains(baseline_path));
}
}