Format entire codebase with rustfmt

This commit is contained in:
Christoph Herzog 2018-01-13 12:25:55 +01:00
parent 406bdaa55c
commit d00e74bb4e
74 changed files with 2910 additions and 1786 deletions

View file

@ -402,9 +402,9 @@ impl InputValue {
(&Null, &Null) => true, (&Null, &Null) => true,
(&Int(i1), &Int(i2)) => i1 == i2, (&Int(i1), &Int(i2)) => i1 == i2,
(&Float(f1), &Float(f2)) => f1 == f2, (&Float(f1), &Float(f2)) => f1 == f2,
(&String(ref s1), &String(ref s2)) | (&String(ref s1), &String(ref s2))
(&Enum(ref s1), &Enum(ref s2)) | | (&Enum(ref s1), &Enum(ref s2))
(&Variable(ref s1), &Variable(ref s2)) => s1 == s2, | (&Variable(ref s1), &Variable(ref s2)) => s1 == s2,
(&Boolean(b1), &Boolean(b2)) => b1 == b2, (&Boolean(b1), &Boolean(b2)) => b1 == b2,
(&List(ref l1), &List(ref l2)) => l1.iter() (&List(ref l1), &List(ref l2)) => l1.iter()
.zip(l2.iter()) .zip(l2.iter())

View file

@ -68,15 +68,21 @@ impl Eq for ExecutionError {}
impl PartialOrd for ExecutionError { impl PartialOrd for ExecutionError {
fn partial_cmp(&self, other: &ExecutionError) -> Option<Ordering> { fn partial_cmp(&self, other: &ExecutionError) -> Option<Ordering> {
(&self.location, &self.path, &self.error.message) (&self.location, &self.path, &self.error.message).partial_cmp(&(
.partial_cmp(&(&other.location, &other.path, &other.error.message)) &other.location,
&other.path,
&other.error.message,
))
} }
} }
impl Ord for ExecutionError { impl Ord for ExecutionError {
fn cmp(&self, other: &ExecutionError) -> Ordering { fn cmp(&self, other: &ExecutionError) -> Ordering {
(&self.location, &self.path, &self.error.message) (&self.location, &self.path, &self.error.message).cmp(&(
.cmp(&(&other.location, &other.path, &other.error.message)) &other.location,
&other.path,
&other.error.message,
))
} }
} }
@ -213,7 +219,8 @@ impl<'a, T: GraphQLType, C> IntoResolvable<'a, T, C> for FieldResult<(&'a T::Con
} }
} }
impl<'a, T: GraphQLType, C> IntoResolvable<'a, Option<T>, C> for FieldResult<Option<(&'a T::Context, T)>> { impl<'a, T: GraphQLType, C> IntoResolvable<'a, Option<T>, C>
for FieldResult<Option<(&'a T::Context, T)>> {
fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>> { fn into(self, _: &'a C) -> FieldResult<Option<(&'a T::Context, Option<T>)>> {
self.map(|o| o.map(|(ctx, v)| (ctx, Some(v)))) self.map(|o| o.map(|(ctx, v)| (ctx, Some(v))))
} }
@ -329,8 +336,10 @@ impl<'a, CtxT> Executor<'a, CtxT> {
current_type: self.schema.make_type( current_type: self.schema.make_type(
&self.current_type &self.current_type
.innermost_concrete() .innermost_concrete()
.field_by_name(field_name).expect("Field not found on inner type") .field_by_name(field_name)
.field_type), .expect("Field not found on inner type")
.field_type,
),
schema: self.schema, schema: self.schema,
context: self.context, context: self.context,
errors: self.errors, errors: self.errors,
@ -478,8 +487,8 @@ where
return Err(GraphQLError::MultipleOperationsProvided); return Err(GraphQLError::MultipleOperationsProvided);
} }
let move_op = operation_name.is_none() || let move_op = operation_name.is_none()
op.item.name.as_ref().map(|s| s.item.as_ref()) == operation_name; || op.item.name.as_ref().map(|s| s.item.as_ref()) == operation_name;
if move_op { if move_op {
operation = Some(op); operation = Some(op);
@ -525,7 +534,10 @@ where
let root_type = match op.item.operation_type { let root_type = match op.item.operation_type {
OperationType::Query => root_node.schema.query_type(), OperationType::Query => root_node.schema.query_type(),
OperationType::Mutation => root_node.schema.mutation_type().expect("No mutation type found") OperationType::Mutation => root_node
.schema
.mutation_type()
.expect("No mutation type found"),
}; };
let executor = Executor { let executor = Executor {

View file

@ -73,47 +73,50 @@ fn scalar_skip_true() {
}); });
} }
#[test] #[test]
fn fragment_spread_include_true() { fn fragment_spread_include_true() {
run_query("{ a, ...Frag @include(if: true) } fragment Frag on TestType { b }", run_query(
|result| { "{ a, ...Frag @include(if: true) } fragment Frag on TestType { b }",
assert_eq!(result.get("a"), Some(&Value::string("a"))); |result| {
assert_eq!(result.get("b"), Some(&Value::string("b"))); assert_eq!(result.get("a"), Some(&Value::string("a")));
}); assert_eq!(result.get("b"), Some(&Value::string("b")));
},
);
} }
#[test] #[test]
fn fragment_spread_include_false() { fn fragment_spread_include_false() {
run_query("{ a, ...Frag @include(if: false) } fragment Frag on TestType { b }", run_query(
|result| { "{ a, ...Frag @include(if: false) } fragment Frag on TestType { b }",
assert_eq!(result.get("a"), Some(&Value::string("a"))); |result| {
assert_eq!(result.get("b"), None); assert_eq!(result.get("a"), Some(&Value::string("a")));
}); assert_eq!(result.get("b"), None);
},
);
} }
#[test] #[test]
fn fragment_spread_skip_false() { fn fragment_spread_skip_false() {
run_query("{ a, ...Frag @skip(if: false) } fragment Frag on TestType { b }", run_query(
|result| { "{ a, ...Frag @skip(if: false) } fragment Frag on TestType { b }",
assert_eq!(result.get("a"), Some(&Value::string("a"))); |result| {
assert_eq!(result.get("b"), Some(&Value::string("b"))); assert_eq!(result.get("a"), Some(&Value::string("a")));
}); assert_eq!(result.get("b"), Some(&Value::string("b")));
},
);
} }
#[test] #[test]
fn fragment_spread_skip_true() { fn fragment_spread_skip_true() {
run_query("{ a, ...Frag @skip(if: true) } fragment Frag on TestType { b }", run_query(
|result| { "{ a, ...Frag @skip(if: true) } fragment Frag on TestType { b }",
assert_eq!(result.get("a"), Some(&Value::string("a"))); |result| {
assert_eq!(result.get("b"), None); assert_eq!(result.get("a"), Some(&Value::string("a")));
}); assert_eq!(result.get("b"), None);
},
);
} }
#[test] #[test]
fn inline_fragment_include_true() { fn inline_fragment_include_true() {
run_query( run_query(
@ -152,9 +155,6 @@ fn inline_fragment_skip_true() {
}); });
} }
#[test] #[test]
fn anonymous_inline_fragment_include_true() { fn anonymous_inline_fragment_include_true() {
run_query("{ a, ... @include(if: true) { b } }", |result| { run_query("{ a, ... @include(if: true) { b } }", |result| {
@ -187,9 +187,6 @@ fn anonymous_inline_fragment_skip_true() {
}); });
} }
#[test] #[test]
fn scalar_include_true_skip_true() { fn scalar_include_true_skip_true() {
run_query("{ a, b @include(if: true) @skip(if: true) }", |result| { run_query("{ a, b @include(if: true) @skip(if: true) }", |result| {

View file

@ -55,18 +55,14 @@ where
#[test] #[test]
fn accepts_enum_literal() { fn accepts_enum_literal() {
run_query("{ toString(color: RED) }", |result| { run_query("{ toString(color: RED) }", |result| {
assert_eq!( assert_eq!(result.get("toString"), Some(&Value::string("Color::Red")));
result.get("toString"),
Some(&Value::string("Color::Red")));
}); });
} }
#[test] #[test]
fn serializes_as_output() { fn serializes_as_output() {
run_query("{ aColor }", |result| { run_query("{ aColor }", |result| {
assert_eq!( assert_eq!(result.get("aColor"), Some(&Value::string("RED")));
result.get("aColor"),
Some(&Value::string("RED")));
}); });
} }
@ -79,26 +75,26 @@ fn does_not_accept_string_literals() {
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err(); let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(error, ValidationError(vec![ assert_eq!(
RuleError::new( error,
r#"Invalid value for argument "color", expected type "Color!""#, ValidationError(vec![
&[SourcePosition::new(18, 0, 18)], RuleError::new(
), r#"Invalid value for argument "color", expected type "Color!""#,
])); &[SourcePosition::new(18, 0, 18)],
),
])
);
} }
#[test] #[test]
fn accepts_strings_in_variables() { fn accepts_strings_in_variables() {
run_variable_query( run_variable_query(
"query q($color: Color!) { toString(color: $color) }", "query q($color: Color!) { toString(color: $color) }",
vec![ vec![("color".to_owned(), InputValue::string("RED"))]
("color".to_owned(), InputValue::string("RED")), .into_iter()
].into_iter()
.collect(), .collect(),
|result| { |result| {
assert_eq!( assert_eq!(result.get("toString"), Some(&Value::string("Color::Red")));
result.get("toString"),
Some(&Value::string("Color::Red")));
}, },
); );
} }
@ -108,19 +104,21 @@ fn does_not_accept_incorrect_enum_name_in_variables() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new()); let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($color: Color!) { toString(color: $color) }"#; let query = r#"query q($color: Color!) { toString(color: $color) }"#;
let vars = vec![ let vars = vec![("color".to_owned(), InputValue::string("BLURPLE"))]
("color".to_owned(), InputValue::string("BLURPLE")), .into_iter()
].into_iter()
.collect(); .collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err(); let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(error, ValidationError(vec![ assert_eq!(
RuleError::new( error,
r#"Variable "$color" got invalid value. Invalid value for enum "Color"."#, ValidationError(vec![
&[SourcePosition::new(8, 0, 8)], RuleError::new(
), r#"Variable "$color" got invalid value. Invalid value for enum "Color"."#,
])); &[SourcePosition::new(8, 0, 8)],
),
])
);
} }
#[test] #[test]
@ -128,17 +126,19 @@ fn does_not_accept_incorrect_type_in_variables() {
let schema = RootNode::new(TestType, EmptyMutation::<()>::new()); let schema = RootNode::new(TestType, EmptyMutation::<()>::new());
let query = r#"query q($color: Color!) { toString(color: $color) }"#; let query = r#"query q($color: Color!) { toString(color: $color) }"#;
let vars = vec![ let vars = vec![("color".to_owned(), InputValue::int(123))]
("color".to_owned(), InputValue::int(123)), .into_iter()
].into_iter()
.collect(); .collect();
let error = ::execute(query, None, &schema, &vars, &()).unwrap_err(); let error = ::execute(query, None, &schema, &vars, &()).unwrap_err();
assert_eq!(error, ValidationError(vec![ assert_eq!(
error,
ValidationError(vec![
RuleError::new( RuleError::new(
r#"Variable "$color" got invalid value. Expected "Color", found not a string or enum."#, r#"Variable "$color" got invalid value. Expected "Color", found not a string or enum."#,
&[SourcePosition::new(8, 0, 8)], &[SourcePosition::new(8, 0, 8)],
), ),
])); ])
);
} }

View file

@ -61,9 +61,8 @@ mod field_execution {
e e
}"; }";
let vars = vec![ let vars = vec![("size".to_owned(), InputValue::int(100))]
("size".to_owned(), InputValue::int(100)) .into_iter()
].into_iter()
.collect(); .collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed");
@ -74,39 +73,60 @@ mod field_execution {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("a", Value::string("Apple")), vec![
("b", Value::string("Banana")), ("a", Value::string("Apple")),
("x", Value::string("Cookie")), ("b", Value::string("Banana")),
("d", Value::string("Donut")), ("x", Value::string("Cookie")),
("e", Value::string("Egg")), ("d", Value::string("Donut")),
("f", Value::string("Fish")), ("e", Value::string("Egg")),
("pic", Value::string("Pic of size: 100")), ("f", Value::string("Fish")),
("deep", Value::object(vec![ ("pic", Value::string("Pic of size: 100")),
("a", Value::string("Already Been Done")), (
("b", Value::string("Boring")), "deep",
("c", Value::list(vec![ Value::object(
Value::string("Contrived"), vec![
Value::null(), ("a", Value::string("Already Been Done")),
Value::string("Confusing"), ("b", Value::string("Boring")),
])), (
("deeper", Value::list(vec![ "c",
Value::object(vec![ Value::list(vec![
("a", Value::string("Apple")), Value::string("Contrived"),
("b", Value::string("Banana")), Value::null(),
].into_iter().collect()), Value::string("Confusing"),
Value::null(), ]),
Value::object(vec![ ),
("a", Value::string("Apple")), (
("b", Value::string("Banana")), "deeper",
].into_iter().collect()), Value::list(vec![
])), Value::object(
].into_iter().collect())), vec![
].into_iter().collect())); ("a", Value::string("Apple")),
("b", Value::string("Banana")),
].into_iter()
.collect(),
),
Value::null(),
Value::object(
vec![
("a", Value::string("Apple")),
("b", Value::string("Banana")),
].into_iter()
.collect(),
),
]),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
)
);
} }
} }
mod merge_parallel_fragments { mod merge_parallel_fragments {
use value::Value; use value::Value;
use schema::model::RootNode; use schema::model::RootNode;
@ -145,19 +165,35 @@ mod merge_parallel_fragments {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("a", Value::string("Apple")), vec![
("b", Value::string("Banana")), ("a", Value::string("Apple")),
("deep", Value::object(vec![
("b", Value::string("Banana")), ("b", Value::string("Banana")),
("deeper", Value::object(vec![ (
("b", Value::string("Banana")), "deep",
("c", Value::string("Cherry")), Value::object(
].into_iter().collect())), vec![
("b", Value::string("Banana")),
(
"deeper",
Value::object(
vec![
("b", Value::string("Banana")),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
),
("c", Value::string("Cherry")),
].into_iter()
.collect(),
),
),
("c", Value::string("Cherry")), ("c", Value::string("Cherry")),
].into_iter().collect())), ].into_iter()
("c", Value::string("Cherry")), .collect()
].into_iter().collect())); )
);
} }
} }
@ -202,9 +238,12 @@ mod threads_context_correctly {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("a", Value::string("Context value")), vec![("a", Value::string("Context value"))]
].into_iter().collect())); .into_iter()
.collect()
)
);
} }
} }
@ -272,8 +311,18 @@ mod dynamic_context_switching {
let ctx = OuterContext { let ctx = OuterContext {
items: vec![ items: vec![
(0, InnerContext { value: "First value".to_owned() }), (
(1, InnerContext { value: "Second value".to_owned() }), 0,
InnerContext {
value: "First value".to_owned(),
},
),
(
1,
InnerContext {
value: "Second value".to_owned(),
},
),
].into_iter() ].into_iter()
.collect(), .collect(),
}; };
@ -286,12 +335,21 @@ mod dynamic_context_switching {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("first", Value::object(vec![ vec![
("value", Value::string("First value")), (
].into_iter().collect())), "first",
("missing", Value::null()), Value::object(
].into_iter().collect())); vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
),
("missing", Value::null()),
].into_iter()
.collect()
)
);
} }
#[test] #[test]
@ -307,8 +365,18 @@ mod dynamic_context_switching {
let ctx = OuterContext { let ctx = OuterContext {
items: vec![ items: vec![
(0, InnerContext { value: "First value".to_owned() }), (
(1, InnerContext { value: "Second value".to_owned() }), 0,
InnerContext {
value: "First value".to_owned(),
},
),
(
1,
InnerContext {
value: "Second value".to_owned(),
},
),
].into_iter() ].into_iter()
.collect(), .collect(),
}; };
@ -321,11 +389,20 @@ mod dynamic_context_switching {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("first", Value::object(vec![ vec![
("value", Value::string("First value")), (
].into_iter().collect())), "first",
].into_iter().collect())); Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
)
);
} }
#[test] #[test]
@ -341,21 +418,34 @@ mod dynamic_context_switching {
let ctx = OuterContext { let ctx = OuterContext {
items: vec![ items: vec![
(0, InnerContext { value: "First value".to_owned() }), (
(1, InnerContext { value: "Second value".to_owned() }), 0,
InnerContext {
value: "First value".to_owned(),
},
),
(
1,
InnerContext {
value: "Second value".to_owned(),
},
),
].into_iter() ].into_iter()
.collect(), .collect(),
}; };
let (result, errs) = ::execute(doc, None, &schema, &vars, &ctx).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &ctx).expect("Execution failed");
assert_eq!(errs, vec![ assert_eq!(
ExecutionError::new( errs,
SourcePosition::new(25, 2, 12), vec![
&["missing"], ExecutionError::new(
FieldError::new("Could not find key 2", Value::null()), SourcePosition::new(25, 2, 12),
), &["missing"],
]); FieldError::new("Could not find key 2", Value::null()),
),
]
);
println!("Result: {:?}", result); println!("Result: {:?}", result);
@ -377,33 +467,55 @@ mod dynamic_context_switching {
let ctx = OuterContext { let ctx = OuterContext {
items: vec![ items: vec![
(0, InnerContext { value: "First value".to_owned() }), (
(1, InnerContext { value: "Second value".to_owned() }), 0,
InnerContext {
value: "First value".to_owned(),
},
),
(
1,
InnerContext {
value: "Second value".to_owned(),
},
),
].into_iter() ].into_iter()
.collect(), .collect(),
}; };
let (result, errs) = ::execute(doc, None, &schema, &vars, &ctx).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &ctx).expect("Execution failed");
assert_eq!(errs, [ assert_eq!(
ExecutionError::new( errs,
SourcePosition::new(123, 4, 12), [
&["tooLarge"], ExecutionError::new(
FieldError::new("Key too large: 200", Value::null()), SourcePosition::new(123, 4, 12),
), &["tooLarge"],
]); FieldError::new("Key too large: 200", Value::null()),
),
]
);
println!("Result: {:?}", result); println!("Result: {:?}", result);
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("first", Value::object(vec![ vec![
("value", Value::string("First value")), (
].into_iter().collect())), "first",
("missing", Value::null()), Value::object(
("tooLarge", Value::null()), vec![("value", Value::string("First value"))]
].into_iter().collect())); .into_iter()
.collect(),
),
),
("missing", Value::null()),
("tooLarge", Value::null()),
].into_iter()
.collect()
)
);
} }
#[test] #[test]
@ -415,8 +527,18 @@ mod dynamic_context_switching {
let ctx = OuterContext { let ctx = OuterContext {
items: vec![ items: vec![
(0, InnerContext { value: "First value".to_owned() }), (
(1, InnerContext { value: "Second value".to_owned() }), 0,
InnerContext {
value: "First value".to_owned(),
},
),
(
1,
InnerContext {
value: "Second value".to_owned(),
},
),
].into_iter() ].into_iter()
.collect(), .collect(),
}; };
@ -429,11 +551,20 @@ mod dynamic_context_switching {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("first", Value::object(vec![ vec![
("value", Value::string("First value")), (
].into_iter().collect())), "first",
].into_iter().collect())); Value::object(
vec![("value", Value::string("First value"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
)
);
} }
} }
@ -473,7 +604,8 @@ mod propagates_errors_to_nullable_fields {
assert_eq!( assert_eq!(
result, result,
graphql_value!({ "inner": { "nullableErrorField": None } })); graphql_value!({ "inner": { "nullableErrorField": None } })
);
assert_eq!( assert_eq!(
errs, errs,
@ -483,7 +615,8 @@ mod propagates_errors_to_nullable_fields {
&["inner", "nullableErrorField"], &["inner", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()), FieldError::new("Error for nullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -497,9 +630,7 @@ mod propagates_errors_to_nullable_fields {
println!("Result: {:?}", result); println!("Result: {:?}", result);
assert_eq!( assert_eq!(result, graphql_value!(None));
result,
graphql_value!(None));
assert_eq!( assert_eq!(
errs, errs,
@ -509,7 +640,8 @@ mod propagates_errors_to_nullable_fields {
&["inner", "nonNullableErrorField"], &["inner", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()), FieldError::new("Error for nonNullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -525,7 +657,8 @@ mod propagates_errors_to_nullable_fields {
assert_eq!( assert_eq!(
result, result,
graphql_value!({ "inner": { "nullableField": None } })); graphql_value!({ "inner": { "nullableField": None } })
);
assert_eq!( assert_eq!(
errs, errs,
@ -535,7 +668,8 @@ mod propagates_errors_to_nullable_fields {
&["inner", "nullableField", "nonNullableErrorField"], &["inner", "nullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()), FieldError::new("Error for nonNullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -549,9 +683,7 @@ mod propagates_errors_to_nullable_fields {
println!("Result: {:?}", result); println!("Result: {:?}", result);
assert_eq!( assert_eq!(result, graphql_value!(None));
result,
graphql_value!(None));
assert_eq!( assert_eq!(
errs, errs,
@ -561,7 +693,8 @@ mod propagates_errors_to_nullable_fields {
&["inner", "nonNullableField", "nonNullableErrorField"], &["inner", "nonNullableField", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()), FieldError::new("Error for nonNullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -577,7 +710,8 @@ mod propagates_errors_to_nullable_fields {
assert_eq!( assert_eq!(
result, result,
graphql_value!({ "inner": { "nonNullableField": { "nullableErrorField": None } } })); graphql_value!({ "inner": { "nonNullableField": { "nullableErrorField": None } } })
);
assert_eq!( assert_eq!(
errs, errs,
@ -587,7 +721,8 @@ mod propagates_errors_to_nullable_fields {
&["inner", "nonNullableField", "nullableErrorField"], &["inner", "nonNullableField", "nullableErrorField"],
FieldError::new("Error for nullableErrorField", Value::null()), FieldError::new("Error for nullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -601,9 +736,7 @@ mod propagates_errors_to_nullable_fields {
println!("Result: {:?}", result); println!("Result: {:?}", result);
assert_eq!( assert_eq!(result, graphql_value!(None));
result,
graphql_value!(None));
assert_eq!( assert_eq!(
errs, errs,
@ -613,7 +746,8 @@ mod propagates_errors_to_nullable_fields {
&["inners", "nonNullableErrorField"], &["inners", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()), FieldError::new("Error for nonNullableErrorField", Value::null()),
), ),
]); ]
);
} }
#[test] #[test]
@ -629,7 +763,8 @@ mod propagates_errors_to_nullable_fields {
assert_eq!( assert_eq!(
result, result,
graphql_value!({ "nullableInners": [None, None, None, None, None] })); graphql_value!({ "nullableInners": [None, None, None, None, None] })
);
assert_eq!( assert_eq!(
errs, errs,
@ -659,7 +794,8 @@ mod propagates_errors_to_nullable_fields {
&["nullableInners", "nonNullableErrorField"], &["nullableInners", "nonNullableErrorField"],
FieldError::new("Error for nonNullableErrorField", Value::null()), FieldError::new("Error for nonNullableErrorField", Value::null()),
), ),
]); ]
);
} }
} }
@ -688,9 +824,8 @@ mod named_operations {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(vec![("a", Value::string("b"))].into_iter().collect())
("a", Value::string("b")), );
].into_iter().collect()));
} }
#[test] #[test]
@ -706,9 +841,8 @@ mod named_operations {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(vec![("a", Value::string("b"))].into_iter().collect())
("a", Value::string("b")), );
].into_iter().collect()));
} }
#[test] #[test]
@ -725,9 +859,8 @@ mod named_operations {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(vec![("second", Value::string("b"))].into_iter().collect())
("second", Value::string("b")), );
].into_iter().collect()));
} }
#[test] #[test]

