artemis 0.5.1 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +64 -0
- data/.gitignore +1 -0
- data/Appraisals +12 -20
- data/CHANGELOG.md +45 -0
- data/Gemfile +2 -0
- data/README.md +71 -6
- data/artemis.gemspec +0 -1
- data/gemfiles/rails_50.gemfile +3 -1
- data/gemfiles/rails_51.gemfile +3 -1
- data/gemfiles/rails_52.gemfile +3 -1
- data/gemfiles/rails_60.gemfile +3 -1
- data/gemfiles/{rails_40.gemfile → rails_61.gemfile} +5 -3
- data/gemfiles/{rails_41.gemfile → rails_70.gemfile} +5 -4
- data/gemfiles/rails_edge.gemfile +2 -0
- data/lib/artemis/adapters/abstract_adapter.rb +1 -1
- data/lib/artemis/adapters/curb_adapter.rb +17 -7
- data/lib/artemis/adapters/multi_domain_adapter.rb +58 -0
- data/lib/artemis/adapters/net_http_adapter.rb +25 -16
- data/lib/artemis/adapters/net_http_persistent_adapter.rb +7 -1
- data/lib/artemis/adapters/test_adapter.rb +22 -3
- data/lib/artemis/adapters.rb +1 -0
- data/lib/artemis/client.rb +42 -8
- data/lib/artemis/graphql_endpoint.rb +11 -5
- data/lib/artemis/railtie.rb +16 -8
- data/lib/artemis/test_helper.rb +2 -1
- data/lib/artemis/version.rb +1 -1
- data/lib/generators/artemis/mutation/templates/mutation.graphql +1 -1
- data/lib/generators/artemis/query/query_generator.rb +14 -2
- data/lib/generators/artemis/query/templates/fixture.yml +19 -0
- data/lib/generators/artemis/query/templates/query.graphql +2 -2
- data/spec/adapters_spec.rb +165 -10
- data/spec/autoloading_spec.rb +4 -4
- data/spec/client_spec.rb +38 -2
- data/spec/fixtures/metaphysics/{_artist_fragment.graphql → _artist_fields.graphql} +0 -0
- data/spec/fixtures/metaphysics/artists.graphql +1 -1
- data/spec/fixtures/responses/{spotify → spotify_client}/artist.yml +0 -0
- data/spec/test_helper_spec.rb +10 -1
- metadata +13 -26
- data/.travis.yml +0 -69
- data/gemfiles/rails_42.gemfile +0 -12
data/lib/artemis/client.rb
CHANGED
@@ -167,17 +167,19 @@ module Artemis
|
|
167
167
|
end
|
168
168
|
|
169
169
|
def resolve_graphql_file_path(filename, fragment: false)
|
170
|
-
|
171
|
-
filename = filename.to_s.underscore
|
170
|
+
filename = filename.to_s.underscore
|
172
171
|
|
173
172
|
graphql_file_paths.detect do |path|
|
174
|
-
path.end_with?("#{namespace}/#{filename}.graphql") ||
|
175
|
-
(fragment && filename.end_with?('fragment') && path.end_with?("#{namespace}/_#{filename}.graphql"))
|
173
|
+
path.end_with?("#{namespace}/#{filename}.graphql") || (fragment && path.end_with?("#{namespace}/_#{filename}.graphql"))
|
176
174
|
end
|
177
175
|
end
|
178
176
|
|
179
177
|
def graphql_file_paths
|
180
|
-
@graphql_file_paths ||= query_paths.flat_map {|path| Dir["#{path}/#{
|
178
|
+
@graphql_file_paths ||= query_paths.flat_map {|path| Dir["#{path}/#{namespace}/*.graphql"] }
|
179
|
+
end
|
180
|
+
|
181
|
+
def namespace
|
182
|
+
name.underscore
|
181
183
|
end
|
182
184
|
|
183
185
|
def preload!
|
@@ -218,6 +220,19 @@ module Artemis
|
|
218
220
|
new(default_context).execute(query, context: context, **arguments)
|
219
221
|
end
|
220
222
|
|
223
|
+
def multiplex(**context, &block)
|
224
|
+
queue = MultiplexQueue.new
|
225
|
+
wrapped_executor = Executor.new(queue, callbacks, default_context.deep_merge(context))
|
226
|
+
api_client = ::GraphQL::Client.new(schema: endpoint.schema, execute: wrapped_executor)
|
227
|
+
|
228
|
+
service_client = new
|
229
|
+
service_client.instance_variable_set(:@client, api_client)
|
230
|
+
|
231
|
+
block.call(service_client)
|
232
|
+
|
233
|
+
connection.multiplex(queue.queries, context: context)
|
234
|
+
end
|
235
|
+
|
221
236
|
private
|
222
237
|
|
223
238
|
# Looks up the GraphQL file that matches the given +const_name+ and sets it to a constant. If the files it not
|
@@ -248,9 +263,9 @@ module Artemis
|
|
248
263
|
# Github.user # => delegates to Github.new(default_context).user
|
249
264
|
#
|
250
265
|
# @api private
|
251
|
-
def method_missing(method_name,
|
266
|
+
def method_missing(method_name, **arguments, &block)
|
252
267
|
if resolve_graphql_file_path(method_name)
|
253
|
-
new(default_context).public_send(method_name,
|
268
|
+
new(default_context).public_send(method_name, **arguments, &block)
|
254
269
|
else
|
255
270
|
super
|
256
271
|
end
|
@@ -345,6 +360,25 @@ module Artemis
|
|
345
360
|
end
|
346
361
|
end
|
347
362
|
|
348
|
-
|
363
|
+
class MultiplexQueue
|
364
|
+
attr_reader :queries
|
365
|
+
|
366
|
+
def initialize
|
367
|
+
@queries = []
|
368
|
+
end
|
369
|
+
|
370
|
+
def execute(document:, operation_name: nil, variables: {}, context: {}) #:nodoc:
|
371
|
+
@queries << {
|
372
|
+
query: document.to_query_string,
|
373
|
+
variables: variables.presence || {},
|
374
|
+
operationName: operation_name,
|
375
|
+
context: context
|
376
|
+
}
|
377
|
+
|
378
|
+
{}
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
private_constant :Callbacks, :Executor, :MultiplexQueue
|
349
383
|
end
|
350
384
|
end
|
@@ -33,7 +33,7 @@ module Artemis
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def register!(service_name, configurations)
|
36
|
-
ENDPOINT_INSTANCES[service_name.to_s.underscore] = new(service_name.to_s, configurations.symbolize_keys)
|
36
|
+
ENDPOINT_INSTANCES[service_name.to_s.underscore] = new(service_name.to_s, **configurations.symbolize_keys)
|
37
37
|
end
|
38
38
|
|
39
39
|
##
|
@@ -44,10 +44,16 @@ module Artemis
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
attr_reader :name, :url, :adapter, :timeout, :schema_path, :pool_size
|
47
|
+
attr_reader :name, :url, :adapter, :timeout, :schema_path, :pool_size, :adapter_options
|
48
48
|
|
49
|
-
def initialize(name, url: nil, adapter: :net_http, timeout: 10, schema_path: nil, pool_size: 25)
|
50
|
-
@name
|
49
|
+
def initialize(name, url: nil, adapter: :net_http, timeout: 10, schema_path: nil, pool_size: 25, adapter_options: {})
|
50
|
+
@name = name.to_s
|
51
|
+
@url = url
|
52
|
+
@adapter = adapter
|
53
|
+
@timeout = timeout
|
54
|
+
@schema_path = schema_path
|
55
|
+
@pool_size = pool_size
|
56
|
+
@adapter_options = adapter_options
|
51
57
|
|
52
58
|
@mutex_for_schema = Mutex.new
|
53
59
|
@mutex_for_connection = Mutex.new
|
@@ -66,7 +72,7 @@ module Artemis
|
|
66
72
|
|
67
73
|
def connection
|
68
74
|
@connection || @mutex_for_connection.synchronize do
|
69
|
-
@connection ||= ::Artemis::Adapters.lookup(adapter).new(url, service_name: name, timeout: timeout, pool_size: pool_size)
|
75
|
+
@connection ||= ::Artemis::Adapters.lookup(adapter).new(url, service_name: name, timeout: timeout, pool_size: pool_size, adapter_options: adapter_options)
|
70
76
|
end
|
71
77
|
end
|
72
78
|
end
|
data/lib/artemis/railtie.rb
CHANGED
@@ -35,10 +35,9 @@ module Artemis
|
|
35
35
|
files_to_watch = Artemis::Client.query_paths.map {|path| [path, config.artemis.graphql_extentions] }.to_h
|
36
36
|
|
37
37
|
app.reloaders << ActiveSupport::FileUpdateChecker.new([], files_to_watch) do
|
38
|
-
|
39
|
-
endpoint_names.each do |endpoint_name|
|
38
|
+
Artemis.config_for_graphql(app).each_key do |endpoint_name|
|
40
39
|
Artemis::Client.query_paths.each do |path|
|
41
|
-
FileUtils.touch("#{path}/#{endpoint_name}.rb")
|
40
|
+
FileUtils.touch("#{path}/#{endpoint_name}.rb") if File.exist?("#{path}/#{endpoint_name}.rb")
|
42
41
|
end
|
43
42
|
end
|
44
43
|
end
|
@@ -48,17 +47,26 @@ module Artemis
|
|
48
47
|
initializer 'graphql.client.load_config' do |app|
|
49
48
|
if Pathname.new("#{app.paths["config"].existent.first}/graphql.yml").exist?
|
50
49
|
Artemis.config_for_graphql(app).each do |endpoint_name, options|
|
51
|
-
Artemis::GraphQLEndpoint
|
52
|
-
|
53
|
-
|
50
|
+
Artemis::GraphQLEndpoint
|
51
|
+
.register!(
|
52
|
+
endpoint_name,
|
53
|
+
schema_path: app.root.join(config.artemis.schema_path, "#{endpoint_name}.json").to_s,
|
54
|
+
**options.symbolize_keys
|
55
|
+
)
|
54
56
|
end
|
55
57
|
end
|
56
58
|
end
|
57
59
|
|
58
60
|
initializer 'graphql.client.preload', after: 'graphql.client.load_config' do |app|
|
59
61
|
if app.config.eager_load && app.config.cache_classes
|
60
|
-
Artemis.
|
61
|
-
|
62
|
+
Artemis::GraphQLEndpoint.registered_services.each do |endpoint_name|
|
63
|
+
begin
|
64
|
+
require endpoint_name # Rails 7.0 requires this.
|
65
|
+
rescue LoadError
|
66
|
+
# no-op...
|
67
|
+
end
|
68
|
+
|
69
|
+
endpoint_name.camelize.constantize.preload!
|
62
70
|
end
|
63
71
|
end
|
64
72
|
end
|
data/lib/artemis/test_helper.rb
CHANGED
@@ -4,6 +4,7 @@ require 'erb'
|
|
4
4
|
require 'yaml'
|
5
5
|
|
6
6
|
require 'active_support/core_ext/module/attribute_accessors'
|
7
|
+
require 'active_support/core_ext/string/inflections'
|
7
8
|
|
8
9
|
require 'artemis/exceptions'
|
9
10
|
|
@@ -110,7 +111,7 @@ module Artemis
|
|
110
111
|
|
111
112
|
def find_fixture_set
|
112
113
|
fixture_set = fixture_sets
|
113
|
-
.detect { |fixture| %r{#{service_name.
|
114
|
+
.detect { |fixture| %r{#{service_name.underscore}/#{query_name}\.(yml|json)\z} =~ fixture.path }
|
114
115
|
fixture_set ||= fixture_sets.detect { |fixture| fixture.name == query_name.to_s }
|
115
116
|
|
116
117
|
if fixture_set.nil?
|
data/lib/artemis/version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
mutation<%= arguments.present? && "(#{ arguments.map {|name, type| "$#{name}: #{type.type}" }.join(", ") })" %> {
|
1
|
+
mutation<%= arguments.present? && "(#{ arguments.map {|name, type| "$#{name}: #{type.type.to_type_signature}" }.join(", ") })" %> {
|
2
2
|
<%= target_mutation.name %><%= arguments.present? && "(#{ arguments.map {|name, type| "#{name}: $#{name}" }.join(", ") })" %> {
|
3
3
|
# Add fields here...
|
4
4
|
}
|
@@ -14,6 +14,10 @@ class Artemis::QueryGenerator < Rails::Generators::Base
|
|
14
14
|
template "query.graphql", graphql_file_path
|
15
15
|
end
|
16
16
|
|
17
|
+
# def generate_text_fixture_file
|
18
|
+
# template "fixture.yml", text_fixture_path
|
19
|
+
# end
|
20
|
+
|
17
21
|
private
|
18
22
|
|
19
23
|
def query_name
|
@@ -21,7 +25,11 @@ class Artemis::QueryGenerator < Rails::Generators::Base
|
|
21
25
|
end
|
22
26
|
|
23
27
|
def graphql_file_path
|
24
|
-
"app/operations/#{service_name.underscore}/#{
|
28
|
+
"app/operations/#{service_name.underscore}/#{qualified_name}.graphql"
|
29
|
+
end
|
30
|
+
|
31
|
+
def text_fixture_path
|
32
|
+
File.join(Artemis::Railtie.config.artemis.fixture_path, service_name.underscore, "#{qualified_name}.yml")
|
25
33
|
end
|
26
34
|
|
27
35
|
def arguments
|
@@ -29,7 +37,7 @@ class Artemis::QueryGenerator < Rails::Generators::Base
|
|
29
37
|
end
|
30
38
|
|
31
39
|
def target_query
|
32
|
-
schema.
|
40
|
+
schema.query.fields[query_type] ||
|
33
41
|
raise(GraphQL::Schema::Finder::MemberNotFoundError, "Could not find type `#{query_type}` in schema.")
|
34
42
|
end
|
35
43
|
|
@@ -49,4 +57,8 @@ class Artemis::QueryGenerator < Rails::Generators::Base
|
|
49
57
|
end
|
50
58
|
end
|
51
59
|
end
|
60
|
+
|
61
|
+
def qualified_name
|
62
|
+
graphql_file_name.presence || query_name
|
63
|
+
end
|
52
64
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# You can stub GraphQL queries by calling the `stub_graphql' method in test:
|
2
|
+
#
|
3
|
+
# stub_graphql(<%= service_name.camelize %>, :<%= qualified_name.underscore %>).to_return(:<%= target_query.name %>_1)
|
4
|
+
#
|
5
|
+
# Or with a arguments matcher:
|
6
|
+
#
|
7
|
+
# stub_graphql(<%= service_name.camelize %>, :<%= qualified_name.underscore %>, <%= arguments.map {|name, _| "#{name}: \"...\"" }.join(", ") %>).to_return(:<%= target_query.name %>_2)
|
8
|
+
#
|
9
|
+
|
10
|
+
<%= target_query.name %>_1:
|
11
|
+
data:
|
12
|
+
<% target_query.type.fields.values.each do |field| -%>
|
13
|
+
<%= field.name %>: # type: <%= field.type.to_type_signature %>
|
14
|
+
<% end %>
|
15
|
+
<%= target_query.name %>_2:
|
16
|
+
data:
|
17
|
+
<% target_query.type.fields.values.each do |field| -%>
|
18
|
+
<%= field.name %>: # type: <%= field.type.to_type_signature %>
|
19
|
+
<% end %>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
query<%= arguments.present?
|
2
|
-
<%= target_query.name %><%= arguments.present?
|
1
|
+
query<%= arguments.present? ? "(#{ arguments.map {|name, type| "$#{name}: #{type.type.to_type_signature}" }.join(", ") })" : "" %> {
|
2
|
+
<%= target_query.name %><%= arguments.present? ? "(#{ arguments.map {|name, type| "#{name}: $#{name}" }.join(", ") })" : "" %> {
|
3
3
|
# Add fields here...
|
4
4
|
}
|
5
5
|
}
|
data/spec/adapters_spec.rb
CHANGED
@@ -1,28 +1,59 @@
|
|
1
1
|
require 'json'
|
2
2
|
require 'rack'
|
3
|
+
require 'webrick'
|
3
4
|
|
4
5
|
describe 'Adapters' do
|
5
6
|
FakeServer = ->(env) {
|
6
7
|
case env['PATH_INFO']
|
7
8
|
when '/slow_server'
|
8
|
-
sleep
|
9
|
+
sleep 2.1
|
9
10
|
|
10
11
|
[200, {}, ['{}']]
|
11
12
|
when '/500'
|
12
13
|
[500, {}, ['Server error']]
|
13
|
-
|
14
|
+
when '/test_multi_domain'
|
14
15
|
body = {
|
15
16
|
data: {
|
16
|
-
body:
|
17
|
+
body: "Endpoint switched.",
|
17
18
|
headers: env.select {|key, val| key.match("^HTTP.*|^CONTENT.*|^AUTHORIZATION.*") }
|
18
|
-
|
19
|
-
|
19
|
+
.collect {|key, val| [key.gsub(/^HTTP_/, ''), val.downcase] }
|
20
|
+
.to_h,
|
20
21
|
},
|
21
22
|
errors: [],
|
22
23
|
extensions: {}
|
23
24
|
}.to_json
|
24
25
|
|
25
26
|
[200, {}, [body]]
|
27
|
+
else
|
28
|
+
request_body = JSON.parse(env['rack.input'].read)
|
29
|
+
|
30
|
+
response_body = if request_body['_json']
|
31
|
+
request_body['_json'].map do |query|
|
32
|
+
{
|
33
|
+
data: {
|
34
|
+
body: query,
|
35
|
+
headers: env.select {|key, val| key.match("^HTTP.*|^CONTENT.*|^AUTHORIZATION.*") }
|
36
|
+
.collect {|key, val| [key.gsub(/^HTTP_/, ''), val.downcase] }
|
37
|
+
.to_h,
|
38
|
+
},
|
39
|
+
errors: [],
|
40
|
+
extensions: {}
|
41
|
+
}
|
42
|
+
end.to_json
|
43
|
+
else
|
44
|
+
{
|
45
|
+
data: {
|
46
|
+
body: request_body,
|
47
|
+
headers: env.select {|key, val| key.match("^HTTP.*|^CONTENT.*|^AUTHORIZATION.*") }
|
48
|
+
.collect {|key, val| [key.gsub(/^HTTP_/, ''), val.downcase] }
|
49
|
+
.to_h,
|
50
|
+
},
|
51
|
+
errors: [],
|
52
|
+
extensions: {}
|
53
|
+
}.to_json
|
54
|
+
end
|
55
|
+
|
56
|
+
[200, {}, [response_body]]
|
26
57
|
end
|
27
58
|
}
|
28
59
|
|
@@ -91,6 +122,51 @@ describe 'Adapters' do
|
|
91
122
|
end.to raise_error(timeout_error)
|
92
123
|
end
|
93
124
|
end
|
125
|
+
|
126
|
+
describe '#multiplex' do
|
127
|
+
it 'makes an HTTP request with multiple queries' do
|
128
|
+
response = adapter.multiplex(
|
129
|
+
[
|
130
|
+
{
|
131
|
+
query: GraphQL::Client::IntrospectionDocument.to_query_string,
|
132
|
+
operationName: 'IntrospectionQuery',
|
133
|
+
variables: {
|
134
|
+
id: 'yayoi-kusama'
|
135
|
+
},
|
136
|
+
},
|
137
|
+
],
|
138
|
+
context: {
|
139
|
+
user_id: 1
|
140
|
+
}
|
141
|
+
)
|
142
|
+
|
143
|
+
introspection_query = response[0]
|
144
|
+
|
145
|
+
expect(introspection_query['data']['body']['query']).to eq(GraphQL::Client::IntrospectionDocument.to_query_string)
|
146
|
+
expect(introspection_query['data']['body']['variables']).to eq('id' => 'yayoi-kusama')
|
147
|
+
expect(introspection_query['data']['body']['operationName']).to eq('IntrospectionQuery')
|
148
|
+
expect(introspection_query['data']['headers']['CONTENT_TYPE']).to eq('application/json')
|
149
|
+
expect(introspection_query['data']['headers']['ACCEPT']).to eq('application/json')
|
150
|
+
expect(introspection_query['errors']).to eq([])
|
151
|
+
expect(introspection_query['extensions']).to eq({})
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'raises an error when it receives a server error' do
|
155
|
+
adapter.uri = URI.parse('http://localhost:8000/500')
|
156
|
+
|
157
|
+
expect do
|
158
|
+
adapter.multiplex([])
|
159
|
+
end.to raise_error(Artemis::GraphQLServerError, "Received server error status 500: Server error")
|
160
|
+
end
|
161
|
+
|
162
|
+
it 'allows for overriding timeout' do
|
163
|
+
adapter.uri = URI.parse('http://localhost:8000/slow_server')
|
164
|
+
|
165
|
+
expect do
|
166
|
+
adapter.multiplex([])
|
167
|
+
end.to raise_error(timeout_error)
|
168
|
+
end
|
169
|
+
end
|
94
170
|
end
|
95
171
|
|
96
172
|
describe Artemis::Adapters::NetHttpAdapter do
|
@@ -102,15 +178,94 @@ describe 'Adapters' do
|
|
102
178
|
|
103
179
|
describe Artemis::Adapters::NetHttpPersistentAdapter do
|
104
180
|
let(:adapter) { Artemis::Adapters::NetHttpPersistentAdapter.new('http://localhost:8000', service_name: nil, timeout: 0.5, pool_size: 5) }
|
105
|
-
let(:timeout_error) { Net::
|
181
|
+
let(:timeout_error) { Net::ReadTimeout }
|
106
182
|
|
107
183
|
it_behaves_like 'an adapter'
|
108
184
|
end
|
109
185
|
|
110
|
-
describe Artemis::Adapters::
|
111
|
-
let(:adapter) { Artemis::Adapters::
|
112
|
-
let(:timeout_error) { Curl::Err::TimeoutError }
|
186
|
+
describe Artemis::Adapters::MultiDomainAdapter do
|
187
|
+
let(:adapter) { Artemis::Adapters::MultiDomainAdapter.new('ignored', service_name: nil, timeout: 0.5, pool_size: 5, adapter_options: { adapter: :net_http }) }
|
113
188
|
|
114
|
-
|
189
|
+
it 'makes an actual HTTP request' do
|
190
|
+
response = adapter.execute(document: GraphQL::Client::IntrospectionDocument, context: { url: 'http://localhost:8000/test_multi_domain' })
|
191
|
+
|
192
|
+
expect(response['data']['body']).to eq("Endpoint switched.")
|
193
|
+
expect(response['errors']).to eq([])
|
194
|
+
expect(response['extensions']).to eq({})
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'can make a multiplex (the graphql feature, not HTTP/2) request' do
|
198
|
+
response = adapter.multiplex(
|
199
|
+
[
|
200
|
+
{
|
201
|
+
query: GraphQL::Client::IntrospectionDocument.to_query_string,
|
202
|
+
operationName: 'IntrospectionQuery',
|
203
|
+
variables: {
|
204
|
+
id: 'yayoi-kusama'
|
205
|
+
},
|
206
|
+
},
|
207
|
+
],
|
208
|
+
context: {
|
209
|
+
url: 'http://localhost:8000/test_multi_domain'
|
210
|
+
}
|
211
|
+
)
|
212
|
+
|
213
|
+
expect(response['data']['body']).to eq("Endpoint switched.")
|
214
|
+
expect(response['errors']).to eq([])
|
215
|
+
expect(response['extensions']).to eq({})
|
216
|
+
end
|
217
|
+
|
218
|
+
it 'can make a multiplex request with custom HTTP headers' do
|
219
|
+
response = adapter.multiplex(
|
220
|
+
[
|
221
|
+
{
|
222
|
+
query: GraphQL::Client::IntrospectionDocument.to_query_string,
|
223
|
+
operationName: 'IntrospectionQuery',
|
224
|
+
},
|
225
|
+
],
|
226
|
+
context: {
|
227
|
+
headers: {
|
228
|
+
Authorization: "Token token",
|
229
|
+
},
|
230
|
+
url: 'http://localhost:8000/test_multi_domain'
|
231
|
+
}
|
232
|
+
)
|
233
|
+
|
234
|
+
expect(response['data']['headers']['AUTHORIZATION']).to eq("token token")
|
235
|
+
end
|
236
|
+
|
237
|
+
it 'raises an error when adapter_options.adapter is set to :multi domain' do
|
238
|
+
expect do
|
239
|
+
Artemis::Adapters::MultiDomainAdapter.new('ignored', service_name: nil, timeout: 0.5, pool_size: 5, adapter_options: { adapter: :multi_domain })
|
240
|
+
end.to raise_error(ArgumentError, 'You can not use the :multi_domain adapter with the :multi_domain adapter.')
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'raises an error when context.url is not specified' do
|
244
|
+
expect do
|
245
|
+
adapter.execute(document: GraphQL::Client::IntrospectionDocument)
|
246
|
+
end.to raise_error(ArgumentError, 'The MultiDomain adapter requires a url on every request. Please specify a ' \
|
247
|
+
'url with a context: Client.with_context(url: "https://awesomeshop.domain.conm")')
|
248
|
+
end
|
249
|
+
|
250
|
+
it 'raises an error when it receives a server error' do
|
251
|
+
expect do
|
252
|
+
adapter.execute(document: GraphQL::Client::IntrospectionDocument, context: { url: 'http://localhost:8000/500' })
|
253
|
+
end.to raise_error(Artemis::GraphQLServerError, "Received server error status 500: Server error")
|
254
|
+
end
|
255
|
+
|
256
|
+
it 'allows for overriding timeout' do
|
257
|
+
expect do
|
258
|
+
adapter.execute(document: GraphQL::Client::IntrospectionDocument, context: { url: 'http://localhost:8000/slow_server' })
|
259
|
+
end.to raise_error(Net::ReadTimeout)
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
if RUBY_ENGINE == 'ruby'
|
264
|
+
describe Artemis::Adapters::CurbAdapter do
|
265
|
+
let(:adapter) { Artemis::Adapters::CurbAdapter.new('http://localhost:8000', service_name: nil, timeout: 2, pool_size: 5) }
|
266
|
+
let(:timeout_error) { Curl::Err::TimeoutError }
|
267
|
+
|
268
|
+
it_behaves_like 'an adapter'
|
269
|
+
end
|
115
270
|
end
|
116
271
|
end
|
data/spec/autoloading_spec.rb
CHANGED
@@ -15,7 +15,7 @@ describe "#{GraphQL::Client} Autoloading" do
|
|
15
15
|
|
16
16
|
describe ".preload!" do
|
17
17
|
it "preloads all the graphQL files in the query paths" do
|
18
|
-
%i(Artist Artwork
|
18
|
+
%i(Artist Artists Artwork ArtistFields)
|
19
19
|
.select {|const_name| Metaphysics.constants.include?(const_name) }
|
20
20
|
.each {|const_name| Metaphysics.send(:remove_const, const_name) }
|
21
21
|
|
@@ -43,12 +43,12 @@ describe "#{GraphQL::Client} Autoloading" do
|
|
43
43
|
end
|
44
44
|
|
45
45
|
it "dynamically loads the matching GraphQL fragment and sets it to a constant" do
|
46
|
-
Metaphysics.send(:remove_const, :
|
46
|
+
Metaphysics.send(:remove_const, :ArtistFields) if Metaphysics.constants.include?(:ArtistFields)
|
47
47
|
|
48
|
-
query = Metaphysics::
|
48
|
+
query = Metaphysics::ArtistFields
|
49
49
|
|
50
50
|
expect(query.document.to_query_string).to eq(<<~GRAPHQL.strip)
|
51
|
-
fragment
|
51
|
+
fragment Metaphysics__ArtistFields on Artist {
|
52
52
|
hometown
|
53
53
|
deathday
|
54
54
|
}
|
data/spec/client_spec.rb
CHANGED
@@ -86,11 +86,11 @@ describe GraphQL::Client do
|
|
86
86
|
name
|
87
87
|
bio
|
88
88
|
birthday
|
89
|
-
...
|
89
|
+
...Metaphysics__ArtistFields
|
90
90
|
}
|
91
91
|
}
|
92
92
|
|
93
|
-
fragment
|
93
|
+
fragment Metaphysics__ArtistFields on Artist {
|
94
94
|
hometown
|
95
95
|
deathday
|
96
96
|
}
|
@@ -171,6 +171,42 @@ describe GraphQL::Client do
|
|
171
171
|
end
|
172
172
|
end
|
173
173
|
|
174
|
+
it "can batch multiple requests using Multiplex" do
|
175
|
+
responses = Metaphysics.multiplex do |queue|
|
176
|
+
queue.artist(id: "yayoi-kusama", context: { headers: { Authorization: 'bearer ...' } })
|
177
|
+
queue.artwork
|
178
|
+
end
|
179
|
+
|
180
|
+
artist_query, artwork_query = requests[0].queries
|
181
|
+
|
182
|
+
expect(artist_query[:operationName]).to eq('Metaphysics__Artist')
|
183
|
+
expect(artist_query[:variables]).to eq('id' => 'yayoi-kusama')
|
184
|
+
expect(artist_query[:context]).to eq({ headers: { Authorization: 'bearer ...' } })
|
185
|
+
expect(artist_query[:query]).to eq(<<~GRAPHQL.strip)
|
186
|
+
query Metaphysics__Artist($id: String!) {
|
187
|
+
artist(id: $id) {
|
188
|
+
name
|
189
|
+
bio
|
190
|
+
birthday
|
191
|
+
}
|
192
|
+
}
|
193
|
+
GRAPHQL
|
194
|
+
|
195
|
+
expect(artwork_query[:operationName]).to eq('Metaphysics__Artwork')
|
196
|
+
expect(artwork_query[:variables]).to be_empty
|
197
|
+
expect(artwork_query[:context]).to eq({})
|
198
|
+
expect(artwork_query[:query]).to eq(<<~GRAPHQL.strip)
|
199
|
+
query Metaphysics__Artwork {
|
200
|
+
artwork(id: "yayoi-kusama-pumpkin-yellow-and-black") {
|
201
|
+
title
|
202
|
+
artist {
|
203
|
+
name
|
204
|
+
}
|
205
|
+
}
|
206
|
+
}
|
207
|
+
GRAPHQL
|
208
|
+
end
|
209
|
+
|
174
210
|
private
|
175
211
|
|
176
212
|
def requests
|
File without changes
|
File without changes
|
data/spec/test_helper_spec.rb
CHANGED
@@ -70,8 +70,17 @@ describe Artemis::TestHelper do
|
|
70
70
|
expect(yoshiki.data.artist.name).to eq("Artist Yoshiki")
|
71
71
|
end
|
72
72
|
|
73
|
+
it "can mock separate GraphQL queries with the same arguments" do
|
74
|
+
stub_graphql("SpotifyClient", :artist, id: "yoshiki").to_return(:yoshiki)
|
75
|
+
stub_graphql(Metaphysics, :artist, id: "yoshiki").to_return(:yoshiki)
|
76
|
+
|
77
|
+
yoshiki = Metaphysics.artist(id: "yoshiki")
|
78
|
+
|
79
|
+
expect(yoshiki.data.artist.name).to eq("Artist Yoshiki")
|
80
|
+
end
|
81
|
+
|
73
82
|
it "allows to get raw fixture data as a Hash" do
|
74
|
-
data = stub_graphql("
|
83
|
+
data = stub_graphql("SpotifyClient", :artist).get(:yoshiki)
|
75
84
|
|
76
85
|
expect(data).to eq({
|
77
86
|
"data" => {
|