artemis 0.2.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ac727e89f6d2c0845b888ea9eeb526bf2607689fa268c9f815b9af3c25c83d72
4
- data.tar.gz: 1cb2c9c3de64e95b729f579dfb4a8bd93a07d6ac4732647bf7aa94a360a6624a
3
+ metadata.gz: 0b5fc48841d80c3f0ebd0cc161938caf1044b09ce300bb55822df3ae1323aed2
4
+ data.tar.gz: e42427484c1786929c66a2f8a7650cb2e631230155f92c92e5d36406a20a41b0
5
5
  SHA512:
6
- metadata.gz: 041b006e10af9271e6cb024f2acfdc1597969ad44ccf371235a12f95c2464afac66110967db926ece6df3c46c3161b3b3f54436ea276b0362234c27f13e5933e
7
- data.tar.gz: 0daaea8bebcbf4ea6c9225781f591b4cd069aa6517dacb09043500b29357c1140d4169ed00e55046003702489addbfea60ef7703bc607692186ef61c7d94c0ac
6
+ metadata.gz: 1b0625a78d265426de79dc77ace3f0ff2336e75a914b37b4179356ec3f0c69c2beda8658e1b0cabf914221aea92e6fb86c6510075b6ab9c9c0e9f04cb1c37368
7
+ data.tar.gz: f80b1e917bfaac00586704ab09a3893f7d879b02a62b5693816f1c7977fed64233585b7e0d17ab8ae7877efdab2a5efc951eab4928f9120d90a41c9895cd0c93
@@ -6,12 +6,12 @@ sudo: false
6
6
  before_install: gem install bundler -v 1.16.1
7
7
 
8
8
  rvm:
9
- - 2.5.1
10
- - 2.4.4
11
- - 2.3.7
12
- # - 2.2.10
9
+ - 2.6.0
10
+ - 2.5.3
11
+ - 2.4.5
12
+ - 2.3.8
13
13
  - ruby-head
14
- # - jruby-9.2.0.0
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.0.0
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.3.7
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
@@ -1,11 +1,20 @@
1
1
  ## Unreleased
2
2
 
3
3
  * Add a new entry here
4
- * [#43](https://github.com/yuki24/artemis/pull/43): Keep persistent connections open for 30 minutes
5
- * [#42](https://github.com/yuki24/artemis/pull/42): Allow for setting up the test adapter without `url`
6
- * [#41](https://github.com/yuki24/artemis/pull/41): Add a mutation generator
7
- * [#40](https://github.com/yuki24/artemis/pull/40): Add a query generator
8
- * [#39](https://github.com/yuki24/artemis/pull/39): Installer now adds a new service if config/graphql.yml is present
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 [![Build Status](https://travis-ci.org/yuki24/artemis.svg?branch=master)](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 30sec.
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.0, the next-gen high-performance protocol.
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&amp;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
- <img width="24" height="24" src="https://avatars1.githubusercontent.com/u/541332?s=48&amp;v=4"> Battled-tested at [Artsy](https://www.artsy.net)
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.0** | **Yes** | **Fastest** | [`curb 0.9.6+`][curb]<br>[`libcurl 7.64.0+`][curl]<br>[`nghttp2 1.0.0+`][nghttp]
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
- **The testing support is incomplete, but there are some examples [available in Artemis' client spec](https://github.com/yuki24/artemis/blob/74095f3acb050e87251439aed5f8b17778ffdd06/spec/client_spec.rb#L36-L54).**
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
 
@@ -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
 
@@ -3,12 +3,10 @@
3
3
  require "bundler/setup"
4
4
  require "artemis"
5
5
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
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
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
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' => {}
@@ -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
@@ -11,6 +11,9 @@ module Artemis
11
11
  class GraphQLFileNotFound < Error
12
12
  end
13
13
 
14
+ class FixtureNotFound < Error
15
+ end
16
+
14
17
  class GraphQLError < Error
15
18
  end
16
19
 
@@ -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
- app.paths.add "app/operations"
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
- Artemis::Client.query_paths = app.paths["app/operations"].existent
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, ["graphql"]] }.to_h
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
- # TODO: Remove the +rescue+ call
33
- (app.config_for(:graphql) rescue {}).each do |endpoint_name, options|
34
- Artemis::GraphQLEndpoint.register!(endpoint_name, { 'schema_path' => app.root.join("vendor/graphql/schema/#{endpoint_name}.json").to_s }.merge(options))
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,10 @@
1
+ require 'artemis/test_helper'
2
+
3
+ RSpec.configure do |config|
4
+ config.include ::Artemis::TestHelper
5
+
6
+ config.before :each do
7
+ graphql_requests.clear
8
+ graphql_responses.clear
9
+ end
10
+ end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Artemis
2
- VERSION = "0.2.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -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,12 @@
1
+ {
2
+ "the_last_supper": {
3
+ "data": {
4
+ "artwork": {
5
+ "title": "The Last Supper",
6
+ "artist": {
7
+ "name": "Leonardo da Vinci"
8
+ }
9
+ }
10
+ }
11
+ }
12
+ }
@@ -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.2.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: 2018-10-30 00:00:00.000000000 Z
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: