Commit ca6498de authored by Alex Kalderimis's avatar Alex Kalderimis

Graphql Helper improvements

These changes to GraphqlHelpers are generally useful, and backwards
compatible with existing code.

They include:

- The addition of `wrap_fields`
- `query_field` accepts an optional type argument
- We assert that none of our queries result in internal server errors
- We use fresh responses by default (helpful for assertions involving
  multiple requests).
- We assert that all types are known in the schema.
parent 312d5560
......@@ -435,13 +435,13 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
let_it_be_with_reload(:release) { create(:release, project: project) }
let(:release_fields) do
query_graphql_field(%{
%{
milestones {
nodes {
title
}
}
})
}
end
let(:actual_milestone_title_order) do
......
......@@ -125,11 +125,15 @@ module GraphqlHelpers
end
def graphql_query_for(name, attributes = {}, fields = nil)
<<~QUERY
{
#{query_graphql_field(name, attributes, fields)}
}
QUERY
type = GitlabSchema.types['Query'].fields[GraphqlHelpers.fieldnamerize(name)]&.type
wrap_query(query_graphql_field(name, attributes, fields, type))
end
def wrap_query(query)
q = query.to_s
return q if q.starts_with?('{')
"{ #{q} }"
end
def graphql_mutation(name, input, fields = nil, &block)
......@@ -219,12 +223,13 @@ module GraphqlHelpers
"#{namerized}#{field_params}"
end
def query_graphql_field(name, attributes = {}, fields = nil)
def query_graphql_field(name, attributes = {}, fields = nil, type = nil)
type ||= name.to_s.classify
attributes, fields = [nil, attributes] if fields.nil? && !attributes.is_a?(Hash)
field = field_with_params(name, attributes)
field + wrap_fields(fields || all_graphql_fields_for(name.to_s.classify)).to_s
field + wrap_fields(fields || all_graphql_fields_for(type)).to_s
end
def page_info_selection
......@@ -281,8 +286,8 @@ module GraphqlHelpers
allow_high_graphql_recursion
allow_high_graphql_transaction_threshold
type = GitlabSchema.types[class_name.to_s]
return "" unless type
type = class_name.respond_to?(:kind) ? class_name : GitlabSchema.types[class_name.to_s]
raise "#{class_name} is not a known type in the GitlabSchema" unless type
# We can't guess arguments, so skip fields that require them
skip = ->(name, field) { excluded.include?(name) || required_arguments?(field) }
......@@ -291,7 +296,7 @@ module GraphqlHelpers
end
def with_signature(variables, query)
%Q[query(#{variables.map(&:sig).join(', ')}) #{query}]
%Q[query(#{variables.map(&:sig).join(', ')}) #{wrap_query(query)}]
end
def var(type)
......@@ -309,6 +314,10 @@ module GraphqlHelpers
def post_graphql(query, current_user: nil, variables: nil, headers: {})
params = { query: query, variables: serialize_variables(variables) }
post api('/', current_user, version: 'graphql'), params: params, headers: headers
if graphql_errors # Errors are acceptable, but not this one:
expect(graphql_errors).not_to include(a_hash_including('message' => 'Internal server error'))
end
end
def post_graphql_mutation(mutation, current_user: nil)
......@@ -378,10 +387,8 @@ module GraphqlHelpers
end
# Raises an error if no data is found
def graphql_data(body = json_response)
# Note that `json_response` is defined as `let(:json_response)` and
# therefore, in a spec with multiple queries, will only contain data
# from the _first_ query, not subsequent ones
# NB: We use fresh_response_data to support tests that make multiple requests.
def graphql_data(body = fresh_response_data)
body['data'] || (raise NoData, graphql_errors(body))
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment