artemis 0.2.0 → 0.4.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/.travis.yml +9 -11
- data/CHANGELOG.md +14 -5
- data/README.md +99 -5
- data/artemis.gemspec +1 -0
- data/bin/console +6 -8
- data/lib/artemis/adapters/test_adapter.rb +8 -1
- data/lib/artemis/client.rb +44 -20
- data/lib/artemis/exceptions.rb +3 -0
- data/lib/artemis/railtie.rb +24 -6
- data/lib/artemis/rspec.rb +10 -0
- data/lib/artemis/test_helper.rb +103 -0
- data/lib/artemis/version.rb +1 -1
- data/spec/fixtures/responses/artist.yml +17 -0
- data/spec/fixtures/responses/artwork.json +12 -0
- data/spec/test_helper_spec.rb +64 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0b5fc48841d80c3f0ebd0cc161938caf1044b09ce300bb55822df3ae1323aed2
|
4
|
+
data.tar.gz: e42427484c1786929c66a2f8a7650cb2e631230155f92c92e5d36406a20a41b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b0625a78d265426de79dc77ace3f0ff2336e75a914b37b4179356ec3f0c69c2beda8658e1b0cabf914221aea92e6fb86c6510075b6ab9c9c0e9f04cb1c37368
|
7
|
+
data.tar.gz: f80b1e917bfaac00586704ab09a3893f7d879b02a62b5693816f1c7977fed64233585b7e0d17ab8ae7877efdab2a5efc951eab4928f9120d90a41c9895cd0c93
|
data/.travis.yml
CHANGED
@@ -6,12 +6,12 @@ sudo: false
|
|
6
6
|
before_install: gem install bundler -v 1.16.1
|
7
7
|
|
8
8
|
rvm:
|
9
|
-
- 2.
|
10
|
-
- 2.
|
11
|
-
- 2.
|
12
|
-
|
9
|
+
- 2.6.0
|
10
|
+
- 2.5.3
|
11
|
+
- 2.4.5
|
12
|
+
- 2.3.8
|
13
13
|
- ruby-head
|
14
|
-
# - jruby-9.2.
|
14
|
+
# - jruby-9.2.3.0
|
15
15
|
# - jruby-head
|
16
16
|
|
17
17
|
gemfile:
|
@@ -24,13 +24,11 @@ gemfile:
|
|
24
24
|
matrix:
|
25
25
|
allow_failures:
|
26
26
|
- rvm: ruby-head
|
27
|
-
# - rvm: jruby-9.2.
|
27
|
+
# - rvm: jruby-9.2.3.0
|
28
28
|
# - rvm: jruby-head
|
29
29
|
- gemfile: gemfiles/rails_edge.gemfile
|
30
30
|
exclude:
|
31
|
-
- rvm: 2.
|
31
|
+
- rvm: 2.4.5
|
32
|
+
gemfile: gemfiles/rails_edge.gemfile
|
33
|
+
- rvm: 2.3.8
|
32
34
|
gemfile: gemfiles/rails_edge.gemfile
|
33
|
-
# - rvm: 2.2.10
|
34
|
-
# gemfile: gemfiles/rails_52.gemfile
|
35
|
-
# - rvm: 2.2.10
|
36
|
-
# gemfile: gemfiles/rails_edge.gemfile
|
data/CHANGELOG.md
CHANGED
@@ -1,11 +1,20 @@
|
|
1
1
|
## Unreleased
|
2
2
|
|
3
3
|
* Add a new entry here
|
4
|
-
* [#
|
5
|
-
* [#
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
* [#48](https://github.com/yuki24/artemis/pull/48): Do not transform keys of query variables [@erikdstock](https://github.com/erikdstock)
|
5
|
+
* [#47](https://github.com/yuki24/artemis/pull/47): Fixes an issue where errors thrown from `config/graphql.yml` get swallowed
|
6
|
+
|
7
|
+
## [v0.2.0: New generators and small improvements](https://github.com/yuki24/artemis/tree/v0.2.0)
|
8
|
+
|
9
|
+
_<sup>released at 2018-10-30 02:09:59 UTC</sup>_
|
10
|
+
|
11
|
+
#### Features
|
12
|
+
|
13
|
+
- [#43](https://github.com/yuki24/artemis/pull/43): Keep persistent connections open for 30 minutes
|
14
|
+
- [#42](https://github.com/yuki24/artemis/pull/42): Allow for setting up the test adapter without `url`
|
15
|
+
- [#41](https://github.com/yuki24/artemis/pull/41): Add a mutation generator
|
16
|
+
- [#40](https://github.com/yuki24/artemis/pull/40): Add a query generator
|
17
|
+
- [#39](https://github.com/yuki24/artemis/pull/39): Installer now adds a new service if config/graphql.yml is present
|
9
18
|
|
10
19
|
## [v0.1.0: First release!](https://github.com/yuki24/artemis/tree/v0.1.0)
|
11
20
|
|
data/README.md
CHANGED
@@ -1,12 +1,35 @@
|
|
1
1
|
# Artemis [](https://travis-ci.org/yuki24/artemis)
|
2
2
|
|
3
|
+
Artemis is a GraphQL client that is designed to fit well on Rails.
|
4
|
+
|
3
5
|
* **Convention over Configuration**: You'll never have to make trivial decisions or spend time on boring setup. Start
|
4
|
-
making a GraphQL request in literally
|
6
|
+
making a GraphQL request in literally 30s.
|
5
7
|
* **Performant by default**: You can't do wrong when it comes to performance. All GraphQL files are pre-loaded only
|
6
8
|
once in production and it'll never affect runtime performance. Comes with options that enable persistent connections
|
7
|
-
and even HTTP/2
|
9
|
+
and even HTTP/2, the next-gen high-performance protocol.
|
10
|
+
* **First-class support for testing**: Testing and stubbing GraphQL requests couldn't be simpler. No need to add
|
11
|
+
external dependencies to test well.
|
12
|
+
|
13
|
+
<img width="24" height="24" src="https://avatars1.githubusercontent.com/u/541332?s=48&v=4"> Battle-tested at [Artsy](https://www.artsy.net)
|
14
|
+
|
15
|
+
## Quick start
|
16
|
+
|
17
|
+
You could set up Artemis with just a few commands. See it in action:
|
8
18
|
|
9
|
-
|
19
|
+
```bash
|
20
|
+
$ bundle add artemis
|
21
|
+
$ rails g artemis:install artsy https://metaphysics-production.artsy.net/
|
22
|
+
$ echo '
|
23
|
+
query($id: String!) {
|
24
|
+
artist(id: $id) {
|
25
|
+
name
|
26
|
+
birthday
|
27
|
+
}
|
28
|
+
}' > app/operations/artsy/artist.graphql
|
29
|
+
$ rails c
|
30
|
+
> Artsy.artist(id: "leonardo-da-vinci").data.artist.name # => "Leonardo da Vinci"
|
31
|
+
> Artsy.artist(id: "leonardo-da-vinci").data.artist.birthday # => "1452/04/15"
|
32
|
+
```
|
10
33
|
|
11
34
|
## Getting started
|
12
35
|
|
@@ -85,6 +108,11 @@ Artemis assumes that the files related to GraphQL are organized in a certain way
|
|
85
108
|
│ │ └── artists.graphql
|
86
109
|
│ └── artsy.rb
|
87
110
|
├──config/graphql.yml
|
111
|
+
├──test/fixtures/graphql
|
112
|
+
│ └── artsy
|
113
|
+
│ ├── artwork.yml
|
114
|
+
│ ├── artist.yml
|
115
|
+
│ └── artists.yml
|
88
116
|
└──vendor/graphql/schema/artsy.json
|
89
117
|
```
|
90
118
|
|
@@ -136,7 +164,7 @@ There are four adapter options available. Choose the adapter that best fits on y
|
|
136
164
|
|
137
165
|
| Adapter | Protocol | Keep-alive | Performance | Dependencies |
|
138
166
|
| ---------------------- | ------------------------ | ----------- | ----------- | ------------ |
|
139
|
-
| `:curb` | HTTP/1.1, **HTTP/2
|
167
|
+
| `:curb` | HTTP/1.1, **HTTP/2** | **Yes** | **Fastest** | [`curb 0.9.6+`][curb]<br>[`libcurl 7.64.0+`][curl]<br>[`nghttp2 1.0.0+`][nghttp]
|
140
168
|
| `:net_http` (default) | HTTP/1.1 only | No | Slow | **None**
|
141
169
|
| `:net_http_persistent` | HTTP/1.1 only | **Yes** | **Fast** | [`net-http-persistent 3.0.0+`][nhp]
|
142
170
|
| `:test` | N/A (See Testing)
|
@@ -152,7 +180,73 @@ Artemis also adds a useful `rake graphql:schema:update` rake task that downloads
|
|
152
180
|
|
153
181
|
## Testing
|
154
182
|
|
155
|
-
|
183
|
+
Given that you have `app/operations/artsy/artist.graphql` and fixture file for the `artist.yml`:
|
184
|
+
|
185
|
+
```yml
|
186
|
+
# test/fixtures/graphql/artist.yml:
|
187
|
+
leonardo_da_vinci:
|
188
|
+
data:
|
189
|
+
artist:
|
190
|
+
name: Leonardo da Vinci
|
191
|
+
birthday: 1452/04/15
|
192
|
+
|
193
|
+
yayoi_kusama:
|
194
|
+
data:
|
195
|
+
artist:
|
196
|
+
name: Yayoi Kusama
|
197
|
+
birthday: 1929/03/22
|
198
|
+
```
|
199
|
+
|
200
|
+
Then you can stub the request with the `stub_graphql` DSL:
|
201
|
+
|
202
|
+
```ruby
|
203
|
+
stub_graphql(Artsy, :artist, id: "yayoi-kusama").to_return(:yayoi_kusama)
|
204
|
+
stub_graphql(Artsy, :artist, id: "leonardo-da-vinci").to_return(:leonardo_da_vinci)
|
205
|
+
|
206
|
+
yayoi_kusama = Artsy.artist(id: "yayoi-kusama")
|
207
|
+
yayoi_kusama.data.artist.name # => "Yayoi Kusama"
|
208
|
+
yayoi_kusama.data.artist.birthday # => "1452/04/15"
|
209
|
+
|
210
|
+
da_vinci = Artsy.artist(id: "leonardo-da-vinci")
|
211
|
+
da_vinci.data.artist.name # => "Leonardo da Vinci"
|
212
|
+
da_vinci.data.artist.birthday # => "1452/04/15"
|
213
|
+
```
|
214
|
+
|
215
|
+
You can also use JSON instead of YAML. See [example fixtures](https://github.com/yuki24/artemis/tree/master/spec/fixtures/responses)
|
216
|
+
and [test cases](https://github.com/yuki24/artemis/blob/master/spec/test_helper_spec.rb#L16-L51).
|
217
|
+
|
218
|
+
### MiniTest
|
219
|
+
|
220
|
+
Setting up the test helper with Artemis is very easy and simple. Just add the following code to the
|
221
|
+
`test/test_helper.rb` in your app:
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
# spec/test_helper.rb
|
225
|
+
require 'artemis/test_helper'
|
226
|
+
|
227
|
+
class ActiveSupport::TestCase
|
228
|
+
setup do
|
229
|
+
graphql_requests.clear
|
230
|
+
graphql_responses.clear
|
231
|
+
end
|
232
|
+
end
|
233
|
+
```
|
234
|
+
|
235
|
+
### RSpec
|
236
|
+
|
237
|
+
Artemis also comes with a script that wires up helper methods on Rspec. Because it is more common to use the `spec/`
|
238
|
+
directory to organize spec files in RSpec, the `config.artemis.fixture_path` config needs to point to
|
239
|
+
`spec/fixtures/graphql`. Other than that, it is very straightforward to set it up:
|
240
|
+
|
241
|
+
```ruby
|
242
|
+
# config/application.rb
|
243
|
+
config.artemis.fixture_path = 'spec/fixtures/graphql'
|
244
|
+
```
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
# Add this to your spec/rails_helper.rb or spec_helper.rb if you don't have rails_helper.rb
|
248
|
+
require 'artemis/rspec'
|
249
|
+
```
|
156
250
|
|
157
251
|
## Development
|
158
252
|
|
data/artemis.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |spec|
|
|
16
16
|
spec.require_paths = ["lib"]
|
17
17
|
|
18
18
|
spec.add_dependency "activesupport", ">= 4.2.0"
|
19
|
+
spec.add_dependency "graphql", ">= 1.8"
|
19
20
|
spec.add_dependency "graphql-client", ">= 0.13.0"
|
20
21
|
spec.add_dependency "railties", ">= 4.2.0"
|
21
22
|
|
data/bin/console
CHANGED
@@ -3,12 +3,10 @@
|
|
3
3
|
require "bundler/setup"
|
4
4
|
require "artemis"
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
Artemis::Client.query_paths = [File.join(__dir__, '../spec/fixtures')]
|
7
|
+
Artemis::GraphQLEndpoint.register!(:metaphysics, adapter: :test, url: '', schema_path: 'spec/fixtures/metaphysics/schema.json')
|
8
|
+
Artemis::GraphQLEndpoint.lookup(:metaphysics).load_schema!
|
9
|
+
require_relative '../spec/fixtures/metaphysics'
|
8
10
|
|
9
|
-
|
10
|
-
|
11
|
-
# Pry.start
|
12
|
-
|
13
|
-
require "irb"
|
14
|
-
IRB.start(__FILE__)
|
11
|
+
require "pry"
|
12
|
+
Pry.start
|
@@ -8,6 +8,9 @@ module Artemis
|
|
8
8
|
cattr_accessor :requests
|
9
9
|
self.requests = []
|
10
10
|
|
11
|
+
cattr_accessor :responses
|
12
|
+
self.responses = []
|
13
|
+
|
11
14
|
Request = Struct.new(:document, :operation_name, :variables, :context)
|
12
15
|
|
13
16
|
private_constant :Request
|
@@ -18,7 +21,11 @@ module Artemis
|
|
18
21
|
def execute(**arguments)
|
19
22
|
self.requests << Request.new(*arguments.values_at(:document, :operation_name, :variables, :context))
|
20
23
|
|
21
|
-
|
24
|
+
response = responses.detect do |mock|
|
25
|
+
arguments[:operation_name] == mock.operation_name && mock.arguments == :__unspecified__ || arguments[:variables] == mock.arguments
|
26
|
+
end
|
27
|
+
|
28
|
+
response&.data || {
|
22
29
|
'data' => { 'test' => 'data' },
|
23
30
|
'errors' => [],
|
24
31
|
'extensions' => {}
|
data/lib/artemis/client.rb
CHANGED
@@ -177,6 +177,18 @@ module Artemis
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
+
# Looks up the GraphQL file that matches the given +const_name+ and sets it to a constant.
|
181
|
+
#
|
182
|
+
# # app/operations/github.rb
|
183
|
+
# class Github < Artemis::Client
|
184
|
+
# end
|
185
|
+
#
|
186
|
+
# defined?(Github::User) # => nil
|
187
|
+
# Github.load_constant(:User) # => loads an operation definition from app/operations/github/user.graphql
|
188
|
+
# defined?(Github::User) # => 'constant'
|
189
|
+
#
|
190
|
+
# Github.load_constant(:None) # => nil
|
191
|
+
#
|
180
192
|
def load_constant(const_name)
|
181
193
|
graphql_file = resolve_graphql_file_path(const_name.to_s.underscore, fragment: true)
|
182
194
|
|
@@ -195,11 +207,33 @@ module Artemis
|
|
195
207
|
|
196
208
|
private
|
197
209
|
|
210
|
+
# Looks up the GraphQL file that matches the given +const_name+ and sets it to a constant. If the files it not
|
211
|
+
# found it will raise an +NameError+.
|
212
|
+
#
|
213
|
+
# # app/operations/github.rb
|
214
|
+
# class Github < Artemis::Client
|
215
|
+
# end
|
216
|
+
#
|
217
|
+
# defined?(Github::User) # => nil
|
218
|
+
# Github::User # => loads an operation definition from app/operations/github/user.graphql
|
219
|
+
# defined?(Github::User) # => 'constant'
|
220
|
+
#
|
221
|
+
# Github::DoesNotExist # => raises an NameError
|
222
|
+
#
|
198
223
|
# @api private
|
199
224
|
def const_missing(const_name)
|
200
225
|
load_constant(const_name) || super
|
201
226
|
end
|
202
227
|
|
228
|
+
# Delegates a class method call to an instance method call, which in turn looks up the GraphQL file that matches
|
229
|
+
# the given +method_name+ and delegates the call to it.
|
230
|
+
#
|
231
|
+
# # app/operations/github.rb
|
232
|
+
# class Github < Artemis::Client
|
233
|
+
# end
|
234
|
+
#
|
235
|
+
# Github.user # => delegates to Github.new(default_context).user
|
236
|
+
#
|
203
237
|
# @api private
|
204
238
|
def method_missing(method_name, *arguments, &block)
|
205
239
|
if resolve_graphql_file_path(method_name)
|
@@ -223,6 +257,15 @@ module Artemis
|
|
223
257
|
|
224
258
|
private
|
225
259
|
|
260
|
+
# Delegates a method call to a GraphQL call.
|
261
|
+
#
|
262
|
+
# # app/operations/github.rb
|
263
|
+
# class Github < Artemis::Client
|
264
|
+
# end
|
265
|
+
#
|
266
|
+
# github = Github.new
|
267
|
+
# github.user # => delegates to app/operations/github/user.graphql
|
268
|
+
#
|
226
269
|
# @api private
|
227
270
|
def method_missing(method_name, context: {}, **arguments)
|
228
271
|
if self.class.resolve_graphql_file_path(method_name)
|
@@ -233,11 +276,7 @@ module Artemis
|
|
233
276
|
self.class.load_constant(const_name)
|
234
277
|
end
|
235
278
|
|
236
|
-
client.query(
|
237
|
-
self.class.const_get(const_name),
|
238
|
-
variables: arguments.deep_transform_keys {|key| key.to_s.camelize(:lower) },
|
239
|
-
context: context
|
240
|
-
)
|
279
|
+
client.query(self.class.const_get(const_name), variables: arguments, context: context)
|
241
280
|
else
|
242
281
|
super
|
243
282
|
end
|
@@ -247,21 +286,6 @@ module Artemis
|
|
247
286
|
self.class.resolve_graphql_file_path(method_name) || super
|
248
287
|
end
|
249
288
|
|
250
|
-
# @api private
|
251
|
-
def compile_query_method!(method_name)
|
252
|
-
const_name = method_name.to_s.camelize
|
253
|
-
|
254
|
-
self.class.send(:class_eval, <<-RUBY, __FILE__, __LINE__ + 1)
|
255
|
-
def #{method_name}(context: {}, **arguments)
|
256
|
-
client.query(
|
257
|
-
self.class::#{const_name},
|
258
|
-
variables: arguments.deep_transform_keys {|key| key.to_s.camelize(:lower) },
|
259
|
-
context: context
|
260
|
-
)
|
261
|
-
end
|
262
|
-
RUBY
|
263
|
-
end
|
264
|
-
|
265
289
|
# Internal collection object that holds references to the callback blocks.
|
266
290
|
#
|
267
291
|
# @api private
|
data/lib/artemis/exceptions.rb
CHANGED
data/lib/artemis/railtie.rb
CHANGED
@@ -2,6 +2,12 @@ require 'active_support/file_update_checker'
|
|
2
2
|
|
3
3
|
module Artemis
|
4
4
|
class Railtie < ::Rails::Railtie #:nodoc:
|
5
|
+
config.artemis = ActiveSupport::OrderedOptions.new
|
6
|
+
config.artemis.query_path = "app/operations"
|
7
|
+
config.artemis.fixture_path = "test/fixtures/graphql"
|
8
|
+
config.artemis.schema_path = "vendor/graphql/schema"
|
9
|
+
config.artemis.graphql_extentions = ["graphql"]
|
10
|
+
|
5
11
|
initializer 'graphql.client.attach_log_subscriber' do
|
6
12
|
if !defined?(GraphQL::Client::LogSubscriber)
|
7
13
|
require "graphql/client/log_subscriber"
|
@@ -10,13 +16,22 @@ module Artemis
|
|
10
16
|
end
|
11
17
|
|
12
18
|
initializer 'graphql.client.set_query_paths' do |app|
|
13
|
-
|
19
|
+
query_path = config.artemis.query_path
|
20
|
+
|
21
|
+
app.paths.add query_path
|
22
|
+
|
23
|
+
Artemis::Client.query_paths = app.paths[query_path].existent
|
24
|
+
end
|
14
25
|
|
15
|
-
|
26
|
+
initializer 'graphql.test_helper' do |app|
|
27
|
+
if !Rails.env.production?
|
28
|
+
require 'artemis/test_helper'
|
29
|
+
Artemis::TestHelper.__graphql_fixture_path__ = app.root.join(config.artemis.fixture_path)
|
30
|
+
end
|
16
31
|
end
|
17
32
|
|
18
33
|
initializer 'graphql.client.set_reloader', after: 'graphql.client.set_query_paths' do |app|
|
19
|
-
files_to_watch = Artemis::Client.query_paths.map {|path| [path,
|
34
|
+
files_to_watch = Artemis::Client.query_paths.map {|path| [path, config.artemis.graphql_extentions] }.to_h
|
20
35
|
|
21
36
|
app.reloaders << ActiveSupport::FileUpdateChecker.new([], files_to_watch) do
|
22
37
|
endpoint_names = app.config_for(:graphql).keys
|
@@ -29,9 +44,12 @@ module Artemis
|
|
29
44
|
end
|
30
45
|
|
31
46
|
initializer 'graphql.client.load_config' do |app|
|
32
|
-
#
|
33
|
-
|
34
|
-
|
47
|
+
if Pathname.new("#{app.paths["config"].existent.first}/graphql.yml").exist?
|
48
|
+
app.config_for(:graphql).each do |endpoint_name, options|
|
49
|
+
Artemis::GraphQLEndpoint.register!(endpoint_name, {
|
50
|
+
'schema_path' => app.root.join(config.artemis.schema_path, "#{endpoint_name}.json").to_s
|
51
|
+
}.merge(options))
|
52
|
+
end
|
35
53
|
end
|
36
54
|
end
|
37
55
|
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
require 'active_support/core_ext/module/attribute_accessors'
|
6
|
+
|
7
|
+
require 'artemis/exceptions'
|
8
|
+
|
9
|
+
module Artemis
|
10
|
+
# TODO: Write documentation for +TestHelper+
|
11
|
+
module TestHelper
|
12
|
+
cattr_accessor :__graphql_fixture_path__
|
13
|
+
|
14
|
+
# Creates an object that stubs a GraphQL request for the given +service+. No mock response is registered until the
|
15
|
+
# +to_return+ method.
|
16
|
+
#
|
17
|
+
# # test/fixtures/graphql/metaphysics/artist.yml
|
18
|
+
# leonardo_da_vinci:
|
19
|
+
# data:
|
20
|
+
# artist:
|
21
|
+
# name: Leonardo da Vinci
|
22
|
+
# birthday: 1452/04/15
|
23
|
+
#
|
24
|
+
# # In a test:
|
25
|
+
# stub_graphql(Metaphysics, :artist).to_return(:leonardo_da_vinci)
|
26
|
+
#
|
27
|
+
# response = Metaphysics.artist(id: "leonardo-da-vinci")
|
28
|
+
#
|
29
|
+
# response.data.artist.name # => "Leonardo da Vinci"
|
30
|
+
# response.data.artist.birthday # => "1452/04/15"
|
31
|
+
#
|
32
|
+
# Test responses could also be parameterized by specifying the +arguments+ argument for the query name.
|
33
|
+
#
|
34
|
+
# stub_graphql(Metaphysics, :artist, id: "pablo-picasso").to_return(:pablo_picasso)
|
35
|
+
# stub_graphql(Metaphysics, :artist, id: "leonardo-da-vinci").to_return(:leonardo_da_vinci)
|
36
|
+
#
|
37
|
+
# pablo_picasso = Metaphysics.artist(id: "pablo-picasso")
|
38
|
+
# da_vinci = Metaphysics.artist(id: "leonardo-da-vinci")
|
39
|
+
#
|
40
|
+
# pablo_picasso.data.artist.name # => "Pablo Picasso"
|
41
|
+
# da_vinci.data.artist.name # => "Leonardo da Vinci"
|
42
|
+
#
|
43
|
+
def stub_graphql(service, query_name, arguments = :__unspecified__)
|
44
|
+
StubbingDSL.new(service.to_s, graphql_fixtures(query_name), arguments)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns out-going GraphQL requests.
|
48
|
+
#
|
49
|
+
def graphql_requests
|
50
|
+
Artemis::Adapters::TestAdapter.requests
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def graphql_responses #:nodoc:
|
56
|
+
Artemis::Adapters::TestAdapter.responses
|
57
|
+
end
|
58
|
+
|
59
|
+
def graphql_fixture_path #:nodoc:
|
60
|
+
__graphql_fixture_path__ || raise(Artemis::ConfigurationError, "GraphQL fixture path is unset")
|
61
|
+
end
|
62
|
+
|
63
|
+
def graphql_fixtures(query_name) #:nodoc:
|
64
|
+
graphql_fixture_files.detect {|fixture| fixture.name == query_name.to_s } || \
|
65
|
+
raise(Artemis::FixtureNotFound, "Fixture file `#{File.join(graphql_fixture_path, "#{query_name}.{yml,json}")}' not found")
|
66
|
+
end
|
67
|
+
|
68
|
+
def graphql_fixture_files #:nodoc:
|
69
|
+
@graphql_fixture_sets ||= Dir["#{graphql_fixture_path}/{**,*}/*.{yml,json}"]
|
70
|
+
.select {|file| ::File.file?(file) }
|
71
|
+
.map {|file| GraphQLFixture.new(File.basename(file, File.extname(file)), file, read_erb_yaml(file)) }
|
72
|
+
end
|
73
|
+
|
74
|
+
def read_erb_yaml(path) #:nodoc:
|
75
|
+
YAML.load(ERB.new(File.read(path)).result)
|
76
|
+
end
|
77
|
+
|
78
|
+
class StubbingDSL #:nodoc:
|
79
|
+
attr_reader :service_name, :fixture_set, :arguments
|
80
|
+
|
81
|
+
def initialize(service_name, fixture_set, arguments) #:nodoc:
|
82
|
+
@service_name, @fixture_set, @arguments = service_name, fixture_set, arguments
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_return(fixture_key) #:nodoc:
|
86
|
+
fixture = fixture_set.data[fixture_key.to_s] || \
|
87
|
+
raise(Artemis::FixtureNotFound, "Fixture `#{fixture_key}' not found in #{fixture_set.path}")
|
88
|
+
|
89
|
+
Artemis::Adapters::TestAdapter.responses <<
|
90
|
+
TestResponse.new(
|
91
|
+
"#{service_name}__#{fixture_set.name.to_s.camelcase}",
|
92
|
+
arguments.respond_to?(:deep_stringify_keys) ? arguments.deep_stringify_keys : arguments,
|
93
|
+
fixture
|
94
|
+
)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
TestResponse = Struct.new(:operation_name, :arguments, :data) #:nodoc:
|
99
|
+
GraphQLFixture = Struct.new(:name, :path, :data) #:nodoc
|
100
|
+
|
101
|
+
private_constant :GraphQLFixture, :StubbingDSL, :TestResponse
|
102
|
+
end
|
103
|
+
end
|
data/lib/artemis/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
yayoi_kusama:
|
2
|
+
data:
|
3
|
+
artist:
|
4
|
+
name: Yayoi Kusama
|
5
|
+
birthday: 1929/03/22
|
6
|
+
|
7
|
+
leonardo_da_vinci:
|
8
|
+
data:
|
9
|
+
artist:
|
10
|
+
name: Leonardo da Vinci
|
11
|
+
birthday: 1452/04/15
|
12
|
+
|
13
|
+
yuki:
|
14
|
+
data:
|
15
|
+
artist:
|
16
|
+
name: Yuki Nishijima
|
17
|
+
birthday: <%= Date.today.year %>/01/01
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'artemis/test_helper'
|
2
|
+
require 'date'
|
3
|
+
|
4
|
+
describe GraphQL::Client do
|
5
|
+
include Artemis::TestHelper
|
6
|
+
|
7
|
+
def graphql_fixture_path
|
8
|
+
File.join(PROJECT_DIR, "spec/fixtures/responses")
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
graphql_requests.clear
|
13
|
+
graphql_responses.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
it "can mock a GraphQL request" do
|
17
|
+
stub_graphql(Metaphysics, :artist).to_return(:yayoi_kusama)
|
18
|
+
|
19
|
+
response = Metaphysics.artist(id: "yayoi-kusama")
|
20
|
+
|
21
|
+
expect(response.data.artist.name).to eq("Yayoi Kusama")
|
22
|
+
expect(response.data.artist.birthday).to eq("1929/03/22")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can mock a GraphQL request with an ERB-enabled fixture" do
|
26
|
+
stub_graphql(Metaphysics, :artist).to_return(:yuki)
|
27
|
+
|
28
|
+
response = Metaphysics.artist(id: "yuki")
|
29
|
+
|
30
|
+
expect(response.data.artist.birthday).to eq("#{Date.today.year}/01/01")
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can mock a GraphQL request with variables using exact match" do
|
34
|
+
stub_graphql(Metaphysics, :artist, id: "yayoi-kusama").to_return(:yayoi_kusama)
|
35
|
+
stub_graphql(Metaphysics, :artist, id: "leonardo-da-vinci").to_return(:leonardo_da_vinci)
|
36
|
+
|
37
|
+
yayoi_kusama = Metaphysics.artist(id: "yayoi-kusama")
|
38
|
+
da_vinci = Metaphysics.artist(id: "leonardo-da-vinci")
|
39
|
+
|
40
|
+
expect(yayoi_kusama.data.artist.name).to eq("Yayoi Kusama")
|
41
|
+
expect(da_vinci.data.artist.name).to eq("Leonardo da Vinci")
|
42
|
+
end
|
43
|
+
|
44
|
+
it "can mock a GraphQL request with a JSON file" do
|
45
|
+
stub_graphql(Metaphysics, :artwork).to_return(:the_last_supper)
|
46
|
+
|
47
|
+
response = Metaphysics.artwork(id: "leonardo-da-vinci-the-last-supper")
|
48
|
+
|
49
|
+
expect(response.data.artwork.title).to eq("The Last Supper")
|
50
|
+
expect(response.data.artwork.artist.name).to eq("Leonardo da Vinci")
|
51
|
+
end
|
52
|
+
|
53
|
+
it "can mock a GraphQL request for a query that has a query name"
|
54
|
+
|
55
|
+
it "raises an exception if the specified fixture file does not exist" do
|
56
|
+
expect { stub_graphql(Metaphysics, :does_not_exist) }
|
57
|
+
.to raise_error(Artemis::FixtureNotFound, %r|spec/fixtures/responses/does_not_exist.{yml,json}|)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "raises an exception if the specified fixture file exists but fixture key does not exist" do
|
61
|
+
expect { stub_graphql(Metaphysics, :artist).to_return(:does_not_exist) }
|
62
|
+
.to raise_error(Artemis::FixtureNotFound, %r|spec/fixtures/responses/artist.yml|)
|
63
|
+
end
|
64
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: artemis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jon Allured
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2019-01-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -25,6 +25,20 @@ dependencies:
|
|
25
25
|
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: 4.2.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: graphql
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '1.8'
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '1.8'
|
28
42
|
- !ruby/object:Gem::Dependency
|
29
43
|
name: graphql-client
|
30
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,6 +191,8 @@ files:
|
|
177
191
|
- lib/artemis/exceptions.rb
|
178
192
|
- lib/artemis/graphql_endpoint.rb
|
179
193
|
- lib/artemis/railtie.rb
|
194
|
+
- lib/artemis/rspec.rb
|
195
|
+
- lib/artemis/test_helper.rb
|
180
196
|
- lib/artemis/version.rb
|
181
197
|
- lib/generators/artemis/install/USAGE
|
182
198
|
- lib/generators/artemis/install/install_generator.rb
|
@@ -200,7 +216,10 @@ files:
|
|
200
216
|
- spec/fixtures/metaphysics/artists.graphql
|
201
217
|
- spec/fixtures/metaphysics/artwork.graphql
|
202
218
|
- spec/fixtures/metaphysics/schema.json
|
219
|
+
- spec/fixtures/responses/artist.yml
|
220
|
+
- spec/fixtures/responses/artwork.json
|
203
221
|
- spec/spec_helper.rb
|
222
|
+
- spec/test_helper_spec.rb
|
204
223
|
- tmp/.gitkeep
|
205
224
|
homepage: https://github.com/yuki24/artemis
|
206
225
|
licenses:
|