use crate::cmd::{cfg_spinner, run_stage};
use crate::install::Tools;
use crate::parse::{Opts, ServeOpts, TestOpts};
use crate::thread::spawn_thread;
use crate::{errors::*, serve};
use console::{style, Emoji};
use indicatif::{MultiProgress, ProgressBar};
use std::path::PathBuf;
use std::process::{Command, Stdio};
static TESTING: Emoji<'_, '_> = Emoji("🧪", "");
macro_rules! handle_exit_code {
($code:expr) => {
let (_, _, code) = $code;
if code != 0 {
return ::std::result::Result::Ok(code);
}
};
}
pub fn test(
dir: PathBuf,
test_opts: &TestOpts,
tools: &Tools,
global_opts: &Opts,
) -> Result<i32, ExecutionError> {
let tools = tools.clone();
let Opts {
cargo_engine_path,
cargo_engine_args,
..
} = global_opts.clone();
let serve_opts = ServeOpts {
no_run: true,
no_build: test_opts.no_build,
release: false,
standalone: false,
watch: test_opts.watch,
custom_watch: test_opts.custom_watch.clone(),
host: test_opts.host.clone(),
port: test_opts.port,
};
let num_steps: u8 = if test_opts.no_build { 2 } else { 4 };
let spinners = MultiProgress::new();
let (exit_code, server_path) = serve(
dir.clone(),
&serve_opts,
&tools,
global_opts,
&spinners,
true,
)?;
if exit_code != 0 {
return Ok(exit_code);
}
if let Some(server_path) = server_path {
let mut server = Command::new(&server_path)
.envs([
("PERSEUS_ENGINE_OPERATION", "serve"),
("PERSEUS_TESTING", "true"),
])
.current_dir(&dir)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::piped())
.spawn()
.map_err(|err| ExecutionError::CmdExecFailed {
cmd: server_path,
source: err,
})?;
let test_msg = format!(
"{} {} Running tests",
style(format!("[{}/{}]", num_steps, num_steps)).bold().dim(),
TESTING,
);
let test_spinner = spinners.insert(num_steps.into(), ProgressBar::new_spinner());
let test_spinner = cfg_spinner(test_spinner, &test_msg);
let test_dir = dir;
let headless = !test_opts.show_browser;
let test_thread = spawn_thread(
move || {
handle_exit_code!(run_stage(
vec![&format!(
"{} test {} -- --test-threads 1",
cargo_engine_path, cargo_engine_args
)],
&test_dir,
&test_spinner,
&test_msg,
if headless {
vec![
("CARGO_TARGET_DIR", "dist/target_engine"),
("RUSTFLAGS", "--cfg=engine"),
("CARGO_TERM_COLOR", "always"),
("PERSEUS_RUN_WASM_TESTS", "true"),
("PERSEUS_RUN_WASM_TESTS_HEADLESS", "true"),
]
} else {
vec![
("CARGO_TARGET_DIR", "dist/target_engine"),
("RUSTFLAGS", "--cfg=engine"),
("CARGO_TERM_COLOR", "always"),
("PERSEUS_RUN_WASM_TESTS", "true"),
]
}
)?);
Ok(0)
},
false,
);
let test_res = test_thread
.join()
.map_err(|_| ExecutionError::ThreadWaitFailed)??;
if test_res != 0 {
return Ok(test_res);
}
let _ = server.kill();
Ok(0)
} else {
Err(ExecutionError::GetServerExecutableFailedSimple.into())
}
}