gitlab-org--gitlab-foss/spec/support/helpers/graphql_helpers.rb
Bob Van Landuyt 04b046587f Add pipeline lists to GraphQL
This adds Keyset pagination to GraphQL lists. PoC for that is
pipelines on merge requests and projects.

When paginating a list, the base-64 encoded id of the ordering
field (in most cases the primary key) can be passed in the `before` or
`after` GraphQL argument.
2018-07-04 10:53:39 +02:00

111 lines
2.5 KiB
Ruby

module GraphqlHelpers
# makes an underscored string look like a fieldname
# "merge_request" => "mergeRequest"
def self.fieldnamerize(underscored_field_name)
graphql_field_name = underscored_field_name.to_s.camelize
graphql_field_name[0] = graphql_field_name[0].downcase
graphql_field_name
end
# Run a loader's named resolver
def resolve(resolver_class, obj: nil, args: {}, ctx: {})
resolver_class.new(object: obj, context: ctx).resolve(args)
end
# Runs a block inside a BatchLoader::Executor wrapper
def batch(max_queries: nil, &blk)
wrapper = proc do
begin
BatchLoader::Executor.ensure_current
yield
ensure
BatchLoader::Executor.clear_current
end
end
if max_queries
result = nil
expect { result = wrapper.call }.not_to exceed_query_limit(max_queries)
result
else
wrapper.call
end
end
def graphql_query_for(name, attributes = {}, fields = nil)
<<~QUERY
{
#{query_graphql_field(name, attributes, fields)}
}
QUERY
end
def query_graphql_field(name, attributes = {}, fields = nil)
fields ||= all_graphql_fields_for(name.classify)
attributes = attributes_to_graphql(attributes)
<<~QUERY
#{name}(#{attributes}) {
#{fields}
}
QUERY
end
def all_graphql_fields_for(class_name)
type = GitlabSchema.types[class_name.to_s]
return "" unless type
type.fields.map do |name, field|
# We can't guess arguments, so skip fields that require them
next if required_arguments?(field)
if nested_fields?(field)
"#{name} { #{all_graphql_fields_for(field_type(field))} }"
else
name
end
end.compact.join("\n")
end
def attributes_to_graphql(attributes)
attributes.map do |name, value|
"#{GraphqlHelpers.fieldnamerize(name.to_s)}: \"#{value}\""
end.join(", ")
end
def post_graphql(query, current_user: nil)
post api('/', current_user, version: 'graphql'), query: query
end
def graphql_data
json_response['data']
end
def graphql_errors
json_response['data']
end
def nested_fields?(field)
!scalar?(field) && !enum?(field)
end
def scalar?(field)
field_type(field).kind.scalar?
end
def enum?(field)
field_type(field).kind.enum?
end
def required_arguments?(field)
field.arguments.values.any? { |argument| argument.type.non_null? }
end
def field_type(field)
if field.type.respond_to?(:of_type)
field.type.of_type
else
field.type
end
end
end