From 980ea7d22ca0550f18a2a10354960d0fb9cd843d Mon Sep 17 00:00:00 2001 From: Alyanna Santos <72548456+al-yanna@users.noreply.github.com> Date: Fri, 6 Dec 2024 11:03:08 -0500 Subject: [PATCH] fix: remove `parent_type.fields` check in analyzer (#46) * fix: remove parent_type.fields check * fix: update to v0.5.3 * fix: lint * fix: update check Co-authored-by: Arya Bhimani * fix: update test * fix: lint --------- Co-authored-by: Arya Bhimani --- Gemfile.lock | 2 +- lib/graphql-hive/analyzer.rb | 2 +- lib/graphql-hive/version.rb | 2 +- spec/graphql/graphql-hive/analyzer_spec.rb | 167 +++++++++++++-------- 4 files changed, 111 insertions(+), 62 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 1385083..ec556a5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - graphql-hive (0.5.2) + graphql-hive (0.5.3) graphql (>= 2.3, < 3) GEM diff --git a/lib/graphql-hive/analyzer.rb b/lib/graphql-hive/analyzer.rb index 0472d44..4b3911f 100644 --- a/lib/graphql-hive/analyzer.rb +++ b/lib/graphql-hive/analyzer.rb @@ -11,7 +11,7 @@ def initialize(query_or_multiplex) def on_enter_field(node, _parent, visitor) parent_type = visitor.parent_type_definition - if parent_type&.respond_to?(:graphql_name) && parent_type.fields[node.name] + if parent_type&.respond_to?(:graphql_name) && node&.respond_to?(:name) @used_fields.add(parent_type.graphql_name) @used_fields.add(make_id(parent_type.graphql_name, node.name)) end diff --git a/lib/graphql-hive/version.rb b/lib/graphql-hive/version.rb index bcfc611..42eef1c 100644 --- a/lib/graphql-hive/version.rb +++ b/lib/graphql-hive/version.rb @@ -2,6 +2,6 @@ module Graphql module Hive - VERSION = "0.5.2" + VERSION = "0.5.3" end end diff --git a/spec/graphql/graphql-hive/analyzer_spec.rb b/spec/graphql/graphql-hive/analyzer_spec.rb index 16b6022..0ed03b6 100644 --- a/spec/graphql/graphql-hive/analyzer_spec.rb +++ b/spec/graphql/graphql-hive/analyzer_spec.rb @@ -16,70 +16,75 @@ end let(:schema) do - GraphQL::Schema.from_definition(%| - type Query { - project(selector: ProjectSelectorInput!): Project - projectsByType(type: ProjectType!): [Project!]! - projectsByManyTypes(type: [ProjectType!]!): [Project!]! - projects(filter: FilterInput): [Project!]! - } + GraphQL::Schema.from_definition( + <<~GQL + type Query { + project(selector: ProjectSelectorInput!): Project + projectsByType(type: ProjectType!): [Project!]! + projectsByManyTypes(type: [ProjectType!]!): [Project!]! + projects(filter: FilterInput): [Project!]! + searchResult(query: String!): SearchResult + } - type Mutation { - deleteProject(selector: ProjectSelectorInput!): DeleteProjectPayload! - } + type Mutation { + deleteProject(selector: ProjectSelectorInput!): DeleteProjectPayload! + } - input ProjectSelectorInput { - organization: ID! - project: ID! - } + input ProjectSelectorInput { + organization: ID! + project: ID! + } - input FilterInput { - type: ProjectType - pagination: PaginationInput - order: [ProjectOrderByInput!] - } + input FilterInput { + type: ProjectType + pagination: PaginationInput + order: [ProjectOrderByInput!] + } - input PaginationInput { - limit: Int - offset: Int - } + input PaginationInput { + limit: Int + offset: Int + } - input ProjectOrderByInput { - field: String! - direction: OrderDirection - } + input ProjectOrderByInput { + field: String! + direction: OrderDirection + } - enum OrderDirection { - ASC - DESC - } + enum OrderDirection { + ASC + DESC + } - type ProjectSelector { - organization: ID! - project: ID! - } + type ProjectSelector { + organization: ID! + project: ID! + } - type DeleteProjectPayload { - selector: ProjectSelector! - deletedProject: Project! - } + type DeleteProjectPayload { + selector: ProjectSelector! + deletedProject: Project! + } - type Project { - id: ID! - cleanId: ID! - name: String! - type: ProjectType! - buildUrl: String - validationUrl: String - } + type Project { + id: ID! + cleanId: ID! + name: String! + type: ProjectType! + buildUrl: String + validationUrl: String + } - enum ProjectType { - FEDERATION - STITCHING - SINGLE - CUSTOM - } - |) + enum ProjectType { + FEDERATION + STITCHING + SINGLE + CUSTOM + } + + union SearchResult = Project | ProjectSelector + GQL + ) end let(:query_string) do @@ -350,11 +355,51 @@ end end + context "with a query containing a union type" do + let(:query_string) do + <<~GQL + query searchProjects { + searchResult(query: $query) { + __typename + ... on Project { + id + } + ... on ProjectSelector { + organization + } + } + } + GQL + end + + it "collects all valid fields from union types" do + expect(used_fields).to contain_exactly( + "Query", + "Query.searchResult", + "Query.searchResult.query", + "SearchResult", + "SearchResult.__typename", + "Project", + "Project.id", + "ProjectSelector", + "ProjectSelector.organization", + "String" + ) + end + end + context "with an invalid field" do let(:query_string) do <<~GQL query getGatewayProjects { - projectsByManyTypes(type: [STITCHING]), + searchResult(query: $query) { + nonExistentField { + subField + } + ... on Project { + id + } + } nonExistentField { subField } @@ -365,10 +410,14 @@ it "collects all valid fields and excludes invalid fields" do expect(used_fields).to contain_exactly( "Query", - "Query.projectsByManyTypes", - "ProjectType", - "Query.projectsByManyTypes.type", - "ProjectType.STITCHING" + "Query.searchResult", + "Query.searchResult.query", + "SearchResult", + "SearchResult.nonExistentField", + "Project", + "Project.id", + "Query.nonExistentField", + "String" ) end end