Add field deprecation support and tests
This commit is contained in:
parent
6cc124d075
commit
1295e42c58
5 changed files with 330 additions and 11 deletions
|
@ -1,6 +1,31 @@
|
|||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! __graphql__build_field_matches {
|
||||
// field deprecated <reason> <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
$resolveargs:tt,
|
||||
( $( $acc:tt )* ),
|
||||
field deprecated $_reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )*
|
||||
) => {
|
||||
__graphql__build_field_matches!(
|
||||
$resolveargs,
|
||||
(($name; $args; $t; $body) $( $acc )*),
|
||||
$( $rest )*);
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> { ... }
|
||||
(
|
||||
$resolveargs:tt,
|
||||
( $( $acc:tt )* ),
|
||||
field deprecated $_reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
) => {
|
||||
__graphql__build_field_matches!(
|
||||
$resolveargs,
|
||||
(($name; $args; $t; $body) $( $acc )*),
|
||||
$( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
$resolveargs:tt,
|
||||
( $( $acc:tt )* ), field $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )*
|
||||
|
@ -11,6 +36,7 @@ macro_rules! __graphql__build_field_matches {
|
|||
$( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> { ... }
|
||||
(
|
||||
$resolveargs:tt,
|
||||
( $( $acc:tt )* ), field $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
|
|
|
@ -88,6 +88,44 @@ macro_rules! graphql_interface {
|
|||
( @as_item, $i:item) => { $i };
|
||||
( @as_expr, $e:expr) => { $e };
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )*
|
||||
) => {
|
||||
$acc.push(__graphql__args!(
|
||||
@apply_args,
|
||||
$reg,
|
||||
$reg.field_inside_result(
|
||||
&$crate::to_snake_case(stringify!($name)),
|
||||
Err("dummy".to_owned()) as $t)
|
||||
.description($desc)
|
||||
.deprecated($reason),
|
||||
$args));
|
||||
|
||||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*);
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> { ... }
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
) => {
|
||||
$acc.push(__graphql__args!(
|
||||
@apply_args,
|
||||
$reg,
|
||||
$reg.field_inside_result(
|
||||
&$crate::to_snake_case(stringify!($name)),
|
||||
Err("dummy".to_owned()) as $t)
|
||||
.deprecated($reason),
|
||||
$args));
|
||||
|
||||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
|
@ -105,6 +143,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> { ... }
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
|
@ -121,6 +160,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*);
|
||||
};
|
||||
|
||||
// description: <description>
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
|
@ -131,16 +171,36 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*)
|
||||
};
|
||||
|
||||
// instance_resolvers: | <ctxtvar> | [...]
|
||||
(
|
||||
@gather_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr,
|
||||
instance_resolvers: | $execvar:pat | $resolvers:tt $( $rest:tt )*
|
||||
instance_resolvers: | $ctxtvar:pat | $resolvers:tt $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@gather_meta, $reg, $acc, $descr, $( $rest )*)
|
||||
};
|
||||
|
||||
( @gather_meta, $reg:expr, $acc:expr, $descr:expr, $(,)* ) => {};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $descr:tt $body:block $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> { ... }
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt,
|
||||
|
@ -149,6 +209,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> { ... }
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt,
|
||||
|
@ -157,6 +218,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// description: <description>
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt, description : $value:tt $( $rest:tt )*
|
||||
|
@ -164,13 +226,25 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@resolve_into_type,
|
||||
$buildargs:tt, interfaces : $value:tt $( $rest:tt )*
|
||||
@concrete_type_name,
|
||||
$buildargs:tt,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $descr:tt $body:block $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@resolve_into_type, $buildargs, $( $rest )*)
|
||||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> { ... }
|
||||
(
|
||||
@concrete_type_name,
|
||||
$buildargs:tt,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@concrete_type_name,
|
||||
$buildargs:tt,
|
||||
|
@ -179,6 +253,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> { ... }
|
||||
(
|
||||
@concrete_type_name,
|
||||
$buildargs:tt,
|
||||
|
@ -187,6 +262,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// description: <description>
|
||||
(
|
||||
@concrete_type_name,
|
||||
$buildargs:tt, description : $value:tt $( $rest:tt )*
|
||||
|
@ -194,13 +270,7 @@ macro_rules! graphql_interface {
|
|||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
(
|
||||
@concrete_type_name,
|
||||
$buildargs:tt, interfaces : $value:tt $( $rest:tt )*
|
||||
) => {
|
||||
graphql_interface!(@concrete_type_name, $buildargs, $( $rest )*)
|
||||
};
|
||||
|
||||
// instance_resolvers: | <ctxtvar> | [...]
|
||||
(
|
||||
@concrete_type_name,
|
||||
($outname:tt, $ctxtarg:ident, $ctxttype:ty),
|
||||
|
@ -225,6 +295,7 @@ macro_rules! graphql_interface {
|
|||
()
|
||||
};
|
||||
|
||||
// instance_resolvers: | <ctxtvar> |
|
||||
(
|
||||
@resolve_into_type,
|
||||
($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty),
|
||||
|
|
|
@ -239,6 +239,44 @@ macro_rules! graphql_object {
|
|||
( @as_item, $i:item) => { $i };
|
||||
( @as_expr, $e:expr) => { $e };
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )*
|
||||
) => {
|
||||
$acc.push(__graphql__args!(
|
||||
@apply_args,
|
||||
$reg,
|
||||
$reg.field_inside_result(
|
||||
&$crate::to_snake_case(stringify!($name)),
|
||||
Err("dummy".to_owned()) as $t)
|
||||
.description($desc)
|
||||
.deprecated($reason),
|
||||
$args));
|
||||
|
||||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*);
|
||||
};
|
||||
|
||||
// field deprecated <reason> <name>(...) -> <type> { ... }
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
field deprecated $reason:tt $name:ident $args:tt -> $t:ty $body:block $( $rest:tt )*
|
||||
) => {
|
||||
$acc.push(__graphql__args!(
|
||||
@apply_args,
|
||||
$reg,
|
||||
$reg.field_inside_result(
|
||||
&$crate::to_snake_case(stringify!($name)),
|
||||
Err("dummy".to_owned()) as $t)
|
||||
.deprecated($reason),
|
||||
$args));
|
||||
|
||||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> as <description> { ... }
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
|
@ -256,6 +294,7 @@ macro_rules! graphql_object {
|
|||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*);
|
||||
};
|
||||
|
||||
// field <name>(...) -> <type> { ... }
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
|
@ -272,6 +311,7 @@ macro_rules! graphql_object {
|
|||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*);
|
||||
};
|
||||
|
||||
// description: <description>
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
|
@ -282,6 +322,7 @@ macro_rules! graphql_object {
|
|||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*)
|
||||
};
|
||||
|
||||
// interfaces: [...]
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr,
|
||||
|
@ -292,6 +333,7 @@ macro_rules! graphql_object {
|
|||
graphql_object!(@gather_object_meta, $reg, $acc, $descr, $ifaces, $( $rest )*)
|
||||
};
|
||||
|
||||
// base case
|
||||
(
|
||||
@gather_object_meta,
|
||||
$reg:expr, $acc:expr, $descr:expr, $ifaces:expr, $(,)*
|
||||
|
|
179
src/macros/tests/field.rs
Normal file
179
src/macros/tests/field.rs
Normal file
|
@ -0,0 +1,179 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use executor::FieldResult;
|
||||
use value::Value;
|
||||
use ast::InputValue;
|
||||
use schema::model::RootNode;
|
||||
|
||||
struct Interface;
|
||||
struct Root;
|
||||
|
||||
/*
|
||||
|
||||
Syntax to validate:
|
||||
|
||||
* Object vs. interface
|
||||
* Description vs. no description
|
||||
* Deprecated vs. not deprecated
|
||||
|
||||
*/
|
||||
|
||||
graphql_object!(Root: () as "Root" |&self| {
|
||||
field simple() -> FieldResult<i64> { Ok(0) }
|
||||
|
||||
field description() -> FieldResult<i64> as "Field description" { Ok(0) }
|
||||
|
||||
field deprecated "Deprecation reason"
|
||||
deprecated() -> FieldResult<i64> { Ok(0) }
|
||||
|
||||
field deprecated "Deprecation reason"
|
||||
deprecated_descr() -> FieldResult<i64> as "Field description" { Ok(0) }
|
||||
|
||||
interfaces: [Interface]
|
||||
});
|
||||
|
||||
graphql_interface!(Interface: () as "Interface" |&self| {
|
||||
field simple() -> FieldResult<i64> { Ok(0) }
|
||||
|
||||
field description() -> FieldResult<i64> as "Field description" { Ok(0) }
|
||||
|
||||
field deprecated "Deprecation reason"
|
||||
deprecated() -> FieldResult<i64> { Ok(0) }
|
||||
|
||||
field deprecated "Deprecation reason"
|
||||
deprecated_descr() -> FieldResult<i64> as "Field description" { Ok(0) }
|
||||
|
||||
instance_resolvers: |&_| [
|
||||
Some(Root {}),
|
||||
]
|
||||
});
|
||||
|
||||
fn run_field_info_query<F>(type_name: &str, field_name: &str, f: F)
|
||||
where F: Fn(&HashMap<String, Value>) -> ()
|
||||
{
|
||||
let doc = r#"
|
||||
query ($typeName: String!) {
|
||||
__type(name: $typeName) {
|
||||
fields(includeDeprecated: true) {
|
||||
name
|
||||
description
|
||||
isDeprecated
|
||||
deprecationReason
|
||||
}
|
||||
}
|
||||
}
|
||||
"#;
|
||||
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 not a list");
|
||||
|
||||
let field = fields
|
||||
.into_iter().filter(
|
||||
|f| f.as_object_value().expect("Field not an object")
|
||||
.get("name").expect("name field missing from field")
|
||||
.as_string_value().expect("name is not a string")
|
||||
== field_name)
|
||||
.next().expect("Field not found")
|
||||
.as_object_value().expect("Field is not an object");
|
||||
|
||||
println!("Field: {:?}", field);
|
||||
|
||||
f(field);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_simple() {
|
||||
run_field_info_query("Root", "simple", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("simple")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_simple() {
|
||||
run_field_info_query("Interface", "simple", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("simple")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_description() {
|
||||
run_field_info_query("Root", "description", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("description")));
|
||||
assert_eq!(field.get("description"), Some(&Value::string("Field description")));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_description() {
|
||||
run_field_info_query("Interface", "description", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("description")));
|
||||
assert_eq!(field.get("description"), Some(&Value::string("Field description")));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_deprecated() {
|
||||
run_field_info_query("Root", "deprecated", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_deprecated() {
|
||||
run_field_info_query("Interface", "deprecated", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
|
||||
assert_eq!(field.get("description"), Some(&Value::null()));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_object_field_deprecated_descr() {
|
||||
run_field_info_query("Root", "deprecatedDescr", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(field.get("description"), Some(&Value::string("Field description")));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason")));
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn introspect_interface_field_deprecated_descr() {
|
||||
run_field_info_query("Interface", "deprecatedDescr", |field| {
|
||||
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
|
||||
assert_eq!(field.get("description"), Some(&Value::string("Field description")));
|
||||
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
|
||||
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason")));
|
||||
});
|
||||
}
|
|
@ -2,3 +2,4 @@ mod enums;
|
|||
mod scalar;
|
||||
#[allow(dead_code)] mod input_object;
|
||||
mod args;
|
||||
mod field;
|
||||
|
|
Loading…
Reference in a new issue