use std::path::{Path, PathBuf};
use std::process::{Command, Output};
fn bin() -> PathBuf {
PathBuf::from(env!("CARGO_BIN_EXE_supercode"))
}
fn scratch() -> PathBuf {
let root = std::env::temp_dir().join(format!(
"supercode-orch21-cli-{}-{}",
std::process::id(),
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_nanos()
));
std::fs::create_dir_all(&root).unwrap();
root
}
fn fake_hermes(root: &Path) -> PathBuf {
let path = root.join("fake-hermes");
std::fs::write(
&path,
"#!/bin/sh\n\
for a in \"$@\"; do name=$a; done\n\
case \"$2\" in\n\
create) mkdir -p \"$HERMES_HOME/profiles/$name\" ;;\n\
delete) rm -rf \"$HERMES_HOME/profiles/$name\" ;;\n\
esac\n\
printf 'ok\\n'\n",
)
.unwrap();
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755)).unwrap();
}
std::fs::create_dir_all(root.join("hermes_home")).unwrap();
path
}
fn run(root: &Path, args: &[&str]) -> Output {
Command::new(bin())
.env("HERMES_HOME", root.join("hermes_home"))
.env("SUPERCODE_HERMES_BIN", root.join("fake-hermes"))
.args(args)
.output()
.expect("supercode binary runs")
}
fn stdout_of(output: &Output) -> String {
assert!(
output.status.success(),
"command failed: {}",
String::from_utf8_lossy(&output.stderr)
);
String::from_utf8_lossy(&output.stdout).into_owned()
}
#[test]
fn profiles_create_and_delete_narrate_the_harness_command_and_the_row() {
let root = scratch();
fake_hermes(&root);
let created = stdout_of(&run(
&root,
&["profiles", "create", "--harness", "hermes", "coder"],
));
assert!(
created.contains("ran: ") && created.contains("profile create --no-alias coder"),
"{created}"
);
assert!(created.contains("hermes profile coder"), "{created}");
assert!(created.contains("kind: hermes_profile"), "{created}");
assert!(
created.contains(&format!(
"home: {}",
root.join("hermes_home/profiles/coder").display()
)),
"{created}"
);
assert!(root.join("hermes_home/profiles/coder").is_dir());
let listed = stdout_of(&run(&root, &["profiles", "list", "--harness", "hermes"]));
assert!(listed.contains("coder"), "{listed}");
let deleted = stdout_of(&run(
&root,
&[
"profiles",
"delete",
"--harness",
"hermes",
"coder",
"--yes",
],
));
assert!(
deleted.contains("profile delete --yes coder")
&& deleted.contains("deleted: hermes profile coder"),
"{deleted}"
);
assert!(!root.join("hermes_home/profiles/coder").exists());
let listed = stdout_of(&run(&root, &["profiles", "list", "--harness", "hermes"]));
assert!(!listed.contains("coder"), "{listed}");
std::fs::remove_dir_all(&root).ok();
}
#[test]
fn profiles_delete_refuses_to_act_unconfirmed_off_a_terminal() {
let root = scratch();
fake_hermes(&root);
std::fs::create_dir_all(root.join("hermes_home/profiles/coder")).unwrap();
let output = run(
&root,
&["profiles", "delete", "--harness", "hermes", "coder"],
);
assert!(!output.status.success(), "{output:?}");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("--yes"), "{stderr}");
assert!(root.join("hermes_home/profiles/coder").is_dir());
std::fs::remove_dir_all(&root).ok();
}
#[test]
fn profiles_create_refuses_codex_and_names_its_own_door() {
let root = scratch();
fake_hermes(&root);
let output = run(
&root,
&["profiles", "create", "--harness", "codex", "review"],
);
assert!(!output.status.success(), "{output:?}");
let stderr = String::from_utf8_lossy(&output.stderr);
assert!(stderr.contains("[profiles.<name>]"), "{stderr}");
std::fs::remove_dir_all(&root).ok();
}