Fixes Issue 914 (#915)

* Add failing tests

* Fix failing test

* cargo fmt
This commit is contained in:
Tilman Roeder 2021-04-18 00:29:08 +01:00 committed by GitHub
parent 5225b9e06c
commit 5ae930bfc7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 136 additions and 3 deletions

View file

@ -0,0 +1,119 @@
use juniper::*;
struct Query;
#[derive(GraphQLObject)]
struct Foo {
bar: Bar,
}
#[derive(GraphQLObject)]
struct Bar {
a: i32,
b: i32,
baz: Baz,
}
#[derive(GraphQLObject)]
struct Baz {
c: i32,
d: i32,
}
#[graphql_object]
impl Query {
fn foo() -> Foo {
let baz = Baz { c: 1, d: 2 };
let bar = Bar { a: 1, b: 2, baz };
Foo { bar }
}
}
type Schema = juniper::RootNode<'static, Query, EmptyMutation, EmptySubscription>;
#[tokio::test]
async fn test_fragments_with_nested_objects_dont_override_previous_selections() {
let query = r#"
query Query {
foo {
...BarA
...BarB
...BazC
...BazD
}
}
fragment BarA on Foo {
bar {
a
}
}
fragment BarB on Foo {
bar {
b
}
}
fragment BazC on Foo {
bar {
baz {
c
}
}
}
fragment BazD on Foo {
bar {
baz {
d
}
}
}
"#;
let (async_value, errors) = juniper::execute(
query,
None,
&Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()),
&Variables::new(),
&(),
)
.await
.unwrap();
assert_eq!(errors.len(), 0);
let (sync_value, errors) = juniper::execute_sync(
query,
None,
&Schema::new(Query, EmptyMutation::new(), EmptySubscription::new()),
&Variables::new(),
&(),
)
.unwrap();
assert_eq!(errors.len(), 0);
assert_eq!(async_value, sync_value);
let bar = async_value
.as_object_value()
.unwrap()
.get_field_value("foo")
.unwrap()
.as_object_value()
.unwrap()
.get_field_value("bar")
.unwrap()
.as_object_value()
.unwrap();
assert!(bar.contains_field("a"), "Field a should be selected");
assert!(bar.contains_field("b"), "Field b should be selected");
let baz = bar
.get_field_value("baz")
.unwrap()
.as_object_value()
.unwrap();
assert!(baz.contains_field("c"), "Field c should be selected");
assert!(baz.contains_field("d"), "Field d should be selected");
}

View file

@ -19,4 +19,6 @@ mod issue_407;
#[cfg(test)]
mod issue_500;
#[cfg(test)]
mod issue_914;
#[cfg(test)]
mod pre_parse;

View file

@ -28,14 +28,26 @@ impl<S> Object<S> {
/// Add a new field with a value
///
/// If there is already a field with the same name the old value
/// is returned
/// If there is already a field for the given key
/// any both values are objects, they are merged.
///
/// Otherwise the existing value is replaced and
/// returned.
pub fn add_field<K>(&mut self, k: K, value: Value<S>) -> Option<Value<S>>
where
K: Into<String>,
for<'a> &'a str: PartialEq<K>,
{
self.key_value_list.insert(k.into(), value)
let key: String = k.into();
match (value, self.key_value_list.get_mut(&key)) {
(Value::<S>::Object(obj_val), Some(Value::<S>::Object(existing_obj))) => {
for (key, val) in obj_val.into_iter() {
existing_obj.add_field::<String>(key, val);
}
None
}
(non_obj_val, _) => self.key_value_list.insert(key, non_obj_val),
}
}
/// Check if the object already contains a field with the given name