async-graphql-test 1.0.0

A test framework for Rust GraphQL servers.
Documentation
use std::fmt::{Display, Formatter};

use async_graphql::async_trait::async_trait;
use async_graphql::{Context, CustomDirective, Directive, ResolveFut, ServerResult, Value};

use super::{MatcherError, Numeric, ValueTypeName};

#[Directive(location = "Field", name = "shouldBeGreaterThanOrEqual")]
pub fn should_be_greater_than_or_equal(
    i: Option<i64>,
    f: Option<f64>,
    bi: Option<String>,
) -> impl CustomDirective {
    let num = if let Some(i) = i {
        Numeric::Int(i)
    } else if let Some(f) = f {
        Numeric::Float(f)
    } else if let Some(s) = bi {
        Numeric::String(s)
    } else {
        panic!("@shouldBeGreaterThenOrEqual missing an argument")
    };
    ShouldBeGreaterThanOrEqual { num }
}

struct ShouldBeGreaterThanOrEqual {
    num: Numeric,
}

impl Display for ShouldBeGreaterThanOrEqual {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        self.num.fmt(f)
    }
}

#[async_trait]
impl CustomDirective for ShouldBeGreaterThanOrEqual {
    async fn resolve_field(
        &self,
        ctx: &Context<'_>,
        resolve: ResolveFut<'_>,
    ) -> ServerResult<Option<Value>> {
        match resolve.await {
            Ok(None) => Ok(None),
            Ok(Some(Value::Number(num))) => {
                if self.num >= num {
                    Ok(Some(Value::Number(num)))
                } else {
                    Err(MatcherError::new(
                        ctx.item.pos,
                        format!("Expected: >= {self}\nReceived:    {num}"),
                    ))
                }
            }
            Ok(Some(value)) => {
                let type_name = ValueTypeName(&value);
                Err(MatcherError::new(
                    ctx.item.pos,
                    format!(
                        "@shouldBeGreaterThenOrEqual error: value must be numeric.\nReceived has type:  {type_name}\nReceived has value: {value}"
                    ),
                ))
            }
            Err(err) => Err(MatcherError::unexpected_error(err)),
        }
    }
}