dynamic-graphql-derive 0.10.2

Dynamic GraphQL schema macro
Documentation
use darling::FromDeriveInput;
use prettier_please::unparse;
use unindent::Unindent;

use super::*;
use crate::FromItemTrait;
use crate::args::one_of_input::OneOfInput;
use crate::utils::impl_block::FromItemImpl;

fn pretty_expand(tokens: impl quote::ToTokens) -> String {
    let tokens = tokens.into_token_stream();
    let file: syn::File = syn::parse2(tokens).unwrap();
    unparse(&file)
}

fn derive<D: FromDeriveInput>(input: impl AsRef<str>) -> D {
    let input = input.as_ref();
    let file: syn::DeriveInput = syn::parse_str(input).unwrap();
    D::from_derive_input(&file).unwrap()
}

fn pretty_derive<D: FromDeriveInput + quote::ToTokens>(input: impl AsRef<str>) -> String {
    let input = input.as_ref().unindent();
    let derived = derive::<D>(&input);
    let pretty = pretty_expand(&derived);
    format!("{}\n{}", input, pretty)
}

fn expand_item_impl<D: FromItemImpl>(input: impl AsRef<str>) -> D {
    let input = input.as_ref();
    let mut file: syn::ItemImpl = syn::parse_str(input).unwrap();
    D::from_item_impl(&mut file).unwrap()
}

fn pretty_expand_item_impl<D: FromItemImpl + quote::ToTokens>(input: impl AsRef<str>) -> String {
    let expanded = expand_item_impl::<D>(&input);
    let pretty = pretty_expand(&expanded);
    format!("{}\n{}", input.as_ref().unindent(), pretty)
}

fn expand_item_trait<D: FromItemTrait>(input: impl AsRef<str>) -> D {
    let input = input.as_ref();
    let mut file: syn::ItemTrait = syn::parse_str(input).unwrap();
    D::from_item_trait(&mut file).unwrap()
}

fn pretty_expand_item_trait<D: FromItemTrait + quote::ToTokens>(input: impl AsRef<str>) -> String {
    let expanded = expand_item_trait::<D>(&input);
    let pretty = pretty_expand(&expanded);
    format!("{}\n{}", input.as_ref().unindent(), pretty)
}

fn md(outputs: &[&str]) -> String {
    format!("```rust\n{}\n```", outputs.join("\n\n"))
}

#[test]
fn test_app() {
    let input = r#"
        struct App(QueryRoot, PostApp);
    "#;

    let pretty = pretty_derive::<App>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_expand_object() {
    let input1 = r#"
        struct ExampleQuery<'a>(&'a Query);
    "#;

    let input2 = r#"
    impl ExampleQuery<'_> {
        fn the_example(&self) -> Example {
            Example {
                field: "field".to_string(),
            }
        }
    }
    "#;

    let pretty1 = pretty_derive::<ExpandObject>(input1);
    let pretty2 = pretty_expand_item_impl::<ExpandObjectFields>(input2);
    let output = md(&[&pretty1, &pretty2]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_enum() {
    let input = r#"
        enum Example {
            Foo,
            Bar,
        }
    "#;
    let pretty = pretty_derive::<Enum>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_input_object() {
    let input = r#"
        struct ExampleInput {
            pub string: String,
        }
    "#;

    let pretty = pretty_derive::<InputObject>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_one_of_input() {
    let input = r#"
        enum ExampleInput {
            Str(String),
            Int(u16),
        }
    "#;

    let pretty = pretty_derive::<OneOfInput>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_interface() {
    let input = r#"
        trait Node {
            fn id(&self) -> String;
        }

    "#;

    let pretty = pretty_expand_item_trait::<Interface>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_mutation() {
    let input1 = r#"
        struct MutationRoot;
    "#;

    let input2 = r#"
        struct MyMutation(MutationRoot);
    "#;
    let input3 = r#"
        impl MyMutation {
            fn the_example() -> String {
                "field".to_string()
            }
        }
    "#;

    let pretty1 = pretty_derive::<MutationRoot>(input1);
    let pretty2 = pretty_derive::<Mutation>(input2);
    let pretty3 = pretty_expand_item_impl::<MutationFields>(input3);
    let output = md(&[&pretty1, &pretty2, &pretty3]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_resoled_object() {
    let input1 = r#"
        struct Example {
            pub field: String,
        }
    "#;

    let input2 = r#"
        impl Example {
            fn field(&self) -> &str {
                &self.field
            }
        }
    "#;

    let pretty1 = pretty_derive::<ResolvedObject>(input1);
    let pretty2 = pretty_expand_item_impl::<ResolvedObjectFields>(input2);
    let output = md(&[&pretty1, &pretty2]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_scalar() {
    let input = r#"
        struct Example;
    "#;

    let pretty = pretty_derive::<Scalar>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_simple_object() {
    let input = r#"
        struct Example {
            pub field: String,
        }
    "#;

    let pretty = pretty_derive::<SimpleObject>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}

#[test]
fn test_union() {
    let input = r#"
        enum Animal {
            Dog(Dog),
            Cat(Cat),
        }
    "#;

    let pretty = pretty_derive::<Union>(input);
    let output = md(&[&pretty]);
    insta::assert_snapshot!(output);
}