use std::process::Command;
use crate::support::{sandbox_with_plugin, stderr_of, stdout_of, Sandbox};
fn write_config(sb: &Sandbox, name: &str, body: &str) {
std::fs::write(sb.project.join(name), body).unwrap();
}
#[cfg(windows)]
const SAY_HI: &str = r#"hi = ["cmd", "/c", "echo", "hi-from-script"]"#;
#[cfg(not(windows))]
const SAY_HI: &str = r#"hi = "echo hi-from-script""#;
#[cfg(windows)]
const QUOTED: &str = r#"say = "cmd /c echo \"a b\"""#;
#[cfg(not(windows))]
const QUOTED: &str = r#"say = "echo \"a b\"""#;
#[test]
fn a_named_command_runs_with_no_plugin_installed() {
let sb = Sandbox::new();
sb.file("fakepm.lock");
write_config(&sb, ".pmpx.toml", &format!("[scripts]\n{SAY_HI}\n"));
let out = sb.run(&["run", "hi"]);
assert!(out.status.success(), "{}", stderr_of(&out));
assert!(
stdout_of(&out).contains("hi-from-script"),
"the script has to have run: {}",
stdout_of(&out)
);
}
#[test]
fn the_arguments_after_the_separator_are_appended() {
let sb = Sandbox::new();
sb.file("fakepm.lock");
write_config(&sb, ".pmpx.toml", &format!("[scripts]\n{SAY_HI}\n"));
let out = sb.run(&["run", "hi", "--", "extra"]);
assert!(out.status.success(), "{}", stderr_of(&out));
assert!(
stdout_of(&out).contains("hi-from-script extra"),
"the extra argument has to reach it: {}",
stdout_of(&out)
);
}
#[test]
fn a_string_entry_is_split_with_quotes_respected() {
let sb = Sandbox::new();
sb.file("fakepm.lock");
write_config(&sb, ".pmpx.toml", &format!("[scripts]\n{QUOTED}\n"));
let out = sb.run(&["run", "say"]);
assert!(out.status.success(), "{}", stderr_of(&out));
assert!(
stdout_of(&out).contains("a b"),
"the quoted argument has to arrive as one: {}",
stdout_of(&out)
);
}
#[test]
fn a_name_that_is_not_in_the_table_still_reaches_the_plugin() {
let (sb, _lib) = sandbox_with_plugin();
sb.file("fakepm.lock");
write_config(&sb, ".pmpx.toml", "[scripts]\nother = \"echo not-this\"\n");
let out = sb.run(&["run", "build"]);
assert!(out.status.success(), "{}", stderr_of(&out));
let stdout = stdout_of(&out);
assert!(
stdout.contains("pmpx-probe") && stdout.contains("verb=run"),
"the plugin is asked, with the name as its argument: {stdout}"
);
assert!(
stdout.contains("args=build"),
"and the name travels with it: {stdout}"
);
}
#[test]
fn the_nearest_layer_defines_the_command() {
let sb = Sandbox::new();
sb.file("fakepm.lock");
write_config(&sb, ".pmpx.toml", "[scripts]\nhi = \"echo from-far\"\n");
std::fs::create_dir_all(sb.project.join("inner")).unwrap();
std::fs::write(
sb.project.join("inner/.pmpx.toml"),
"[scripts]\nhi = \"echo from-near\"\n",
)
.unwrap();
let inner = sb.project.join("inner");
let out = Command::new(env!("CARGO_BIN_EXE_pmpx"))
.args(["-C"])
.arg(&inner)
.args(["run", "hi"])
.env("PMPX_CONFIG_DIR", &sb.config_dir)
.env("PMPX_DATA_DIR", &sb.data_dir)
.output()
.expect("should be able to start pmpx");
assert!(out.status.success(), "{}", stderr_of(&out));
let stdout = stdout_of(&out);
assert!(stdout.contains("from-near"), "{stdout}");
assert!(!stdout.contains("from-far"), "{stdout}");
}