async_graphql_test/matchers/
should_throw.rs1use 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(®ex)
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 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}