use serde_json::{json, Value};
use crate::request::{
AssertionDiff, AssertionMismatch, AssertionMismatchValue, AssertionOutcome,
ExecutionTraceEntry,
};
use super::redaction::OutputRedactor;
pub(crate) fn assertion_results_json(
assertions: &[AssertionOutcome],
redactor: &OutputRedactor,
) -> Vec<Value> {
assertions
.iter()
.map(|assertion| {
json!({
"assertion": assertion.assertion,
"status": assertion.status.as_str(),
"message": redactor.redact_optional_text(assertion.message.as_deref()),
"mismatch": assertion.mismatch.as_ref().map(|mismatch| assertion_mismatch_json(mismatch, redactor)),
"diff": assertion.diff.as_ref().map(|diff| assertion_diff_json(diff, redactor)),
})
})
.collect()
}
pub(crate) fn assertion_diff_json(diff: &AssertionDiff, redactor: &OutputRedactor) -> Value {
json!({
"format": diff.format.as_str(),
"path": diff.path,
"text": redactor.redact_text(&diff.rendered),
})
}
pub(crate) fn assertion_mismatch_json(
mismatch: &AssertionMismatch,
redactor: &OutputRedactor,
) -> Value {
json!({
"kind": mismatch.kind.as_str(),
"reason": mismatch.reason.as_str(),
"target": mismatch.target,
"path": mismatch.path,
"actualPath": mismatch.actual_path,
"comparedPath": mismatch.compared_path,
"operator": mismatch.operator,
"actual": assertion_mismatch_value_json(&mismatch.actual, redactor),
"expected": assertion_mismatch_value_json(&mismatch.expected, redactor),
})
}
pub(crate) fn assertion_mismatch_value_json(
value: &AssertionMismatchValue,
redactor: &OutputRedactor,
) -> Value {
json!({
"type": value.value_type,
"value": redactor.redact_json_value(&value.value),
})
}
pub(crate) fn execution_trace_json(entry: &ExecutionTraceEntry) -> Value {
let redactor = OutputRedactor::with_header_names(
&entry.sensitive_values,
&entry.sensitive_header_names,
);
json!({
"seq": entry.seq,
"kind": entry.kind.as_str(),
"index": entry.request_index,
"request": entry.request.as_deref().map(|request| redactor.redact_text(request)),
"dependencies": entry.dependencies.iter().map(|dependency| redactor.redact_text(dependency)).collect::<Vec<_>>(),
"waitingOn": entry.waiting_on.iter().map(|request| redactor.redact_text(request)).collect::<Vec<_>>(),
"protocol": entry.protocol.map(|protocol| protocol.as_str()),
"protocolContext": entry.protocol_context.as_ref().map(|value| redactor.redact_json_value(value)),
"durationMs": entry.duration.map(|duration| duration.as_millis() as u64),
"reason": entry.reason,
"relatedRequest": entry.related_request.as_deref().map(|request| redactor.redact_text(request)),
"group": entry.group.as_deref().map(|group| redactor.redact_text(group)),
"cause": entry.cause.as_deref().map(|cause| redactor.redact_text(cause)),
"message": entry.message.as_deref().map(|message| redactor.redact_text(message)),
"signal": entry.signal.map(|signal| signal.as_str()),
})
}
pub(crate) fn with_type(mut value: Value, kind: &str) -> Value {
if let Value::Object(ref mut map) = value {
map.insert("type".to_string(), Value::String(kind.to_string()));
}
value
}