graphql_client 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rubocop-http---shopify-github-io-ruby-style-guide-rubocop-yml +1133 -0
- data/.rubocop.yml +24 -0
- data/.travis.yml +6 -0
- data/CHANGELOG.md +3 -0
- data/CODE_OF_CONDUCT.md +45 -0
- data/CONTRIBUTING.md +28 -0
- data/CONTRIBUTING_DEVELOPER_CERTIFICATE_OF_ORIGIN.txt +37 -0
- data/Gemfile +8 -0
- data/LICENSE.md +21 -0
- data/README.md +96 -0
- data/Rakefile +13 -0
- data/bin/graphql-client +79 -0
- data/bin/rake +17 -0
- data/circle.yml +3 -0
- data/dev.yml +7 -0
- data/graphql_ruby_client.gemspec +26 -0
- data/lib/graphql_client.rb +46 -0
- data/lib/graphql_client/adapters/http_adapter.rb +72 -0
- data/lib/graphql_client/base.rb +53 -0
- data/lib/graphql_client/config.rb +42 -0
- data/lib/graphql_client/deserialization.rb +36 -0
- data/lib/graphql_client/error.rb +22 -0
- data/lib/graphql_client/graph_connection.rb +21 -0
- data/lib/graphql_client/graph_node.rb +24 -0
- data/lib/graphql_client/graph_object.rb +56 -0
- data/lib/graphql_client/introspection_query.rb +80 -0
- data/lib/graphql_client/query/add_inline_fragment.rb +42 -0
- data/lib/graphql_client/query/argument.rb +30 -0
- data/lib/graphql_client/query/document.rb +86 -0
- data/lib/graphql_client/query/field.rb +91 -0
- data/lib/graphql_client/query/fragment.rb +41 -0
- data/lib/graphql_client/query/has_selection_set.rb +72 -0
- data/lib/graphql_client/query/inline_fragment.rb +35 -0
- data/lib/graphql_client/query/mutation_document.rb +20 -0
- data/lib/graphql_client/query/operation.rb +46 -0
- data/lib/graphql_client/query/operations/mutation_operation.rb +17 -0
- data/lib/graphql_client/query/operations/query_operation.rb +17 -0
- data/lib/graphql_client/query/query_document.rb +20 -0
- data/lib/graphql_client/query/selection_set.rb +53 -0
- data/lib/graphql_client/response.rb +21 -0
- data/lib/graphql_client/response_connection.rb +18 -0
- data/lib/graphql_client/response_object.rb +32 -0
- data/lib/graphql_client/schema_patches.rb +17 -0
- data/lib/graphql_client/version.rb +7 -0
- data/shipit.rubygems.yml +1 -0
- data/shipit.yml +4 -0
- data/test/graphql_client/adapters/http_adapter_test.rb +111 -0
- data/test/graphql_client/config_test.rb +68 -0
- data/test/graphql_client/graph_connection_test.rb +8 -0
- data/test/graphql_client/graph_node_test.rb +8 -0
- data/test/graphql_client/graph_object_query_transforming_test.rb +156 -0
- data/test/graphql_client/graph_object_test.rb +142 -0
- data/test/graphql_client/graphql_client_test.rb +41 -0
- data/test/graphql_client/http_client_test.rb +52 -0
- data/test/graphql_client/query/add_inline_fragment_test.rb +57 -0
- data/test/graphql_client/query/arguments_test.rb +89 -0
- data/test/graphql_client/query/document_test.rb +246 -0
- data/test/graphql_client/query/field_test.rb +163 -0
- data/test/graphql_client/query/fragment_test.rb +45 -0
- data/test/graphql_client/query/inline_fragment_test.rb +37 -0
- data/test/graphql_client/query/mutation_document_test.rb +30 -0
- data/test/graphql_client/query/mutation_operation_test.rb +89 -0
- data/test/graphql_client/query/query_document_test.rb +30 -0
- data/test/graphql_client/query/query_operation_test.rb +262 -0
- data/test/graphql_client/query/selection_set_test.rb +116 -0
- data/test/graphql_client/response_connection_test.rb +50 -0
- data/test/graphql_client/response_object_test.rb +109 -0
- data/test/graphql_client/response_test.rb +67 -0
- data/test/support/fixtures/schema.json +13710 -0
- data/test/test_helper.rb +37 -0
- metadata +227 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
module Query
|
6
|
+
class QueryOperation < Operation
|
7
|
+
def operation_type
|
8
|
+
'query'
|
9
|
+
end
|
10
|
+
|
11
|
+
def resolver_type
|
12
|
+
schema.type(schema.query_root_name)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
module Query
|
6
|
+
class QueryDocument
|
7
|
+
def self.new(schema, name = nil)
|
8
|
+
document = Document.new(schema)
|
9
|
+
query = document.add_query(name)
|
10
|
+
|
11
|
+
if block_given?
|
12
|
+
yield query
|
13
|
+
end
|
14
|
+
|
15
|
+
query
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
module Query
|
6
|
+
class SelectionSet
|
7
|
+
attr_reader :fields, :fragments, :fields, :inline_fragments
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@fragments = {}
|
11
|
+
@fields = {}
|
12
|
+
@inline_fragments = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def add_field(field)
|
16
|
+
@fields[field.name] = field
|
17
|
+
end
|
18
|
+
|
19
|
+
def add_fragment(fragment)
|
20
|
+
@fragments[fragment.name] = fragment
|
21
|
+
end
|
22
|
+
|
23
|
+
def add_inline_fragment(inline_fragment)
|
24
|
+
@inline_fragments << inline_fragment
|
25
|
+
end
|
26
|
+
|
27
|
+
def contains?(field_name)
|
28
|
+
fields.key?(field_name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def empty?
|
32
|
+
selections.empty?
|
33
|
+
end
|
34
|
+
|
35
|
+
def lookup(name)
|
36
|
+
fields.fetch(name)
|
37
|
+
end
|
38
|
+
|
39
|
+
def selections
|
40
|
+
fields.values + fragments.values + inline_fragments
|
41
|
+
end
|
42
|
+
|
43
|
+
def to_query(indent = '')
|
44
|
+
selections.map do |selection|
|
45
|
+
selection.to_query(indent: indent + ' ')
|
46
|
+
end.join("\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
alias_method :to_s, :to_query
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
class Response
|
6
|
+
attr_reader :body, :data, :errors, :extensions
|
7
|
+
|
8
|
+
def initialize(response_body)
|
9
|
+
response = JSON.parse(response_body)
|
10
|
+
data, errors, extensions = response.values_at('data', 'errors', 'extensions')
|
11
|
+
|
12
|
+
raise ResponseError, errors if !data && errors
|
13
|
+
|
14
|
+
@body = response
|
15
|
+
@data = data
|
16
|
+
@errors = errors.to_a
|
17
|
+
@extensions = extensions.to_a
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
class ResponseConnection < ResponseObject
|
6
|
+
extend Forwardable
|
7
|
+
include Enumerable
|
8
|
+
|
9
|
+
def_delegator :page_info, :has_next_page, :has_next_page?
|
10
|
+
def_delegator :page_info, :has_previous_page, :has_previous_page?
|
11
|
+
|
12
|
+
def each
|
13
|
+
return enum_for(:each) unless block_given?
|
14
|
+
edges.each { |edge| yield edge.node }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
class ResponseObject
|
6
|
+
include Deserialization
|
7
|
+
|
8
|
+
attr_reader :data
|
9
|
+
|
10
|
+
def initialize(data)
|
11
|
+
@data = Hash(data)
|
12
|
+
|
13
|
+
@data.each do |field_name, value|
|
14
|
+
response_object = case value
|
15
|
+
when Hash
|
16
|
+
if value.key?('edges')
|
17
|
+
ResponseConnection.new(value)
|
18
|
+
else
|
19
|
+
self.class.new(value)
|
20
|
+
end
|
21
|
+
when Array
|
22
|
+
value.map { |v| v.is_a?(Hash) ? self.class.new(v) : v }
|
23
|
+
else
|
24
|
+
value
|
25
|
+
end
|
26
|
+
|
27
|
+
create_accessor_methods(field_name, response_object)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class GraphQLSchema
|
4
|
+
def query_root
|
5
|
+
type(query_root_name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def type(name)
|
9
|
+
types_by_name.fetch(name)
|
10
|
+
end
|
11
|
+
|
12
|
+
class TypeDefinition
|
13
|
+
def field(name)
|
14
|
+
fields_by_name.fetch(name)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/shipit.rubygems.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# using the default shipit config
|
data/shipit.yml
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
module Adapters
|
6
|
+
class HTTPAdapterTest < Minitest::Test
|
7
|
+
def test_request_builds_a_request
|
8
|
+
config = Config.new(url: 'http://example.org')
|
9
|
+
adapter = HTTPAdapter.new(config)
|
10
|
+
|
11
|
+
stub_request(:post, 'http://example.org')
|
12
|
+
.with(
|
13
|
+
body: {
|
14
|
+
query: 'query { shop }',
|
15
|
+
variables: {},
|
16
|
+
operation_name: nil
|
17
|
+
}.to_json,
|
18
|
+
headers: { 'Accept' => 'application/json' }
|
19
|
+
)
|
20
|
+
.to_return(body: { data: { id: 1 } }.to_json)
|
21
|
+
|
22
|
+
adapter.request('query { shop }')
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_send_request_builds_a_request_with_operation_name
|
26
|
+
config = Config.new(url: 'http://example.org')
|
27
|
+
adapter = HTTPAdapter.new(config)
|
28
|
+
|
29
|
+
stub_request(:post, 'http://example.org')
|
30
|
+
.with(
|
31
|
+
body: {
|
32
|
+
query: 'query shopQuery { shop }',
|
33
|
+
variables: {},
|
34
|
+
operation_name: 'shopQuery'
|
35
|
+
}.to_json,
|
36
|
+
headers: { 'Accept' => 'application/json' }
|
37
|
+
)
|
38
|
+
.to_return(body: { data: { id: 1 } }.to_json)
|
39
|
+
|
40
|
+
adapter.request('query shopQuery { shop }', operation_name: 'shopQuery')
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_send_request_returns_a_response_instance
|
44
|
+
config = Config.new(url: 'http://example.org')
|
45
|
+
adapter = HTTPAdapter.new(config)
|
46
|
+
|
47
|
+
stub_request(:post, 'http://example.org')
|
48
|
+
.with(
|
49
|
+
body: {
|
50
|
+
query: 'query { shop }',
|
51
|
+
variables: {},
|
52
|
+
operation_name: nil
|
53
|
+
}.to_json,
|
54
|
+
headers: { 'Accept' => 'application/json' }
|
55
|
+
)
|
56
|
+
.to_return(body: { data: { id: 1 } }.to_json)
|
57
|
+
|
58
|
+
response = adapter.request('query { shop }')
|
59
|
+
|
60
|
+
assert_instance_of Response, response
|
61
|
+
end
|
62
|
+
|
63
|
+
def test_send_request_raises_an_exception_on_net_http_error
|
64
|
+
config = Config.new(url: 'http://example.org')
|
65
|
+
adapter = HTTPAdapter.new(config)
|
66
|
+
|
67
|
+
stub_request(:post, 'http://example.org')
|
68
|
+
.with(
|
69
|
+
body: {
|
70
|
+
query: 'query { shop }',
|
71
|
+
variables: {},
|
72
|
+
operation_name: nil
|
73
|
+
}.to_json,
|
74
|
+
headers: { 'Accept' => 'application/json' }
|
75
|
+
)
|
76
|
+
.to_return(status: [401, 'Unauthorized'])
|
77
|
+
|
78
|
+
exception = assert_raises ClientError do
|
79
|
+
adapter.request('query { shop }')
|
80
|
+
end
|
81
|
+
|
82
|
+
assert_equal '401 Unauthorized', exception.message
|
83
|
+
assert_equal '401', exception.response.code
|
84
|
+
assert(exception.response.body.nil? || exception.response.body == '')
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_send_request_raises_an_exception_on_net_http_open_timeout_error
|
88
|
+
config = Config.new(url: 'http://example.org')
|
89
|
+
adapter = HTTPAdapter.new(config)
|
90
|
+
|
91
|
+
stub_request(:post, 'http://example.org').to_raise(Net::OpenTimeout)
|
92
|
+
|
93
|
+
assert_raises OpenTimeoutError do
|
94
|
+
adapter.request('query { shop }')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_send_request_raises_an_exception_on_net_http_read_timeout_error
|
99
|
+
config = Config.new(url: 'http://example.org')
|
100
|
+
adapter = HTTPAdapter.new(config)
|
101
|
+
|
102
|
+
stub_request(:post, 'http://example.org').to_raise(Net::ReadTimeout)
|
103
|
+
|
104
|
+
assert_raises ReadTimeoutError do
|
105
|
+
adapter.request('query { shop }')
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
class ConfigTest < Minitest::Test
|
6
|
+
def test_initialize_overrides_defaults
|
7
|
+
config = Config.new(
|
8
|
+
debug: true,
|
9
|
+
password: 'foo',
|
10
|
+
per_page: 5,
|
11
|
+
)
|
12
|
+
|
13
|
+
assert config.debug
|
14
|
+
assert_equal({}, config.headers)
|
15
|
+
assert_equal 'foo', config.password
|
16
|
+
assert_equal 5, config.per_page
|
17
|
+
assert_nil config.username
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_initialize_parses_url_as_uri
|
21
|
+
config = Config.new(url: 'http://example.com')
|
22
|
+
|
23
|
+
assert_kind_of URI, config.url
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_initialize_accepts_open_timeout_in_seconds
|
27
|
+
config = Config.new(open_timeout: 2)
|
28
|
+
assert_equal 2, config.open_timeout
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_initialize_accepts_read_timeout_in_seconds
|
32
|
+
config = Config.new(read_timeout: 5)
|
33
|
+
assert_equal 5, config.read_timeout
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_setting_open_timeout_after_initialization
|
37
|
+
config = Config.new
|
38
|
+
config.open_timeout = 2
|
39
|
+
|
40
|
+
assert_equal 2, config.open_timeout
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_setting_read_timeout_after_initialization
|
44
|
+
config = Config.new
|
45
|
+
config.read_timeout = 5
|
46
|
+
|
47
|
+
assert_equal 5, config.read_timeout
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_opent_timeout_is_5_seconds_when_not_set
|
51
|
+
config = Config.new
|
52
|
+
assert_equal 5, config.open_timeout
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_read_timeout_is_5_seconds_when_not_set
|
56
|
+
config = Config.new
|
57
|
+
assert_equal 5, config.read_timeout
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_url_writer_coerces_to_uri
|
61
|
+
config = Config.new
|
62
|
+
config.url = 'http://example.com'
|
63
|
+
|
64
|
+
assert_kind_of URI, config.url
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module GraphQL
|
4
|
+
module Client
|
5
|
+
class GraphObjectQueryTransformingTest < Minitest::Test
|
6
|
+
COLLECTION_ID = 'gid://shopify/Collection/67890'
|
7
|
+
COLLECTION_CURSOR = 'collection-cursor'
|
8
|
+
PRODUCT_ID = 'gid://shopify/Product/72727'
|
9
|
+
VARIANTS_CURSOR = 'variants-cursor'
|
10
|
+
GRAPH_FIXTURE = {
|
11
|
+
data: {
|
12
|
+
shop: {
|
13
|
+
name: 'my-shop',
|
14
|
+
privacyPolicy: {
|
15
|
+
body: 'Text'
|
16
|
+
},
|
17
|
+
collections: {
|
18
|
+
pageInfo: {
|
19
|
+
hasPreviousPage: false,
|
20
|
+
hasNextPage: true
|
21
|
+
},
|
22
|
+
edges: [{
|
23
|
+
cursor: COLLECTION_CURSOR,
|
24
|
+
node: {
|
25
|
+
id: COLLECTION_ID,
|
26
|
+
handle: 'fancy-poles'
|
27
|
+
}
|
28
|
+
}]
|
29
|
+
},
|
30
|
+
products: {
|
31
|
+
pageInfo: {
|
32
|
+
hasPreviousPage: false,
|
33
|
+
hasNextPage: true
|
34
|
+
},
|
35
|
+
edges: [{
|
36
|
+
cursor: 'product-cursor',
|
37
|
+
node: {
|
38
|
+
id: PRODUCT_ID,
|
39
|
+
handle: 'some-product',
|
40
|
+
variants: {
|
41
|
+
pageInfo: {
|
42
|
+
hasPreviousPage: false,
|
43
|
+
hasNextPage: true
|
44
|
+
},
|
45
|
+
edges: [{
|
46
|
+
cursor: VARIANTS_CURSOR,
|
47
|
+
node: {
|
48
|
+
id: PRODUCT_ID,
|
49
|
+
title: 'large'
|
50
|
+
}
|
51
|
+
}]
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}]
|
55
|
+
}
|
56
|
+
}
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
def setup
|
61
|
+
@schema = GraphQLSchema.new(schema_fixture('schema.json'))
|
62
|
+
@graphql_schema = GraphQL::Schema::Loader.load(schema_fixture('schema.json'))
|
63
|
+
|
64
|
+
@base_query = Query::QueryDocument.new(@schema) do |root|
|
65
|
+
root.add_field('shop') do |shop|
|
66
|
+
shop.add_field('name')
|
67
|
+
shop.add_field('privacyPolicy') do |address|
|
68
|
+
address.add_field('body')
|
69
|
+
end
|
70
|
+
shop.add_connection('collections', first: 1) do |collections|
|
71
|
+
collections.add_field('handle')
|
72
|
+
end
|
73
|
+
shop.add_connection('products', first: 1) do |products|
|
74
|
+
products.add_field('handle')
|
75
|
+
products.add_connection('variants', first: 1) do |variants|
|
76
|
+
variants.add_field('title')
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
data = GRAPH_FIXTURE[:data].to_json
|
83
|
+
@graph = GraphObject.new(data: JSON.parse(data), query: @base_query)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_nodes_can_generate_a_query_to_refetch_themselves
|
87
|
+
query_string = <<~QUERY
|
88
|
+
query {
|
89
|
+
node(id: "#{COLLECTION_ID}") {
|
90
|
+
... on Collection {
|
91
|
+
id
|
92
|
+
handle
|
93
|
+
}
|
94
|
+
}
|
95
|
+
}
|
96
|
+
QUERY
|
97
|
+
|
98
|
+
assert_equal query_string, @graph.shop.collections.to_a[0].refetch_query.to_query
|
99
|
+
assert_valid_query query_string, @graphql_schema
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_arrays_of_nodes_can_generate_a_query_to_fetch_the_next_page
|
103
|
+
query_string = <<~QUERY
|
104
|
+
query {
|
105
|
+
shop {
|
106
|
+
collections(first: 1, after: "#{COLLECTION_CURSOR}") {
|
107
|
+
edges {
|
108
|
+
cursor
|
109
|
+
node {
|
110
|
+
id
|
111
|
+
handle
|
112
|
+
}
|
113
|
+
}
|
114
|
+
pageInfo {
|
115
|
+
hasPreviousPage
|
116
|
+
hasNextPage
|
117
|
+
}
|
118
|
+
}
|
119
|
+
}
|
120
|
+
}
|
121
|
+
QUERY
|
122
|
+
|
123
|
+
assert_equal query_string, @graph.shop.collections.next_page_query.to_query
|
124
|
+
assert_valid_query query_string, @graphql_schema
|
125
|
+
end
|
126
|
+
|
127
|
+
def test_arrays_of_nodes_nested_under_a_truncated_query_to_fetch_their_next_page
|
128
|
+
query_string = <<~QUERY
|
129
|
+
query {
|
130
|
+
node(id: "#{PRODUCT_ID}") {
|
131
|
+
... on Product {
|
132
|
+
id
|
133
|
+
variants(first: 1, after: "#{VARIANTS_CURSOR}") {
|
134
|
+
edges {
|
135
|
+
cursor
|
136
|
+
node {
|
137
|
+
id
|
138
|
+
title
|
139
|
+
}
|
140
|
+
}
|
141
|
+
pageInfo {
|
142
|
+
hasPreviousPage
|
143
|
+
hasNextPage
|
144
|
+
}
|
145
|
+
}
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
QUERY
|
150
|
+
|
151
|
+
assert_equal query_string, @graph.shop.products.to_a[0].variants.next_page_query.to_query
|
152
|
+
assert_valid_query query_string, @graphql_schema
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|