Support __typename for unions

See http://graphql.org/learn/queries/#meta-fields.

Fixes https://github.com/graphql-rust/juniper/issues/112.
This commit is contained in:
Christian Legnitto 2017-12-05 15:56:17 -08:00 committed by Magnus Hallin
parent ca9d5c1c1a
commit 203af1ce98
2 changed files with 35 additions and 0 deletions

View file

@ -204,6 +204,7 @@ mod union {
let doc = r"
{
pets {
__typename
... on Dog {
name
woofs
@ -228,10 +229,12 @@ mod union {
Value::object(vec![
("pets", Value::list(vec![
Value::object(vec![
("__typename", Value::string("Dog")),
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter().collect()),
Value::object(vec![
("__typename", Value::string("Cat")),
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter().collect()),

View file

@ -1,4 +1,5 @@
use ast::Field;
use schema::meta::MetaType;
use validation::{ValidatorContext, Visitor};
use parser::Spanning;
@ -16,6 +17,19 @@ impl<'a> Visitor<'a> for FieldsOnCorrectType {
let type_name = parent_type.name().unwrap_or("<unknown>");
if parent_type.field_by_name(field_name.item).is_none() {
match *parent_type {
MetaType::Union(..) => {
// You can query for `__typename` on a union,
// but it isn't a field on the union...it is
// instead on the resulting object returned.
if field_name.item == "__typename" {
return;
}
}
_ => {}
}
context.report_error(
&error_message(field_name.item, type_name),
&[field_name.start.clone()],
@ -318,6 +332,24 @@ mod tests {
);
}
#[test]
fn typename_on_union() {
expect_passes_rule(
factory,
r#"
fragment objectFieldSelection on Pet {
__typename
... on Dog {
name
}
... on Cat {
name
}
}
"#,
);
}
#[test]
fn valid_field_in_inline_fragment() {
expect_passes_rule(