Skip to main content

api_testing_core/rest/
report.rs

1use crate::report::{ReportBuilder, ReportHeader};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct RestReportAssertion {
5    pub label: String,
6    pub state: String,
7}
8
9#[derive(Debug, Clone, PartialEq, Eq)]
10pub struct RestReport {
11    pub report_date: String,
12    pub case_name: String,
13    pub generated_at: String,
14    pub endpoint_note: String,
15    pub result_note: String,
16    pub command_snippet: Option<String>,
17    pub assertions: Vec<RestReportAssertion>,
18    pub request_json: String,
19    pub response_lang: String,
20    pub response_body: String,
21    pub stderr_note: Option<String>,
22}
23
24pub fn render_rest_report_markdown(report: &RestReport) -> String {
25    let header = ReportHeader {
26        report_date: &report.report_date,
27        case_name: &report.case_name,
28        generated_at: &report.generated_at,
29        endpoint_note: &report.endpoint_note,
30        result_note: &report.result_note,
31        command_snippet: report.command_snippet.as_deref(),
32    };
33    let mut builder = ReportBuilder::new(header);
34
35    if !report.assertions.is_empty() {
36        builder.push_section_heading("Assertions");
37        for a in &report.assertions {
38            builder.push_list_item(&format!("{} ({})", a.label, a.state));
39        }
40        builder.push_blank_line();
41    }
42
43    builder.push_code_section("Request", "json", &report.request_json, None, true);
44    builder.push_code_section(
45        "Response",
46        &report.response_lang,
47        &report.response_body,
48        None,
49        true,
50    );
51
52    if let Some(stderr_note) = &report.stderr_note
53        && !stderr_note.is_empty()
54    {
55        builder.push_code_section("stderr", "text", stderr_note, None, false);
56    }
57
58    builder.finish()
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64    use pretty_assertions::assert_eq;
65
66    #[test]
67    fn rest_report_renders_markdown_with_optional_sections() {
68        let report = RestReport {
69            report_date: "2026-02-01".to_string(),
70            case_name: "Health".to_string(),
71            generated_at: "2026-02-01T00:00:00Z".to_string(),
72            endpoint_note: "Endpoint: http://localhost:8080/health".to_string(),
73            result_note: "Result: OK".to_string(),
74            command_snippet: Some("curl -sS http://localhost:8080/health".to_string()),
75            assertions: vec![RestReportAssertion {
76                label: "status".to_string(),
77                state: "pass".to_string(),
78            }],
79            request_json: r#"{"method":"GET","path":"/health"}"#.to_string(),
80            response_lang: "json".to_string(),
81            response_body: r#"{"ok":true}"#.to_string(),
82            stderr_note: Some("warning: retrying".to_string()),
83        };
84
85        let got = render_rest_report_markdown(&report);
86        let expected = concat!(
87            "# API Test Report (2026-02-01)\n",
88            "\n",
89            "## Test Case: Health\n",
90            "\n",
91            "## Command\n",
92            "\n",
93            "```bash\n",
94            "curl -sS http://localhost:8080/health\n",
95            "```\n",
96            "\n",
97            "Generated at: 2026-02-01T00:00:00Z\n",
98            "\n",
99            "Endpoint: http://localhost:8080/health\n",
100            "\n",
101            "Result: OK\n",
102            "\n",
103            "### Assertions\n",
104            "\n",
105            "- status (pass)\n",
106            "\n",
107            "### Request\n",
108            "\n",
109            "```json\n",
110            "{\"method\":\"GET\",\"path\":\"/health\"}\n",
111            "```\n",
112            "\n",
113            "### Response\n",
114            "\n",
115            "```json\n",
116            "{\"ok\":true}\n",
117            "```\n",
118            "\n",
119            "### stderr\n",
120            "\n",
121            "```text\n",
122            "warning: retrying\n",
123            "```\n"
124        );
125        assert_eq!(got, expected);
126    }
127
128    #[test]
129    fn rest_report_omits_command_assertions_and_empty_stderr() {
130        let report = RestReport {
131            report_date: "2026-02-01".to_string(),
132            case_name: "No-Options".to_string(),
133            generated_at: "2026-02-01T00:00:00Z".to_string(),
134            endpoint_note: "Endpoint: x".to_string(),
135            result_note: "Result: y".to_string(),
136            command_snippet: None,
137            assertions: vec![],
138            request_json: "{}".to_string(),
139            response_lang: "text".to_string(),
140            response_body: "ok".to_string(),
141            stderr_note: Some("".to_string()),
142        };
143
144        let got = render_rest_report_markdown(&report);
145        assert!(!got.contains("## Command\n"));
146        assert!(!got.contains("### Assertions\n"));
147        assert!(!got.contains("### stderr\n"));
148    }
149}