// Integration coverage for client process startup behavior. // // Scope: launch the real `lesavka-client` binary and validate guarded startup // behavior when desktop runtime prerequisites are missing. // Targets: `client/src/main.rs`. // Why: process-level startup failures should stay deterministic and // user-readable. use serial_test::serial; use std::path::{Path, PathBuf}; use std::process::Command; fn candidate_dirs() -> Vec { let exe = std::env::current_exe().expect("current exe path"); let mut dirs = Vec::new(); if let Some(parent) = exe.parent() { dirs.push(parent.to_path_buf()); if let Some(grand) = parent.parent() { dirs.push(grand.to_path_buf()); } } dirs.push(PathBuf::from("target/debug")); dirs.push(PathBuf::from("target/llvm-cov-target/debug")); dirs } fn find_binary(name: &str) -> Option { candidate_dirs() .into_iter() .map(|dir| dir.join(name)) .find(|path| path.exists() && path.is_file()) } #[test] #[serial] fn client_binary_fails_fast_without_runtime_dir() { let Some(bin) = find_binary("lesavka-client") else { return; }; let status = Command::new(Path::new(&bin)) .env_remove("XDG_RUNTIME_DIR") .env_remove("LESAVKA_HEADLESS") .status() .expect("spawn lesavka-client"); assert!(!status.success(), "startup should fail without runtime dir"); } #[test] #[serial] fn client_binary_version_does_not_start_gtk_or_require_desktop_runtime() { let Some(bin) = find_binary("lesavka-client") else { return; }; let output = Command::new(Path::new(&bin)) .arg("--version") .env_remove("XDG_RUNTIME_DIR") .env_remove("LESAVKA_HEADLESS") .output() .expect("spawn lesavka-client --version"); assert!( output.status.success(), "--version should be safe in installer and terminal checks" ); let stdout = String::from_utf8_lossy(&output.stdout); assert!( stdout.starts_with("lesavka-client "), "version output should identify the installed client binary, got {stdout:?}" ); assert!( output.stderr.is_empty(), "--version should not initialize GTK/GDK and emit desktop warnings" ); }