async_graphql_test/matchers/
should_have_length.rs1use async_graphql::async_trait::async_trait;
2use async_graphql::{Context, CustomDirective, Directive, ResolveFut, ServerResult, Value};
3
4use super::{MatcherError, ValueTypeName};
5
6#[Directive(location = "Field", name = "shouldHaveLength")]
10pub fn should_have_length(n: usize) -> impl CustomDirective {
11 ShouldHaveLength { len: n }
12}
13
14struct ShouldHaveLength {
15 len: usize,
16}
17
18#[async_trait]
19impl CustomDirective for ShouldHaveLength {
20 async fn resolve_field(
21 &self,
22 ctx: &Context<'_>,
23 resolve: ResolveFut<'_>,
24 ) -> ServerResult<Option<Value>> {
25 match resolve.await {
26 Ok(None) => Ok(None),
27 Ok(Some(Value::List(list))) => {
29 if list.len() == self.len {
30 Ok(Some(Value::List(list)))
31 } else {
32 Err(MatcherError::new(
33 ctx.item.pos,
34 format!(
35 "Expected length: {}\nReceived length: {}\nReceived array: {}",
36 self.len,
37 list.len(),
38 Value::List(list)
39 ),
40 ))
41 }
42 }
43 Ok(Some(Value::String(string))) => {
44 if string.len() == self.len {
45 Ok(Some(Value::String(string)))
46 } else {
47 Err(MatcherError::new(
48 ctx.item.pos,
49 format!(
50 "Expected length: {}\nReceived length: {}\nReceived string: {}",
51 self.len,
52 string.len(),
53 Value::String(string)
54 ),
55 ))
56 }
57 }
58 Ok(Some(value)) => {
59 let type_name = ValueTypeName(&value);
60 Err(MatcherError::new(
61 ctx.item.pos,
62 format!(
63 "@shouldHaveLength error: value must have a length property.\nReceived has type: {type_name}\nReceived has value: {value}"
64 ),
65 ))
66 }
67 Err(err) => Err(MatcherError::unexpected_error(err)),
68 }
69 }
70}