Skip to content

Commit

Permalink
Fixes Issue 914 (#915)
Browse files Browse the repository at this point in the history
* Add failing tests

* Fix failing test

* cargo fmt
  • Loading branch information
dyedgreen committed Apr 17, 2021
1 parent 5225b9e commit 5ae930b
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 3 deletions.
119 changes: 119 additions & 0 deletions integration_tests/juniper_tests/src/issue_914.rs
Original file line number Diff line number Diff line change
@@ -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");
}
2 changes: 2 additions & 0 deletions integration_tests/juniper_tests/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ mod issue_407;
#[cfg(test)]
mod issue_500;
#[cfg(test)]
mod issue_914;
#[cfg(test)]
mod pre_parse;
18 changes: 15 additions & 3 deletions juniper/src/value/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5ae930b

Please sign in to comment.