async-graphql-test 1.0.0

A test framework for Rust GraphQL servers.
Documentation
//! A library of assertions, provided as GraphQL directives.
//!
//! In most cases, you should just call [`register_directives`] to add those to your schema.

use async_graphql::*;

mod register_directives;
pub use register_directives::register_directives;

// We add a trailing underscore to the module names to avoid name conflicts with the re-exported funtions.
#[path = "should_be_close_to.rs"]
mod should_be_close_to_;
#[path = "should_be_defined.rs"]
mod should_be_defined_;
#[path = "should_be_falsy.rs"]
mod should_be_falsy_;
#[path = "should_be_greater_than.rs"]
mod should_be_greater_than_;
#[path = "should_be_greater_than_or_equal.rs"]
mod should_be_greater_than_or_equal_;
#[path = "should_be_less_than.rs"]
mod should_be_less_than_;
#[path = "should_be_less_than_or_equal.rs"]
mod should_be_less_than_or_equal_;
#[path = "should_be_not_null.rs"]
mod should_be_not_null_;
#[path = "should_be_null.rs"]
mod should_be_null_;
#[path = "should_be_one_of.rs"]
mod should_be_one_of_;
#[path = "should_be_truthy.rs"]
mod should_be_truthy_;
#[path = "should_contain.rs"]
mod should_contain_;
#[path = "should_equal.rs"]
mod should_equal_;
#[path = "should_have_length.rs"]
mod should_have_length_;
#[path = "should_match.rs"]
mod should_match_;
#[path = "should_throw.rs"]
mod should_throw_;

pub use should_be_close_to_::should_be_close_to;
pub use should_be_defined_::should_be_defined;
pub use should_be_falsy_::should_be_falsy;
pub use should_be_greater_than_::should_be_greater_than;
pub use should_be_greater_than_or_equal_::should_be_greater_than_or_equal;
pub use should_be_less_than_::should_be_less_than;
pub use should_be_less_than_or_equal_::should_be_less_than_or_equal;
pub use should_be_not_null_::should_be_not_null;
pub use should_be_null_::should_be_null;
pub use should_be_one_of_::should_be_one_of;
pub use should_be_truthy_::should_be_truthy;
pub use should_contain_::should_contain;
pub use should_equal_::should_equal;
pub use should_have_length_::should_have_length;
pub use should_match_::should_match;
pub use should_throw_::should_throw;

#[derive(Debug)]
pub struct MatcherError;

impl MatcherError {
    #[expect(clippy::new_ret_no_self)]
    pub fn new(pos: Pos, message: String) -> ServerError {
        ServerError {
            source: Some(std::sync::Arc::new(MatcherError)),
            ..ServerError::new(message, Some(pos))
        }
    }

    pub fn unexpected_error(mut err: ServerError) -> ServerError {
        err.message = format!("Unexpected error occurred:\n\n{}", err.message);
        err.source = Some(std::sync::Arc::new(MatcherError));
        err
    }
}

struct ValueTypeName<'a>(&'a Value);

impl std::fmt::Display for ValueTypeName<'_> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.write_str(match self.0 {
            Value::Null => "null",
            Value::Number(_) => "number",
            Value::String(_) => "string",
            Value::Boolean(_) => "boolean",
            Value::Binary(_) => "binary",
            Value::Enum(_) => "enum",
            Value::List(_) => "list", // probably should be [Type!]!
            Value::Object(_) => "object",
        })
    }
}

enum Numeric {
    Int(i64),
    Float(f64),
    /// Long arithmetics
    String(String),
}

impl std::fmt::Display for Numeric {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        match self {
            Numeric::Int(x) => x.fmt(f),
            Numeric::Float(x) => x.fmt(f),
            Numeric::String(x) => x.fmt(f),
        }
    }
}

impl PartialEq<serde_json::Number> for Numeric {
    fn eq(&self, other: &serde_json::Number) -> bool {
        match self {
            &Numeric::Int(x) => {
                (other.is_i64() && other.as_i64() == Some(x))
                    || (other.is_u64() && other.as_u64() == Some(x as u64))
                    || (other.is_f64() && other.as_f64() == Some(x as f64))
            }
            &Numeric::Float(x) => other.as_f64() == Some(x),
            Numeric::String(_) => unimplemented!(),
        }
    }
}

impl PartialOrd<serde_json::Number> for Numeric {
    fn partial_cmp(&self, other: &serde_json::Number) -> Option<std::cmp::Ordering> {
        match self {
            &Numeric::Int(x) => match other {
                other if other.is_i64() => other.as_i64().partial_cmp(&Some(x)),
                other if other.is_u64() => other.as_u64().partial_cmp(&Some(x as u64)),
                other if other.is_f64() => other.as_f64().partial_cmp(&Some(x as f64)),
                _ => unreachable!(
                    "serde_json::Number shouldn't have any other representations, see its definition"
                ),
            },
            &Numeric::Float(x) => other.as_f64().partial_cmp(&Some(x)),
            Numeric::String(_) => unimplemented!(),
        }
    }
}