Skip to content

Commit

Permalink
fix(modify): bug in modify for graphql (#2983)
Browse files Browse the repository at this point in the history
Co-authored-by: Heikel Bouzayene <[email protected]>
  • Loading branch information
MedHeikelBouzayene and Heikel Bouzayene authored Oct 12, 2024
1 parent 1679aea commit 9b003f8
Show file tree
Hide file tree
Showing 7 changed files with 130 additions and 11 deletions.
23 changes: 19 additions & 4 deletions src/core/blueprint/operators/graphql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,25 @@ fn create_related_fields(
if let Some(type_) = config.find_type(type_name) {
for (name, field) in &type_.fields {
if !field.has_resolver() {
map.insert(
name.clone(),
create_related_fields(config, field.type_of.name(), visited),
);
if let Some(modify) = &field.modify {
if let Some(modified_name) = &modify.name {
map.insert(
modified_name.clone(),
(
name.clone(),
create_related_fields(config, field.type_of.name(), visited),
),
);
}
} else {
map.insert(
name.clone(),
(
name.clone(),
create_related_fields(config, field.type_of.name(), visited),
),
);
}
}
}
} else if let Some(union_) = config.find_union(type_name) {
Expand Down
13 changes: 8 additions & 5 deletions src/core/ir/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ fn format_selection_set<'a>(
let set = selection_set
.filter_map(|field| {
// add to set only related fields that should be resolved with current resolver
related_fields
.get(field.name())
.map(|related_fields| format_selection_field(field, related_fields))
related_fields.get(field.name()).map(|related_fields| {
format_selection_field(field, &related_fields.0, &related_fields.1)
})
})
.collect::<Vec<_>>();

Expand All @@ -143,8 +143,11 @@ fn format_selection_set<'a>(
Some(format!("{{ {} }}", set.join(" ")))
}

fn format_selection_field(field: &SelectionField, related_fields: &RelatedFields) -> String {
let name = field.name();
fn format_selection_field(
field: &SelectionField,
name: &str,
related_fields: &RelatedFields,
) -> String {
let arguments = format_selection_field_arguments(field);
let selection_set = format_selection_set(field.selection_set(), related_fields);

Expand Down
4 changes: 2 additions & 2 deletions src/core/ir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ pub use resolver_context_like::{
/// resolver i.e. fields that don't have their own resolver and are resolved by
/// the ancestor
#[derive(Debug, Default, Clone)]
pub struct RelatedFields(pub HashMap<String, RelatedFields>);
pub struct RelatedFields(pub HashMap<String, (String, RelatedFields)>);

impl Deref for RelatedFields {
type Target = HashMap<String, RelatedFields>;
type Target = HashMap<String, (String, RelatedFields)>;

fn deref(&self) -> &Self::Target {
&self.0
Expand Down
18 changes: 18 additions & 0 deletions tests/core/snapshots/graphql-conformance-018.md_0.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
---
source: tests/core/spec.rs
expression: response
---
{
"status": 200,
"headers": {
"content-type": "application/json"
},
"body": {
"data": {
"user": {
"city": "Globe",
"newName": "Tailcall"
}
}
}
}
17 changes: 17 additions & 0 deletions tests/core/snapshots/graphql-conformance-018.md_client.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
source: tests/core/spec.rs
expression: formatted
---
type Query {
user(id: ID!): User!
}

type User {
city: String
id: ID!
newName: String!
}

schema {
query: Query
}
19 changes: 19 additions & 0 deletions tests/core/snapshots/graphql-conformance-018.md_merged.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
source: tests/core/spec.rs
expression: formatter
---
schema
@server(hostname: "0.0.0.0", port: 8001, queryValidation: false)
@upstream(baseURL: "http://upstream/graphql", httpCache: 42) {
query: Query
}

type Query {
user(id: ID!): User! @graphQL(args: [{key: "id", value: "{{.args.id}}"}], name: "user")
}

type User {
city: String
id: ID!
name: String! @modify(name: "newName")
}
47 changes: 47 additions & 0 deletions tests/execution/graphql-conformance-018.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Basic queries with field modify check

```graphql @config
schema
@server(port: 8001, queryValidation: false, hostname: "0.0.0.0")
@upstream(baseURL: "http://upstream/graphql", httpCache: 42) {
query: Query
}

type Query {
user(id: ID!): User! @graphQL(name: "user", args: [{key: "id", value: "{{.args.id}}"}])
}

type User {
id: ID!
name: String! @modify(name: "newName")
city: String
}
```

```yml @mock
- request:
method: POST
url: http://upstream/graphql
textBody: '{ "query": "query { user(id: 4) { city name } }" }'
expectedHits: 1
response:
status: 200
body:
data:
user:
city: Globe
name: Tailcall
```

```yml @test
- method: POST
url: http://localhost:8080/graphql
body:
query: |
query getUser {
user(id: 4) {
city
newName
}
}
```

1 comment on commit 9b003f8

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Running 30s test @ http://localhost:8000/graphql

4 threads and 100 connections

Thread Stats Avg Stdev Max +/- Stdev
Latency 7.50ms 3.31ms 45.90ms 72.70%
Req/Sec 3.39k 415.16 3.91k 94.92%

405064 requests in 30.02s, 787.53MB read

Requests/sec: 13491.87

Transfer/sec: 26.23MB

Please sign in to comment.