use serde_json::Value;
use crate::{helpers::spawn_http_server, support::TestWorkspace};
#[test]
fn run_outputs_ndjson_report() {
let server_url = spawn_http_server(
200,
"OK",
"application/json",
r#"{"ok":true,"service":"hen"}"#,
);
let workspace = TestWorkspace::new();
workspace.write_file(
"collection.hen",
&format!(
r#"NDJSON Fixture
Exercises streaming machine-readable output.
---
Fetch fixture
GET {server_url}
^ & body.ok == true
[ true == false ] ^ & body.service == 'hen'
"#
),
);
let output = workspace.run_hen(["run", "collection.hen", "--output", "ndjson"]);
assert_eq!(output.status_code, 0, "stderr: {}", output.stderr);
assert!(output.stderr.is_empty(), "stderr: {}", output.stderr);
let lines = output
.stdout
.lines()
.map(|line| serde_json::from_str::<Value>(line).expect("line should be valid json"))
.collect::<Vec<_>>();
assert_eq!(lines.len(), 4);
assert_eq!(lines[0]["type"], "run");
assert_eq!(lines[0]["interrupted"], false);
assert_eq!(lines[0]["interruptSignal"], Value::Null);
assert_eq!(lines[0]["traceCount"], 2);
assert_eq!(lines[1]["type"], "record");
assert_eq!(lines[1]["status"], 200);
assert_eq!(lines[1]["assertions"][0]["status"], "passed");
assert_eq!(lines[1]["assertions"][1]["status"], "skipped");
assert_eq!(lines[2]["type"], "trace");
assert_eq!(lines[2]["kind"], "started");
assert_eq!(lines[3]["type"], "trace");
assert_eq!(lines[3]["kind"], "completed");
}
#[test]
fn run_outputs_ndjson_report_for_schema_failures() {
let server_url = spawn_http_server(
200,
"OK",
"application/json",
r#"[{"id":"550e8400-e29b-41d4-a716-446655440000"},{"id":"not-a-uuid"}]"#,
);
let workspace = TestWorkspace::new();
workspace.write_file(
"collection.hen",
&format!(
r#"schema User {{
id: UUID
}}
schema Users = User[]
---
Schema NDJSON Failure Fixture
GET {server_url}
^ & body === Users
"#
),
);
let output = workspace.run_hen(["run", "collection.hen", "--output", "ndjson"]);
assert_eq!(output.status_code, 1, "stderr: {}", output.stderr);
assert!(output.stderr.is_empty(), "stderr: {}", output.stderr);
let lines = output
.stdout
.lines()
.map(|line| serde_json::from_str::<Value>(line).expect("line should be valid json"))
.collect::<Vec<_>>();
assert_eq!(lines.len(), 4);
assert_eq!(lines[0]["type"], "run");
assert_eq!(lines[0]["traceCount"], 2);
assert_eq!(lines[1]["type"], "failure");
assert_eq!(lines[2]["type"], "trace");
assert_eq!(lines[2]["kind"], "started");
assert_eq!(lines[3]["type"], "trace");
assert_eq!(lines[3]["kind"], "failed");
let mismatch = &lines[1]["assertions"][0]["mismatch"];
assert_eq!(mismatch["kind"], "schema");
assert_eq!(mismatch["reason"], "array_item_mismatch");
assert_eq!(mismatch["target"], "Users");
assert_eq!(mismatch["path"], "body[1].id");
assert_eq!(mismatch["actualPath"], "body");
assert_eq!(mismatch["operator"], "===");
assert_eq!(mismatch["actual"]["type"], "string");
assert_eq!(mismatch["actual"]["value"], "not-a-uuid");
assert_eq!(mismatch["expected"]["type"], "format");
assert_eq!(mismatch["expected"]["value"], "UUID");
}