Fixes Issue 914 (#915)
* Add failing tests * Fix failing test * cargo fmt
This commit is contained in:
parent
5225b9e06c
commit
5ae930bfc7
3 changed files with 136 additions and 3 deletions
119
integration_tests/juniper_tests/src/issue_914.rs
Normal file
119
integration_tests/juniper_tests/src/issue_914.rs
Normal 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");
|
||||||
|
}
|
|
@ -19,4 +19,6 @@ mod issue_407;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod issue_500;
|
mod issue_500;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
mod issue_914;
|
||||||
|
#[cfg(test)]
|
||||||
mod pre_parse;
|
mod pre_parse;
|
||||||
|
|
|
@ -28,14 +28,26 @@ impl<S> Object<S> {
|
||||||
|
|
||||||
/// Add a new field with a value
|
/// Add a new field with a value
|
||||||
///
|
///
|
||||||
/// If there is already a field with the same name the old value
|
/// If there is already a field for the given key
|
||||||
/// is returned
|
/// 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>>
|
pub fn add_field<K>(&mut self, k: K, value: Value<S>) -> Option<Value<S>>
|
||||||
where
|
where
|
||||||
K: Into<String>,
|
K: Into<String>,
|
||||||
for<'a> &'a str: PartialEq<K>,
|
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
|
/// Check if the object already contains a field with the given name
|
||||||
|
|
Loading…
Reference in a new issue