Add object macro tests, fix minor issues
This commit is contained in:
parent
88c967f804
commit
f3469dd270
4 changed files with 303 additions and 1 deletions
|
@ -59,6 +59,10 @@ macro_rules! __graphql__build_field_matches {
|
||||||
__graphql__build_field_matches!($resolveargs, $acc, $( $rest )*);
|
__graphql__build_field_matches!($resolveargs, $acc, $( $rest )*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
( $resolveargs:tt, $acc:tt, , $( $rest:tt )*) => {
|
||||||
|
__graphql__build_field_matches!($resolveargs, $acc, $( $rest )*);
|
||||||
|
};
|
||||||
|
|
||||||
(
|
(
|
||||||
($outname:tt, $selfvar:ident, $fieldvar:ident, $argsvar:ident, $executorvar:ident),
|
($outname:tt, $selfvar:ident, $fieldvar:ident, $argsvar:ident, $executorvar:ident),
|
||||||
( $( ( $name:ident; ( $($args:tt)* ); $t:ty; $body:block ) )* ),
|
( $( ( $name:ident; ( $($args:tt)* ); $t:ty; $body:block ) )* ),
|
||||||
|
|
|
@ -333,10 +333,18 @@ macro_rules! graphql_object {
|
||||||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*)
|
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// eat commas
|
||||||
|
(
|
||||||
|
@gather_object_meta,
|
||||||
|
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr, , $( $rest:tt )*
|
||||||
|
) => {
|
||||||
|
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*)
|
||||||
|
};
|
||||||
|
|
||||||
// base case
|
// base case
|
||||||
(
|
(
|
||||||
@gather_object_meta,
|
@gather_object_meta,
|
||||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr, $(,)*
|
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||||
) => {};
|
) => {};
|
||||||
|
|
||||||
( @assign_interfaces, $reg:expr, $tgt:expr, [ $($t:ty,)* ] ) => {
|
( @assign_interfaces, $reg:expr, $tgt:expr, [ $($t:ty,)* ] ) => {
|
||||||
|
@ -418,4 +426,13 @@ macro_rules! graphql_object {
|
||||||
graphql_object!(
|
graphql_object!(
|
||||||
( ); $name; $ctxt; $outname; $mainself; $( $items )*);
|
( ); $name; $ctxt; $outname; $mainself; $( $items )*);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(
|
||||||
|
$name:ty : $ctxt:ty | &$mainself:ident | {
|
||||||
|
$( $items:tt )*
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
graphql_object!(
|
||||||
|
( ); $name; $ctxt; (stringify!($name)); $mainself; $( $items )*);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,3 +3,4 @@ mod scalar;
|
||||||
#[allow(dead_code)] mod input_object;
|
#[allow(dead_code)] mod input_object;
|
||||||
mod args;
|
mod args;
|
||||||
mod field;
|
mod field;
|
||||||
|
mod object;
|
||||||
|
|
280
src/macros/tests/object.rs
Normal file
280
src/macros/tests/object.rs
Normal file
|
@ -0,0 +1,280 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use ast::InputValue;
|
||||||
|
use executor::FieldResult;
|
||||||
|
use value::Value;
|
||||||
|
use schema::model::RootNode;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Syntax to validate:
|
||||||
|
|
||||||
|
* Order of items: fields, description, interfaces
|
||||||
|
* Optional Generics/lifetimes
|
||||||
|
* Custom name vs. default name
|
||||||
|
* Optional commas between items
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct Interface;
|
||||||
|
|
||||||
|
struct DefaultName;
|
||||||
|
|
||||||
|
struct WithLifetime;
|
||||||
|
struct WithGenerics;
|
||||||
|
|
||||||
|
struct DescriptionFirst;
|
||||||
|
struct FieldsFirst;
|
||||||
|
struct InterfacesFirst;
|
||||||
|
|
||||||
|
struct CommasWithTrailing;
|
||||||
|
struct CommasOnMeta;
|
||||||
|
|
||||||
|
struct Root;
|
||||||
|
|
||||||
|
graphql_object!(DefaultName: () |&self| {
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
graphql_object!(<'a> &'a WithLifetime: () as "WithLifetime" |&self| {
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(<CtxT> WithGenerics: CtxT as "WithGenerics" |&self| {
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_interface!(Interface: () as "Interface" |&self| {
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
|
||||||
|
instance_resolvers: |_| [
|
||||||
|
Some(DescriptionFirst {}),
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(DescriptionFirst: () as "DescriptionFirst" |&self| {
|
||||||
|
description: "A description"
|
||||||
|
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
|
||||||
|
interfaces: [Interface]
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(FieldsFirst: () as "FieldsFirst" |&self| {
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
|
||||||
|
description: "A description"
|
||||||
|
|
||||||
|
interfaces: [Interface]
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(InterfacesFirst: () as "InterfacesFirst" |&self| {
|
||||||
|
interfaces: [Interface]
|
||||||
|
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
|
||||||
|
description: "A description"
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(CommasWithTrailing: () as "CommasWithTrailing" |&self| {
|
||||||
|
interfaces: [Interface],
|
||||||
|
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) },
|
||||||
|
|
||||||
|
description: "A description",
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
graphql_object!(CommasOnMeta: () as "CommasOnMeta" |&self| {
|
||||||
|
interfaces: [Interface],
|
||||||
|
description: "A description",
|
||||||
|
|
||||||
|
field simple() -> FieldResult<i64> { Ok(0) }
|
||||||
|
});
|
||||||
|
|
||||||
|
graphql_object!(Root: () as "Root" |&self| {
|
||||||
|
field default_name() -> FieldResult<DefaultName> { Ok(DefaultName {}) }
|
||||||
|
|
||||||
|
field with_lifetime() -> FieldResult<&WithLifetime> { Err("Nope".to_owned()) }
|
||||||
|
field with_generics() -> FieldResult<WithGenerics> { Ok(WithGenerics {}) }
|
||||||
|
|
||||||
|
field description_first() -> FieldResult<DescriptionFirst> { Ok(DescriptionFirst {}) }
|
||||||
|
field fields_first() -> FieldResult<FieldsFirst> { Ok(FieldsFirst {}) }
|
||||||
|
field interfaces_first() -> FieldResult<InterfacesFirst> { Ok(InterfacesFirst {}) }
|
||||||
|
|
||||||
|
field commas_with_trailing() -> FieldResult<CommasWithTrailing> { Ok(CommasWithTrailing {}) }
|
||||||
|
field commas_on_meta() -> FieldResult<CommasOnMeta> { Ok(CommasOnMeta {}) }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
fn run_type_info_query<F>(type_name: &str, f: F)
|
||||||
|
where F: Fn(&HashMap<String, Value>, &Vec<Value>) -> ()
|
||||||
|
{
|
||||||
|
let doc = r#"
|
||||||
|
query ($typeName: String!) {
|
||||||
|
__type(name: $typeName) {
|
||||||
|
name
|
||||||
|
description
|
||||||
|
fields(includeDeprecated: true) {
|
||||||
|
name
|
||||||
|
}
|
||||||
|
interfaces {
|
||||||
|
name
|
||||||
|
kind
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let schema = RootNode::new(Root {}, ());
|
||||||
|
let vars = vec![
|
||||||
|
("typeName".to_owned(), InputValue::string(type_name)),
|
||||||
|
].into_iter().collect();
|
||||||
|
|
||||||
|
let (result, errs) = ::execute(doc, None, &schema, &vars, &())
|
||||||
|
.expect("Execution failed");
|
||||||
|
|
||||||
|
assert_eq!(errs, []);
|
||||||
|
|
||||||
|
println!("Result: {:?}", result);
|
||||||
|
|
||||||
|
let type_info = result
|
||||||
|
.as_object_value().expect("Result is not an object")
|
||||||
|
.get("__type").expect("__type field missing")
|
||||||
|
.as_object_value().expect("__type field not an object value");
|
||||||
|
|
||||||
|
let fields = type_info
|
||||||
|
.get("fields").expect("fields field missing")
|
||||||
|
.as_list_value().expect("fields field not a list value");
|
||||||
|
|
||||||
|
f(type_info, fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_default_name() {
|
||||||
|
run_type_info_query("DefaultName", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("DefaultName")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_with_lifetime() {
|
||||||
|
run_type_info_query("WithLifetime", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("WithLifetime")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_with_generics() {
|
||||||
|
run_type_info_query("WithGenerics", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("WithGenerics")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::null()));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_description_first() {
|
||||||
|
run_type_info_query("DescriptionFirst", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::string("A description")));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![
|
||||||
|
Value::object(vec![
|
||||||
|
("name", Value::string("Interface")),
|
||||||
|
("kind", Value::string("INTERFACE")),
|
||||||
|
].into_iter().collect()),
|
||||||
|
])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_fields_first() {
|
||||||
|
run_type_info_query("FieldsFirst", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::string("A description")));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![
|
||||||
|
Value::object(vec![
|
||||||
|
("name", Value::string("Interface")),
|
||||||
|
("kind", Value::string("INTERFACE")),
|
||||||
|
].into_iter().collect()),
|
||||||
|
])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_interfaces_first() {
|
||||||
|
run_type_info_query("InterfacesFirst", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::string("A description")));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![
|
||||||
|
Value::object(vec![
|
||||||
|
("name", Value::string("Interface")),
|
||||||
|
("kind", Value::string("INTERFACE")),
|
||||||
|
].into_iter().collect()),
|
||||||
|
])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_commas_with_trailing() {
|
||||||
|
run_type_info_query("CommasWithTrailing", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("CommasWithTrailing")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::string("A description")));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![
|
||||||
|
Value::object(vec![
|
||||||
|
("name", Value::string("Interface")),
|
||||||
|
("kind", Value::string("INTERFACE")),
|
||||||
|
].into_iter().collect()),
|
||||||
|
])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn introspect_commas_on_meta() {
|
||||||
|
run_type_info_query("CommasOnMeta", |object, fields| {
|
||||||
|
assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta")));
|
||||||
|
assert_eq!(object.get("description"), Some(&Value::string("A description")));
|
||||||
|
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![
|
||||||
|
Value::object(vec![
|
||||||
|
("name", Value::string("Interface")),
|
||||||
|
("kind", Value::string("INTERFACE")),
|
||||||
|
].into_iter().collect()),
|
||||||
|
])));
|
||||||
|
|
||||||
|
assert!(fields.contains(&Value::object(vec![
|
||||||
|
("name", Value::string("simple")),
|
||||||
|
].into_iter().collect())));
|
||||||
|
});
|
||||||
|
}
|
Loading…
Reference in a new issue