use std::io::Write as _;
use std::process::Command;
use tempfile::NamedTempFile;
const MARTIN_BIN: &str = env!("CARGO_BIN_EXE_martin");
fn run_with_bad_config(yaml: &str, extra_env: &[(&str, &str)]) -> String {
let mut cfg = NamedTempFile::new().expect("could not create temp file");
cfg.write_all(yaml.as_bytes()).expect("could not write");
cfg.flush().expect("could not flush");
let mut cmd = Command::new(MARTIN_BIN);
cmd.arg("--config").arg(cfg.path()).env("RUST_LOG", "off");
for (k, v) in extra_env {
cmd.env(k, v);
}
let output = cmd.output().expect("failed to spawn martin binary");
assert!(
!output.status.success(),
"expected non-zero exit; stderr was:\n{}",
String::from_utf8_lossy(&output.stderr),
);
let stderr = String::from_utf8(output.stderr).expect("stderr was not UTF-8");
let path = cfg.path().to_str().expect("temp path was not UTF-8");
stderr.replace(path, "<config>")
}
#[test]
fn json_format_emits_structured_diagnostic_on_stderr() {
let stderr = run_with_bad_config("cors: 42\n", &[("RUST_LOG_FORMAT", "json")]);
insta::assert_snapshot!(stderr.trim(), @r#"{"message": "invalid type: integer `42`, expected either a boolean (`cors: true` / `cors: false`) or a properties map with at least an `origin` list","severity": "error","causes": [],"filename": "<config>","labels": [{"label": "invalid type: integer `42`, expected either a boolean (`cors: true` / `cors: false`) or a properties map with at least an `origin` list","span": {"offset": 0,"length": 4}}],"related": []}"#);
}
#[test]
fn graphical_format_emits_human_diagnostic_on_stderr() {
let stderr = run_with_bad_config("cors: 42\n", &[]);
insta::assert_snapshot!(stderr.trim(), @"
× invalid type: integer `42`, expected either a boolean (`cors: true` /
│ `cors: false`) or a properties map with at least an `origin` list
╭─[<config>:1:1]
1 │ cors: 42
· ──┬─
· ╰── invalid type: integer `42`, expected either a boolean (`cors: true` / `cors: false`) or a properties map with at least an `origin` list
╰────
");
}