use std::path::PathBuf;
use std::process::{Command, Output};
fn repo() -> PathBuf {
PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../..")
}
fn doc(args: &[&str]) -> Output {
Command::new(env!("CARGO_BIN_EXE_blue"))
.env_remove("BLUE_CONFIG")
.env_remove("BLUE_TIER")
.env("BLUE_PATH", repo().join("bidamas"))
.current_dir(repo())
.arg("doc")
.args(args)
.output()
.expect("spawn")
}
fn json_lines(o: &Output) -> Vec<serde_json::Value> {
String::from_utf8_lossy(&o.stdout)
.lines()
.map(|l| serde_json::from_str(l).unwrap_or_else(|e| panic!("{l}: {e}")))
.collect()
}
#[test]
fn a_builtin_has_its_signature_doc_tier_and_spec_row_example() {
let o = doc(&["blue::length", "--json"]);
assert!(o.status.success(), "{}", String::from_utf8_lossy(&o.stderr));
let found = json_lines(&o);
assert_eq!(found.len(), 1, "{found:?}");
let e = &found[0];
assert_eq!(e["name"], "length");
assert_eq!(e["namespace"], "blue");
assert_eq!(e["tier"], "builtin");
assert_eq!(e["signature"], "length(xs)");
assert!(e["doc"][0].as_str().is_some_and(|d| !d.is_empty()), "{e}");
assert!(
e["example"]["from"]
.as_str()
.is_some_and(|f| f.starts_with("spec row ")),
"{e}"
);
}
#[test]
fn a_bidama_definition_has_its_doc_namespace_and_test_example() {
let o = doc(&["retsu::size", "--json"]);
assert!(o.status.success(), "{}", String::from_utf8_lossy(&o.stderr));
let e = &json_lines(&o)[0];
assert_eq!(e["name"], "retsu::size");
assert_eq!(e["namespace"], "retsu");
assert_eq!(e["tier"], "qualified");
assert_eq!(e["signature"], "retsu::size(xs)");
assert_eq!(
e["doc"][0],
"Total length: nil counts as empty rather than erroring."
);
assert!(
e["example"]["code"].as_array().is_some_and(|c| c
.iter()
.any(|l| l.as_str().is_some_and(|l| l.contains("size(")))),
"{e}"
);
}
#[test]
fn a_bare_name_answers_every_owner_and_file_gives_the_tier() {
let o = doc(&["first", "--json"]);
let names: Vec<String> = json_lines(&o)
.iter()
.map(|e| e["name"].as_str().unwrap_or_default().to_string())
.collect();
assert!(names.contains(&"retsu::first".to_string()), "{names:?}");
assert!(names.contains(&"first".to_string()), "{names:?}");
let o = doc(&["first", "--file", "bidamas/moji/moji.b", "--json"]);
let found = json_lines(&o);
let retsu = found
.iter()
.find(|e| e["name"] == "retsu::first")
.expect("retsu::first");
assert_eq!(retsu["tier"], "imported", "moji lists first from retsu");
}
#[test]
fn an_unknown_name_fails_naming_where_it_looked() {
let o = doc(&["no_such_definition_anywhere"]);
assert_eq!(o.status.code(), Some(1));
let err = String::from_utf8_lossy(&o.stderr);
assert!(
err.contains("no `no_such_definition_anywhere` in the builtins and"),
"{err}"
);
assert!(o.stdout.is_empty());
}
#[test]
fn a_package_name_lists_the_package() {
let o = doc(&["kazu", "--json"]);
assert!(o.status.success(), "{}", String::from_utf8_lossy(&o.stderr));
let p = &json_lines(&o)[0];
assert_eq!(p["package"], "kazu");
assert!(
p["gloss"].as_str().is_some_and(|g| g.starts_with("kazu")),
"{p}"
);
assert!(
p["definitions"]
.as_array()
.is_some_and(|d| d.iter().any(|d| d["name"] == "abs")),
"{p}"
);
}