summaryrefslogtreecommitdiff
path: root/spec/support/helpers/graphql_helpers.rb
blob: 0930b9da368b0ade1b9a822879a76b48308e6edf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
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 field.arguments.any?

      if scalar?(field)
        name
      else
        "#{name} { #{all_graphql_fields_for(field_type(field))} }"
      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 scalar?(field)
    field_type(field).kind.scalar?
  end

  def field_type(field)
    if field.type.respond_to?(:of_type)
      field.type.of_type
    else
      field.type
    end
  end
end