nils-api-testing-core 0.7.3

Library crate for nils-api-testing-core in the nils-cli workspace.
Documentation
use std::io::{Read, Write};
use std::path::PathBuf;

use anyhow::anyhow;

use crate::Result;

pub fn read_response_bytes(response: &str, stdin: &mut dyn Read) -> Result<Vec<u8>> {
    if response == "-" {
        let mut buf = Vec::new();
        stdin
            .read_to_end(&mut buf)
            .map_err(|_| anyhow!("error: failed to read response from stdin"))?;
        return Ok(buf);
    }

    let resp_path = PathBuf::from(response);
    if !resp_path.is_file() {
        return Err(anyhow!("Response file not found: {}", resp_path.display()));
    }

    std::fs::read(&resp_path).map_err(|_| {
        anyhow!(
            "error: failed to read response file: {}",
            resp_path.display()
        )
    })
}

pub fn maybe_print_failure_body_to_stderr(
    body: &[u8],
    max_bytes: usize,
    stdout_is_tty: bool,
    stderr: &mut dyn Write,
) {
    if stdout_is_tty || body.is_empty() {
        return;
    }

    if serde_json::from_slice::<serde_json::Value>(body).is_ok() {
        return;
    }

    let _ = writeln!(stderr, "Response body (non-JSON; first {max_bytes} bytes):");
    let _ = stderr.write_all(&body[..body.len().min(max_bytes)]);
    let _ = writeln!(stderr);
}

#[cfg(test)]
mod tests {
    use super::maybe_print_failure_body_to_stderr;

    #[test]
    fn maybe_print_failure_body_skips_when_stdout_is_tty() {
        let mut stderr = Vec::new();
        maybe_print_failure_body_to_stderr(b"not-json", 16, true, &mut stderr);
        assert!(stderr.is_empty());
    }

    #[test]
    fn maybe_print_failure_body_skips_when_response_is_json() {
        let mut stderr = Vec::new();
        maybe_print_failure_body_to_stderr(br#"{"ok":true}"#, 16, false, &mut stderr);
        assert!(stderr.is_empty());
    }

    #[test]
    fn maybe_print_failure_body_prints_non_json_preview() {
        let mut stderr = Vec::new();
        maybe_print_failure_body_to_stderr(b"abcdef", 4, false, &mut stderr);
        let text = String::from_utf8(stderr).expect("utf8");
        assert!(text.contains("Response body (non-JSON; first 4 bytes):"));
        assert!(text.contains("abcd"));
    }
}