dynamic-graphql-derive 0.10.2

Dynamic GraphQL schema macro
Documentation
use async_trait::async_trait;
use dynamic_graphql::App;
use dynamic_graphql::FieldValue;
use dynamic_graphql::Instance;
use dynamic_graphql::Interface;
use dynamic_graphql::ResolvedObject;
use dynamic_graphql::ResolvedObjectFields;
use dynamic_graphql::SimpleObject;
use dynamic_graphql::dynamic::DynamicRequestExt;

use crate::schema_utils::normalize_schema;

#[tokio::test]
async fn test_async_trait() {
    #[Interface]
    #[async_trait]
    trait Foo {
        fn sync_value(&self) -> String;
        async fn async_value(&self) -> String;
    }

    #[derive(SimpleObject)]
    #[graphql(implements(Foo))]
    struct FooValue;

    #[async_trait]
    impl Foo for FooValue {
        fn sync_value(&self) -> String {
            "sync_value".to_string()
        }

        async fn async_value(&self) -> String {
            "async_value".to_string()
        }
    }

    #[derive(ResolvedObject)]
    #[graphql(root)]
    struct Query;

    #[ResolvedObjectFields]
    impl Query {
        async fn foo(&self) -> Instance<'static, dyn Foo> {
            Instance::new_owned(FooValue)
        }
    }

    #[derive(App)]
    struct App(Query, FooValue);

    let schema = App::create_schema().finish().unwrap();
    let sdl = schema.sdl();

    insta::assert_snapshot!(normalize_schema(&sdl), @r#"
    interface Foo {
      syncValue: String!
      asyncValue: String!
    }

    type FooValue implements Foo {
      syncValue: String!
      asyncValue: String!
    }

    type Query {
      foo: Foo!
    }

    "Directs the executor to include this field or fragment only when the `if` argument is true."
    directive @include(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

    "Directs the executor to skip this field or fragment when the `if` argument is true."
    directive @skip(if: Boolean!) on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT

    schema {
      query: Query
    }
    "#);

    let query = r#"

        query {
            foo {
                syncValue
                asyncValue
            }
        }

    "#;

    let root = Query;
    let req = dynamic_graphql::Request::new(query).root_value(FieldValue::owned_any(root));
    let res = schema.execute(req).await;

    assert_eq!(
        res.data.into_json().unwrap(),
        serde_json::json!({
            "foo": {
                "syncValue": "sync_value",
                "asyncValue": "async_value"
            }
        })
    );
}