Skip to main content

async_graphql_test/matchers/
should_throw.rs

1use std::fmt::{Display, Formatter};
2
3use async_graphql::async_trait::async_trait;
4use async_graphql::{Context, CustomDirective, Directive, ResolveFut, ServerResult, Value};
5
6use super::MatcherError;
7
8#[Directive(location = "Field", name = "shouldThrow")]
9pub fn should_throw(
10    msg_like: Option<String>,
11    msg_like_regex: Option<String>,
12) -> impl CustomDirective {
13    if let Some(sub) = msg_like {
14        return ShouldThrow::String(sub);
15    }
16
17    if let Some(regex) = msg_like_regex {
18        return ShouldThrow::Regex(
19            regex::Regex::new(&regex)
20                .map_err(|err| format!("incorrect regular expression: {err}"))
21                .unwrap(),
22        );
23    }
24
25    ShouldThrow::Wildcard
26}
27
28enum ShouldThrow {
29    Wildcard,
30    Regex(regex::Regex),
31    String(String),
32}
33
34impl Display for ShouldThrow {
35    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36        match self {
37            ShouldThrow::Wildcard => write!(f, "*"),
38            ShouldThrow::Regex(regex) => write!(f, "/{regex}/"),
39            ShouldThrow::String(sub) => sub.fmt(f),
40        }
41    }
42}
43
44impl ShouldThrow {
45    pub fn matches(&self, text: &str) -> bool {
46        match self {
47            ShouldThrow::Wildcard => true,
48            ShouldThrow::String(sub) => text.contains(sub),
49            ShouldThrow::Regex(regex) => regex.is_match(text),
50        }
51    }
52}
53
54#[async_trait]
55impl CustomDirective for ShouldThrow {
56    async fn resolve_field(
57        &self,
58        ctx: &Context<'_>,
59        resolve: ResolveFut<'_>,
60    ) -> ServerResult<Option<Value>> {
61        match resolve.await {
62            Ok(_) => Err(MatcherError::new(
63                ctx.item.pos,
64                "Expected the function to throw an error.\nBut it didn't throw anything.".into(),
65            )),
66            Err(err) => {
67                if self.matches(&err.message) {
68                    // todo: this branch should probably just return Err(err)
69                    Ok(None)
70                } else {
71                    Err(MatcherError::new(
72                        ctx.item.pos,
73                        format!("Expected: \"{self}\"\nReceived: \"{}\"", err.message),
74                    ))
75                }
76            }
77        }
78    }
79}