Skip to main content

api_testing_core/
cli_io.rs

1use std::io::{Read, Write};
2use std::path::PathBuf;
3
4use anyhow::anyhow;
5
6use crate::Result;
7
8pub fn read_response_bytes(response: &str, stdin: &mut dyn Read) -> Result<Vec<u8>> {
9    if response == "-" {
10        let mut buf = Vec::new();
11        stdin
12            .read_to_end(&mut buf)
13            .map_err(|_| anyhow!("error: failed to read response from stdin"))?;
14        return Ok(buf);
15    }
16
17    let resp_path = PathBuf::from(response);
18    if !resp_path.is_file() {
19        return Err(anyhow!("Response file not found: {}", resp_path.display()));
20    }
21
22    std::fs::read(&resp_path).map_err(|_| {
23        anyhow!(
24            "error: failed to read response file: {}",
25            resp_path.display()
26        )
27    })
28}
29
30pub fn maybe_print_failure_body_to_stderr(
31    body: &[u8],
32    max_bytes: usize,
33    stdout_is_tty: bool,
34    stderr: &mut dyn Write,
35) {
36    if stdout_is_tty || body.is_empty() {
37        return;
38    }
39
40    if serde_json::from_slice::<serde_json::Value>(body).is_ok() {
41        return;
42    }
43
44    let _ = writeln!(stderr, "Response body (non-JSON; first {max_bytes} bytes):");
45    let _ = stderr.write_all(&body[..body.len().min(max_bytes)]);
46    let _ = writeln!(stderr);
47}
48
49#[cfg(test)]
50mod tests {
51    use super::maybe_print_failure_body_to_stderr;
52
53    #[test]
54    fn maybe_print_failure_body_skips_when_stdout_is_tty() {
55        let mut stderr = Vec::new();
56        maybe_print_failure_body_to_stderr(b"not-json", 16, true, &mut stderr);
57        assert!(stderr.is_empty());
58    }
59
60    #[test]
61    fn maybe_print_failure_body_skips_when_response_is_json() {
62        let mut stderr = Vec::new();
63        maybe_print_failure_body_to_stderr(br#"{"ok":true}"#, 16, false, &mut stderr);
64        assert!(stderr.is_empty());
65    }
66
67    #[test]
68    fn maybe_print_failure_body_prints_non_json_preview() {
69        let mut stderr = Vec::new();
70        maybe_print_failure_body_to_stderr(b"abcdef", 4, false, &mut stderr);
71        let text = String::from_utf8(stderr).expect("utf8");
72        assert!(text.contains("Response body (non-JSON; first 4 bytes):"));
73        assert!(text.contains("abcd"));
74    }
75}