Skip to main content

api_testing_core/graphql/
expect.rs

1use crate::Result;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct GraphqlAssertions {
5    pub default_no_errors: String,
6    pub default_has_data: Option<String>,
7    pub jq: Option<String>,
8}
9
10impl GraphqlAssertions {
11    pub fn to_json(&self) -> serde_json::Value {
12        let mut obj = serde_json::Map::new();
13        obj.insert(
14            "defaultNoErrors".to_string(),
15            serde_json::Value::String(self.default_no_errors.clone()),
16        );
17        if let Some(v) = &self.default_has_data {
18            obj.insert(
19                "defaultHasData".to_string(),
20                serde_json::Value::String(v.clone()),
21            );
22        }
23        if let Some(v) = &self.jq {
24            obj.insert("jq".to_string(), serde_json::Value::String(v.clone()));
25        }
26        serde_json::Value::Object(obj)
27    }
28}
29
30fn errors_len(value: &serde_json::Value) -> usize {
31    value
32        .get("errors")
33        .and_then(|v| v.as_array())
34        .map(|a| a.len())
35        .unwrap_or(0)
36}
37
38pub fn evaluate_graphql_response_for_suite(
39    response_json: &serde_json::Value,
40    allow_errors: bool,
41    expect_jq: Option<&str>,
42) -> Result<GraphqlAssertions> {
43    let default_no_errors = if errors_len(response_json) == 0 {
44        "passed"
45    } else {
46        "failed"
47    };
48
49    let default_has_data = if !allow_errors && expect_jq.is_none() {
50        let ok = response_json
51            .get("data")
52            .is_some_and(|v| !v.is_null() && v.is_object());
53        Some(if ok { "passed" } else { "failed" }.to_string())
54    } else {
55        None
56    };
57
58    let jq = if let Some(expr) = expect_jq {
59        let ok = crate::jq::eval_exit_status(response_json, expr).unwrap_or(false);
60        Some(if ok { "passed" } else { "failed" }.to_string())
61    } else {
62        None
63    };
64
65    Ok(GraphqlAssertions {
66        default_no_errors: default_no_errors.to_string(),
67        default_has_data,
68        jq,
69    })
70}
71
72#[cfg(test)]
73mod tests {
74    use super::*;
75    use pretty_assertions::assert_eq;
76
77    #[test]
78    fn graphql_expect_default_no_errors_and_has_data() {
79        let v = serde_json::json!({"data": {"x": 1}});
80        let a = evaluate_graphql_response_for_suite(&v, false, None).unwrap();
81        assert_eq!(a.default_no_errors, "passed");
82        assert_eq!(a.default_has_data.as_deref(), Some("passed"));
83        assert!(a.jq.is_none());
84    }
85
86    #[test]
87    fn graphql_expect_errors_present_marks_failed() {
88        let v = serde_json::json!({"data": {"x": 1}, "errors": [{"message": "no"}]});
89        let a = evaluate_graphql_response_for_suite(&v, false, None).unwrap();
90        assert_eq!(a.default_no_errors, "failed");
91    }
92
93    #[test]
94    fn graphql_expect_jq_is_evaluated() {
95        let v = serde_json::json!({"data": {"ok": true}});
96        let a = evaluate_graphql_response_for_suite(&v, false, Some(".data.ok == true")).unwrap();
97        assert_eq!(a.jq.as_deref(), Some("passed"));
98        assert!(a.default_has_data.is_none());
99    }
100}