use std::fs;
use assert_cmd::cargo::cargo_bin_cmd;
use predicates::prelude::*;
#[test]
fn clap_handles_help_errors_delimiters_and_conflicts() {
cargo_bin_cmd!("qrab")
.arg("--help")
.assert()
.success()
.stdout(predicate::str::contains("Usage: qrab <COMMAND>"));
cargo_bin_cmd!("qrab")
.args(["check", "--version"])
.assert()
.success()
.stdout(predicate::str::contains(env!("CARGO_PKG_VERSION")));
cargo_bin_cmd!("qrab")
.args(["compil", "missing.qrab"])
.assert()
.code(2)
.stderr(predicate::str::contains("compile"));
cargo_bin_cmd!("qrab")
.args(["compile", "missing.qrab", "-o", "--target"])
.assert()
.code(2)
.stderr(predicate::str::contains("--output <OUTPUT>"));
cargo_bin_cmd!("qrab")
.args(["compile", "missing.qrab", "-t", "latex", "-t", "typst"])
.assert()
.code(2)
.stderr(predicate::str::contains("cannot be used multiple times"));
cargo_bin_cmd!("qrab")
.args([
"compile",
"missing.qrab",
"-o",
"output.tex",
"--target",
"all",
])
.assert()
.code(2)
.stderr(predicate::str::contains(
"cannot be used with '--target all'",
));
let directory =
std::env::temp_dir().join(format!("qrab-cli-{}-{}", std::process::id(), line!()));
fs::create_dir(&directory).expect("create CLI test directory");
let source = directory.join("input.qrab");
fs::write(&source, "circuit cli { qubit q; h q }\n").expect("write CLI test source");
cargo_bin_cmd!("qrab")
.args(["compile", "--"])
.arg(&source)
.assert()
.success();
assert!(source.with_extension("tex").is_file());
assert!(source.with_extension("typ").is_file());
assert!(source.with_extension("svg").is_file());
assert!(source.with_extension("url").is_file());
assert!(
fs::read_to_string(source.with_extension("url"))
.expect("read Quirk URL")
.starts_with("https://algassert.com/quirk#circuit=")
);
fs::remove_dir_all(directory).expect("remove CLI test directory");
let missing = std::env::temp_dir().join(format!(
"qrab-missing-source-{}-{}.qrab",
std::process::id(),
line!()
));
cargo_bin_cmd!("qrab")
.arg("check")
.arg(missing)
.assert()
.code(1)
.stderr(predicate::str::contains("cannot read"))
.stderr(predicate::str::contains("Usage:").not());
}
#[test]
fn installs_agent_skill_without_overwriting_changes() {
let directory =
std::env::temp_dir().join(format!("qrab-skill-{}-{}", std::process::id(), line!()));
fs::create_dir(&directory).expect("create skill test directory");
let skill = directory.join(".agents/skills/qrab/SKILL.md");
cargo_bin_cmd!("qrab")
.current_dir(&directory)
.arg("install-skill")
.assert()
.success()
.stdout(predicate::str::contains(
"installed .agents/skills/qrab/SKILL.md",
));
assert_eq!(
fs::read_to_string(&skill).expect("read installed skill"),
include_str!("../.agents/skills/qrab/SKILL.md")
);
cargo_bin_cmd!("qrab")
.current_dir(&directory)
.arg("install-skill")
.assert()
.success()
.stdout(predicate::str::contains("already installed"));
fs::write(&skill, "local changes\n").expect("customize installed skill");
cargo_bin_cmd!("qrab")
.current_dir(&directory)
.arg("install-skill")
.assert()
.failure()
.stderr(predicate::str::contains("refusing to overwrite"));
assert_eq!(
fs::read_to_string(skill).expect("read customized skill"),
"local changes\n"
);
fs::remove_dir_all(directory).expect("remove skill test directory");
}
#[test]
fn shipped_man_pages_carry_this_crate_version() {
let version = env!("CARGO_PKG_VERSION");
for page in [
"qrab.1",
"qrab-check.1",
"qrab-compile.1",
"qrab-install-skill.1",
] {
let path = concat!(env!("CARGO_MANIFEST_DIR"), "/assets/");
let text = fs::read_to_string(format!("{path}{page}"))
.unwrap_or_else(|error| panic!("reading assets/{page}: {error}"));
assert!(
text.contains(version),
"assets/{page} does not mention version {version}; run `just gen-assets`"
);
}
}
#[test]
fn miette_reports_imported_source_help_and_multiple_errors() {
let directory = std::env::temp_dir().join(format!(
"qrab-diagnostics-{}-{}",
std::process::id(),
line!()
));
fs::create_dir(&directory).expect("create diagnostic test directory");
fs::write(
directory.join("gates.qrab"),
"fn broken(a) { // context before\n\th missing\n} // context after\n",
)
.expect("write imported source");
let imported = directory.join("imported.qrab");
fs::write(
&imported,
"import \"gates.qrab\"\ncircuit imported { qubit q; broken(q) }\n",
)
.expect("write importing source");
cargo_bin_cmd!("qrab")
.env("NO_COLOR", "1")
.arg("check")
.arg(&imported)
.assert()
.code(1)
.stderr(predicate::str::contains("gates.qrab:2:4"))
.stderr(predicate::str::contains("context before"))
.stderr(predicate::str::contains("context after"))
.stderr(predicate::str::contains("h missing"))
.stderr(predicate::str::contains(
"declare it before use or enable `autowires`",
));
let multiple = directory.join("multiple.qrab");
fs::write(
&multiple,
"circuit bad {\n\tqubit q\n\th missing\n\tx absent\n}\n",
)
.expect("write multiple-error source");
cargo_bin_cmd!("qrab")
.env("NO_COLOR", "1")
.arg("check")
.arg(&multiple)
.assert()
.code(1)
.stderr(predicate::str::contains("2 errors found"))
.stderr(predicate::str::contains("unknown wire `missing`"))
.stderr(predicate::str::contains("unknown wire `absent`"));
fs::remove_dir_all(directory).expect("remove diagnostic test directory");
}