Add support for using doc comments as descriptions
Fixes https://github.com/graphql-rust/juniper/issues/194.
This commit is contained in:
parent
e84167286b
commit
1fd5c10327
10 changed files with 337 additions and 6 deletions
changelog
juniper_codegen/src
juniper_tests
|
@ -1,6 +1,7 @@
|
||||||
# [master] yyyy-mm-dd
|
# [master] yyyy-mm-dd
|
||||||
|
|
||||||
## Changes
|
## Changes
|
||||||
|
|
||||||
* Changed serialization of `NaiveDate` when using the optional `chronos` support.
|
* Changed serialization of `NaiveDate` when using the optional `chronos` support.
|
||||||
|
|
||||||
**Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application.
|
**Note:** while this is not a Rust breaking change, if you relied on the serialization format (perhaps by storing serialized data in a database or making asumptions in your client code written in another language) it could be a breaking change for your application.
|
||||||
|
@ -8,7 +9,7 @@
|
||||||
[#151](https://github.com/graphql-rust/juniper/pull/151)
|
[#151](https://github.com/graphql-rust/juniper/pull/151)
|
||||||
|
|
||||||
* The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives will reject
|
* The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives will reject
|
||||||
invalid [names](http://facebook.github.io/graphql/October2016/#Name) at compile time.
|
invalid [names](http://facebook.github.io/graphql/October2016/#Name) at compile time.
|
||||||
|
|
||||||
[#170](https://github.com/graphql-rust/juniper/pull/170)
|
[#170](https://github.com/graphql-rust/juniper/pull/170)
|
||||||
|
|
||||||
|
@ -19,4 +20,11 @@
|
||||||
fractional part could not be decoded (because they are represented without
|
fractional part could not be decoded (because they are represented without
|
||||||
a decimal part `.0`).
|
a decimal part `.0`).
|
||||||
|
|
||||||
[#179](https://github.com/graphql-rust/juniper/pull/179)
|
[#179](https://github.com/graphql-rust/juniper/pull/179)
|
||||||
|
|
||||||
|
* The `GraphQLObject`, `GraphQLInputObject`, and `GraphQLEnum` custom derives
|
||||||
|
now parse doc strings and use them as descriptions. This behavior can be
|
||||||
|
overridden by using an explicit GraphQL `description` annotation such as
|
||||||
|
`#[graphql(description = "my description")]`.
|
||||||
|
|
||||||
|
[#194](https://github.com/graphql-rust/juniper/issues/194)
|
||||||
|
|
|
@ -28,6 +28,9 @@ impl EnumAttrs {
|
||||||
internal: false,
|
internal: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&input.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&input.attrs) {
|
if let Some(items) = get_graphl_attr(&input.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
@ -74,6 +77,9 @@ impl EnumVariantAttrs {
|
||||||
fn from_input(variant: &Variant) -> EnumVariantAttrs {
|
fn from_input(variant: &Variant) -> EnumVariantAttrs {
|
||||||
let mut res = EnumVariantAttrs::default();
|
let mut res = EnumVariantAttrs::default();
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&variant.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
|
|
@ -25,6 +25,9 @@ impl ObjAttrs {
|
||||||
fn from_input(input: &DeriveInput) -> ObjAttrs {
|
fn from_input(input: &DeriveInput) -> ObjAttrs {
|
||||||
let mut res = ObjAttrs::default();
|
let mut res = ObjAttrs::default();
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&input.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&input.attrs) {
|
if let Some(items) = get_graphl_attr(&input.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
@ -72,6 +75,9 @@ impl ObjFieldAttrs {
|
||||||
fn from_input(variant: &Field) -> ObjFieldAttrs {
|
fn from_input(variant: &Field) -> ObjFieldAttrs {
|
||||||
let mut res = ObjFieldAttrs::default();
|
let mut res = ObjFieldAttrs::default();
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&variant.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
|
|
@ -19,6 +19,9 @@ impl ObjAttrs {
|
||||||
fn from_input(input: &DeriveInput) -> ObjAttrs {
|
fn from_input(input: &DeriveInput) -> ObjAttrs {
|
||||||
let mut res = ObjAttrs::default();
|
let mut res = ObjAttrs::default();
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&input.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&input.attrs) {
|
if let Some(items) = get_graphl_attr(&input.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
@ -56,6 +59,9 @@ impl ObjFieldAttrs {
|
||||||
fn from_input(variant: &Field) -> ObjFieldAttrs {
|
fn from_input(variant: &Field) -> ObjFieldAttrs {
|
||||||
let mut res = ObjFieldAttrs::default();
|
let mut res = ObjFieldAttrs::default();
|
||||||
|
|
||||||
|
// Check doc comments for description.
|
||||||
|
res.description = get_doc_comment(&variant.attrs);
|
||||||
|
|
||||||
// Check attributes for name and description.
|
// Check attributes for name and description.
|
||||||
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
if let Some(items) = get_graphl_attr(&variant.attrs) {
|
||||||
for item in items {
|
for item in items {
|
||||||
|
|
|
@ -1,11 +1,67 @@
|
||||||
use syn::{
|
use syn::{
|
||||||
Attribute,
|
Attribute,
|
||||||
Meta,
|
Meta,
|
||||||
|
MetaNameValue,
|
||||||
NestedMeta,
|
NestedMeta,
|
||||||
Lit,
|
Lit,
|
||||||
};
|
};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
|
||||||
|
// Gets doc comment.
|
||||||
|
pub fn get_doc_comment(attrs: &Vec<Attribute>) -> Option<String> {
|
||||||
|
if let Some(items) = get_doc_attr(attrs) {
|
||||||
|
if let Some(doc_strings) = get_doc_strings(&items) {
|
||||||
|
return Some(join_doc_strings(&doc_strings));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Concatenates doc strings into one string.
|
||||||
|
fn join_doc_strings(docs: &Vec<String>) -> String {
|
||||||
|
let s: String = docs.iter()
|
||||||
|
// Convert empty comments to newlines.
|
||||||
|
.map(|x| if x == "" { "\n".to_string() } else { x.clone() })
|
||||||
|
.collect::<Vec<String>>()
|
||||||
|
.join(" ");
|
||||||
|
// Clean up spacing on empty lines.
|
||||||
|
s.replace(" \n ", "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets doc strings from doc comment attributes.
|
||||||
|
fn get_doc_strings(items: &Vec<MetaNameValue>) -> Option<Vec<String>> {
|
||||||
|
let mut docs = Vec::new();
|
||||||
|
for item in items {
|
||||||
|
match item.lit {
|
||||||
|
Lit::Str(ref strlit) => {
|
||||||
|
docs.push(strlit.value().trim().to_string());
|
||||||
|
},
|
||||||
|
_ => panic!("doc attributes only have string literal"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !docs.is_empty() {
|
||||||
|
return Some(docs);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets doc comment attributes.
|
||||||
|
fn get_doc_attr(attrs: &Vec<Attribute>) -> Option<Vec<MetaNameValue>> {
|
||||||
|
let mut docs = Vec::new();
|
||||||
|
for attr in attrs {
|
||||||
|
match attr.interpret_meta() {
|
||||||
|
Some(Meta::NameValue(ref nv)) if nv.ident == "doc" => {
|
||||||
|
docs.push(nv.clone())
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !docs.is_empty() {
|
||||||
|
return Some(docs);
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
// Get the nested items of a a #[graphql(...)] attribute.
|
// Get the nested items of a a #[graphql(...)] attribute.
|
||||||
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<Vec<NestedMeta>> {
|
pub fn get_graphl_attr(attrs: &Vec<Attribute>) -> Option<Vec<NestedMeta>> {
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
|
@ -124,12 +180,12 @@ pub fn is_valid_name(field_name: &str) -> bool {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_is_valid_name(){
|
fn test_is_valid_name(){
|
||||||
assert_eq!(is_valid_name("yesItIs"), true);
|
assert_eq!(is_valid_name("yesItIs"), true);
|
||||||
assert_eq!(is_valid_name("NoitIsnt"), true);
|
assert_eq!(is_valid_name("NoitIsnt"), true);
|
||||||
assert_eq!(is_valid_name("iso6301"), true);
|
assert_eq!(is_valid_name("iso6301"), true);
|
||||||
assert_eq!(is_valid_name("thisIsATest"), true);
|
assert_eq!(is_valid_name("thisIsATest"), true);
|
||||||
assert_eq!(is_valid_name("i6Op"), true);
|
assert_eq!(is_valid_name("i6Op"), true);
|
||||||
assert_eq!(is_valid_name("i!"), false);
|
assert_eq!(is_valid_name("i!"), false);
|
||||||
assert_eq!(is_valid_name(""), false);
|
assert_eq!(is_valid_name(""), false);
|
||||||
assert_eq!(is_valid_name("aTest"), true);
|
assert_eq!(is_valid_name("aTest"), true);
|
||||||
assert_eq!(is_valid_name("__Atest90"), true);
|
assert_eq!(is_valid_name("__Atest90"), true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ serde_json = { version = "1" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
fnv = "1.0.3"
|
fnv = "1.0.3"
|
||||||
|
indexmap = "1.0"
|
||||||
|
|
||||||
[[test]]
|
[[test]]
|
||||||
name = "integration_tests"
|
name = "integration_tests"
|
||||||
|
|
|
@ -11,6 +11,33 @@ enum SomeEnum {
|
||||||
#[graphql(name = "FULL", description = "field descr", deprecated = "depr")] Full,
|
#[graphql(name = "FULL", description = "field descr", deprecated = "depr")] Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enum doc.
|
||||||
|
#[derive(GraphQLEnum)]
|
||||||
|
enum DocEnum {
|
||||||
|
/// Variant doc.
|
||||||
|
Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Doc 1.
|
||||||
|
/// Doc 2.
|
||||||
|
///
|
||||||
|
/// Doc 4.
|
||||||
|
#[derive(GraphQLEnum, Debug, PartialEq)]
|
||||||
|
enum MultiDocEnum {
|
||||||
|
/// Variant 1.
|
||||||
|
/// Variant 2.
|
||||||
|
Foo,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[derive(GraphQLEnum, Debug, PartialEq)]
|
||||||
|
#[graphql(description = "enum override")]
|
||||||
|
enum OverrideDocEnum {
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[graphql(description = "variant override")]
|
||||||
|
Foo,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derived_enum() {
|
fn test_derived_enum() {
|
||||||
// Ensure that rename works.
|
// Ensure that rename works.
|
||||||
|
@ -43,3 +70,25 @@ fn test_derived_enum() {
|
||||||
Some(SomeEnum::Full)
|
Some(SomeEnum::Full)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = DocEnum::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Enum doc.".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multi_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = MultiDocEnum::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Doc 1. Doc 2.\nDoc 4.".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment_override() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = OverrideDocEnum::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"enum override".to_string()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,33 @@ struct Input {
|
||||||
#[graphql(default)] other: Option<bool>,
|
#[graphql(default)] other: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Object comment.
|
||||||
|
#[derive(GraphQLInputObject, Debug, PartialEq)]
|
||||||
|
struct DocComment {
|
||||||
|
/// Field comment.
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Doc 1.
|
||||||
|
/// Doc 2.
|
||||||
|
///
|
||||||
|
/// Doc 4.
|
||||||
|
#[derive(GraphQLInputObject, Debug, PartialEq)]
|
||||||
|
struct MultiDocComment {
|
||||||
|
/// Field 1.
|
||||||
|
/// Field 2.
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[derive(GraphQLInputObject, Debug, PartialEq)]
|
||||||
|
#[graphql(description = "obj override")]
|
||||||
|
struct OverrideDocComment {
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[graphql(description = "field override")]
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derived_input_object() {
|
fn test_derived_input_object() {
|
||||||
assert_eq!(Input::name(&()), Some("MyInput"));
|
assert_eq!(Input::name(&()), Some("MyInput"));
|
||||||
|
@ -57,3 +84,24 @@ fn test_derived_input_object() {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = DocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Object comment.".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multi_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = MultiDocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Doc 1. Doc 2.\nDoc 4.".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment_override() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = OverrideDocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"obj override".to_string()));
|
||||||
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use fnv::FnvHashMap;
|
use fnv::FnvHashMap;
|
||||||
|
#[cfg(test)]
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use juniper::{self, execute, EmptyMutation, GraphQLType, RootNode, Value, Variables};
|
use juniper::{self, execute, EmptyMutation, GraphQLType, RootNode, Value, Variables};
|
||||||
|
@ -18,6 +20,33 @@ struct Nested {
|
||||||
|
|
||||||
struct Query;
|
struct Query;
|
||||||
|
|
||||||
|
/// Object comment.
|
||||||
|
#[derive(GraphQLObject, Debug, PartialEq)]
|
||||||
|
struct DocComment {
|
||||||
|
/// Field comment.
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Doc 1.
|
||||||
|
/// Doc 2.
|
||||||
|
///
|
||||||
|
/// Doc 4.
|
||||||
|
#[derive(GraphQLObject, Debug, PartialEq)]
|
||||||
|
struct MultiDocComment {
|
||||||
|
/// Field 1.
|
||||||
|
/// Field 2.
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[derive(GraphQLObject, Debug, PartialEq)]
|
||||||
|
#[graphql(description = "obj override")]
|
||||||
|
struct OverrideDocComment {
|
||||||
|
/// This is not used as the description.
|
||||||
|
#[graphql(description = "field override")]
|
||||||
|
regular_field: bool,
|
||||||
|
}
|
||||||
|
|
||||||
graphql_object!(Query: () |&self| {
|
graphql_object!(Query: () |&self| {
|
||||||
field obj() -> Obj {
|
field obj() -> Obj {
|
||||||
Obj{
|
Obj{
|
||||||
|
@ -34,8 +63,68 @@ graphql_object!(Query: () |&self| {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
field doc() -> DocComment {
|
||||||
|
DocComment{
|
||||||
|
regular_field: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field multi_doc() -> MultiDocComment {
|
||||||
|
MultiDocComment{
|
||||||
|
regular_field: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
field override_doc() -> OverrideDocComment {
|
||||||
|
OverrideDocComment{
|
||||||
|
regular_field: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = DocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Object comment.".to_string()));
|
||||||
|
|
||||||
|
check_descriptions(
|
||||||
|
"DocComment",
|
||||||
|
&Value::string("Object comment."),
|
||||||
|
"regularField",
|
||||||
|
&Value::string("Field comment."),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multi_doc_comment() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = MultiDocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"Doc 1. Doc 2.\nDoc 4.".to_string()));
|
||||||
|
|
||||||
|
check_descriptions(
|
||||||
|
"MultiDocComment",
|
||||||
|
&Value::string("Doc 1. Doc 2.\nDoc 4."),
|
||||||
|
"regularField",
|
||||||
|
&Value::string("Field 1. Field 2."),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_doc_comment_override() {
|
||||||
|
let mut registry = juniper::Registry::new(FnvHashMap::default());
|
||||||
|
let meta = OverrideDocComment::meta(&(), &mut registry);
|
||||||
|
assert_eq!(meta.description(), Some(&"obj override".to_string()));
|
||||||
|
|
||||||
|
check_descriptions(
|
||||||
|
"OverrideDocComment",
|
||||||
|
&Value::string("obj override"),
|
||||||
|
"regularField",
|
||||||
|
&Value::string("field override"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_derived_object() {
|
fn test_derived_object() {
|
||||||
assert_eq!(Obj::name(&()), Some("MyObj"));
|
assert_eq!(Obj::name(&()), Some("MyObj"));
|
||||||
|
@ -124,3 +213,63 @@ fn test_derived_object_nested() {
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn check_descriptions(object_name: &str, object_description: &Value, field_name: &str, field_value: &Value ) {
|
||||||
|
let doc = format!(r#"
|
||||||
|
{{
|
||||||
|
__type(name: "{}") {{
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
fields {{
|
||||||
|
name
|
||||||
|
description
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
"#, object_name);
|
||||||
|
run_type_info_query(&doc, |(type_info, values)| {
|
||||||
|
assert_eq!(type_info.get("name"), Some(&Value::string(object_name)));
|
||||||
|
assert_eq!(type_info.get("description"), Some(object_description));
|
||||||
|
assert!(
|
||||||
|
values.contains(&Value::object(
|
||||||
|
vec![
|
||||||
|
("name", Value::string(field_name)),
|
||||||
|
("description", field_value.clone()),
|
||||||
|
].into_iter()
|
||||||
|
.collect(),
|
||||||
|
))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
fn run_type_info_query<F>(doc: &str, f: F)
|
||||||
|
where
|
||||||
|
F: Fn((&IndexMap<String, Value>, &Vec<Value>)) -> (),
|
||||||
|
{
|
||||||
|
let schema = RootNode::new(Query, EmptyMutation::<()>::new());
|
||||||
|
|
||||||
|
let (result, errs) =
|
||||||
|
execute(doc, None, &schema, &Variables::new(), &()).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");
|
||||||
|
|
||||||
|
f((type_info, fields));
|
||||||
|
}
|
||||||
|
|
|
@ -6,5 +6,7 @@ extern crate serde_json;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
extern crate fnv;
|
extern crate fnv;
|
||||||
|
#[cfg(test)]
|
||||||
|
extern crate indexmap;
|
||||||
|
|
||||||
mod codegen;
|
mod codegen;
|
||||||
|
|
Loading…
Add table
Reference in a new issue