Add interface and union tests

This commit is contained in:
Magnus Hallin 2016-11-12 22:52:34 +01:00
parent c555241978
commit 0ea61fa493
3 changed files with 235 additions and 0 deletions

View file

@ -0,0 +1,221 @@
mod interface {
use value::Value;
use schema::model::RootNode;
trait Pet {
fn name(&self) -> &str;
fn as_dog(&self) -> Option<&Dog> { None }
fn as_cat(&self) -> Option<&Cat> { None }
}
graphql_interface!(<'a> &'a Pet: () as "Pet" |&self| {
field name() -> &str { self.name() }
instance_resolvers: |&_| {
&Dog => self.as_dog(),
&Cat => self.as_cat(),
}
});
struct Dog {
name: String,
woofs: bool,
}
impl Pet for Dog {
fn name(&self) -> &str { &self.name }
fn as_dog(&self) -> Option<&Dog> { Some(self) }
}
graphql_object!(Dog: () |&self| {
field name() -> &str { &self.name }
field woofs() -> bool { self.woofs }
interfaces: [&Pet]
});
struct Cat {
name: String,
meows: bool,
}
impl Pet for Cat {
fn name(&self) -> &str { &self.name }
fn as_cat(&self) -> Option<&Cat> { Some(self) }
}
graphql_object!(Cat: () |&self| {
field name() -> &str { &self.name }
field meows() -> bool { self.meows }
interfaces: [&Pet]
});
struct Schema {
pets: Vec<Box<Pet>>,
}
graphql_object!(Schema: () |&self| {
field pets() -> Vec<&Pet> {
self.pets.iter().map(|p| p.as_ref()).collect()
}
});
#[test]
fn test() {
let schema = RootNode::new(
Schema {
pets: vec![
Box::new(Dog { name: "Odie".to_owned(), woofs: true }),
Box::new(Cat { name: "Garfield".to_owned(), meows: false }),
],
},
());
let doc = r"
{
pets {
name
... on Dog {
woofs
}
... on Cat {
meows
}
}
}";
let vars = vec![
].into_iter().collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &())
.expect("Execution failed");
assert_eq!(errs, []);
println!("Result: {:?}", result);
assert_eq!(
result,
Value::object(vec![
("pets", Value::list(vec![
Value::object(vec![
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter().collect()),
Value::object(vec![
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter().collect()),
])),
].into_iter().collect()));
}
}
mod union {
use value::Value;
use schema::model::RootNode;
trait Pet {
fn as_dog(&self) -> Option<&Dog> { None }
fn as_cat(&self) -> Option<&Cat> { None }
}
graphql_union!(<'a> &'a Pet: () as "Pet" |&self| {
instance_resolvers: |&_| {
&Dog => self.as_dog(),
&Cat => self.as_cat(),
}
});
struct Dog {
name: String,
woofs: bool,
}
impl Pet for Dog {
fn as_dog(&self) -> Option<&Dog> { Some(self) }
}
graphql_object!(Dog: () |&self| {
field name() -> &str { &self.name }
field woofs() -> bool { self.woofs }
});
struct Cat {
name: String,
meows: bool,
}
impl Pet for Cat {
fn as_cat(&self) -> Option<&Cat> { Some(self) }
}
graphql_object!(Cat: () |&self| {
field name() -> &str { &self.name }
field meows() -> bool { self.meows }
});
struct Schema {
pets: Vec<Box<Pet>>,
}
graphql_object!(Schema: () |&self| {
field pets() -> Vec<&Pet> {
self.pets.iter().map(|p| p.as_ref()).collect()
}
});
#[test]
fn test() {
let schema = RootNode::new(
Schema {
pets: vec![
Box::new(Dog { name: "Odie".to_owned(), woofs: true }),
Box::new(Cat { name: "Garfield".to_owned(), meows: false }),
],
},
());
let doc = r"
{
pets {
... on Dog {
name
woofs
}
... on Cat {
name
meows
}
}
}";
let vars = vec![
].into_iter().collect();
let (result, errs) = ::execute(doc, None, &schema, &vars, &())
.expect("Execution failed");
assert_eq!(errs, []);
println!("Result: {:?}", result);
assert_eq!(
result,
Value::object(vec![
("pets", Value::list(vec![
Value::object(vec![
("name", Value::string("Odie")),
("woofs", Value::boolean(true)),
].into_iter().collect()),
Value::object(vec![
("name", Value::string("Garfield")),
("meows", Value::boolean(false)),
].into_iter().collect()),
])),
].into_iter().collect()));
}
}

View file

@ -3,3 +3,4 @@ mod variables;
mod enums;
mod directives;
mod executor;
mod interfaces_unions;

View file

@ -169,6 +169,19 @@ macro_rules! graphql_interface {
graphql_interface!(@gather_meta, ($reg, $acc, $descr), $( $rest )*)
};
// instance_resolvers: | <ctxtvar> | [...]
(
@ gather_meta,
($reg:expr, $acc:expr, $descr:expr),
instance_resolvers : | $ctxtvar:pat | { $( $srctype:ty => $resolver:expr ),* $(,)* } $( $rest:tt )*
) => {
$(
let _ = $reg.get_type::<$srctype>();
)*
graphql_interface!(@gather_meta, ($reg, $acc, $descr), $( $rest )*)
};
// instance_resolvers: | <ctxtvar> | [...]
(
@ concrete_type_name,