use assert_cmd::Command;
use predicates::prelude::*;
use std::fs;
mod common;
use common::fixtures;
fn has_required_wasm_tools() -> bool {
which::which("wasm-bindgen").is_ok()
}
macro_rules! require_wasm_tools {
() => {
if !has_required_wasm_tools() {
eprintln!("⚠️ Skipping test: wasm-bindgen-cli not found in PATH");
eprintln!(" Install with: cargo install wasm-bindgen-cli");
return;
}
};
}
fn get_bin() -> Command {
Command::new(env!("CARGO_BIN_EXE_wasm-slim"))
}
#[test]
fn test_complete_optimization_workflow() {
require_wasm_tools!();
let (temp_dir, cargo_toml) =
fixtures::create_minimal_wasm_lib("workflow-test").expect("Failed to create test fixture");
let project_root = temp_dir.path();
fs::write(
&cargo_toml,
r#"
[package]
name = "workflow-test"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
wasm-bindgen = "0.2"
getrandom = "0.2"
"#,
)
.expect("Failed to write Cargo.toml");
let src_dir = project_root.join("src");
fs::write(
src_dir.join("lib.rs"),
r#"
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn calculate(x: i32, y: i32) -> i32 {
x + y
}
"#,
)
.expect("Failed to write lib.rs");
let mut cmd = get_bin();
cmd.arg("init")
.arg("--template")
.arg("minimal")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Created .wasm-slim.toml"));
assert!(
project_root.join(".wasm-slim.toml").exists(),
"Config file should be created by init command"
);
let mut cmd = get_bin();
let analyze_output = cmd
.arg("analyze")
.arg("--mode")
.arg("deps")
.arg("--json")
.current_dir(project_root)
.assert()
.success()
.get_output()
.stdout
.clone();
let analyze_json: serde_json::Value =
serde_json::from_slice(&analyze_output).expect("Analyze output should be valid JSON");
assert!(
analyze_json["total_deps"].is_number(),
"Analyze output should contain total_deps"
);
let mut cmd = get_bin();
cmd.arg("analyze")
.arg("--mode")
.arg("deps")
.arg("--fix")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Applied").and(predicate::str::contains("fixes")));
let mut cmd = get_bin();
cmd.arg("build")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Build complete"));
let backup_dir = temp_dir.path().join(".wasm-slim/backups");
assert!(
backup_dir.exists(),
"Backup directory should be created after applying fixes"
);
let backup_files: Vec<_> = std::fs::read_dir(&backup_dir)
.unwrap()
.filter_map(|e| e.ok())
.filter(|e| e.path().extension().and_then(|s| s.to_str()) == Some("backup"))
.collect();
assert!(
!backup_files.is_empty(),
"At least one backup file should be created"
);
}
#[test]
fn test_iterative_optimization_workflow() {
require_wasm_tools!();
let (temp_dir, cargo_toml) =
fixtures::create_minimal_wasm_lib("iterative-test").expect("Failed to create test fixture");
let project_root = temp_dir.path();
let mut cmd = get_bin();
cmd.arg("build")
.current_dir(project_root)
.assert()
.success();
let cargo_content =
fs::read_to_string(&cargo_toml).expect("Failed to read Cargo.toml after first build");
assert!(
cargo_content.contains("[profile.release]")
|| cargo_content.contains("lto")
|| cargo_content.contains("opt-level"),
"First build should add optimization profiles"
);
let mut cmd = get_bin();
cmd.arg("analyze")
.arg("deps")
.current_dir(project_root)
.assert()
.success();
let mut cmd = get_bin();
cmd.arg("build")
.current_dir(project_root)
.assert()
.success();
let final_cargo =
fs::read_to_string(&cargo_toml).expect("Failed to read Cargo.toml after second build");
final_cargo
.parse::<toml_edit::DocumentMut>()
.expect("Cargo.toml should remain valid after multiple builds");
}
#[test]
fn test_compare_before_after_workflow() {
require_wasm_tools!();
let (temp_dir, _cargo_toml) =
fixtures::create_minimal_wasm_lib("compare-test").expect("Failed to create test fixture");
let project_root = temp_dir.path();
let before_wasm = project_root.join("before.wasm");
fs::write(&before_wasm, fixtures::WASM_MAGIC_HEADER).expect("Failed to write before WASM file");
let mut cmd = get_bin();
cmd.arg("build")
.current_dir(project_root)
.assert()
.success();
let after_wasm = project_root.join("after.wasm");
fs::write(&after_wasm, fixtures::WASM_MAGIC_HEADER).expect("Failed to write after WASM file");
let mut cmd = get_bin();
cmd.arg("compare")
.arg(&before_wasm)
.arg(&after_wasm)
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Before").or(predicate::str::contains("After")));
}
#[test]
fn test_analyze_assets_then_build_workflow() {
let (temp_dir, _cargo_toml) =
fixtures::create_project_with_assets("assets-test").expect("Failed to create test fixture");
let project_root = temp_dir.path();
let mut cmd = get_bin();
cmd.arg("analyze")
.arg("--mode")
.arg("assets")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Asset").or(predicate::str::contains("include_bytes")));
let mut cmd = get_bin();
cmd.arg("analyze")
.arg("--mode")
.arg("assets")
.arg("--guide")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("Externalization").or(predicate::str::contains("guide")));
}
#[test]
fn test_dry_run_then_real_build_workflow() {
require_wasm_tools!();
let (temp_dir, cargo_toml) =
fixtures::create_minimal_wasm_lib("dryrun-test").expect("Failed to create test fixture");
let project_root = temp_dir.path();
let original_cargo_content =
fs::read_to_string(&cargo_toml).expect("Failed to read original Cargo.toml");
let mut cmd = get_bin();
cmd.arg("build")
.arg("--dry-run")
.current_dir(project_root)
.assert()
.success()
.stdout(predicate::str::contains("DRY RUN"));
let after_dry_run =
fs::read_to_string(&cargo_toml).expect("Failed to read Cargo.toml after dry run");
assert_eq!(
original_cargo_content.trim(),
after_dry_run.trim(),
"Cargo.toml should not be modified by dry run"
);
let mut cmd = get_bin();
cmd.arg("build")
.current_dir(project_root)
.assert()
.success();
let after_real_build =
fs::read_to_string(&cargo_toml).expect("Failed to read Cargo.toml after real build");
assert_ne!(
original_cargo_content.trim(),
after_real_build.trim(),
"Cargo.toml should be modified by real build"
);
}