View file

@ -80,8 +80,14 @@ mod interface {
let schema = RootNode::new( let schema = RootNode::new(
Schema { Schema {
pets: vec![ pets: vec![
Box::new(Dog { name: "Odie".to_owned(), woofs: true }), Box::new(Dog {
Box::new(Cat { name: "Garfield".to_owned(), meows: false }), name: "Odie".to_owned(),
woofs: true,
}),
Box::new(Cat {
name: "Garfield".to_owned(),
meows: false,
}),
], ],
}, },
EmptyMutation::<()>::new(), EmptyMutation::<()>::new(),
@ -109,24 +115,34 @@ mod interface {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("pets", Value::list(vec![ vec![
Value::object(vec![ (
("name", Value::string("Odie")), "pets",
("woofs", Value::boolean(true)), Value::list(vec![
].into_iter().collect()), Value::object(
Value::object(vec![ vec![
("name", Value::string("Garfield")), ("name", Value::string("Odie")),
("meows", Value::boolean(false)), ("woofs", Value::boolean(true)),
].into_iter().collect()), ].into_iter()
])), .collect(),
].into_iter().collect())); ),
Value::object(
vec![
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
),
].into_iter()
.collect()
)
);
} }
} }
mod union { mod union {
use value::Value; use value::Value;
use schema::model::RootNode; use schema::model::RootNode;
@ -195,8 +211,14 @@ mod union {
let schema = RootNode::new( let schema = RootNode::new(
Schema { Schema {
pets: vec![ pets: vec![
Box::new(Dog { name: "Odie".to_owned(), woofs: true }), Box::new(Dog {
Box::new(Cat { name: "Garfield".to_owned(), meows: false }), name: "Odie".to_owned(),
woofs: true,
}),
Box::new(Cat {
name: "Garfield".to_owned(),
meows: false,
}),
], ],
}, },
EmptyMutation::<()>::new(), EmptyMutation::<()>::new(),
@ -226,19 +248,32 @@ mod union {
assert_eq!( assert_eq!(
result, result,
Value::object(vec![ Value::object(
("pets", Value::list(vec![ vec![
Value::object(vec![ (
("__typename", Value::string("Dog")), "pets",
("name", Value::string("Odie")), Value::list(vec![
("woofs", Value::boolean(true)), Value::object(
].into_iter().collect()), vec![
Value::object(vec![ ("__typename", Value::string("Dog")),
("__typename", Value::string("Cat")), ("name", Value::string("Odie")),
("name", Value::string("Garfield")), ("woofs", Value::boolean(true)),
("meows", Value::boolean(false)), ].into_iter()
].into_iter().collect()), .collect(),
])), ),
].into_iter().collect())); Value::object(
vec![
("__typename", Value::string("Cat")),
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter()
.collect(),
),
]),
),
].into_iter()
.collect()
)
);
} }
} }

View file

@ -48,19 +48,15 @@ enum EnumDescription {
#[derive(GraphQLEnum)] #[derive(GraphQLEnum)]
#[graphql(_internal)] #[graphql(_internal)]
enum EnumValueDescription { enum EnumValueDescription {
#[graphql(description = "The FOO value")] #[graphql(description = "The FOO value")] Foo,
Foo, #[graphql(description = "The BAR value")] Bar,
#[graphql(description = "The BAR value")]
Bar,
} }
#[derive(GraphQLEnum)] #[derive(GraphQLEnum)]
#[graphql(_internal)] #[graphql(_internal)]
enum EnumDeprecation { enum EnumDeprecation {
#[graphql(deprecated = "Please don't use FOO any more")] #[graphql(deprecated = "Please don't use FOO any more")] Foo,
Foo, #[graphql(description = "The BAR value", deprecated = "Please don't use BAR any more")] Bar,
#[graphql(description = "The BAR value", deprecated = "Please don't use BAR any more")]
Bar,
} }
struct Root; struct Root;
@ -127,19 +123,29 @@ fn default_name_introspection() {
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("FOO")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("BAR")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -166,19 +172,29 @@ fn named_introspection() {
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("FOO")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("BAR")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -200,24 +216,37 @@ fn no_trailing_comma_introspection() {
"#; "#;
run_type_info_query(doc, |(type_info, values)| { run_type_info_query(doc, |(type_info, values)| {
assert_eq!(type_info.get("name"), Some(&Value::string("NoTrailingComma"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("NoTrailingComma"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("FOO")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("BAR")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -239,24 +268,40 @@ fn enum_description_introspection() {
"#; "#;
run_type_info_query(doc, |(type_info, values)| { run_type_info_query(doc, |(type_info, values)| {
assert_eq!(type_info.get("name"), Some(&Value::string("EnumDescription"))); assert_eq!(
assert_eq!(type_info.get("description"), Some(&Value::string("A description of the enum itself"))); type_info.get("name"),
Some(&Value::string("EnumDescription"))
);
assert_eq!(
type_info.get("description"),
Some(&Value::string("A description of the enum itself"))
);
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("FOO")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("BAR")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -278,24 +323,37 @@ fn enum_value_description_introspection() {
"#; "#;
run_type_info_query(doc, |(type_info, values)| { run_type_info_query(doc, |(type_info, values)| {
assert_eq!(type_info.get("name"), Some(&Value::string("EnumValueDescription"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("EnumValueDescription"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::string("The FOO value")), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("FOO")),
("deprecationReason", Value::null()), ("description", Value::string("The FOO value")),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::string("The BAR value")), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("BAR")),
("deprecationReason", Value::null()), ("description", Value::string("The BAR value")),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -317,24 +375,43 @@ fn enum_deprecation_introspection() {
"#; "#;
run_type_info_query(doc, |(type_info, values)| { run_type_info_query(doc, |(type_info, values)| {
assert_eq!(type_info.get("name"), Some(&Value::string("EnumDeprecation"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("EnumDeprecation"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("FOO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(true)), ("name", Value::string("FOO")),
("deprecationReason", Value::string("Please don't use FOO any more")), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(true)),
(
"deprecationReason",
Value::string("Please don't use FOO any more"),
),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("BAR")), values.contains(&Value::object(
("description", Value::string("The BAR value")), vec![
("isDeprecated", Value::boolean(true)), ("name", Value::string("BAR")),
("deprecationReason", Value::string("Please don't use BAR any more")), ("description", Value::string("The BAR value")),
].into_iter().collect()))); ("isDeprecated", Value::boolean(true)),
(
"deprecationReason",
Value::string("Please don't use BAR any more"),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -356,7 +433,10 @@ fn enum_deprecation_no_values_introspection() {
"#; "#;
run_type_info_query(doc, |(type_info, values)| { run_type_info_query(doc, |(type_info, values)| {
assert_eq!(type_info.get("name"), Some(&Value::string("EnumDeprecation"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("EnumDeprecation"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(values.len(), 0); assert_eq!(values.len(), 0);

View file

@ -19,7 +19,7 @@ struct DefaultName {
#[graphql(_internal)] #[graphql(_internal)]
struct NoTrailingComma { struct NoTrailingComma {
field_one: String, field_one: String,
field_two: String field_two: String,
} }
#[derive(GraphQLInputObject, Debug)] #[derive(GraphQLInputObject, Debug)]
@ -54,8 +54,7 @@ pub struct PublicWithDescription {
#[derive(GraphQLInputObject, Debug)] #[derive(GraphQLInputObject, Debug)]
#[graphql(name = "APublicNamedInputObjectWithDescription", #[graphql(name = "APublicNamedInputObjectWithDescription",
description = "Description for the input object", description = "Description for the input object", _internal)]
_internal)]
pub struct NamedPublicWithDescription { pub struct NamedPublicWithDescription {
field_one: String, field_one: String,
} }
@ -69,19 +68,15 @@ pub struct NamedPublic {
#[derive(GraphQLInputObject, Debug)] #[derive(GraphQLInputObject, Debug)]
#[graphql(_internal)] #[graphql(_internal)]
struct FieldDescription { struct FieldDescription {
#[graphql(description = "The first field")] #[graphql(description = "The first field")] field_one: String,
field_one: String, #[graphql(description = "The second field")] field_two: String,
#[graphql(description = "The second field")]
field_two: String,
} }
#[derive(GraphQLInputObject, Debug)] #[derive(GraphQLInputObject, Debug)]
#[graphql(_internal)] #[graphql(_internal)]
struct FieldWithDefaults { struct FieldWithDefaults {
#[graphql(default = "123")] #[graphql(default = "123")] field_one: i32,
field_one: i32, #[graphql(default = "456", description = "The second field")] field_two: i32,
#[graphql(default = "456", description = "The second field")]
field_two: i32,
} }
graphql_object!(Root: () |&self| { graphql_object!(Root: () |&self| {
@ -159,27 +154,59 @@ fn default_name_introspection() {
assert_eq!(fields.len(), 2); assert_eq!(fields.len(), 2);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldTwo")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldTwo")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -187,9 +214,9 @@ fn default_name_introspection() {
fn default_name_input_value() { fn default_name_input_value() {
let iv = InputValue::object( let iv = InputValue::object(
vec![ vec![
("fieldOne", InputValue::string("number one")), ("fieldOne", InputValue::string("number one")),
("fieldTwo", InputValue::string("number two")), ("fieldTwo", InputValue::string("number two")),
].into_iter() ].into_iter()
.collect(), .collect(),
); );
@ -225,32 +252,67 @@ fn no_trailing_comma_introspection() {
"#; "#;
run_type_info_query(doc, |type_info, fields| { run_type_info_query(doc, |type_info, fields| {
assert_eq!(type_info.get("name"), Some(&Value::string("NoTrailingComma"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("NoTrailingComma"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(fields.len(), 2); assert_eq!(fields.len(), 2);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldTwo")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldTwo")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -281,23 +343,44 @@ fn derive_introspection() {
assert_eq!(fields.len(), 1); assert_eq!(fields.len(), 1);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
#[test] #[test]
fn derive_derived() { fn derive_derived() {
assert_eq!( assert_eq!(
format!("{:?}", Derive { field_one: "test".to_owned() }), format!(
"{:?}",
Derive {
field_one: "test".to_owned(),
}
),
"Derive { field_one: \"test\" }" "Derive { field_one: \"test\" }"
); );
} }
@ -324,21 +407,40 @@ fn named_introspection() {
"#; "#;
run_type_info_query(doc, |type_info, fields| { run_type_info_query(doc, |type_info, fields| {
assert_eq!(type_info.get("name"), Some(&Value::string("ANamedInputObject"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("ANamedInputObject"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(fields.len(), 1); assert_eq!(fields.len(), 1);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -365,20 +467,39 @@ fn description_introspection() {
run_type_info_query(doc, |type_info, fields| { run_type_info_query(doc, |type_info, fields| {
assert_eq!(type_info.get("name"), Some(&Value::string("Description"))); assert_eq!(type_info.get("name"), Some(&Value::string("Description")));
assert_eq!(type_info.get("description"), Some(&Value::string("Description for the input object"))); assert_eq!(
type_info.get("description"),
Some(&Value::string("Description for the input object"))
);
assert_eq!(fields.len(), 1); assert_eq!(fields.len(), 1);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::null()), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::null()),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -404,32 +525,67 @@ fn field_description_introspection() {
"#; "#;
run_type_info_query(doc, |type_info, fields| { run_type_info_query(doc, |type_info, fields| {
assert_eq!(type_info.get("name"), Some(&Value::string("FieldDescription"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("FieldDescription"))
);
assert_eq!(type_info.get("description"), Some(&Value::null())); assert_eq!(type_info.get("description"), Some(&Value::null()));
assert_eq!(fields.len(), 2); assert_eq!(fields.len(), 2);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("description", Value::string("The first field")), vec![
("type", Value::object(vec![ ("name", Value::string("fieldOne")),
("ofType", Value::object(vec![ ("description", Value::string("The first field")),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldTwo")), fields.contains(&Value::object(
("description", Value::string("The second field")), vec![
("type", Value::object(vec![ ("name", Value::string("fieldTwo")),
("ofType", Value::object(vec![ ("description", Value::string("The second field")),
("name", Value::string("String")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("defaultValue", Value::null()), vec![
].into_iter().collect()))); (
"ofType",
Value::object(
vec![("name", Value::string("String"))]
.into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("defaultValue", Value::null()),
].into_iter()
.collect()
))
);
}); });
} }
@ -451,24 +607,39 @@ fn field_with_defaults_introspection() {
"#; "#;
run_type_info_query(doc, |type_info, fields| { run_type_info_query(doc, |type_info, fields| {
assert_eq!(type_info.get("name"), Some(&Value::string("FieldWithDefaults"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("FieldWithDefaults"))
);
assert_eq!(fields.len(), 2); assert_eq!(fields.len(), 2);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldOne")), fields.contains(&Value::object(
("type", Value::object(vec![ vec![
("name", Value::string("Int")), ("name", Value::string("fieldOne")),
].into_iter().collect())), (
("defaultValue", Value::string("123")), "type",
].into_iter().collect()))); Value::object(vec![("name", Value::string("Int"))].into_iter().collect()),
),
("defaultValue", Value::string("123")),
].into_iter()
.collect()
))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("fieldTwo")), fields.contains(&Value::object(
("type", Value::object(vec![ vec![
("name", Value::string("Int")), ("name", Value::string("fieldTwo")),
].into_iter().collect())), (
("defaultValue", Value::string("456")), "type",
].into_iter().collect()))); Value::object(vec![("name", Value::string("Int"))].into_iter().collect()),
),
("defaultValue", Value::string("456")),
].into_iter()
.collect()
))
);
}); });
} }

View file

@ -80,11 +80,17 @@ fn test_execution() {
println!("Result: {:?}", result); println!("Result: {:?}", result);
assert_eq!(result, Value::object(vec![ assert_eq!(
("sampleEnum", Value::string("ONE")), result,
("first", Value::int(123)), Value::object(
("second", Value::int(30)), vec![
].into_iter().collect())); ("sampleEnum", Value::string("ONE")),
("first", Value::int(123)),
("second", Value::int(30)),
].into_iter()
.collect()
)
);
} }
#[test] #[test]
@ -141,19 +147,29 @@ fn enum_introspection() {
assert_eq!(values.len(), 2); assert_eq!(values.len(), 2);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("ONE")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("ONE")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(values.contains(&Value::object(vec![ assert!(
("name", Value::string("TWO")), values.contains(&Value::object(
("description", Value::null()), vec![
("isDeprecated", Value::boolean(false)), ("name", Value::string("TWO")),
("deprecationReason", Value::null()), ("description", Value::null()),
].into_iter().collect()))); ("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
} }
#[test] #[test]
@ -208,9 +224,15 @@ fn interface_introspection() {
.as_object_value() .as_object_value()
.expect("__type field not an object value"); .expect("__type field not an object value");
assert_eq!(type_info.get("name"), Some(&Value::string("SampleInterface"))); assert_eq!(
type_info.get("name"),
Some(&Value::string("SampleInterface"))
);
assert_eq!(type_info.get("kind"), Some(&Value::string("INTERFACE"))); assert_eq!(type_info.get("kind"), Some(&Value::string("INTERFACE")));
assert_eq!(type_info.get("description"), Some(&Value::string("A sample interface"))); assert_eq!(
type_info.get("description"),
Some(&Value::string("A sample interface"))
);
assert_eq!(type_info.get("interfaces"), Some(&Value::null())); assert_eq!(type_info.get("interfaces"), Some(&Value::null()));
assert_eq!(type_info.get("enumValues"), Some(&Value::null())); assert_eq!(type_info.get("enumValues"), Some(&Value::null()));
assert_eq!(type_info.get("inputFields"), Some(&Value::null())); assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
@ -224,9 +246,9 @@ fn interface_introspection() {
assert_eq!(possible_types.len(), 1); assert_eq!(possible_types.len(), 1);
assert!(possible_types.contains(&Value::object(vec![ assert!(possible_types.contains(&Value::object(
("name", Value::string("Root")), vec![("name", Value::string("Root"))].into_iter().collect()
].into_iter().collect()))); )));
let fields = type_info let fields = type_info
.get("fields") .get("fields")
@ -236,21 +258,41 @@ fn interface_introspection() {
assert_eq!(fields.len(), 1); assert_eq!(fields.len(), 1);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("sampleEnum")), fields.contains(&Value::object(
("description", Value::string("A sample field in the interface")), vec![
("args", Value::list(vec![])), ("name", Value::string("sampleEnum")),
("type", Value::object(vec![ (
("name", Value::null()), "description",
("kind", Value::string("NON_NULL")), Value::string("A sample field in the interface"),
("ofType", Value::object(vec![ ),
("name", Value::string("SampleEnum")), ("args", Value::list(vec![])),
("kind", Value::string("ENUM")), (
].into_iter().collect())), "type",
].into_iter().collect())), Value::object(
("isDeprecated", Value::boolean(false)), vec![
("deprecationReason", Value::null()), ("name", Value::null()),
].into_iter().collect()))); ("kind", Value::string("NON_NULL")),
(
"ofType",
Value::object(
vec![
("name", Value::string("SampleEnum")),
("kind", Value::string("ENUM")),
].into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
} }
#[test] #[test]
@ -318,14 +360,20 @@ fn object_introspection() {
assert_eq!(type_info.get("name"), Some(&Value::string("Root"))); assert_eq!(type_info.get("name"), Some(&Value::string("Root")));
assert_eq!(type_info.get("kind"), Some(&Value::string("OBJECT"))); assert_eq!(type_info.get("kind"), Some(&Value::string("OBJECT")));
assert_eq!(type_info.get("description"), Some(&Value::string("The root query object in the schema"))); assert_eq!(
type_info.get("description"),
Some(&Value::string("The root query object in the schema"))
);
assert_eq!( assert_eq!(
type_info.get("interfaces"), type_info.get("interfaces"),
Some(&Value::list(vec![ Some(&Value::list(vec![
Value::object(vec![ Value::object(
("name", Value::string("SampleInterface")), vec![("name", Value::string("SampleInterface"))]
].into_iter().collect()), .into_iter()
]))); .collect(),
),
]))
);
assert_eq!(type_info.get("enumValues"), Some(&Value::null())); assert_eq!(type_info.get("enumValues"), Some(&Value::null()));
assert_eq!(type_info.get("inputFields"), Some(&Value::null())); assert_eq!(type_info.get("inputFields"), Some(&Value::null()));
assert_eq!(type_info.get("ofType"), Some(&Value::null())); assert_eq!(type_info.get("ofType"), Some(&Value::null()));
@ -341,62 +389,126 @@ fn object_introspection() {
println!("Fields: {:#?}", fields); println!("Fields: {:#?}", fields);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("sampleEnum")), fields.contains(&Value::object(
("description", Value::null()), vec![
("args", Value::list(vec![])), ("name", Value::string("sampleEnum")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("args", Value::list(vec![])),
("kind", Value::string("NON_NULL")), (
("ofType", Value::object(vec![ "type",
("name", Value::string("SampleEnum")), Value::object(
("kind", Value::string("ENUM")), vec![
].into_iter().collect())), ("name", Value::null()),
].into_iter().collect())), ("kind", Value::string("NON_NULL")),
("isDeprecated", Value::boolean(false)), (
("deprecationReason", Value::null()), "ofType",
].into_iter().collect()))); Value::object(
vec![
("name", Value::string("SampleEnum")),
("kind", Value::string("ENUM")),
].into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("sampleScalar")), fields.contains(&Value::object(
("description", Value::string("A sample scalar field on the object")), vec![
("args", Value::list(vec![ ("name", Value::string("sampleScalar")),
Value::object(vec![ (
("name", Value::string("first")), "description",
("description", Value::string("The first number")), Value::string("A sample scalar field on the object"),
("type", Value::object(vec![ ),
("name", Value::null()), (
("kind", Value::string("NON_NULL")), "args",
("ofType", Value::object(vec![ Value::list(vec![
("name", Value::string("Int")), Value::object(
("kind", Value::string("SCALAR")), vec![
("ofType", Value::null()), ("name", Value::string("first")),
].into_iter().collect())), ("description", Value::string("The first number")),
].into_iter().collect())), (
("defaultValue", Value::null()), "type",
].into_iter().collect()), Value::object(
Value::object(vec![ vec![
("name", Value::string("second")), ("name", Value::null()),
("description", Value::string("The second number")), ("kind", Value::string("NON_NULL")),
("type", Value::object(vec![ (
("name", Value::string("Int")), "ofType",
("kind", Value::string("SCALAR")), Value::object(
("ofType", Value::null()), vec![
].into_iter().collect())), ("name", Value::string("Int")),
("defaultValue", Value::string("123")), ("kind", Value::string("SCALAR")),
].into_iter().collect()), ("ofType", Value::null()),
])), ].into_iter()
("type", Value::object(vec![ .collect(),
("name", Value::null()), ),
("kind", Value::string("NON_NULL")), ),
("ofType", Value::object(vec![ ].into_iter()
("name", Value::string("SampleScalar")), .collect(),
("kind", Value::string("SCALAR")), ),
].into_iter().collect())), ),
].into_iter().collect())), ("defaultValue", Value::null()),
("isDeprecated", Value::boolean(false)), ].into_iter()
("deprecationReason", Value::null()), .collect(),
].into_iter().collect()))); ),
Value::object(
vec![
("name", Value::string("second")),
("description", Value::string("The second number")),
(
"type",
Value::object(
vec![
("name", Value::string("Int")),
("kind", Value::string("SCALAR")),
("ofType", Value::null()),
].into_iter()
.collect(),
),
),
("defaultValue", Value::string("123")),
].into_iter()
.collect(),
),
]),
),
(
"type",
Value::object(
vec![
("name", Value::null()),
("kind", Value::string("NON_NULL")),
(
"ofType",
Value::object(
vec![
("name", Value::string("SampleScalar")),
("kind", Value::string("SCALAR")),
].into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
("isDeprecated", Value::boolean(false)),
("deprecationReason", Value::null()),
].into_iter()
.collect()
))
);
} }
#[test] #[test]
@ -431,15 +543,21 @@ fn scalar_introspection() {
.get("__type") .get("__type")
.expect("__type field missing"); .expect("__type field missing");
assert_eq!(type_info, &Value::object(vec![ assert_eq!(
("name", Value::string("SampleScalar")), type_info,
("kind", Value::string("SCALAR")), &Value::object(
("description", Value::null()), vec![
("fields", Value::null()), ("name", Value::string("SampleScalar")),
("interfaces", Value::null()), ("kind", Value::string("SCALAR")),
("possibleTypes", Value::null()), ("description", Value::null()),
("enumValues", Value::null()), ("fields", Value::null()),
("inputFields", Value::null()), ("interfaces", Value::null()),
("ofType", Value::null()), ("possibleTypes", Value::null()),
].into_iter().collect())); ("enumValues", Value::null()),
("inputFields", Value::null()),
("ofType", Value::null()),
].into_iter()
.collect()
)
);
} }

File diff suppressed because it is too large Load diff

View file

@ -62,5 +62,4 @@ pub fn graphiql_source(graphql_endpoint_url: &str) -> String {
graphql_url = graphql_endpoint_url, graphql_url = graphql_endpoint_url,
stylesheet_source = stylesheet_source, stylesheet_source = stylesheet_source,
fetcher_source = fetcher_source) fetcher_source = fetcher_source)
} }

View file

@ -19,8 +19,7 @@ use executor::ExecutionError;
#[derive(Deserialize, Clone, Serialize, PartialEq, Debug)] #[derive(Deserialize, Clone, Serialize, PartialEq, Debug)]
pub struct GraphQLRequest { pub struct GraphQLRequest {
query: String, query: String,
#[serde(rename = "operationName")] #[serde(rename = "operationName")] operation_name: Option<String>,
operation_name: Option<String>,
variables: Option<InputValue>, variables: Option<InputValue>,
} }

View file

@ -15,7 +15,7 @@
*/ */
use chrono::prelude::*; use chrono::prelude::*;
use ::Value; use Value;
#[doc(hidden)] #[doc(hidden)]
pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%.f%:z"; pub static RFC3339_FORMAT: &'static str = "%Y-%m-%dT%H:%M:%S%.f%:z";
@ -113,7 +113,9 @@ mod test {
let input = ::InputValue::String(raw.to_string()); let input = ::InputValue::String(raw.to_string());
let parsed: DateTime<Utc> = ::FromInputValue::from_input_value(&input).unwrap(); let parsed: DateTime<Utc> = ::FromInputValue::from_input_value(&input).unwrap();
let expected = DateTime::parse_from_rfc3339(raw).unwrap().with_timezone(&Utc); let expected = DateTime::parse_from_rfc3339(raw)
.unwrap()
.with_timezone(&Utc);
assert_eq!(parsed, expected); assert_eq!(parsed, expected);
} }

View file

@ -47,9 +47,8 @@ impl<'a> ser::Serialize for GraphQLError<'a> {
GraphQLError::NoOperationProvided => { GraphQLError::NoOperationProvided => {
serializer.serialize_str("Must provide an operation") serializer.serialize_str("Must provide an operation")
} }
GraphQLError::MultipleOperationsProvided => serializer.serialize_str( GraphQLError::MultipleOperationsProvided => serializer
"Must provide operation name if query contains multiple operations", .serialize_str("Must provide operation name if query contains multiple operations"),
),
GraphQLError::UnknownOperationName => serializer.serialize_str("Unknown operation"), GraphQLError::UnknownOperationName => serializer.serialize_str("Unknown operation"),
} }
} }

View file

@ -1,6 +1,6 @@
use url::Url; use url::Url;
use ::Value; use Value;
graphql_scalar!(Url { graphql_scalar!(Url {
description: "Url" description: "Url"

View file

@ -1,6 +1,6 @@
use uuid::Uuid; use uuid::Uuid;
use ::Value; use Value;
graphql_scalar!(Uuid { graphql_scalar!(Uuid {
description: "Uuid" description: "Uuid"
@ -29,4 +29,4 @@ mod test {
assert_eq!(parsed, id); assert_eq!(parsed, id);
} }
} }

View file

@ -212,5 +212,3 @@ impl<'a> From<Spanning<ParseError<'a>>> for GraphQLError<'a> {
GraphQLError::ParseError(f) GraphQLError::ParseError(f)
} }
} }

View file

@ -5,7 +5,12 @@ macro_rules! __graphql__build_field_matches {
( (
$resolveargs:tt, $resolveargs:tt,
( $( $acc:tt )* ), ( $( $acc:tt )* ),
field deprecated $_reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* field deprecated $_reason:tt
$name:ident
$args:tt -> $t:ty
as $desc:tt
$body:block
$( $rest:tt )*
) => { ) => {
__graphql__build_field_matches!( __graphql__build_field_matches!(
$resolveargs, $resolveargs,
@ -28,7 +33,12 @@ macro_rules! __graphql__build_field_matches {
// field <name>(...) -> <type> as <description> { ... } // field <name>(...) -> <type> as <description> { ... }
( (
$resolveargs:tt, $resolveargs:tt,
( $( $acc:tt )* ), field $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* ( $( $acc:tt )* ),
field $name:ident
$args:tt -> $t:ty
as $desc:tt
$body:block
$( $rest:tt )*
) => { ) => {
__graphql__build_field_matches!( __graphql__build_field_matches!(
$resolveargs, $resolveargs,
@ -55,7 +65,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, instance_resolvers : | $execvar:pat | $resolvers:tt $( $rest:tt )*) => { ( $resolveargs:tt,
$acc:tt,
instance_resolvers : | $execvar:pat | $resolvers:tt $( $rest:tt )*
) => {
__graphql__build_field_matches!($resolveargs, $acc, $( $rest )*); __graphql__build_field_matches!($resolveargs, $acc, $( $rest )*);
}; };
@ -79,7 +92,8 @@ macro_rules! __graphql__build_field_matches {
return ($crate::IntoResolvable::into(result, $executorvar.context())).and_then( return ($crate::IntoResolvable::into(result, $executorvar.context())).and_then(
|res| match res { |res| match res {
Some((ctx, r)) => $executorvar.replaced_context(ctx).resolve_with_ctx(&(), &r), Some((ctx, r)) =>
$executorvar.replaced_context(ctx).resolve_with_ctx(&(), &r),
None => Ok($crate::Value::null()), None => Ok($crate::Value::null()),
}) })
} }

View file

@ -94,7 +94,11 @@ macro_rules! graphql_interface {
( (
@ gather_meta, @ gather_meta,
($reg:expr, $acc:expr, $info:expr, $descr:expr), ($reg:expr, $acc:expr, $info:expr, $descr:expr),
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* field deprecated $reason:tt
$name:ident
$args:tt -> $t:ty as $desc:tt
$body:block
$( $rest:tt )*
) => { ) => {
$acc.push(__graphql__args!( $acc.push(__graphql__args!(
@apply_args, @apply_args,
@ -177,7 +181,8 @@ macro_rules! graphql_interface {
( (
@ gather_meta, @ gather_meta,
($reg:expr, $acc:expr, $info:expr, $descr:expr), ($reg:expr, $acc:expr, $info:expr, $descr:expr),
instance_resolvers : | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers : | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
$( $(
let _ = $reg.get_type::<$srctype>(&()); let _ = $reg.get_type::<$srctype>(&());
@ -190,7 +195,8 @@ macro_rules! graphql_interface {
( (
@ concrete_type_name, @ concrete_type_name,
($outname:tt, $ctxtarg:ident, $ctxttype:ty), ($outname:tt, $ctxtarg:ident, $ctxttype:ty),
instance_resolvers : | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers : | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
let $ctxtvar = &$ctxtarg; let $ctxtvar = &$ctxtarg;
@ -207,7 +213,8 @@ macro_rules! graphql_interface {
( (
@ resolve_into_type, @ resolve_into_type,
($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty), ($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty),
instance_resolvers : | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers : | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
let $ctxtvar = &$execarg.context(); let $ctxtvar = &$execarg.context();
@ -241,10 +248,15 @@ macro_rules! graphql_interface {
#[allow(unused_assignments)] #[allow(unused_assignments)]
#[allow(unused_mut)] #[allow(unused_mut)]
fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { fn meta<'r>(
info: &(),
registry: &mut $crate::Registry<'r>
) -> $crate::meta::MetaType<'r> {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut description = None; let mut description = None;
graphql_interface!(@ gather_meta, (registry, fields, info, description), $($items)*); graphql_interface!(
@ gather_meta, (registry, fields, info, description), $($items)*
);
let mut mt = registry.build_interface_type::<$name>(&(), &fields); let mut mt = registry.build_interface_type::<$name>(&(), &fields);
if let Some(description) = description { if let Some(description) = description {
@ -256,7 +268,13 @@ macro_rules! graphql_interface {
#[allow(unused_variables)] #[allow(unused_variables)]
#[allow(unused_mut)] #[allow(unused_mut)]
fn resolve_field(&$mainself, info: &(), field: &str, args: &$crate::Arguments, mut executor: &$crate::Executor<Self::Context>) -> $crate::ExecutionResult { fn resolve_field(
&$mainself,
info: &(),
field: &str,
args: &$crate::Arguments,
mut executor: &$crate::Executor<Self::Context>
) -> $crate::ExecutionResult {
__graphql__build_field_matches!( __graphql__build_field_matches!(
($outname, $mainself, field, args, executor), ($outname, $mainself, field, args, executor),
(), (),

View file

@ -246,7 +246,13 @@ macro_rules! graphql_object {
( (
@gather_object_meta, @gather_object_meta,
$reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr, $reg:expr, $acc:expr, $info:expr, $descr:expr, $ifaces:expr,
field deprecated $reason:tt $name:ident $args:tt -> $t:ty as $desc:tt $body:block $( $rest:tt )* field deprecated
$reason:tt
$name:ident
$args:tt -> $t:ty
as $desc:tt
$body:block
$( $rest:tt )*
) => { ) => {
$acc.push(__graphql__args!( $acc.push(__graphql__args!(
@apply_args, @apply_args,
@ -376,7 +382,10 @@ macro_rules! graphql_object {
#[allow(unused_assignments)] #[allow(unused_assignments)]
#[allow(unused_mut)] #[allow(unused_mut)]
fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { fn meta<'r>(
info: &(),
registry: &mut $crate::Registry<'r>
) -> $crate::meta::MetaType<'r> {
let mut fields = Vec::new(); let mut fields = Vec::new();
let mut description = None; let mut description = None;
let mut interfaces: Option<Vec<$crate::Type>> = None; let mut interfaces: Option<Vec<$crate::Type>> = None;

View file

@ -71,7 +71,10 @@ macro_rules! graphql_scalar {
Some(graphql_scalar!( @as_expr, $outname )) Some(graphql_scalar!( @as_expr, $outname ))
} }
fn meta<'r>(info: &(), registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> { fn meta<'r>(
info: &(),
registry: &mut $crate::Registry<'r>
) -> $crate::meta::MetaType<'r> {
graphql_scalar!( graphql_scalar!(
@maybe_apply, $descr, description, @maybe_apply, $descr, description,
registry.build_scalar_type::<Self>(info)) registry.build_scalar_type::<Self>(info))

View file

@ -170,17 +170,31 @@ fn introspect_field_exec_arg_and_more() {
run_args_info_query("execArgAndMore", |args| { run_args_info_query("execArgAndMore", |args| {
assert_eq!(args.len(), 1); assert_eq!(args.len(), 1);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -189,17 +203,31 @@ fn introspect_field_single_arg() {
run_args_info_query("singleArg", |args| { run_args_info_query("singleArg", |args| {
assert_eq!(args.len(), 1); assert_eq!(args.len(), 1);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -208,29 +236,57 @@ fn introspect_field_multi_args() {
run_args_info_query("multiArgs", |args| { run_args_info_query("multiArgs", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -239,29 +295,57 @@ fn introspect_field_multi_args_trailing_comma() {
run_args_info_query("multiArgsTrailingComma", |args| { run_args_info_query("multiArgsTrailingComma", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::null()), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -270,17 +354,31 @@ fn introspect_field_single_arg_descr() {
run_args_info_query("singleArgDescr", |args| { run_args_info_query("singleArgDescr", |args| {
assert_eq!(args.len(), 1); assert_eq!(args.len(), 1);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg")), args.contains(&Value::object(
("description", Value::string("The arg")), vec![
("defaultValue", Value::null()), ("name", Value::string("arg")),
("type", Value::object(vec![ ("description", Value::string("The arg")),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -289,29 +387,57 @@ fn introspect_field_multi_args_descr() {
run_args_info_query("multiArgsDescr", |args| { run_args_info_query("multiArgsDescr", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::string("The first arg")), vec![
("defaultValue", Value::null()), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::string("The first arg")),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::string("The second arg")), vec![
("defaultValue", Value::null()), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::string("The second arg")),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -320,29 +446,57 @@ fn introspect_field_multi_args_descr_trailing_comma() {
run_args_info_query("multiArgsDescrTrailingComma", |args| { run_args_info_query("multiArgsDescrTrailingComma", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::string("The first arg")), vec![
("defaultValue", Value::null()), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::string("The first arg")),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::string("The second arg")), vec![
("defaultValue", Value::null()), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::string("The second arg")),
("name", Value::null()), ("defaultValue", Value::null()),
("ofType", Value::object(vec![ (
("name", Value::string("Int")), "type",
].into_iter().collect())), Value::object(
].into_iter().collect())), vec![
].into_iter().collect()))); ("name", Value::null()),
(
"ofType",
Value::object(
vec![("name", Value::string("Int"))].into_iter().collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -351,15 +505,24 @@ fn introspect_field_arg_with_default() {
run_args_info_query("argWithDefault", |args| { run_args_info_query("argWithDefault", |args| {
assert_eq!(args.len(), 1); assert_eq!(args.len(), 1);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -368,25 +531,43 @@ fn introspect_field_multi_args_with_default() {
run_args_info_query("multiArgsWithDefault", |args| { run_args_info_query("multiArgsWithDefault", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::string("456")), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::string("Int")), ("defaultValue", Value::string("456")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -395,25 +576,43 @@ fn introspect_field_multi_args_with_default_trailing_comma() {
run_args_info_query("multiArgsWithDefaultTrailingComma", |args| { run_args_info_query("multiArgsWithDefaultTrailingComma", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::null()), vec![
("defaultValue", Value::string("456")), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::null()),
("name", Value::string("Int")), ("defaultValue", Value::string("456")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -422,15 +621,24 @@ fn introspect_field_arg_with_default_descr() {
run_args_info_query("argWithDefaultDescr", |args| { run_args_info_query("argWithDefaultDescr", |args| {
assert_eq!(args.len(), 1); assert_eq!(args.len(), 1);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg")), args.contains(&Value::object(
("description", Value::string("The arg")), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg")),
("type", Value::object(vec![ ("description", Value::string("The arg")),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -439,25 +647,43 @@ fn introspect_field_multi_args_with_default_descr() {
run_args_info_query("multiArgsWithDefaultDescr", |args| { run_args_info_query("multiArgsWithDefaultDescr", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::string("The first arg")), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::string("The first arg")),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::string("The second arg")), vec![
("defaultValue", Value::string("456")), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::string("The second arg")),
("name", Value::string("Int")), ("defaultValue", Value::string("456")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -466,25 +692,43 @@ fn introspect_field_multi_args_with_default_trailing_comma_descr() {
run_args_info_query("multiArgsWithDefaultTrailingCommaDescr", |args| { run_args_info_query("multiArgsWithDefaultTrailingCommaDescr", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::string("The first arg")), vec![
("defaultValue", Value::string("123")), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::string("The first arg")),
("name", Value::string("Int")), ("defaultValue", Value::string("123")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::string("The second arg")), vec![
("defaultValue", Value::string("456")), ("name", Value::string("arg2")),
("type", Value::object(vec![ ("description", Value::string("The second arg")),
("name", Value::string("Int")), ("defaultValue", Value::string("456")),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("Int")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }
@ -493,24 +737,45 @@ fn introspect_field_args_with_complex_default() {
run_args_info_query("argsWithComplexDefault", |args| { run_args_info_query("argsWithComplexDefault", |args| {
assert_eq!(args.len(), 2); assert_eq!(args.len(), 2);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg1")), args.contains(&Value::object(
("description", Value::string("A string default argument")), vec![
("defaultValue", Value::string(r#""test""#)), ("name", Value::string("arg1")),
("type", Value::object(vec![ ("description", Value::string("A string default argument")),
("name", Value::string("String")), ("defaultValue", Value::string(r#""test""#)),
("ofType", Value::null()), (
].into_iter().collect())), "type",
].into_iter().collect()))); Value::object(
vec![("name", Value::string("String")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
assert!(args.contains(&Value::object(vec![ assert!(
("name", Value::string("arg2")), args.contains(&Value::object(
("description", Value::string("An input object default argument")), vec![
("defaultValue", Value::string(r#"{x: 1}"#)), ("name", Value::string("arg2")),
("type", Value::object(vec![ (
("name", Value::string("Point")), "description",
("ofType", Value::null()), Value::string("An input object default argument"),
].into_iter().collect())), ),
].into_iter().collect()))); ("defaultValue", Value::string(r#"{x: 1}"#)),
(
"type",
Value::object(
vec![("name", Value::string("Point")), ("ofType", Value::null())]
.into_iter()
.collect(),
),
),
].into_iter()
.collect()
))
);
}); });
} }

View file

@ -74,9 +74,8 @@ where
} }
"#; "#;
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new()); let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
let vars = vec![ let vars = vec![("typeName".to_owned(), InputValue::string(type_name))]
("typeName".to_owned(), InputValue::string(type_name)), .into_iter()
].into_iter()
.collect(); .collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed");
@ -143,7 +142,10 @@ fn introspect_interface_field_simple() {
fn introspect_object_field_description() { fn introspect_object_field_description() {
run_field_info_query("Root", "description", |field| { run_field_info_query("Root", "description", |field| {
assert_eq!(field.get("name"), Some(&Value::string("description"))); assert_eq!(field.get("name"), Some(&Value::string("description")));
assert_eq!(field.get("description"), Some(&Value::string("Field description"))); assert_eq!(
field.get("description"),
Some(&Value::string("Field description"))
);
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
assert_eq!(field.get("deprecationReason"), Some(&Value::null())); assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
}); });
@ -153,7 +155,10 @@ fn introspect_object_field_description() {
fn introspect_interface_field_description() { fn introspect_interface_field_description() {
run_field_info_query("Interface", "description", |field| { run_field_info_query("Interface", "description", |field| {
assert_eq!(field.get("name"), Some(&Value::string("description"))); assert_eq!(field.get("name"), Some(&Value::string("description")));
assert_eq!(field.get("description"), Some(&Value::string("Field description"))); assert_eq!(
field.get("description"),
Some(&Value::string("Field description"))
);
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(false)));
assert_eq!(field.get("deprecationReason"), Some(&Value::null())); assert_eq!(field.get("deprecationReason"), Some(&Value::null()));
}); });
@ -165,7 +170,10 @@ fn introspect_object_field_deprecated() {
assert_eq!(field.get("name"), Some(&Value::string("deprecated"))); assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
assert_eq!(field.get("description"), Some(&Value::null())); assert_eq!(field.get("description"), Some(&Value::null()));
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason"))); assert_eq!(
field.get("deprecationReason"),
Some(&Value::string("Deprecation reason"))
);
}); });
} }
@ -175,7 +183,10 @@ fn introspect_interface_field_deprecated() {
assert_eq!(field.get("name"), Some(&Value::string("deprecated"))); assert_eq!(field.get("name"), Some(&Value::string("deprecated")));
assert_eq!(field.get("description"), Some(&Value::null())); assert_eq!(field.get("description"), Some(&Value::null()));
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason"))); assert_eq!(
field.get("deprecationReason"),
Some(&Value::string("Deprecation reason"))
);
}); });
} }
@ -183,9 +194,15 @@ fn introspect_interface_field_deprecated() {
fn introspect_object_field_deprecated_descr() { fn introspect_object_field_deprecated_descr() {
run_field_info_query("Root", "deprecatedDescr", |field| { run_field_info_query("Root", "deprecatedDescr", |field| {
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr"))); assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
assert_eq!(field.get("description"), Some(&Value::string("Field description"))); assert_eq!(
field.get("description"),
Some(&Value::string("Field description"))
);
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason"))); assert_eq!(
field.get("deprecationReason"),
Some(&Value::string("Deprecation reason"))
);
}); });
} }
@ -193,8 +210,14 @@ fn introspect_object_field_deprecated_descr() {
fn introspect_interface_field_deprecated_descr() { fn introspect_interface_field_deprecated_descr() {
run_field_info_query("Interface", "deprecatedDescr", |field| { run_field_info_query("Interface", "deprecatedDescr", |field| {
assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr"))); assert_eq!(field.get("name"), Some(&Value::string("deprecatedDescr")));
assert_eq!(field.get("description"), Some(&Value::string("Field description"))); assert_eq!(
field.get("description"),
Some(&Value::string("Field description"))
);
assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true))); assert_eq!(field.get("isDeprecated"), Some(&Value::boolean(true)));
assert_eq!(field.get("deprecationReason"), Some(&Value::string("Deprecation reason"))); assert_eq!(
field.get("deprecationReason"),
Some(&Value::string("Deprecation reason"))
);
}); });
} }

View file

@ -53,7 +53,6 @@ graphql_interface!(CustomName: () as "ACustomNamedInterface" |&self| {
instance_resolvers: |_| { Concrete => Some(Concrete) } instance_resolvers: |_| { Concrete => Some(Concrete) }
}); });
graphql_interface!(<'a> WithLifetime<'a>: () as "WithLifetime" |&self| { graphql_interface!(<'a> WithLifetime<'a>: () as "WithLifetime" |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
instance_resolvers: |_| { Concrete => Some(Concrete) } instance_resolvers: |_| { Concrete => Some(Concrete) }
@ -64,7 +63,6 @@ graphql_interface!(<T> WithGenerics<T>: () as "WithGenerics" |&self| {
instance_resolvers: |_| { Concrete => Some(Concrete) } instance_resolvers: |_| { Concrete => Some(Concrete) }
}); });
graphql_interface!(DescriptionFirst: () |&self| { graphql_interface!(DescriptionFirst: () |&self| {
description: "A description" description: "A description"
@ -97,7 +95,6 @@ graphql_interface!(CommasWithTrailing: () |&self| {
description: "A description", description: "A description",
}); });
graphql_interface!(CommasOnMeta: () |&self| { graphql_interface!(CommasOnMeta: () |&self| {
instance_resolvers: |_| { Concrete => Some(Concrete) } instance_resolvers: |_| { Concrete => Some(Concrete) }
description: "A description", description: "A description",
@ -105,7 +102,6 @@ graphql_interface!(CommasOnMeta: () |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
}); });
graphql_interface!(ResolversWithTrailingComma: () |&self| { graphql_interface!(ResolversWithTrailingComma: () |&self| {
instance_resolvers: |_| { Concrete => Some(Concrete), } instance_resolvers: |_| { Concrete => Some(Concrete), }
description: "A description", description: "A description",
@ -132,7 +128,6 @@ graphql_object!(<'a> Root: () as "Root" |&self| {
}); });
fn run_type_info_query<F>(type_name: &str, f: F) fn run_type_info_query<F>(type_name: &str, f: F)
where where
F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (), F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (),
@ -149,9 +144,8 @@ where
} }
"#; "#;
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new()); let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
let vars = vec![ let vars = vec![("typeName".to_owned(), InputValue::string(type_name))]
("typeName".to_owned(), InputValue::string(type_name)), .into_iter()
].into_iter()
.collect(); .collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed");
@ -180,12 +174,19 @@ where
#[test] #[test]
fn introspect_custom_name() { fn introspect_custom_name() {
run_type_info_query("ACustomNamedInterface", |object, fields| { run_type_info_query("ACustomNamedInterface", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("ACustomNamedInterface"))); assert_eq!(
object.get("name"),
Some(&Value::string("ACustomNamedInterface"))
);
assert_eq!(object.get("description"), Some(&Value::null())); assert_eq!(object.get("description"), Some(&Value::null()));
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -195,9 +196,13 @@ fn introspect_with_lifetime() {
assert_eq!(object.get("name"), Some(&Value::string("WithLifetime"))); assert_eq!(object.get("name"), Some(&Value::string("WithLifetime")));
assert_eq!(object.get("description"), Some(&Value::null())); assert_eq!(object.get("description"), Some(&Value::null()));
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -207,9 +212,13 @@ fn introspect_with_generics() {
assert_eq!(object.get("name"), Some(&Value::string("WithGenerics"))); assert_eq!(object.get("name"), Some(&Value::string("WithGenerics")));
assert_eq!(object.get("description"), Some(&Value::null())); assert_eq!(object.get("description"), Some(&Value::null()));
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -217,11 +226,18 @@ fn introspect_with_generics() {
fn introspect_description_first() { fn introspect_description_first() {
run_type_info_query("DescriptionFirst", |object, fields| { run_type_info_query("DescriptionFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst"))); assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -229,11 +245,18 @@ fn introspect_description_first() {
fn introspect_fields_first() { fn introspect_fields_first() {
run_type_info_query("FieldsFirst", |object, fields| { run_type_info_query("FieldsFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst"))); assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -241,23 +264,40 @@ fn introspect_fields_first() {
fn introspect_interfaces_first() { fn introspect_interfaces_first() {
run_type_info_query("InterfacesFirst", |object, fields| { run_type_info_query("InterfacesFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst"))); assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
#[test] #[test]
fn introspect_commas_with_trailing() { fn introspect_commas_with_trailing() {
run_type_info_query("CommasWithTrailing", |object, fields| { run_type_info_query("CommasWithTrailing", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("CommasWithTrailing"))); assert_eq!(
assert_eq!(object.get("description"), Some(&Value::string("A description"))); object.get("name"),
Some(&Value::string("CommasWithTrailing"))
);
assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -265,22 +305,39 @@ fn introspect_commas_with_trailing() {
fn introspect_commas_on_meta() { fn introspect_commas_on_meta() {
run_type_info_query("CommasOnMeta", |object, fields| { run_type_info_query("CommasOnMeta", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta"))); assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }
#[test] #[test]
fn introspect_resolvers_with_trailing_comma() { fn introspect_resolvers_with_trailing_comma() {
run_type_info_query("ResolversWithTrailingComma", |object, fields| { run_type_info_query("ResolversWithTrailingComma", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("ResolversWithTrailingComma"))); assert_eq!(
assert_eq!(object.get("description"), Some(&Value::string("A description"))); object.get("name"),
Some(&Value::string("ResolversWithTrailingComma"))
);
assert_eq!(
object.get("description"),
Some(&Value::string("A description"))
);
assert!(fields.contains(&Value::object(vec![ assert!(
("name", Value::string("simple")), fields.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("simple"))]
.into_iter()
.collect()
))
);
}); });
} }

View file

@ -4,6 +4,3 @@ mod field;
mod object; mod object;
mod interface; mod interface;
mod union; mod union;

View file

@ -5,7 +5,7 @@ use ast::InputValue;
use value::Value; use value::Value;
use schema::model::RootNode; use schema::model::RootNode;
use types::scalars::EmptyMutation; use types::scalars::EmptyMutation;
use executor::{FieldResult, Context}; use executor::{Context, FieldResult};
/* /*
@ -46,7 +46,6 @@ graphql_object!(CustomName: () as "ACustomNamedType" |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
}); });
graphql_object!(<'a> WithLifetime<'a>: () as "WithLifetime" |&self| { graphql_object!(<'a> WithLifetime<'a>: () as "WithLifetime" |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
}); });
@ -55,7 +54,6 @@ graphql_object!(<T> WithGenerics<T>: () as "WithGenerics" |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
}); });
graphql_interface!(Interface: () |&self| { graphql_interface!(Interface: () |&self| {
field simple() -> i32 { 0 } field simple() -> i32 { 0 }
@ -96,7 +94,6 @@ graphql_object!(CommasWithTrailing: () |&self| {
description: "A description", description: "A description",
}); });
graphql_object!(CommasOnMeta: () |&self| { graphql_object!(CommasOnMeta: () |&self| {
interfaces: [Interface], interfaces: [Interface],
description: "A description", description: "A description",
@ -108,15 +105,25 @@ struct InnerContext;
impl Context for InnerContext {} impl Context for InnerContext {}
struct InnerType; struct InnerType;
graphql_object!(InnerType: InnerContext |&self| { graphql_object!(InnerType: InnerContext | &self | {});
});
struct CtxSwitcher; struct CtxSwitcher;
graphql_object!(CtxSwitcher: InnerContext |&self| { graphql_object!(CtxSwitcher: InnerContext |&self| {
field ctx_switch_always(&executor) -> (&InnerContext, InnerType) { (executor.context(), InnerType) } field ctx_switch_always(&executor) -> (&InnerContext, InnerType) {
field ctx_switch_opt(&executor) -> Option<(&InnerContext, InnerType)> { Some((executor.context(), InnerType)) } (executor.context(), InnerType)
field ctx_switch_res(&executor) -> FieldResult<(&InnerContext, InnerType)> { Ok((executor.context(), InnerType)) } }
field ctx_switch_res_opt(&executor) -> FieldResult<Option<(&InnerContext, InnerType)>> { Ok(Some((executor.context(), InnerType))) }
field ctx_switch_opt(&executor) -> Option<(&InnerContext, InnerType)> {
Some((executor.context(), InnerType))
}
field ctx_switch_res(&executor) -> FieldResult<(&InnerContext, InnerType)> {
Ok((executor.context(), InnerType))
}
field ctx_switch_res_opt(&executor) -> FieldResult<Option<(&InnerContext, InnerType)>> {
Ok(Some((executor.context(), InnerType)))
}
}); });
graphql_object!(<'a> Root: InnerContext as "Root" |&self| { graphql_object!(<'a> Root: InnerContext as "Root" |&self| {
@ -135,7 +142,6 @@ graphql_object!(<'a> Root: InnerContext as "Root" |&self| {
field ctx_switcher() -> CtxSwitcher { CtxSwitcher {} } field ctx_switcher() -> CtxSwitcher { CtxSwitcher {} }
}); });
fn run_type_info_query<F>(type_name: &str, f: F) fn run_type_info_query<F>(type_name: &str, f: F)
where where
F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (), F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (),
@ -164,12 +170,12 @@ where
} }
"#; "#;
let schema = RootNode::new(Root {}, EmptyMutation::<InnerContext>::new()); let schema = RootNode::new(Root {}, EmptyMutation::<InnerContext>::new());
let vars = vec![ let vars = vec![("typeName".to_owned(), InputValue::string(type_name))]
("typeName".to_owned(), InputValue::string(type_name)), .into_iter()
].into_iter()
.collect(); .collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &InnerContext).expect("Execution failed"); let (result, errs) =
::execute(doc, None, &schema, &vars, &InnerContext).expect("Execution failed");
assert_eq!(errs, []); assert_eq!(errs, []);
@ -238,13 +244,22 @@ fn introspect_with_generics() {
fn introspect_description_first() { fn introspect_description_first() {
run_type_info_query("DescriptionFirst", |object, fields| { run_type_info_query("DescriptionFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst"))); assert_eq!(object.get("name"), Some(&Value::string("DescriptionFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![ object.get("description"),
Value::object(vec![ Some(&Value::string("A description"))
("name", Value::string("Interface")), );
("kind", Value::string("INTERFACE")), assert_eq!(
].into_iter().collect()), object.get("interfaces"),
]))); Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
);
assert!(fields.contains(&graphql_value!({ assert!(fields.contains(&graphql_value!({
"name": "simple", "name": "simple",
@ -257,13 +272,22 @@ fn introspect_description_first() {
fn introspect_fields_first() { fn introspect_fields_first() {
run_type_info_query("FieldsFirst", |object, fields| { run_type_info_query("FieldsFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst"))); assert_eq!(object.get("name"), Some(&Value::string("FieldsFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![ object.get("description"),
Value::object(vec![ Some(&Value::string("A description"))
("name", Value::string("Interface")), );
("kind", Value::string("INTERFACE")), assert_eq!(
].into_iter().collect()), object.get("interfaces"),
]))); Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
);
assert!(fields.contains(&graphql_value!({ assert!(fields.contains(&graphql_value!({
"name": "simple", "name": "simple",
@ -276,13 +300,22 @@ fn introspect_fields_first() {
fn introspect_interfaces_first() { fn introspect_interfaces_first() {
run_type_info_query("InterfacesFirst", |object, fields| { run_type_info_query("InterfacesFirst", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst"))); assert_eq!(object.get("name"), Some(&Value::string("InterfacesFirst")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![ object.get("description"),
Value::object(vec![ Some(&Value::string("A description"))
("name", Value::string("Interface")), );
("kind", Value::string("INTERFACE")), assert_eq!(
].into_iter().collect()), object.get("interfaces"),
]))); Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
);
assert!(fields.contains(&graphql_value!({ assert!(fields.contains(&graphql_value!({
"name": "simple", "name": "simple",
@ -294,14 +327,26 @@ fn introspect_interfaces_first() {
#[test] #[test]
fn introspect_commas_with_trailing() { fn introspect_commas_with_trailing() {
run_type_info_query("CommasWithTrailing", |object, fields| { run_type_info_query("CommasWithTrailing", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("CommasWithTrailing"))); assert_eq!(
assert_eq!(object.get("description"), Some(&Value::string("A description"))); object.get("name"),
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![ Some(&Value::string("CommasWithTrailing"))
Value::object(vec![ );
("name", Value::string("Interface")), assert_eq!(
("kind", Value::string("INTERFACE")), object.get("description"),
].into_iter().collect()), 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(&graphql_value!({ assert!(fields.contains(&graphql_value!({
"name": "simple", "name": "simple",
@ -314,13 +359,22 @@ fn introspect_commas_with_trailing() {
fn introspect_commas_on_meta() { fn introspect_commas_on_meta() {
run_type_info_query("CommasOnMeta", |object, fields| { run_type_info_query("CommasOnMeta", |object, fields| {
assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta"))); assert_eq!(object.get("name"), Some(&Value::string("CommasOnMeta")));
assert_eq!(object.get("description"), Some(&Value::string("A description"))); assert_eq!(
assert_eq!(object.get("interfaces"), Some(&Value::list(vec![ object.get("description"),
Value::object(vec![ Some(&Value::string("A description"))
("name", Value::string("Interface")), );
("kind", Value::string("INTERFACE")), assert_eq!(
].into_iter().collect()), object.get("interfaces"),
]))); Some(&Value::list(vec![
Value::object(
vec![
("name", Value::string("Interface")),
("kind", Value::string("INTERFACE")),
].into_iter()
.collect(),
),
]))
);
assert!(fields.contains(&graphql_value!({ assert!(fields.contains(&graphql_value!({
"name": "simple", "name": "simple",

View file

@ -157,7 +157,13 @@ fn scalar_description_introspection() {
"#; "#;
run_type_info_query(doc, |type_info| { run_type_info_query(doc, |type_info| {
assert_eq!(type_info.get("name"), Some(&Value::string("ScalarDescription"))); assert_eq!(
assert_eq!(type_info.get("description"), Some(&Value::string("A sample scalar, represented as an integer"))); type_info.get("name"),
Some(&Value::string("ScalarDescription"))
);
assert_eq!(
type_info.get("description"),
Some(&Value::string("A sample scalar, represented as an integer"))
);
}); });
} }

View file

@ -109,7 +109,6 @@ graphql_object!(<'a> Root: () as "Root" |&self| {
} }
}); });
fn run_type_info_query<F>(type_name: &str, f: F) fn run_type_info_query<F>(type_name: &str, f: F)
where where
F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (), F: Fn(&OrderMap<String, Value>, &Vec<Value>) -> (),
@ -126,9 +125,8 @@ where
} }
"#; "#;
let schema = RootNode::new(Root {}, EmptyMutation::<()>::new()); let schema = RootNode::new(Root {}, EmptyMutation::<()>::new());
let vars = vec![ let vars = vec![("typeName".to_owned(), InputValue::string(type_name))]
("typeName".to_owned(), InputValue::string(type_name)), .into_iter()
].into_iter()
.collect(); .collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed"); let (result, errs) = ::execute(doc, None, &schema, &vars, &()).expect("Execution failed");
@ -154,16 +152,19 @@ where
f(type_info, possible_types); f(type_info, possible_types);
} }
#[test] #[test]
fn introspect_custom_name() { fn introspect_custom_name() {
run_type_info_query("ACustomNamedUnion", |union, possible_types| { run_type_info_query("ACustomNamedUnion", |union, possible_types| {
assert_eq!(union.get("name"), Some(&Value::string("ACustomNamedUnion"))); assert_eq!(union.get("name"), Some(&Value::string("ACustomNamedUnion")));
assert_eq!(union.get("description"), Some(&Value::null())); assert_eq!(union.get("description"), Some(&Value::null()));
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -173,9 +174,13 @@ fn introspect_with_lifetime() {
assert_eq!(union.get("name"), Some(&Value::string("WithLifetime"))); assert_eq!(union.get("name"), Some(&Value::string("WithLifetime")));
assert_eq!(union.get("description"), Some(&Value::null())); assert_eq!(union.get("description"), Some(&Value::null()));
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -185,9 +190,13 @@ fn introspect_with_generics() {
assert_eq!(union.get("name"), Some(&Value::string("WithGenerics"))); assert_eq!(union.get("name"), Some(&Value::string("WithGenerics")));
assert_eq!(union.get("description"), Some(&Value::null())); assert_eq!(union.get("description"), Some(&Value::null()));
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -195,11 +204,18 @@ fn introspect_with_generics() {
fn introspect_description_first() { fn introspect_description_first() {
run_type_info_query("DescriptionFirst", |union, possible_types| { run_type_info_query("DescriptionFirst", |union, possible_types| {
assert_eq!(union.get("name"), Some(&Value::string("DescriptionFirst"))); assert_eq!(union.get("name"), Some(&Value::string("DescriptionFirst")));
assert_eq!(union.get("description"), Some(&Value::string("A description"))); assert_eq!(
union.get("description"),
Some(&Value::string("A description"))
);
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
@ -207,34 +223,61 @@ fn introspect_description_first() {
fn introspect_resolvers_first() { fn introspect_resolvers_first() {
run_type_info_query("ResolversFirst", |union, possible_types| { run_type_info_query("ResolversFirst", |union, possible_types| {
assert_eq!(union.get("name"), Some(&Value::string("ResolversFirst"))); assert_eq!(union.get("name"), Some(&Value::string("ResolversFirst")));
assert_eq!(union.get("description"), Some(&Value::string("A description"))); assert_eq!(
union.get("description"),
Some(&Value::string("A description"))
);
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
#[test] #[test]
fn introspect_commas_with_trailing() { fn introspect_commas_with_trailing() {
run_type_info_query("CommasWithTrailing", |union, possible_types| { run_type_info_query("CommasWithTrailing", |union, possible_types| {
assert_eq!(union.get("name"), Some(&Value::string("CommasWithTrailing"))); assert_eq!(
assert_eq!(union.get("description"), Some(&Value::string("A description"))); union.get("name"),
Some(&Value::string("CommasWithTrailing"))
);
assert_eq!(
union.get("description"),
Some(&Value::string("A description"))
);
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }
#[test] #[test]
fn introspect_resolvers_with_trailing_comma() { fn introspect_resolvers_with_trailing_comma() {
run_type_info_query("ResolversWithTrailingComma", |union, possible_types| { run_type_info_query("ResolversWithTrailingComma", |union, possible_types| {
assert_eq!(union.get("name"), Some(&Value::string("ResolversWithTrailingComma"))); assert_eq!(
assert_eq!(union.get("description"), Some(&Value::string("A description"))); union.get("name"),
Some(&Value::string("ResolversWithTrailingComma"))
);
assert_eq!(
union.get("description"),
Some(&Value::string("A description"))
);
assert!(possible_types.contains(&Value::object(vec![ assert!(
("name", Value::string("Concrete")), possible_types.contains(&Value::object(
].into_iter().collect()))); vec![("name", Value::string("Concrete"))]
.into_iter()
.collect()
))
);
}); });
} }

View file

@ -40,7 +40,8 @@ macro_rules! graphql_union {
( (
@ gather_meta, @ gather_meta,
($reg:expr, $acc:expr, $descr:expr), ($reg:expr, $acc:expr, $descr:expr),
instance_resolvers: | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
$acc = vec![ $acc = vec![
$( $(
@ -56,7 +57,8 @@ macro_rules! graphql_union {
( (
@ concrete_type_name, @ concrete_type_name,
($outname:tt, $ctxtarg:ident, $ctxttype:ty), ($outname:tt, $ctxtarg:ident, $ctxttype:ty),
instance_resolvers: | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
let $ctxtvar = &$ctxtarg; let $ctxtvar = &$ctxtarg;
@ -74,7 +76,8 @@ macro_rules! graphql_union {
( (
@ resolve_into_type, @ resolve_into_type,
($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty), ($outname:tt, $typenamearg:ident, $execarg:ident, $ctxttype:ty),
instance_resolvers: | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )* instance_resolvers: | $ctxtvar:pat
| { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => { ) => {
let $ctxtvar = &$execarg.context(); let $ctxtvar = &$execarg.context();

View file

@ -32,9 +32,9 @@ fn parse_definition<'a>(parser: &mut Parser<'a>) -> UnlocatedParseResult<'a, Def
Token::CurlyOpen | Token::Name("query") | Token::Name("mutation") => Ok( Token::CurlyOpen | Token::Name("query") | Token::Name("mutation") => Ok(
Definition::Operation(try!(parse_operation_definition(parser))), Definition::Operation(try!(parse_operation_definition(parser))),
), ),
Token::Name("fragment") => Ok(Definition::Fragment( Token::Name("fragment") => Ok(Definition::Fragment(try!(parse_fragment_definition(
try!(parse_fragment_definition(parser)), parser
)), )))),
_ => Err(parser.next()?.map(ParseError::UnexpectedToken)), _ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
} }
} }
@ -237,13 +237,12 @@ fn parse_arguments<'a>(parser: &mut Parser<'a>) -> OptionParseResult<'a, Argumen
Ok(None) Ok(None)
} else { } else {
Ok(Some( Ok(Some(
try!( try!(parser.delimited_nonempty_list(
parser &Token::ParenOpen,
.delimited_nonempty_list(&Token::ParenOpen, parse_argument, &Token::ParenClose) parse_argument,
).map(|args| { &Token::ParenClose
Arguments { )).map(|args| Arguments {
items: args.into_iter().map(|s| s.item).collect(), items: args.into_iter().map(|s| s.item).collect(),
}
}), }),
)) ))
} }
@ -282,10 +281,8 @@ fn parse_variable_definitions<'a>(
&Token::ParenOpen, &Token::ParenOpen,
parse_variable_definition, parse_variable_definition,
&Token::ParenClose &Token::ParenClose
)).map(|defs| { )).map(|defs| VariableDefinitions {
VariableDefinitions { items: defs.into_iter().map(|s| s.item).collect(),
items: defs.into_iter().map(|s| s.item).collect(),
}
}), }),
)) ))
} }

View file

@ -127,9 +127,8 @@ impl<'a> Lexer<'a> {
let start_pos = self.position.clone(); let start_pos = self.position.clone();
self.next_char().expect( self.next_char()
"Internal error in GraphQL lexer: emit_single_char reached EOF", .expect("Internal error in GraphQL lexer: emit_single_char reached EOF");
);
Spanning::single_width(&start_pos, t) Spanning::single_width(&start_pos, t)
} }
@ -345,12 +344,12 @@ impl<'a> Lexer<'a> {
)); ));
} }
let code_point = try!(u32::from_str_radix(escape, 16).map_err(|_| { let code_point = try!(
Spanning::zero_width( u32::from_str_radix(escape, 16).map_err(|_| Spanning::zero_width(
start_pos, start_pos,
LexerError::UnknownEscapeSequence("\\u".to_owned() + escape), LexerError::UnknownEscapeSequence("\\u".to_owned() + escape),
) ))
})); );
char::from_u32(code_point).ok_or_else(|| { char::from_u32(code_point).ok_or_else(|| {
Spanning::zero_width( Spanning::zero_width(
@ -392,10 +391,12 @@ impl<'a> Lexer<'a> {
let mantissa = frac_part let mantissa = frac_part
.map(|f| f as f64) .map(|f| f as f64)
.map(|frac| if frac > 0f64 { .map(|frac| {
frac / 10f64.powf(frac.log10().floor() + 1f64) if frac > 0f64 {
} else { frac / 10f64.powf(frac.log10().floor() + 1f64)
0f64 } else {
0f64
}
}) })
.map(|m| if int_part < 0 { -m } else { m }); .map(|m| if int_part < 0 { -m } else { m });
@ -472,9 +473,8 @@ impl<'a> Lexer<'a> {
} }
} }
i32::from_str_radix(&self.source[start_idx..end_idx + 1], 10).map_err(|_| { i32::from_str_radix(&self.source[start_idx..end_idx + 1], 10)
Spanning::zero_width(&start_pos, LexerError::InvalidNumber) .map_err(|_| Spanning::zero_width(&start_pos, LexerError::InvalidNumber))
})
} }
} }

View file

@ -171,10 +171,12 @@ impl<'a> Parser<'a> {
Spanning { Spanning {
item: Token::Name(_), item: Token::Name(_),
.. ..
} => Ok(self.next()?.map(|token| if let Token::Name(name) = token { } => Ok(self.next()?.map(|token| {
name if let Token::Name(name) = token {
} else { name
panic!("Internal parse error in `expect_name`"); } else {
panic!("Internal parse error in `expect_name`");
}
})), })),
Spanning { Spanning {
item: Token::EndOfFile, item: Token::EndOfFile,

View file

@ -4,7 +4,6 @@ use ast::InputValue;
use parser::{Lexer, Parser, SourcePosition, Spanning}; use parser::{Lexer, Parser, SourcePosition, Spanning};
use parser::value::parse_value_literal; use parser::value::parse_value_literal;
fn parse_value(s: &str) -> Spanning<InputValue> { fn parse_value(s: &str) -> Spanning<InputValue> {
let mut lexer = Lexer::new(s); let mut lexer = Lexer::new(s);
let mut parser = Parser::new(&mut lexer).expect(&format!("Lexer error on input {:#?}", s)); let mut parser = Parser::new(&mut lexer).expect(&format!("Lexer error on input {:#?}", s));

View file

@ -33,10 +33,12 @@ pub fn parse_value_literal<'a>(
Spanning { Spanning {
item: Token::String(_), item: Token::String(_),
.. ..
} => Ok(parser.next()?.map(|t| if let Token::String(s) = t { } => Ok(parser.next()?.map(|t| {
InputValue::string(s) if let Token::String(s) = t {
} else { InputValue::string(s)
panic!("Internal parser error"); } else {
panic!("Internal parser error");
}
})), })),
Spanning { Spanning {
item: Token::Name("true"), item: Token::Name("true"),
@ -53,38 +55,30 @@ pub fn parse_value_literal<'a>(
Spanning { Spanning {
item: Token::Name(name), item: Token::Name(name),
.. ..
} => Ok( } => Ok(parser
parser .next()?
.next()? .map(|_| InputValue::enum_value(name.to_owned()))),
.map(|_| InputValue::enum_value(name.to_owned())),
),
_ => Err(parser.next()?.map(ParseError::UnexpectedToken)), _ => Err(parser.next()?.map(ParseError::UnexpectedToken)),
} }
} }
fn parse_list_literal<'a>(parser: &mut Parser<'a>, is_const: bool) -> ParseResult<'a, InputValue> { fn parse_list_literal<'a>(parser: &mut Parser<'a>, is_const: bool) -> ParseResult<'a, InputValue> {
Ok( Ok(try!(parser.delimited_list(
try!(parser.delimited_list( &Token::BracketOpen,
&Token::BracketOpen, |p| parse_value_literal(p, is_const),
|p| parse_value_literal(p, is_const), &Token::BracketClose
&Token::BracketClose )).map(InputValue::parsed_list))
)).map(InputValue::parsed_list),
)
} }
fn parse_object_literal<'a>( fn parse_object_literal<'a>(
parser: &mut Parser<'a>, parser: &mut Parser<'a>,
is_const: bool, is_const: bool,
) -> ParseResult<'a, InputValue> { ) -> ParseResult<'a, InputValue> {
Ok( Ok(try!(parser.delimited_list(
try!(parser.delimited_list( &Token::CurlyOpen,
&Token::CurlyOpen, |p| parse_object_field(p, is_const),
|p| parse_object_field(p, is_const), &Token::CurlyClose
&Token::CurlyClose )).map(|items| InputValue::parsed_object(items.into_iter().map(|s| s.item).collect())))
)).map(|items| {
InputValue::parsed_object(items.into_iter().map(|s| s.item).collect())
}),
)
} }
fn parse_object_field<'a>( fn parse_object_field<'a>(

View file

@ -8,85 +8,62 @@ use types::base::TypeKind;
/// Scalar type metadata /// Scalar type metadata
pub struct ScalarMeta<'a> { pub struct ScalarMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
pub description: Option<String>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
} }
/// List type metadata /// List type metadata
#[derive(Debug)] #[derive(Debug)]
pub struct ListMeta<'a> { pub struct ListMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub of_type: Type<'a>,
pub of_type: Type<'a>,
} }
/// Nullable type metadata /// Nullable type metadata
#[derive(Debug)] #[derive(Debug)]
pub struct NullableMeta<'a> { pub struct NullableMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub of_type: Type<'a>,
pub of_type: Type<'a>,
} }
/// Object type metadata /// Object type metadata
#[derive(Debug)] #[derive(Debug)]
pub struct ObjectMeta<'a> { pub struct ObjectMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub fields: Vec<Field<'a>>,
pub description: Option<String>, #[doc(hidden)] pub interface_names: Vec<String>,
#[doc(hidden)]
pub fields: Vec<Field<'a>>,
#[doc(hidden)]
pub interface_names: Vec<String>,
} }
/// Enum type metadata /// Enum type metadata
pub struct EnumMeta<'a> { pub struct EnumMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub values: Vec<EnumValue>,
pub description: Option<String>, #[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
#[doc(hidden)]
pub values: Vec<EnumValue>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
} }
/// Interface type metadata /// Interface type metadata
#[derive(Debug)] #[derive(Debug)]
pub struct InterfaceMeta<'a> { pub struct InterfaceMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub fields: Vec<Field<'a>>,
pub description: Option<String>,
#[doc(hidden)]
pub fields: Vec<Field<'a>>,
} }
/// Union type metadata /// Union type metadata
#[derive(Debug)] #[derive(Debug)]
pub struct UnionMeta<'a> { pub struct UnionMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub of_type_names: Vec<String>,
pub description: Option<String>,
#[doc(hidden)]
pub of_type_names: Vec<String>,
} }
/// Input object metadata /// Input object metadata
pub struct InputObjectMeta<'a> { pub struct InputObjectMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: Cow<'a, str>,
pub name: Cow<'a, str>, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub input_fields: Vec<Argument<'a>>,
pub description: Option<String>, #[doc(hidden)] pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
#[doc(hidden)]
pub input_fields: Vec<Argument<'a>>,
#[doc(hidden)]
pub try_parse_fn: Box<Fn(&InputValue) -> bool + Send + Sync>,
} }
/// A placeholder for not-yet-registered types /// A placeholder for not-yet-registered types
@ -95,59 +72,40 @@ pub struct InputObjectMeta<'a> {
/// is inserted into a registry to indicate existence. /// is inserted into a registry to indicate existence.
#[derive(Debug)] #[derive(Debug)]
pub struct PlaceholderMeta<'a> { pub struct PlaceholderMeta<'a> {
#[doc(hidden)] #[doc(hidden)] pub of_type: Type<'a>,
pub of_type: Type<'a>,
} }
/// Generic type metadata /// Generic type metadata
#[derive(Debug)] #[derive(Debug)]
pub enum MetaType<'a> { pub enum MetaType<'a> {
#[doc(hidden)] #[doc(hidden)] Scalar(ScalarMeta<'a>),
Scalar(ScalarMeta<'a>), #[doc(hidden)] List(ListMeta<'a>),
#[doc(hidden)] #[doc(hidden)] Nullable(NullableMeta<'a>),
List(ListMeta<'a>), #[doc(hidden)] Object(ObjectMeta<'a>),
#[doc(hidden)] #[doc(hidden)] Enum(EnumMeta<'a>),
Nullable(NullableMeta<'a>), #[doc(hidden)] Interface(InterfaceMeta<'a>),
#[doc(hidden)] #[doc(hidden)] Union(UnionMeta<'a>),
Object(ObjectMeta<'a>), #[doc(hidden)] InputObject(InputObjectMeta<'a>),
#[doc(hidden)] #[doc(hidden)] Placeholder(PlaceholderMeta<'a>),
Enum(EnumMeta<'a>),
#[doc(hidden)]
Interface(InterfaceMeta<'a>),
#[doc(hidden)]
Union(UnionMeta<'a>),
#[doc(hidden)]
InputObject(InputObjectMeta<'a>),
#[doc(hidden)]
Placeholder(PlaceholderMeta<'a>),
} }
/// Metadata for a field /// Metadata for a field
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Field<'a> { pub struct Field<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: String,
pub name: String, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub arguments: Option<Vec<Argument<'a>>>,
pub description: Option<String>, #[doc(hidden)] pub field_type: Type<'a>,
#[doc(hidden)] #[doc(hidden)] pub deprecation_reason: Option<String>,
pub arguments: Option<Vec<Argument<'a>>>,
#[doc(hidden)]
pub field_type: Type<'a>,
#[doc(hidden)]
pub deprecation_reason: Option<String>,
} }
/// Metadata for an argument to a field /// Metadata for an argument to a field
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Argument<'a> { pub struct Argument<'a> {
#[doc(hidden)] #[doc(hidden)] pub name: String,
pub name: String, #[doc(hidden)] pub description: Option<String>,
#[doc(hidden)] #[doc(hidden)] pub arg_type: Type<'a>,
pub description: Option<String>, #[doc(hidden)] pub default_value: Option<InputValue>,
#[doc(hidden)]
pub arg_type: Type<'a>,
#[doc(hidden)]
pub default_value: Option<InputValue>,
} }
/// Metadata for a single value in an enum /// Metadata for a single value in an enum
@ -174,12 +132,12 @@ impl<'a> MetaType<'a> {
/// Lists, non-null wrappers, and placeholders don't have names. /// Lists, non-null wrappers, and placeholders don't have names.
pub fn name(&self) -> Option<&str> { pub fn name(&self) -> Option<&str> {
match *self { match *self {
MetaType::Scalar(ScalarMeta { ref name, .. }) | MetaType::Scalar(ScalarMeta { ref name, .. })
MetaType::Object(ObjectMeta { ref name, .. }) | | MetaType::Object(ObjectMeta { ref name, .. })
MetaType::Enum(EnumMeta { ref name, .. }) | | MetaType::Enum(EnumMeta { ref name, .. })
MetaType::Interface(InterfaceMeta { ref name, .. }) | | MetaType::Interface(InterfaceMeta { ref name, .. })
MetaType::Union(UnionMeta { ref name, .. }) | | MetaType::Union(UnionMeta { ref name, .. })
MetaType::InputObject(InputObjectMeta { ref name, .. }) => Some(name), | MetaType::InputObject(InputObjectMeta { ref name, .. }) => Some(name),
_ => None, _ => None,
} }
} }
@ -191,20 +149,20 @@ impl<'a> MetaType<'a> {
match *self { match *self {
MetaType::Scalar(ScalarMeta { MetaType::Scalar(ScalarMeta {
ref description, .. ref description, ..
}) | })
MetaType::Object(ObjectMeta { | MetaType::Object(ObjectMeta {
ref description, .. ref description, ..
}) | })
MetaType::Enum(EnumMeta { | MetaType::Enum(EnumMeta {
ref description, .. ref description, ..
}) | })
MetaType::Interface(InterfaceMeta { | MetaType::Interface(InterfaceMeta {
ref description, .. ref description, ..
}) | })
MetaType::Union(UnionMeta { | MetaType::Union(UnionMeta {
ref description, .. ref description, ..
}) | })
MetaType::InputObject(InputObjectMeta { | MetaType::InputObject(InputObjectMeta {
ref description, .. ref description, ..
}) => description.as_ref(), }) => description.as_ref(),
_ => None, _ => None,
@ -234,8 +192,8 @@ impl<'a> MetaType<'a> {
/// Only objects and interfaces have fields. This method always returns `None` for other types. /// Only objects and interfaces have fields. This method always returns `None` for other types.
pub fn field_by_name(&self, name: &str) -> Option<&Field> { pub fn field_by_name(&self, name: &str) -> Option<&Field> {
match *self { match *self {
MetaType::Object(ObjectMeta { ref fields, .. }) | MetaType::Object(ObjectMeta { ref fields, .. })
MetaType::Interface(InterfaceMeta { ref fields, .. }) => { | MetaType::Interface(InterfaceMeta { ref fields, .. }) => {
fields.iter().find(|f| f.name == name) fields.iter().find(|f| f.name == name)
} }
_ => None, _ => None,
@ -257,12 +215,12 @@ impl<'a> MetaType<'a> {
/// Construct a `Type` literal instance based on the metadata /// Construct a `Type` literal instance based on the metadata
pub fn as_type(&self) -> Type<'a> { pub fn as_type(&self) -> Type<'a> {
match *self { match *self {
MetaType::Scalar(ScalarMeta { ref name, .. }) | MetaType::Scalar(ScalarMeta { ref name, .. })
MetaType::Object(ObjectMeta { ref name, .. }) | | MetaType::Object(ObjectMeta { ref name, .. })
MetaType::Enum(EnumMeta { ref name, .. }) | | MetaType::Enum(EnumMeta { ref name, .. })
MetaType::Interface(InterfaceMeta { ref name, .. }) | | MetaType::Interface(InterfaceMeta { ref name, .. })
MetaType::Union(UnionMeta { ref name, .. }) | | MetaType::Union(UnionMeta { ref name, .. })
MetaType::InputObject(InputObjectMeta { ref name, .. }) => { | MetaType::InputObject(InputObjectMeta { ref name, .. }) => {
Type::NonNullNamed(name.clone()) Type::NonNullNamed(name.clone())
} }
MetaType::List(ListMeta { ref of_type }) => { MetaType::List(ListMeta { ref of_type }) => {
@ -287,11 +245,11 @@ impl<'a> MetaType<'a> {
match *self { match *self {
MetaType::Scalar(ScalarMeta { MetaType::Scalar(ScalarMeta {
ref try_parse_fn, .. ref try_parse_fn, ..
}) | })
MetaType::Enum(EnumMeta { | MetaType::Enum(EnumMeta {
ref try_parse_fn, .. ref try_parse_fn, ..
}) | })
MetaType::InputObject(InputObjectMeta { | MetaType::InputObject(InputObjectMeta {
ref try_parse_fn, .. ref try_parse_fn, ..
}) => Some(try_parse_fn), }) => Some(try_parse_fn),
_ => None, _ => None,
@ -345,7 +303,9 @@ impl<'a> ScalarMeta<'a> {
ScalarMeta { ScalarMeta {
name: name, name: name,
description: None, description: None,
try_parse_fn: Box::new(|v: &InputValue| <T as FromInputValue>::from_input_value(v).is_some()), try_parse_fn: Box::new(|v: &InputValue| {
<T as FromInputValue>::from_input_value(v).is_some()
}),
} }
} }
@ -431,7 +391,9 @@ impl<'a> EnumMeta<'a> {
name: name, name: name,
description: None, description: None,
values: values.to_vec(), values: values.to_vec(),
try_parse_fn: Box::new(|v: &InputValue| <T as FromInputValue>::from_input_value(v).is_some()), try_parse_fn: Box::new(|v: &InputValue| {
<T as FromInputValue>::from_input_value(v).is_some()
}),
} }
} }
@ -510,7 +472,9 @@ impl<'a> InputObjectMeta<'a> {
name: name, name: name,
description: None, description: None,
input_fields: input_fields.to_vec(), input_fields: input_fields.to_vec(),
try_parse_fn: Box::new(|v: &InputValue| <T as FromInputValue>::from_input_value(v).is_some()), try_parse_fn: Box::new(|v: &InputValue| {
<T as FromInputValue>::from_input_value(v).is_some()
}),
} }
} }

View file

@ -13,16 +13,11 @@ use schema::meta::{Argument, InterfaceMeta, MetaType, ObjectMeta, PlaceholderMet
/// This brings the mutation and query types together, and provides the /// This brings the mutation and query types together, and provides the
/// predefined metadata fields. /// predefined metadata fields.
pub struct RootNode<'a, QueryT: GraphQLType, MutationT: GraphQLType> { pub struct RootNode<'a, QueryT: GraphQLType, MutationT: GraphQLType> {
#[doc(hidden)] #[doc(hidden)] pub query_type: QueryT,
pub query_type: QueryT, #[doc(hidden)] pub query_info: QueryT::TypeInfo,
#[doc(hidden)] #[doc(hidden)] pub mutation_type: MutationT,
pub query_info: QueryT::TypeInfo, #[doc(hidden)] pub mutation_info: MutationT::TypeInfo,
#[doc(hidden)] #[doc(hidden)] pub schema: SchemaType<'a>,
pub mutation_type: MutationT,
#[doc(hidden)]
pub mutation_info: MutationT::TypeInfo,
#[doc(hidden)]
pub schema: SchemaType<'a>,
} }
/// Metadata for a schema /// Metadata for a schema
@ -55,12 +50,9 @@ pub enum DirectiveLocation {
Query, Query,
Mutation, Mutation,
Field, Field,
#[graphql(name = "FRAGMENT_DEFINITION")] #[graphql(name = "FRAGMENT_DEFINITION")] FragmentDefinition,
FragmentDefinition, #[graphql(name = "FRAGMENT_SPREAD")] FragmentSpread,
#[graphql(name = "FRAGMENT_SPREAD")] #[graphql(name = "INLINE_SPREAD")] InlineFragment,
FragmentSpread,
#[graphql(name = "INLINE_SPREAD")]
InlineFragment,
} }
impl<'a, QueryT, MutationT> RootNode<'a, QueryT, MutationT> impl<'a, QueryT, MutationT> RootNode<'a, QueryT, MutationT>
@ -277,9 +269,9 @@ impl<'a> SchemaType<'a> {
} }
pub fn is_possible_type(&self, abstract_type: &MetaType, possible_type: &MetaType) -> bool { pub fn is_possible_type(&self, abstract_type: &MetaType, possible_type: &MetaType) -> bool {
self.possible_types(abstract_type).into_iter().any(|t| { self.possible_types(abstract_type)
(t as *const MetaType) == (possible_type as *const MetaType) .into_iter()
}) .any(|t| (t as *const MetaType) == (possible_type as *const MetaType))
} }
pub fn is_subtype<'b>(&self, sub_type: &Type<'b>, super_type: &Type<'b>) -> bool { pub fn is_subtype<'b>(&self, sub_type: &Type<'b>, super_type: &Type<'b>) -> bool {
@ -290,14 +282,14 @@ impl<'a> SchemaType<'a> {
} }
match (super_type, sub_type) { match (super_type, sub_type) {
(&NonNullNamed(ref super_name), &NonNullNamed(ref sub_name)) | (&NonNullNamed(ref super_name), &NonNullNamed(ref sub_name))
(&Named(ref super_name), &Named(ref sub_name)) | | (&Named(ref super_name), &Named(ref sub_name))
(&Named(ref super_name), &NonNullNamed(ref sub_name)) => { | (&Named(ref super_name), &NonNullNamed(ref sub_name)) => {
self.is_named_subtype(sub_name, super_name) self.is_named_subtype(sub_name, super_name)
} }
(&NonNullList(ref super_inner), &NonNullList(ref sub_inner)) | (&NonNullList(ref super_inner), &NonNullList(ref sub_inner))
(&List(ref super_inner), &List(ref sub_inner)) | | (&List(ref super_inner), &List(ref sub_inner))
(&List(ref super_inner), &NonNullList(ref sub_inner)) => { | (&List(ref super_inner), &NonNullList(ref sub_inner)) => {
self.is_subtype(sub_inner, super_inner) self.is_subtype(sub_inner, super_inner)
} }
_ => false, _ => false,

View file

@ -142,11 +142,15 @@ graphql_object!(<'a> TypeType<'a>: SchemaType<'a> as "__Type" |&self| {
.filter_map(|tn| schema.type_by_name(tn)) .filter_map(|tn| schema.type_by_name(tn))
.collect()) .collect())
} }
TypeType::Concrete(&MetaType::Interface(InterfaceMeta { name: ref iface_name, .. })) => { TypeType::Concrete(&MetaType::Interface(InterfaceMeta{name: ref iface_name, .. })) => {
Some(schema.concrete_type_list() Some(schema.concrete_type_list()
.iter() .iter()
.filter_map(|&ct| .filter_map(|&ct|
if let MetaType::Object(ObjectMeta { ref name, ref interface_names, .. }) = *ct { if let MetaType::Object(ObjectMeta{
ref name,
ref interface_names,
..
}) = *ct {
if interface_names.contains(&iface_name.to_string()) { if interface_names.contains(&iface_name.to_string()) {
schema.type_by_name(name) schema.type_by_name(name)
} else { None } } else { None }
@ -232,7 +236,6 @@ graphql_object!(EnumValue: () as "__EnumValue" |&self| {
} }
}); });
graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| { graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self| {
field name() -> &String { field name() -> &String {
&self.name &self.name
@ -270,4 +273,3 @@ graphql_object!(<'a> DirectiveType<'a>: SchemaType<'a> as "__Directive" |&self|
self.locations.contains(&DirectiveLocation::Field) self.locations.contains(&DirectiveLocation::Field)
} }
}); });

View file

@ -5,8 +5,7 @@ use std::collections::HashMap;
#[derive(GraphQLEnum, Copy, Clone, Eq, PartialEq, Debug)] #[derive(GraphQLEnum, Copy, Clone, Eq, PartialEq, Debug)]
#[graphql(_internal)] #[graphql(_internal)]
pub enum Episode { pub enum Episode {
#[graphql(name = "NEW_HOPE")] #[graphql(name = "NEW_HOPE")] NewHope,
NewHope,
Empire, Empire,
Jedi, Jedi,
} }

View file

@ -83,7 +83,6 @@ graphql_object!(<'a> &'a Droid: Database as "Droid" |&self| {
} }
}); });
graphql_object!(Database: Database as "Query" |&self| { graphql_object!(Database: Database as "Query" |&self| {
description: "The root query object of the schema" description: "The root query object of the schema"

View file

@ -328,7 +328,8 @@ fn resolve_selection_set_into<T, CtxT>(
selection_set: &[Selection], selection_set: &[Selection],
executor: &Executor<CtxT>, executor: &Executor<CtxT>,
result: &mut OrderMap<String, Value>, result: &mut OrderMap<String, Value>,
) -> bool where ) -> bool
where
T: GraphQLType<Context = CtxT>, T: GraphQLType<Context = CtxT>,
{ {
let meta_type = executor let meta_type = executor
@ -441,7 +442,8 @@ fn resolve_selection_set_into<T, CtxT>(
let sub_exec = executor.type_sub_executor( let sub_exec = executor.type_sub_executor(
fragment.type_condition.as_ref().map(|c| c.item), fragment.type_condition.as_ref().map(|c| c.item),
Some(&fragment.selection_set[..])); Some(&fragment.selection_set[..]),
);
if let Some(ref type_condition) = fragment.type_condition { if let Some(ref type_condition) = fragment.type_condition {
let sub_result = instance.resolve_into_type( let sub_result = instance.resolve_into_type(
@ -472,7 +474,7 @@ fn resolve_selection_set_into<T, CtxT>(
} }
} }
} }
true true
} }
@ -491,8 +493,8 @@ fn is_excluded(directives: &Option<Vec<Spanning<Directive>>>, vars: &Variables)
.next() .next()
.unwrap(); .unwrap();
if (directive.name.item == "skip" && condition) || if (directive.name.item == "skip" && condition)
(directive.name.item == "include" && !condition) || (directive.name.item == "include" && !condition)
{ {
return true; return true;
} }

View file

@ -152,9 +152,15 @@ where
} }
} }
fn resolve_into_list<T: GraphQLType, I: Iterator<Item=T>>(executor: &Executor<T::Context>, info: &T::TypeInfo, iter: I) -> Value { fn resolve_into_list<T: GraphQLType, I: Iterator<Item = T>>(
let stop_on_null = executor.current_type() executor: &Executor<T::Context>,
.list_contents().expect("Current type is not a list type") info: &T::TypeInfo,
iter: I,
) -> Value {
let stop_on_null = executor
.current_type()
.list_contents()
.expect("Current type is not a list type")
.is_non_null(); .is_non_null();
let mut result = Vec::new(); let mut result = Vec::new();
@ -169,4 +175,4 @@ fn resolve_into_list<T: GraphQLType, I: Iterator<Item=T>>(executor: &Executor<T:
} }
Value::list(result) Value::list(result)
} }

View file

@ -44,7 +44,6 @@ graphql_scalar!(ID as "ID" {
} }
}); });
graphql_scalar!(String as "String" { graphql_scalar!(String as "String" {
resolve(&self) -> Value { resolve(&self) -> Value {
Value::string(self) Value::string(self)
@ -58,7 +57,6 @@ graphql_scalar!(String as "String" {
} }
}); });
impl<'a> GraphQLType for &'a str { impl<'a> GraphQLType for &'a str {
type Context = (); type Context = ();
type TypeInfo = (); type TypeInfo = ();
@ -82,8 +80,6 @@ impl<'a> ToInputValue for &'a str {
} }
} }
graphql_scalar!(bool as "Boolean" { graphql_scalar!(bool as "Boolean" {
resolve(&self) -> Value { resolve(&self) -> Value {
Value::boolean(*self) Value::boolean(*self)
@ -97,7 +93,6 @@ graphql_scalar!(bool as "Boolean" {
} }
}); });
graphql_scalar!(i32 as "Int" { graphql_scalar!(i32 as "Int" {
resolve(&self) -> Value { resolve(&self) -> Value {
Value::int(*self) Value::int(*self)
@ -111,7 +106,6 @@ graphql_scalar!(i32 as "Int" {
} }
}); });
graphql_scalar!(f64 as "Float" { graphql_scalar!(f64 as "Float" {
resolve(&self) -> Value { resolve(&self) -> Value {
Value::float(*self) Value::float(*self)
@ -126,7 +120,6 @@ graphql_scalar!(f64 as "Float" {
} }
}); });
impl GraphQLType for () { impl GraphQLType for () {
type Context = (); type Context = ();
type TypeInfo = (); type TypeInfo = ();
@ -146,7 +139,6 @@ impl FromInputValue for () {
} }
} }
/// Utility type to define read-only schemas /// Utility type to define read-only schemas
/// ///
/// If you instantiate `RootNode` with this as the mutation, no mutation will be /// If you instantiate `RootNode` with this as the mutation, no mutation will be

View file

@ -31,26 +31,29 @@ pub fn is_valid_literal_value(
match *arg_value { match *arg_value {
InputValue::Null | InputValue::Variable(_) => true, InputValue::Null | InputValue::Variable(_) => true,
ref v @ InputValue::Int(_) | ref v @ InputValue::Int(_)
ref v @ InputValue::Float(_) | | ref v @ InputValue::Float(_)
ref v @ InputValue::String(_) | | ref v @ InputValue::String(_)
ref v @ InputValue::Boolean(_) | | ref v @ InputValue::Boolean(_)
ref v @ InputValue::Enum(_) => if let Some(parse_fn) = t.input_value_parse_fn() { | ref v @ InputValue::Enum(_) => if let Some(parse_fn) = t.input_value_parse_fn() {
parse_fn(v) parse_fn(v)
} else { } else {
false false
}, },
InputValue::List(_) => false, InputValue::List(_) => false,
InputValue::Object(ref obj) => if let MetaType::InputObject(InputObjectMeta { InputValue::Object(ref obj) => if let MetaType::InputObject(InputObjectMeta {
ref input_fields, .. ref input_fields,
..
}) = *t }) = *t
{ {
let mut remaining_required_fields = input_fields let mut remaining_required_fields = input_fields
.iter() .iter()
.filter_map(|f| if f.arg_type.is_non_null() { .filter_map(|f| {
Some(&f.name) if f.arg_type.is_non_null() {
} else { Some(&f.name)
None } else {
None
}
}) })
.collect::<HashSet<_>>(); .collect::<HashSet<_>>();

View file

@ -277,9 +277,7 @@ fn push_unification_error<'a>(
errors.push(RuleError::new( errors.push(RuleError::new(
&format!( &format!(
r#"Variable "${}" got invalid value. {}{}."#, r#"Variable "${}" got invalid value. {}{}."#,
var_name, var_name, path, message,
path,
message,
), ),
&[var_pos.clone()], &[var_pos.clone()],
)); ));

View file

@ -60,12 +60,10 @@ impl<'a> Visitor<'a> for ArgumentsOfCorrectType<'a> {
fn error_message(arg_name: &str, type_name: &str) -> String { fn error_message(arg_name: &str, type_name: &str) -> String {
format!( format!(
"Invalid value for argument \"{}\", expected type \"{}\"", "Invalid value for argument \"{}\", expected type \"{}\"",
arg_name, arg_name, type_name
type_name
) )
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{error_message, factory}; use super::{error_message, factory};

View file

@ -43,16 +43,14 @@ impl<'a> Visitor<'a> for DefaultValuesOfCorrectType {
fn type_error_message(arg_name: &str, type_name: &str) -> String { fn type_error_message(arg_name: &str, type_name: &str) -> String {
format!( format!(
"Invalid default value for argument \"{}\", expected type \"{}\"", "Invalid default value for argument \"{}\", expected type \"{}\"",
arg_name, arg_name, type_name
type_name
) )
} }
fn non_null_error_message(arg_name: &str, type_name: &str) -> String { fn non_null_error_message(arg_name: &str, type_name: &str) -> String {
format!( format!(
"Argument \"{}\" has type \"{}\" and is not nullable, so it't can't have a default value", "Argument \"{}\" has type \"{}\" and is not nullable, so it't can't have a default value",
arg_name, arg_name, type_name
type_name
) )
} }

View file

@ -17,7 +17,6 @@ impl<'a> Visitor<'a> for FieldsOnCorrectType {
let type_name = parent_type.name().unwrap_or("<unknown>"); let type_name = parent_type.name().unwrap_or("<unknown>");
if parent_type.field_by_name(field_name.item).is_none() { if parent_type.field_by_name(field_name.item).is_none() {
match *parent_type { match *parent_type {
MetaType::Union(..) => { MetaType::Union(..) => {
// You can query for `__typename` on a union, // You can query for `__typename` on a union,

View file

@ -55,8 +55,7 @@ fn error_message(fragment_name: Option<&str>, on_type: &str) -> String {
if let Some(name) = fragment_name { if let Some(name) = fragment_name {
format!( format!(
r#"Fragment "{}" cannot condition non composite type "{}"#, r#"Fragment "{}" cannot condition non composite type "{}"#,
name, name, on_type
on_type
) )
} else { } else {
format!( format!(

View file

@ -23,14 +23,14 @@ impl<'a> Visitor<'a> for KnownArgumentNames<'a> {
ctx: &mut ValidatorContext<'a>, ctx: &mut ValidatorContext<'a>,
directive: &'a Spanning<Directive>, directive: &'a Spanning<Directive>,
) { ) {
self.current_args = ctx.schema.directive_by_name(directive.item.name.item).map( self.current_args = ctx.schema
|d| { .directive_by_name(directive.item.name.item)
.map(|d| {
( (
ArgumentPosition::Directive(directive.item.name.item), ArgumentPosition::Directive(directive.item.name.item),
&d.arguments, &d.arguments,
) )
}, });
);
} }
fn exit_directive(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Directive>) { fn exit_directive(&mut self, _: &mut ValidatorContext<'a>, _: &'a Spanning<Directive>) {
@ -84,17 +84,14 @@ impl<'a> Visitor<'a> for KnownArgumentNames<'a> {
fn field_error_message(arg_name: &str, field_name: &str, type_name: &str) -> String { fn field_error_message(arg_name: &str, field_name: &str, type_name: &str) -> String {
format!( format!(
r#"Unknown argument "{}" on field "{}" of type "{}""#, r#"Unknown argument "{}" on field "{}" of type "{}""#,
arg_name, arg_name, field_name, type_name
field_name,
type_name
) )
} }
fn directive_error_message(arg_name: &str, directive_name: &str) -> String { fn directive_error_message(arg_name: &str, directive_name: &str) -> String {
format!( format!(
r#"Unknown argument "{}" on directive "{}""#, r#"Unknown argument "{}" on directive "{}""#,
arg_name, arg_name, directive_name
directive_name
) )
} }

View file

@ -132,8 +132,7 @@ fn unknown_error_message(directive_name: &str) -> String {
fn misplaced_error_message(directive_name: &str, location: &DirectiveLocation) -> String { fn misplaced_error_message(directive_name: &str, location: &DirectiveLocation) -> String {
format!( format!(
r#"Directive "{}" may not be used on {}"#, r#"Directive "{}" may not be used on {}"#,
directive_name, directive_name, location
location
) )
} }

View file

@ -150,8 +150,7 @@ fn error_message(var_name: &str, op_name: Option<&str>) -> String {
if let Some(op_name) = op_name { if let Some(op_name) = op_name {
format!( format!(
r#"Variable "${}" is not defined by operation "{}""#, r#"Variable "${}" is not defined by operation "{}""#,
var_name, var_name, op_name
op_name
) )
} else { } else {
format!(r#"Variable "${}" is not defined"#, var_name) format!(r#"Variable "${}" is not defined"#, var_name)

View file

@ -140,8 +140,7 @@ fn error_message(var_name: &str, op_name: Option<&str>) -> String {
if let Some(op_name) = op_name { if let Some(op_name) = op_name {
format!( format!(
r#"Variable "${}" is not defined by operation "{}""#, r#"Variable "${}" is not defined by operation "{}""#,
var_name, var_name, op_name
op_name
) )
} else { } else {
format!(r#"Variable "${}" is not defined"#, var_name) format!(r#"Variable "${}" is not defined"#, var_name)

View file

@ -204,18 +204,21 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
}; };
{ {
if self.compared_fragments if self.compared_fragments.borrow().contains(
.borrow() fragment_name1,
.contains(fragment_name1, fragment_name2, mutually_exclusive) fragment_name2,
{ mutually_exclusive,
) {
return; return;
} }
} }
{ {
self.compared_fragments self.compared_fragments.borrow_mut().insert(
.borrow_mut() fragment_name1,
.insert(fragment_name1, fragment_name2, mutually_exclusive); fragment_name2,
mutually_exclusive,
);
} }
let (field_map1, fragment_names1) = let (field_map1, fragment_names1) =
@ -338,9 +341,9 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
let AstAndDef(ref parent_type1, ast1, ref def1) = *field1; let AstAndDef(ref parent_type1, ast1, ref def1) = *field1;
let AstAndDef(ref parent_type2, ast2, ref def2) = *field2; let AstAndDef(ref parent_type2, ast2, ref def2) = *field2;
let mutually_exclusive = parents_mutually_exclusive || let mutually_exclusive = parents_mutually_exclusive
(parent_type1 != parent_type2 && self.is_object_type(ctx, *parent_type1) && || (parent_type1 != parent_type2 && self.is_object_type(ctx, *parent_type1)
self.is_object_type(ctx, *parent_type2)); && self.is_object_type(ctx, *parent_type2));
if !mutually_exclusive { if !mutually_exclusive {
let name1 = &ast1.item.name.item; let name1 = &ast1.item.name.item;
@ -350,9 +353,10 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
return Some(Conflict( return Some(Conflict(
ConflictReason( ConflictReason(
response_name.to_owned(), response_name.to_owned(),
ConflictReasonMessage::Message( ConflictReasonMessage::Message(format!(
format!("{} and {} are different fields", name1, name2), "{} and {} are different fields",
), name1, name2
)),
), ),
vec![ast1.start.clone()], vec![ast1.start.clone()],
vec![ast2.start.clone()], vec![ast2.start.clone()],
@ -379,9 +383,10 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
return Some(Conflict( return Some(Conflict(
ConflictReason( ConflictReason(
response_name.to_owned(), response_name.to_owned(),
ConflictReasonMessage::Message( ConflictReasonMessage::Message(format!(
format!("they return conflicting types {} and {}", t1, t2), "they return conflicting types {} and {}",
), t1, t2
)),
), ),
vec![ast1.start.clone()], vec![ast1.start.clone()],
vec![ast2.start.clone()], vec![ast2.start.clone()],
@ -389,8 +394,7 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
} }
} }
if let (&Some(ref s1), &Some(ref s2)) = if let (&Some(ref s1), &Some(ref s2)) = (&ast1.item.selection_set, &ast2.item.selection_set)
(&ast1.item.selection_set, &ast2.item.selection_set)
{ {
let conflicts = self.find_conflicts_between_sub_selection_sets( let conflicts = self.find_conflicts_between_sub_selection_sets(
mutually_exclusive, mutually_exclusive,
@ -506,17 +510,17 @@ impl<'a> OverlappingFieldsCanBeMerged<'a> {
fn is_type_conflict(&self, ctx: &ValidatorContext<'a>, t1: &Type, t2: &Type) -> bool { fn is_type_conflict(&self, ctx: &ValidatorContext<'a>, t1: &Type, t2: &Type) -> bool {
match (t1, t2) { match (t1, t2) {
(&Type::List(ref inner1), &Type::List(ref inner2)) | (&Type::List(ref inner1), &Type::List(ref inner2))
(&Type::NonNullList(ref inner1), &Type::NonNullList(ref inner2)) => { | (&Type::NonNullList(ref inner1), &Type::NonNullList(ref inner2)) => {
self.is_type_conflict(ctx, inner1, inner2) self.is_type_conflict(ctx, inner1, inner2)
} }
(&Type::NonNullNamed(ref n1), &Type::NonNullNamed(ref n2)) | (&Type::NonNullNamed(ref n1), &Type::NonNullNamed(ref n2))
(&Type::Named(ref n1), &Type::Named(ref n2)) => { | (&Type::Named(ref n1), &Type::Named(ref n2)) => {
let ct1 = ctx.schema.concrete_type_by_name(n1); let ct1 = ctx.schema.concrete_type_by_name(n1);
let ct2 = ctx.schema.concrete_type_by_name(n2); let ct2 = ctx.schema.concrete_type_by_name(n2);
if ct1.map(|ct| ct.is_leaf()).unwrap_or(false) || if ct1.map(|ct| ct.is_leaf()).unwrap_or(false)
ct2.map(|ct| ct.is_leaf()).unwrap_or(false) || ct2.map(|ct| ct.is_leaf()).unwrap_or(false)
{ {
n1 != n2 n1 != n2
} else { } else {
@ -1755,9 +1759,7 @@ mod tests {
RuleError::new( RuleError::new(
&error_message( &error_message(
"scalar", "scalar",
&Message( &Message("they return conflicting types String! and String".to_owned()),
"they return conflicting types String! and String".to_owned(),
),
), ),
&[ &[
SourcePosition::new(100, 4, 18), SourcePosition::new(100, 4, 18),

View file

@ -78,16 +78,13 @@ fn error_message(frag_name: Option<&str>, parent_type_name: &str, frag_type: &st
format!( format!(
"Fragment \"{}\" cannot be spread here as objects of type \ "Fragment \"{}\" cannot be spread here as objects of type \
\"{}\" can never be of type \"{}\"", \"{}\" can never be of type \"{}\"",
frag_name, frag_name, parent_type_name, frag_type
parent_type_name,
frag_type
) )
} else { } else {
format!( format!(
"Fragment cannot be spread here as objects of type \"{}\" \ "Fragment cannot be spread here as objects of type \"{}\" \
can never be of type \"{}\"", can never be of type \"{}\"",
parent_type_name, parent_type_name, frag_type
frag_type
) )
} }
} }

View file

@ -20,8 +20,8 @@ impl<'a> Visitor<'a> for ProvidedNonNullArguments {
}) = ctx.parent_type().and_then(|t| t.field_by_name(field_name)) }) = ctx.parent_type().and_then(|t| t.field_by_name(field_name))
{ {
for meta_arg in meta_args { for meta_arg in meta_args {
if meta_arg.arg_type.is_non_null() && if meta_arg.arg_type.is_non_null()
field && field
.item .item
.arguments .arguments
.as_ref() .as_ref()
@ -54,8 +54,8 @@ impl<'a> Visitor<'a> for ProvidedNonNullArguments {
}) = ctx.schema.directive_by_name(directive_name) }) = ctx.schema.directive_by_name(directive_name)
{ {
for meta_arg in meta_args { for meta_arg in meta_args {
if meta_arg.arg_type.is_non_null() && if meta_arg.arg_type.is_non_null()
directive && directive
.item .item
.arguments .arguments
.as_ref() .as_ref()
@ -79,18 +79,14 @@ impl<'a> Visitor<'a> for ProvidedNonNullArguments {
fn field_error_message(field_name: &str, arg_name: &str, type_name: &str) -> String { fn field_error_message(field_name: &str, arg_name: &str, type_name: &str) -> String {
format!( format!(
r#"Field "{}" argument "{}" of type "{}" is required but not provided"#, r#"Field "{}" argument "{}" of type "{}" is required but not provided"#,
field_name, field_name, arg_name, type_name
arg_name,
type_name
) )
} }
fn directive_error_message(directive_name: &str, arg_name: &str, type_name: &str) -> String { fn directive_error_message(directive_name: &str, arg_name: &str, type_name: &str) -> String {
format!( format!(
r#"Directive "@{}" argument "{}" of type "{}" is required but not provided"#, r#"Directive "@{}" argument "{}" of type "{}" is required but not provided"#,
directive_name, directive_name, arg_name, type_name
arg_name,
type_name
) )
} }

View file

@ -39,8 +39,7 @@ impl<'a> Visitor<'a> for ScalarLeafs {
fn no_allowed_error_message(field_name: &str, type_name: &str) -> String { fn no_allowed_error_message(field_name: &str, type_name: &str) -> String {
format!( format!(
r#"Field "{}" must not have a selection since type {} has no subfields"#, r#"Field "{}" must not have a selection since type {} has no subfields"#,
field_name, field_name, type_name
type_name
) )
} }

View file

@ -30,8 +30,7 @@ impl<'a> Visitor<'a> for UniqueVariableNames {
fn error_message(var_name: &str, type_name: &str) -> String { fn error_message(var_name: &str, type_name: &str) -> String {
format!( format!(
"Variable \"{}\" cannot be of non-input type \"{}\"", "Variable \"{}\" cannot be of non-input type \"{}\"",
var_name, var_name, type_name
type_name
) )
} }

View file

@ -148,9 +148,7 @@ impl<'a> Visitor<'a> for VariableInAllowedPosition<'a> {
fn error_message(var_name: &str, type_name: &str, expected_type_name: &str) -> String { fn error_message(var_name: &str, type_name: &str, expected_type_name: &str) -> String {
format!( format!(
"Variable \"{}\" of type \"{}\" used in position expecting type \"{}\"", "Variable \"{}\" of type \"{}\" used in position expecting type \"{}\"",
var_name, var_name, type_name, expected_type_name
type_name,
expected_type_name
) )
} }

View file

@ -236,10 +236,7 @@ impl GraphQLType for Cat {
registry registry
.build_object_type::<Self>(i, fields) .build_object_type::<Self>(i, fields)
.interfaces(&[ .interfaces(&[registry.get_type::<Being>(i), registry.get_type::<Pet>(i)])
registry.get_type::<Being>(i),
registry.get_type::<Pet>(i),
])
.into_meta() .into_meta()
} }
} }
@ -434,9 +431,7 @@ impl GraphQLType for ComplicatedArgs {
.argument(registry.arg::<Option<ID>>("idArg", i)), .argument(registry.arg::<Option<ID>>("idArg", i)),
registry registry
.field::<Option<String>>("stringListArgField", i) .field::<Option<String>>("stringListArgField", i)
.argument( .argument(registry.arg::<Option<Vec<Option<String>>>>("stringListArg", i)),
registry.arg::<Option<Vec<Option<String>>>>("stringListArg", i),
),
registry registry
.field::<Option<String>>("complexArgField", i) .field::<Option<String>>("complexArgField", i)
.argument(registry.arg::<Option<ComplexInput>>("complexArg", i)), .argument(registry.arg::<Option<ComplexInput>>("complexArg", i)),

View file

@ -3,7 +3,6 @@ use ast::{Directive, Document, Field, Fragment, FragmentSpread, InlineFragment,
use parser::Spanning; use parser::Spanning;
use validation::ValidatorContext; use validation::ValidatorContext;
#[doc(hidden)] #[doc(hidden)]
pub trait Visitor<'a> { pub trait Visitor<'a> {
fn enter_document(&mut self, _: &mut ValidatorContext<'a>, _: &'a Document) {} fn enter_document(&mut self, _: &mut ValidatorContext<'a>, _: &'a Document) {}

View file

@ -22,26 +22,29 @@ fn visit_definitions<'a, V: Visitor<'a>>(
for def in d { for def in d {
let def_type = match *def { let def_type = match *def {
Definition::Fragment(Spanning { Definition::Fragment(Spanning {
item: Fragment { item:
type_condition: Spanning { item: name, .. }, Fragment {
.. type_condition: Spanning { item: name, .. },
}, ..
},
.. ..
}) => Some(Type::NonNullNamed(Cow::Borrowed(name))), }) => Some(Type::NonNullNamed(Cow::Borrowed(name))),
Definition::Operation(Spanning { Definition::Operation(Spanning {
item: Operation { item:
operation_type: OperationType::Query, Operation {
.. operation_type: OperationType::Query,
}, ..
},
.. ..
}) => Some(Type::NonNullNamed(Cow::Borrowed( }) => Some(Type::NonNullNamed(Cow::Borrowed(
ctx.schema.concrete_query_type().name().unwrap(), ctx.schema.concrete_query_type().name().unwrap(),
))), ))),
Definition::Operation(Spanning { Definition::Operation(Spanning {
item: Operation { item:
operation_type: OperationType::Mutation, Operation {
.. operation_type: OperationType::Mutation,
}, ..
},
.. ..
}) => ctx.schema }) => ctx.schema
.concrete_mutation_type() .concrete_mutation_type()
@ -284,8 +287,10 @@ fn visit_input_value<'a, V: Visitor<'a>>(
_ => None, _ => None,
}); });
ctx.with_pushed_input_type(inner_type.as_ref(), |ctx| for value in ls { ctx.with_pushed_input_type(inner_type.as_ref(), |ctx| {
visit_input_value(v, ctx, value); for value in ls {
visit_input_value(v, ctx, value);
}
}) })
} }
_ => (), _ => (),

View file

@ -125,13 +125,18 @@ impl ToInputValue for Value {
Value::Float(f) => InputValue::Float(f), Value::Float(f) => InputValue::Float(f),
Value::String(ref s) => InputValue::String(s.clone()), Value::String(ref s) => InputValue::String(s.clone()),
Value::Boolean(b) => InputValue::Boolean(b), Value::Boolean(b) => InputValue::Boolean(b),
Value::List(ref l) => { Value::List(ref l) => InputValue::List(
InputValue::List(l.iter().map(|x| Spanning::unlocated(x.to_input_value())).collect()) l.iter()
} .map(|x| Spanning::unlocated(x.to_input_value()))
.collect(),
),
Value::Object(ref o) => InputValue::Object( Value::Object(ref o) => InputValue::Object(
o.iter() o.iter()
.map(|(k, v)| { .map(|(k, v)| {
(Spanning::unlocated(k.clone()), Spanning::unlocated(v.to_input_value())) (
Spanning::unlocated(k.clone()),
Spanning::unlocated(v.to_input_value()),
)
}) })
.collect(), .collect(),
), ),
@ -169,11 +174,14 @@ impl From<f64> for Value {
} }
} }
impl<T> From<Option<T>> for Value where Value: From<T> { impl<T> From<Option<T>> for Value
where
Value: From<T>,
{
fn from(v: Option<T>) -> Value { fn from(v: Option<T>) -> Value {
match v { match v {
Some(v) => Value::from(v), Some(v) => Value::from(v),
None => Value::null() None => Value::null(),
} }
} }
} }
@ -215,52 +223,34 @@ mod tests {
#[test] #[test]
fn value_macro_string() { fn value_macro_string() {
assert_eq!( assert_eq!(graphql_value!("test"), Value::string("test"));
graphql_value!("test"),
Value::string("test")
);
} }
#[test] #[test]
fn value_macro_int() { fn value_macro_int() {
assert_eq!( assert_eq!(graphql_value!(123), Value::int(123));
graphql_value!(123),
Value::int(123)
);
} }
#[test] #[test]
fn value_macro_float() { fn value_macro_float() {
assert_eq!( assert_eq!(graphql_value!(123.5), Value::float(123.5));
graphql_value!(123.5),
Value::float(123.5)
);
} }
#[test] #[test]
fn value_macro_boolean() { fn value_macro_boolean() {
assert_eq!( assert_eq!(graphql_value!(false), Value::boolean(false));
graphql_value!(false),
Value::boolean(false)
);
} }
#[test] #[test]
fn value_macro_option() { fn value_macro_option() {
assert_eq!( assert_eq!(graphql_value!(Some("test")), Value::string("test"));
graphql_value!(Some("test")), assert_eq!(graphql_value!(None), Value::null());
Value::string("test")
);
assert_eq!(
graphql_value!(None),
Value::null()
);
} }
#[test] #[test]
fn value_macro_list() { fn value_macro_list() {
assert_eq!( assert_eq!(
graphql_value!([ 123, "Test", false ]), graphql_value!([123, "Test", false]),
Value::list(vec![ Value::list(vec![
Value::int(123), Value::int(123),
Value::string("Test"), Value::string("Test"),
@ -268,10 +258,10 @@ mod tests {
]) ])
); );
assert_eq!( assert_eq!(
graphql_value!([ 123, [ 456 ], 789 ]), graphql_value!([123, [456], 789]),
Value::list(vec![ Value::list(vec![
Value::int(123), Value::int(123),
Value::list(vec![ Value::int(456) ]), Value::list(vec![Value::int(456)]),
Value::int(789), Value::int(789),
]) ])
); );
@ -281,10 +271,11 @@ mod tests {
fn value_macro_object() { fn value_macro_object() {
assert_eq!( assert_eq!(
graphql_value!({ "key": 123, "next": true }), graphql_value!({ "key": 123, "next": true }),
Value::object(vec![ Value::object(
("key", Value::int(123)), vec![("key", Value::int(123)), ("next", Value::boolean(true))]
("next", Value::boolean(true)), .into_iter()
].into_iter().collect()) .collect()
)
); );
} }
} }

View file

@ -4,7 +4,6 @@ use quote::Tokens;
use util::*; use util::*;
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct EnumAttrs { struct EnumAttrs {
name: Option<String>, name: Option<String>,
@ -14,7 +13,7 @@ struct EnumAttrs {
impl EnumAttrs { impl EnumAttrs {
fn from_input(input: &DeriveInput) -> EnumAttrs { fn from_input(input: &DeriveInput) -> EnumAttrs {
let mut res = EnumAttrs{ let mut res = EnumAttrs {
name: None, name: None,
description: None, description: None,
/// Flag to specify whether the calling crate is the "juniper" crate itself. /// Flag to specify whether the calling crate is the "juniper" crate itself.
@ -38,8 +37,8 @@ impl EnumAttrs {
res.internal = true; res.internal = true;
continue; continue;
} }
}, }
_ => {}, _ => {}
} }
panic!(format!( panic!(format!(
"Unknown attribute for #[derive(GraphQLEnum)]: {:?}", "Unknown attribute for #[derive(GraphQLEnum)]: {:?}",
@ -87,7 +86,6 @@ impl EnumVariantAttrs {
} }
} }
pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens { pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
let variants = match ast.body { let variants = match ast.body {
Body::Enum(ref var) => var, Body::Enum(ref var) => var,
@ -171,7 +169,9 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
Some(#name) Some(#name)
} }
fn meta<'r>(_: &(), registry: &mut _juniper::Registry<'r>) -> _juniper::meta::MetaType<'r> { fn meta<'r>(_: &(), registry: &mut _juniper::Registry<'r>)
-> _juniper::meta::MetaType<'r>
{
let meta = registry.build_enum_type::<#ident>(&(), &[ let meta = registry.build_enum_type::<#ident>(&(), &[
#(#values)* #(#values)*
]); ]);
@ -179,7 +179,12 @@ pub fn impl_enum(ast: &syn::DeriveInput) -> Tokens {
meta.into_meta() meta.into_meta()
} }
fn resolve(&self, _: &(), _: Option<&[_juniper::Selection]>, _: &_juniper::Executor<Self::Context>) -> _juniper::Value { fn resolve(
&self,
_: &(),
_: Option<&[_juniper::Selection]>,
_: &_juniper::Executor<Self::Context>
) -> _juniper::Value {
match self { match self {
#(#resolves)* #(#resolves)*
} }

View file

@ -4,7 +4,6 @@ use quote::Tokens;
use util::*; use util::*;
#[derive(Default, Debug)] #[derive(Default, Debug)]
struct ObjAttrs { struct ObjAttrs {
name: Option<String>, name: Option<String>,
@ -33,8 +32,8 @@ impl ObjAttrs {
res.internal = true; res.internal = true;
continue; continue;
} }
}, }
_ => {}, _ => {}
} }
panic!(format!( panic!(format!(
"Unknown attribute for #[derive(GraphQLInputObject)]: {:?}", "Unknown attribute for #[derive(GraphQLInputObject)]: {:?}",
@ -80,7 +79,7 @@ impl ObjFieldAttrs {
continue; continue;
} }
} }
_ => {}, _ => {}
} }
panic!(format!( panic!(format!(
"Unknown attribute for #[derive(GraphQLInputObject)]: {:?}", "Unknown attribute for #[derive(GraphQLInputObject)]: {:?}",
@ -144,7 +143,7 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
let default = { let default = {
if field_attrs.default { if field_attrs.default {
Some(quote! { Default::default() } ) Some(quote! { Default::default() })
} else { } else {
match field_attrs.default_expr { match field_attrs.default_expr {
Some(ref def) => match syn::parse_token_trees(def) { Some(ref def) => match syn::parse_token_trees(def) {
@ -221,7 +220,10 @@ pub fn impl_input_object(ast: &syn::DeriveInput) -> Tokens {
Some(#name) Some(#name)
} }
fn meta<'r>(_: &(), registry: &mut _juniper::Registry<'r>) -> _juniper::meta::MetaType<'r> { fn meta<'r>(
_: &(),
registry: &mut _juniper::Registry<'r>
) -> _juniper::meta::MetaType<'r> {
let fields = &[ let fields = &[
#(#meta_fields)* #(#meta_fields)*
]; ];

View file

@ -135,7 +135,6 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens {
// Build from_input clause. // Build from_input clause.
let resolver = quote!{ let resolver = quote!{
#name => executor.resolve_with_ctx(&(), &self.#field_ident), #name => executor.resolve_with_ctx(&(), &self.#field_ident),
}; };
@ -155,7 +154,10 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens {
#name.to_string() #name.to_string()
} }
fn meta<'r>(_: &(), registry: &mut ::juniper::Registry<'r>) -> ::juniper::meta::MetaType<'r> { fn meta<'r>(
_: &(),
registry: &mut ::juniper::Registry<'r>
) -> ::juniper::meta::MetaType<'r> {
let fields = &[ let fields = &[
#(#meta_fields)* #(#meta_fields)*
]; ];
@ -164,8 +166,13 @@ pub fn impl_object(ast: &syn::DeriveInput) -> Tokens {
builder.into_meta() builder.into_meta()
} }
fn resolve_field(&self, _: &(), field_name: &str, _: &::juniper::Arguments, executor: &::juniper::Executor<Self::Context>) fn resolve_field(
-> ::juniper::ExecutionResult &self,
_: &(),
field_name: &str,
_: &::juniper::Arguments,
executor: &::juniper::Executor<Self::Context>
) -> ::juniper::ExecutionResult
{ {
match field_name { match field_name {

View file

@ -7,9 +7,9 @@
#![recursion_limit = "1024"] #![recursion_limit = "1024"]
extern crate proc_macro; extern crate proc_macro;
extern crate syn;
#[macro_use] #[macro_use]
extern crate quote; extern crate quote;
extern crate syn;
mod util; mod util;
mod derive_enum; mod derive_enum;

View file

@ -87,8 +87,7 @@ pub(crate) fn to_upper_snake_case(s: &str) -> String {
for c in s.chars() { for c in s.chars() {
if c == '_' { if c == '_' {
last_lower = false; last_lower = false;
} } else if c.is_lowercase() {
else if c.is_lowercase() {
last_lower = true; last_lower = true;
} else if c.is_uppercase() { } else if c.is_uppercase() {
if last_lower { if last_lower {

View file

@ -1,9 +1,9 @@
extern crate iron; extern crate iron;
extern crate mount;
extern crate logger;
extern crate serde;
extern crate juniper; extern crate juniper;
extern crate juniper_iron; extern crate juniper_iron;
extern crate logger;
extern crate mount;
extern crate serde;
use std::env; use std::env;

View file

@ -101,13 +101,13 @@ supported.
*/ */
extern crate serde_json;
extern crate juniper;
extern crate urlencoded;
#[macro_use] #[macro_use]
extern crate iron; extern crate iron;
#[cfg(test)] #[cfg(test)]
extern crate iron_test; extern crate iron_test;
extern crate juniper;
extern crate serde_json;
extern crate urlencoded;
use iron::prelude::*; use iron::prelude::*;
use iron::middleware::Handler; use iron::middleware::Handler;
@ -151,14 +151,11 @@ pub struct GraphiQLHandler {
graphql_url: String, graphql_url: String,
} }
fn get_single_value<T>(mut values: Vec<T>) -> IronResult<T> { fn get_single_value<T>(mut values: Vec<T>) -> IronResult<T> {
if values.len() == 1 { if values.len() == 1 {
Ok(values.remove(0)) Ok(values.remove(0))
} else { } else {
Err( Err(GraphQLIronError::InvalidData("Duplicate URL query parameter").into())
GraphQLIronError::InvalidData("Duplicate URL query parameter").into(),
)
} }
} }
@ -172,22 +169,22 @@ fn parse_url_param(params: Option<Vec<String>>) -> IronResult<Option<String>> {
fn parse_variable_param(params: Option<Vec<String>>) -> IronResult<Option<InputValue>> { fn parse_variable_param(params: Option<Vec<String>>) -> IronResult<Option<InputValue>> {
if let Some(values) = params { if let Some(values) = params {
Ok(serde_json::from_str::<InputValue>( Ok(
get_single_value(values)?.as_ref(), serde_json::from_str::<InputValue>(get_single_value(values)?.as_ref())
).map(Some) .map(Some)
.map_err(GraphQLIronError::Serde)?) .map_err(GraphQLIronError::Serde)?,
)
} else { } else {
Ok(None) Ok(None)
} }
} }
impl<'a, CtxFactory, Query, Mutation, CtxT> GraphQLHandler<'a, CtxFactory, Query, Mutation, CtxT> impl<'a, CtxFactory, Query, Mutation, CtxT> GraphQLHandler<'a, CtxFactory, Query, Mutation, CtxT>
where where
CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static, CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static,
CtxT: 'static, CtxT: 'static,
Query: GraphQLType<Context = CtxT, TypeInfo=()> + Send + Sync + 'static, Query: GraphQLType<Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
Mutation: GraphQLType<Context = CtxT, TypeInfo=()> + Send + Sync + 'static, Mutation: GraphQLType<Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
{ {
/// Build a new GraphQL handler /// Build a new GraphQL handler
/// ///
@ -202,7 +199,6 @@ where
} }
} }
fn handle_get(&self, req: &mut Request) -> IronResult<http::GraphQLRequest> { fn handle_get(&self, req: &mut Request) -> IronResult<http::GraphQLRequest> {
let url_query_string = req.get_mut::<UrlEncodedQuery>() let url_query_string = req.get_mut::<UrlEncodedQuery>()
.map_err(|e| GraphQLIronError::Url(e))?; .map_err(|e| GraphQLIronError::Url(e))?;
@ -223,9 +219,10 @@ where
let mut request_payload = String::new(); let mut request_payload = String::new();
itry!(req.body.read_to_string(&mut request_payload)); itry!(req.body.read_to_string(&mut request_payload));
Ok(serde_json::from_str::<http::GraphQLRequest>( Ok(
request_payload.as_str(), serde_json::from_str::<http::GraphQLRequest>(request_payload.as_str())
).map_err(|err| GraphQLIronError::Serde(err))?) .map_err(|err| GraphQLIronError::Serde(err))?,
)
} }
fn execute(&self, context: &CtxT, request: http::GraphQLRequest) -> IronResult<Response> { fn execute(&self, context: &CtxT, request: http::GraphQLRequest) -> IronResult<Response> {
@ -258,8 +255,8 @@ impl<'a, CtxFactory, Query, Mutation, CtxT> Handler
where where
CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static, CtxFactory: Fn(&mut Request) -> CtxT + Send + Sync + 'static,
CtxT: 'static, CtxT: 'static,
Query: GraphQLType<Context = CtxT, TypeInfo=()> + Send + Sync + 'static, Query: GraphQLType<Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
Mutation: GraphQLType<Context = CtxT, TypeInfo=()> + Send + Sync + 'static, Mutation: GraphQLType<Context = CtxT, TypeInfo = ()> + Send + Sync + 'static,
'a: 'static, 'a: 'static,
{ {
fn handle(&self, mut req: &mut Request) -> IronResult<Response> { fn handle(&self, mut req: &mut Request) -> IronResult<Response> {

View file

@ -1,9 +1,9 @@
#![feature(plugin)] #![feature(plugin)]
#![plugin(rocket_codegen)] #![plugin(rocket_codegen)]
extern crate rocket;
extern crate juniper; extern crate juniper;
extern crate juniper_rocket; extern crate juniper_rocket;
extern crate rocket;
use rocket::response::content; use rocket::response::content;
use rocket::State; use rocket::State;

View file

@ -40,8 +40,8 @@ Check the LICENSE file for details.
#![plugin(rocket_codegen)] #![plugin(rocket_codegen)]
extern crate juniper; extern crate juniper;
extern crate serde_json;
extern crate rocket; extern crate rocket;
extern crate serde_json;
use std::io::{Cursor, Read}; use std::io::{Cursor, Read};
use std::error::Error; use std::error::Error;
@ -123,9 +123,8 @@ impl<'f> FromForm<'f> for GraphQLRequest {
} }
"operation_name" => { "operation_name" => {
if operation_name.is_some() { if operation_name.is_some() {
return Err( return Err("Operation name parameter must not occur more than once"
"Operation name parameter must not occur more than once".to_owned(), .to_owned());
);
} else { } else {
match value.url_decode() { match value.url_decode() {
Ok(v) => operation_name = Some(v), Ok(v) => operation_name = Some(v),
@ -135,20 +134,15 @@ impl<'f> FromForm<'f> for GraphQLRequest {
} }
"variables" => { "variables" => {
if variables.is_some() { if variables.is_some() {
return Err( return Err("Variables parameter must not occur more than once".to_owned());
"Variables parameter must not occur more than once".to_owned(),
);
} else { } else {
let decoded; let decoded;
match value.url_decode() { match value.url_decode() {
Ok(v) => decoded = v, Ok(v) => decoded = v,
Err(e) => return Err(e.description().to_string()), Err(e) => return Err(e.description().to_string()),
} }
variables = Some(serde_json::from_str::<InputValue>(&decoded).map_err( variables = Some(serde_json::from_str::<InputValue>(&decoded)
|err| { .map_err(|err| err.description().to_owned())?);
err.description().to_owned()
},
)?);
} }
} }
_ => { _ => {
@ -160,9 +154,11 @@ impl<'f> FromForm<'f> for GraphQLRequest {
} }
if let Some(query) = query { if let Some(query) = query {
Ok(GraphQLRequest( Ok(GraphQLRequest(http::GraphQLRequest::new(
http::GraphQLRequest::new(query, operation_name, variables), query,
)) operation_name,
variables,
)))
} else { } else {
Err("Query parameter missing".to_owned()) Err("Query parameter missing".to_owned())
} }
@ -193,13 +189,11 @@ impl<'r> Responder<'r> for GraphQLResponse {
fn respond_to(self, _: &Request) -> Result<Response<'r>, Status> { fn respond_to(self, _: &Request) -> Result<Response<'r>, Status> {
let GraphQLResponse(status, body) = self; let GraphQLResponse(status, body) = self;
Ok( Ok(Response::build()
Response::build() .header(ContentType::new("application", "json"))
.header(ContentType::new("application", "json")) .status(status)
.status(status) .sized_body(Cursor::new(body))
.sized_body(Cursor::new(body)) .finalize())
.finalize(),
)
} }
} }
@ -208,7 +202,7 @@ mod fromform_tests {
use super::*; use super::*;
use std::str; use std::str;
use juniper::InputValue; use juniper::InputValue;
use rocket::request::{FromForm, FormItems}; use rocket::request::{FormItems, FromForm};
fn check_error(input: &str, error: &str, strict: bool) { fn check_error(input: &str, error: &str, strict: bool) {
let mut items = FormItems::from(input); let mut items = FormItems::from(input);
@ -224,16 +218,16 @@ mod fromform_tests {
#[test] #[test]
fn test_no_query() { fn test_no_query() {
check_error("operation_name=foo&variables={}", "Query parameter missing", false); check_error(
"operation_name=foo&variables={}",
"Query parameter missing",
false,
);
} }
#[test] #[test]
fn test_strict() { fn test_strict() {
check_error( check_error("query=test&foo=bar", "Prohibited extra field \'foo\'", true);
"query=test&foo=bar",
"Prohibited extra field \'foo\'",
true,
);
} }
#[test] #[test]

View file

@ -9,8 +9,7 @@ use juniper::{self, FromInputValue, GraphQLType, InputValue, ToInputValue};
enum SomeEnum { enum SomeEnum {
Regular, Regular,
#[graphql(name = "full", description = "field descr", deprecated = "depr")] #[graphql(name = "full", description = "field descr", deprecated = "depr")] Full,
Full,
} }
#[test] #[test]
@ -26,14 +25,20 @@ fn test_derived_enum() {
assert_eq!(meta.description(), Some(&"enum descr".to_string())); assert_eq!(meta.description(), Some(&"enum descr".to_string()));
// Test Regular variant. // Test Regular variant.
assert_eq!(SomeEnum::Regular.to_input_value(), InputValue::String("REGULAR".into())); assert_eq!(
SomeEnum::Regular.to_input_value(),
InputValue::String("REGULAR".into())
);
assert_eq!( assert_eq!(
FromInputValue::from_input_value(&InputValue::String("REGULAR".into())), FromInputValue::from_input_value(&InputValue::String("REGULAR".into())),
Some(SomeEnum::Regular) Some(SomeEnum::Regular)
); );
// Test FULL variant. // Test FULL variant.
assert_eq!(SomeEnum::Full.to_input_value(), InputValue::String("full".into())); assert_eq!(
SomeEnum::Full.to_input_value(),
InputValue::String("full".into())
);
assert_eq!( assert_eq!(
FromInputValue::from_input_value(&InputValue::String("full".into())), FromInputValue::from_input_value(&InputValue::String("full".into())),
Some(SomeEnum::Full) Some(SomeEnum::Full)

View file

@ -8,11 +8,9 @@ use juniper::{self, FromInputValue, GraphQLType, InputValue};
#[graphql(name = "MyInput", description = "input descr")] #[graphql(name = "MyInput", description = "input descr")]
struct Input { struct Input {
regular_field: String, regular_field: String,
#[graphql(name = "haha", default = "33", description = "haha descr")] #[graphql(name = "haha", default = "33", description = "haha descr")] c: i32,
c: i32,
#[graphql(default)] #[graphql(default)] other: Option<bool>,
other: Option<bool>,
} }
#[test] #[test]
@ -32,11 +30,14 @@ fn test_derived_input_object() {
})).unwrap(); })).unwrap();
let output_no_defaults: Input = FromInputValue::from_input_value(&input_no_defaults).unwrap(); let output_no_defaults: Input = FromInputValue::from_input_value(&input_no_defaults).unwrap();
assert_eq!(output_no_defaults, Input{ assert_eq!(
regular_field: "a".into(), output_no_defaults,
c: 33, Input {
other: None, regular_field: "a".into(),
}); c: 33,
other: None,
}
);
// Test with all values supplied. // Test with all values supplied.
@ -47,9 +48,12 @@ fn test_derived_input_object() {
})).unwrap(); })).unwrap();
let output: Input = FromInputValue::from_input_value(&input).unwrap(); let output: Input = FromInputValue::from_input_value(&input).unwrap();
assert_eq!(output, Input{ assert_eq!(
regular_field: "a".into(), output,
c: 55, Input {
other: Some(true), regular_field: "a".into(),
}); c: 55,
other: Some(true),
}
);
} }

View file

@ -8,8 +8,7 @@ use juniper::{self, execute, EmptyMutation, GraphQLType, RootNode, Value, Variab
#[graphql(name = "MyObj", description = "obj descr")] #[graphql(name = "MyObj", description = "obj descr")]
struct Obj { struct Obj {
regular_field: bool, regular_field: bool,
#[graphql(name = "renamedField", description = "descr", deprecation = "field descr")] #[graphql(name = "renamedField", description = "descr", deprecation = "field descr")] c: i32,
c: i32,
} }
#[derive(GraphQLObject, Debug, PartialEq)] #[derive(GraphQLObject, Debug, PartialEq)]
@ -59,14 +58,26 @@ fn test_derived_object() {
let schema = RootNode::new(Query, EmptyMutation::<()>::new()); let schema = RootNode::new(Query, EmptyMutation::<()>::new());
assert_eq!( assert_eq!(
execute(doc, None, &schema, &Variables::new(), &()), execute(doc, None, &schema, &Variables::new(), &()),
Ok((Value::object(vec![ Ok((
("obj", Value::object(vec![ Value::object(
("regularField", Value::boolean(true)), vec![
("renamedField", Value::int(22)), (
].into_iter().collect())), "obj",
].into_iter().collect()), Value::object(
vec![]))); vec![
("regularField", Value::boolean(true)),
("renamedField", Value::int(22)),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
),
vec![]
))
);
} }
#[test] #[test]
@ -85,13 +96,31 @@ fn test_derived_object_nested() {
assert_eq!( assert_eq!(
execute(doc, None, &schema, &Variables::new(), &()), execute(doc, None, &schema, &Variables::new(), &()),
Ok((Value::object(vec![ Ok((
("nested", Value::object(vec![ Value::object(
("obj", Value::object(vec![ vec![
("regularField", Value::boolean(false)), (
("renamedField", Value::int(333)), "nested",
].into_iter().collect()) Value::object(
)].into_iter().collect())), vec![
].into_iter().collect()), (
vec![]))); "obj",
Value::object(
vec![
("regularField", Value::boolean(false)),
("renamedField", Value::int(333)),
].into_iter()
.collect(),
),
),
].into_iter()
.collect(),
),
),
].into_iter()
.collect()
),
vec![]
))
);
} }