#![allow(dead_code, unused_variables, unused_imports)]
#[macro_use]
extern crate juniper;
#[macro_use]
extern crate maplit;
use assert_json_diff::assert_json_include;
use juniper::{Executor, FieldResult, Variables, ID};
use juniper_from_schema::{graphql_schema, graphql_schema_from_file};
use serde_json::{self, json, Value};
use std::collections::HashMap;
graphql_schema_from_file!("tests/schemas/complex_schema.graphql");
pub struct Query;
impl QueryFields for Query {
fn field_hero<'a>(
&self,
executor: &Executor<'a, Context>,
trail: &QueryTrail<'a, Character, Walked>,
episode: Option<Episode>,
) -> FieldResult<Option<Character>> {
let hero = episode.and_then(|episode| {
let luke = executor
.context()
.db
.humans
.get(&"1")
.map(|h| Character::from(h.clone()));
match episode {
Episode::Newhope => luke,
Episode::Empire => luke,
Episode::Jedi => luke,
}
});
Ok(hero)
}
fn field_search<'a>(
&self,
executor: &Executor<'a, Context>,
trail: &QueryTrail<'a, SearchResult, Walked>,
text: Option<String>,
) -> FieldResult<Option<Vec<SearchResult>>> {
let results = text.map(|text| {
executor
.context()
.db
.humans
.clone()
.into_iter()
.map(|(_, human)| human)
.filter(|human| human.name.contains(&text))
.map(SearchResult::from)
.collect::<Vec<_>>()
});
Ok(results)
}
}
pub struct Mutation;
impl MutationFields for Mutation {
fn field_create_review<'a>(
&self,
executor: &Executor<'a, Context>,
trail: &QueryTrail<'a, Review, Walked>,
episode: Option<Episode>,
review: ReviewInput,
) -> FieldResult<Option<Review>> {
let review = Review {
episode,
stars: review.stars,
commentary: review.commentary,
favorite_color: review.favorite_color,
};
Ok(Some(review))
}
}
pub struct Review {
episode: Option<Episode>,
stars: i32,
commentary: Option<String>,
favorite_color: Option<ColorInput>,
}
impl ReviewFields for Review {
fn field_episode<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<&Option<Episode>> {
Ok(&self.episode)
}
fn field_stars<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<&i32> {
Ok(&self.stars)
}
fn field_commentary<'a>(
&self,
executor: &Executor<'a, Context>,
) -> FieldResult<&Option<String>> {
Ok(&self.commentary)
}
fn field_favorite_color<'a>(
&self,
executor: &Executor<'a, Context>,
_: &QueryTrail<'a, ColorInput, Walked>,
) -> FieldResult<&Option<ColorInput>> {
Ok(&self.favorite_color)
}
}
#[derive(Clone)]
pub struct Human {
id: &'static str,
name: String,
}
impl HumanFields for Human {
fn field_id<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<ID> {
Ok(ID::new(self.id))
}
fn field_name<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<&String> {
Ok(&self.name)
}
}
#[derive(Clone)]
pub struct Droid {
id: &'static str,
name: String,
}
impl DroidFields for Droid {
fn field_id<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<ID> {
Ok(ID::new(self.id))
}
fn field_name<'a>(&self, executor: &Executor<'a, Context>) -> FieldResult<&String> {
Ok(&self.name)
}
}
pub struct Context {
db: Db,
}
impl juniper::Context for Context {}
pub struct Db {
humans: HashMap<&'static str, Human>,
}
#[test]
fn query_hero() {
let value = run_query(r#"query { hero(episode: NEWHOPE) { id name } }"#);
assert_json_include!(
actual: value,
expected: json!({
"hero": {
"id": "1",
"name": "Luke Skywalker",
}
})
);
let value = run_query(r#"query { hero(episode: EMPIRE) { id name } }"#);
assert_json_include!(
actual: value,
expected: json!({
"hero": {
"id": "1",
"name": "Luke Skywalker",
}
})
);
let value = run_query(r#"query { hero(episode: JEDI) { id name } }"#);
assert_json_include!(
actual: value,
expected: json!({
"hero": {
"id": "1",
"name": "Luke Skywalker",
}
})
);
}
#[test]
fn search() {
let value = run_query(
r#"
query {
search(text: "Luke") {
... on Human {
id name
}
... on Droid {
id name
}
}
}
"#,
);
assert_json_include!(
actual: value,
expected: json!({
"search": [
{ "id": "1", "name": "Luke Skywalker" },
]
})
);
}
fn run_query(query: &str) -> Value {
let db = Db {
humans: hashmap! {
"1" => Human { id: "1", name: "Luke Skywalker".to_string() },
},
};
let ctx = Context { db };
let (res, _errors) = juniper::execute(
query,
None,
&Schema::new(Query, Mutation),
&Variables::new(),
&ctx,
)
.unwrap();
serde_json::from_str(&serde_json::to_string(&res).unwrap()).unwrap()
}