async_graphql_test/
executor.rs1use std::future::Future;
2
3use async_graphql::PathSegment;
4use itertools::Itertools;
5
6use crate::matchers::MatcherError;
7use crate::script::Script;
8
9pub async fn execute_script<F, Fut>(
19 mut execute_request: F,
20 script: Script,
21) -> Vec<async_graphql::Response>
22where
23 F: FnMut(async_graphql::Request) -> Fut,
24 Fut: Future<Output = async_graphql::Response>,
25{
26 let requests = script.requests;
27 let mut acc = Vec::with_capacity(requests.len());
28
29 if requests.is_empty() {
30 panic!("at least one query or mutation must be present");
31 }
32
33 for mut req in requests {
34 let op = req
37 .parsed_query()
38 .unwrap()
39 .operations
40 .iter()
41 .next()
42 .unwrap()
43 .1
44 .clone();
45 let op_type = op.node.ty;
46
47 let op_name = req.operation_name.take().unwrap_or_default();
48 let failure_causes_panic = op_name.starts_with('_');
49
50 let res = execute_request(req).await;
51
52 let has_matcher_err = res
53 .errors
54 .iter()
55 .any(|err| err.source::<MatcherError>().is_some());
56
57 if res.is_err() && (has_matcher_err || failure_causes_panic) {
58 if let Some(err) = res.errors.first() {
60 let path = GraphQLPathSegments(&err.path);
62 let source = err.source.as_deref();
63 eprintln!(
65 "{:?} '{}' ({}) raised an error at line {}\n\n{}\n\nSource:\n{:?}\n",
66 op_type, op_name, path, err.locations[0], err.message, source,
67 );
68 panic!();
70 }
71 }
72
73 if !failure_causes_panic || acc.len() == 1 {
74 acc.push(res);
75 }
76 }
77
78 acc
79}
80
81struct GraphQLPathSegments<'a>(&'a [PathSegment]);
82
83impl std::fmt::Display for GraphQLPathSegments<'_> {
84 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85 self.0
86 .iter()
87 .format_with(".", |segment, f| match segment {
88 PathSegment::Field(name) => f(name),
89 PathSegment::Index(idx) => f(&format_args!("[{idx}]")),
90 })
91 .fmt(f)
92 }
93}