rspec-graphql_response 0.2.0 → 0.5.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: 352fd084b9379469d7b4f71c86cfe94ea90172047c61c1ea2d20dced4bc85026
4
- data.tar.gz: 7eccaeb870a708fe43f2b0891a45d703b7d1fd64901efddd5323a27b6d87a77f
3
+ metadata.gz: 7104f657d559b5617486876024bc92367f177b94734ac8f224452cf6e4917f3e
4
+ data.tar.gz: f9c0df4206c1dd6c02f7b744b5edaa91c877a2e0be5c1ee235d6a05e0c3df9f0
5
5
  SHA512:
6
- metadata.gz: 83ebc95cd8c33beb6f62df67c9eb7a6846f820ca7bbc2c8412aadd0b4ceb0098449c23aeaf599bcaf65db6ddd4f4d92d2029a46e5a83c2b463f26e826040156c
7
- data.tar.gz: 876549c88363f4e330bdb01416940116bb7a997ee7f22d2864a0d8c7a55b9310df7198b135d4bc1d655b22adecfc02df09e89feb7e173f5febfd4f2a0bd73f9a
6
+ metadata.gz: 71ef7903cb4b46d5588b03402a5c3e44d6c61e13b898f8269f44ec3acd3b976cd3c77f921b68fc050dab0a20700f5846007c79cacfef8acfe1516f6af1a2045d
7
+ data.tar.gz: e9bbad747532e9fca29ed6e0bf8b4299be8896344f9541527bff4f71242ecfe4117f02d9946d0aece0215ec1952ce391bb5bfe74eccce747c167da52fe06acb2
data/Gemfile.lock CHANGED
@@ -1,17 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- rspec-graphql_response (0.1.0)
5
- rspec (~> 3.10)
4
+ rspec-graphql_response (0.5.0)
5
+ graphql (>= 1.0)
6
+ rspec (>= 3.0)
6
7
 
7
8
  GEM
8
9
  remote: https://rubygems.org/
9
10
  specs:
11
+ attr_extras (6.2.4)
10
12
  byebug (11.1.3)
11
13
  coderay (1.1.3)
12
14
  diff-lcs (1.4.4)
13
- graphql (1.12.4)
15
+ graphql (1.12.6)
14
16
  method_source (1.0.0)
17
+ optimist (3.0.1)
18
+ patience_diff (1.2.0)
19
+ optimist (~> 3.0)
15
20
  pry (0.14.0)
16
21
  coderay (~> 1.1)
17
22
  method_source (~> 1.0)
@@ -32,17 +37,21 @@ GEM
32
37
  diff-lcs (>= 1.2.0, < 2.0)
33
38
  rspec-support (~> 3.10.0)
34
39
  rspec-support (3.10.2)
40
+ super_diff (0.6.1)
41
+ attr_extras (>= 6.2.4)
42
+ diff-lcs
43
+ patience_diff
35
44
 
36
45
  PLATFORMS
37
46
  ruby
38
47
 
39
48
  DEPENDENCIES
40
49
  bundler (~> 1.17)
41
- graphql (~> 1.12)
42
50
  pry (~> 0.14)
43
51
  pry-byebug (~> 3.8)
44
52
  rake (>= 12.0)
45
53
  rspec-graphql_response!
54
+ super_diff (~> 0.6)
46
55
 
47
56
  BUNDLED WITH
48
57
  1.17.2
data/README.md CHANGED
@@ -30,40 +30,45 @@ Or install it yourself as:
30
30
 
31
31
  ## Full Documentation
32
32
 
33
- * [Release Notes](/RELEASE_NOTES.md)
34
- * [Upgrade Guide](/UPGRADE.md)
33
+ - [Release Notes](/RELEASE_NOTES.md)
34
+ - [Upgrade Guide](/UPGRADE.md)
35
35
 
36
36
  The full documentation for RSpec::GraphQLResponse can be found in the `/docs` folder.
37
37
 
38
38
  Configuration:
39
- * [RSpec::GraphQLResponse.configure](/docs/configuration.md)
40
- * [Spec Type :graphql](/docs/graphql_spec_type.md)
39
+
40
+ - [RSpec::GraphQLResponse.configure](/docs/configuration.md)
41
+ - [Spec Type :graphql](/docs/graphql_spec_type.md)
41
42
 
42
43
  Custom Matchers:
43
- * [have_errors](/docs/have_errors.md) - validates errors, or lack of, on the GraphQL response
44
- * [have_operation](/docs/have_operation.md) - validates the presence of a specified graphql operation in the graphql response
44
+
45
+ - [have_errors](/docs/have_errors.md) - validates errors, or lack of, on the GraphQL response
46
+ - [have_field](/docs/have_field.md) - validates the presence of a specified graphql operation in the graphql response
45
47
 
46
48
  Context / Describe Helper Methods:
47
- * [execute_graphql](/docs/execute_graphql.md) - executes a graphql call with the registered schema, query, variables and context
48
- * [graphql_query](/docs/execute_graphql.md) - the query to execute
49
- * [graphql_variables](/docs/execute_graphql.md) - a hash of variables the query expects
50
- * [graphql_context](/docs/execute_graphql.md) - the `context` of a query or mutation's resolver
49
+
50
+ - [graphql_operation](/docs/execute_graphql.md) - the operation to execute (i.e query or mutation)
51
+ - [graphql_variables](/docs/execute_graphql.md) - a hash of variables the query expects
52
+ - [graphql_context](/docs/execute_graphql.md) - the `context` of a query or mutation's resolver
51
53
 
52
54
  Spec Helper Methods:
53
- * [response](/docs/response.md) - the response, as JSON, of the executed graphql query
54
- * [operation](/docs/operation.md) - retrieves the results of a named operation from the GraphQL response
55
+
56
+ - [execute_graphql](/docs/execute_graphql.md) - executes a graphql call with the registered schema, query, variables and context
57
+ - [response](/docs/response.md) - the response, as JSON, of the executed graphql query
58
+ - [response_data](/docs/response_data.md) - digs through the graphql response to return data from the specified node(s)
55
59
 
56
60
  API / Development
57
- * [.add_matcher](/docs/add_matcher.md) - add a custom RSpec matcher to the GraphQLResponse matchers
58
- * [.add_validator](/docs/add_validator.md) - add a custom validator to be used by the custom matchers
59
- * [.add_helper](/docs/add_helper.md) - add helper methods to your specs, made avialable in `it` or `describe` / `context` blocks
61
+
62
+ - [.add_matcher](/docs/add_matcher.md) - add a custom RSpec matcher to the GraphQLResponse matchers
63
+ - [.add_validator](/docs/add_validator.md) - add a custom validator to be used by the custom matchers
64
+ - [.add_helper](/docs/add_helper.md) - add helper methods to your specs, made avialable in `it` or `describe` / `context` blocks
60
65
 
61
66
  ## Getting Started
62
67
 
63
- There are only a couple of bits you need to get started:
68
+ There are only a couple of bits you need to get started:
64
69
 
65
- * configuration of a GraphQL Schema in [`RSpec::GraphQLResponse.configure`](/docs/configuration.md)
66
- * the inclusion of [`type: :graphql`](/docs/graphql_spec_type.md) in your `RSpec.describe` call
70
+ - configuration of a GraphQL Schema in [`RSpec::GraphQLResponse.configure`](/docs/configuration.md)
71
+ - the inclusion of [`type: :graphql`](/docs/graphql_spec_type.md) in your `RSpec.describe` call
67
72
 
68
73
  ```ruby
69
74
  RSpec::GraphQLResponse.configure do |config|
@@ -114,7 +119,7 @@ in your specs.
114
119
 
115
120
  ```ruby
116
121
  RSpec.describe Some::Thing, type: :graphql do
117
- graphql_query <<-GQL
122
+ graphql_operation <<-GQL
118
123
  query ListCharacters{
119
124
  characters {
120
125
  id
@@ -138,7 +143,7 @@ way. The reduce this, `RSpec::GraphQLResponse` provides a built-in `response` he
138
143
 
139
144
  ```ruby
140
145
  RSpec.describe Some::Thing, type: :graphql do
141
- graphql_query <<-GQL
146
+ graphql_operation <<-GQL
142
147
  query ListCharacters{
143
148
  characters {
144
149
  id
@@ -157,15 +162,15 @@ RSpec.describe Some::Thing, type: :graphql do
157
162
  end
158
163
  ```
159
164
 
160
- #### Retrieve operation results with `operation`
165
+ #### Retrieve response results with `response_data`
161
166
 
162
167
  Now that the GraphQL query has been executed and a response has been obtained, it's time to check for the results of a GraphQL
163
168
  operation. In the previous example, the spec is expecting to find `data` with `characters` in the response hash. To reduce the
164
- nested hash checking, use the built-in `operation` method to retrieve the `characters`:
169
+ nested hash checking, use the built-in `response_data` method to retrieve the `characters`:
165
170
 
166
171
  ```ruby
167
172
  RSpec.describe Some::Thing, type: :graphql do
168
- graphql_query <<-GQL
173
+ graphql_operation <<-GQL
169
174
  query ListCharacters{
170
175
  characters {
171
176
  id
@@ -175,18 +180,17 @@ RSpec.describe Some::Thing, type: :graphql do
175
180
  GQL
176
181
 
177
182
  it "executes the query" do
178
- characters = operation(:characters)
179
-
180
- expect(characters).to include(
181
- # ...
183
+ expect(response_data :characters).to include(
184
+ # ...
182
185
  )
183
186
  end
184
187
  end
185
188
  ```
186
189
 
187
- Note the lack of `response` use here. Internally, the `operation` method uses the `response` to obtain the data requested. This
190
+ Note the lack of `response` use here. Internally, the `response_data` method uses the `response` to obtain the data requested. This
188
191
  means the entire chain of operations from executing the GraphQL request, to converting the response into a hash, and digging
189
- through the results to find the correction operation, has been handled behind the scenes.
192
+ through the results to find the correction operation, has been handled behind the scenes. To see more examples of how to use
193
+ `response_data` dig through your response check out it's full documenation [here.](/docs/response_data.md)
190
194
 
191
195
  ## Development
192
196
 
data/RELEASE_NOTES.md CHANGED
@@ -4,6 +4,17 @@ Release notes for various versions of RSpec::GraphQLResponse
4
4
 
5
5
  See [the upgrade guide](/UPGRADE.md) for details on changes between versions and how to upgrade.
6
6
 
7
+ ## v0.5.0 - Helper API change
8
+
9
+ - Fully deprecates `operation`.
10
+ - Renames `have_operation` to `have_field` to clarify its use.
11
+
12
+ ## v0.4.0 - Helper API change
13
+
14
+ ### Breaking Changes
15
+
16
+ The helper `graphql_query` was renamed to `graphql_operation` to better communicate the use of the helper. Naming the helper with `_query` lead to an association that its use was meant for GraphQL query operations and could not also be used for a mutation.
17
+
7
18
  ## v0.2.0 - GraphQL Configuration DSL and Refactorings
8
19
 
9
20
  Misc changes and corrections, some new features, and generally trying to create a more robust
@@ -11,13 +22,13 @@ and usable experience, right out of the box.
11
22
 
12
23
  ### New Features
13
24
 
14
- * Significantly improved documentation
15
- * `have_operation` matcher
16
- * GraphQL configuration DSL
17
- * `graphql_query`
18
- * `graphql_variables`
19
- * `graphql_context`
20
- * Describe/Context level RSpec helper methods via `.add_context_helper` DSL
25
+ - Significantly improved documentation
26
+ - `have_operation` matcher
27
+ - GraphQL configuration DSL
28
+ - `graphql_query`
29
+ - `graphql_variables`
30
+ - `graphql_context`
31
+ - Describe/Context level RSpec helper methods via `.add_context_helper` DSL
21
32
 
22
33
  ### Breaking Changes
23
34
 
@@ -32,8 +43,8 @@ Lots of misc bug fixes, including caching of values, ensuring things work in nes
32
43
 
33
44
  Early beta work to get this out the door and begin adoption
34
45
 
35
- * `have_errors` matcher
36
- * `operation` helper
37
- * `response` helper
38
- * `execute_graphql` helper
39
- * DSL for adding custom matchers, validators, and helpers
46
+ - `have_errors` matcher
47
+ - `operation` helper
48
+ - `response` helper
49
+ - `execute_graphql` helper
50
+ - DSL for adding custom matchers, validators, and helpers
data/UPGRADE.md CHANGED
@@ -1,8 +1,12 @@
1
1
  # Upgrade Guide
2
2
 
3
+ ## v0.3.0 to v0.4.0
4
+
5
+ There is a breaking change between v0.3.0 and v0.4.0 where the helper `graphql_query` was renamed to `graphql_operation`. In order to migrate to v0.4.0 all references to `graphql_query` can be replaced with `graphql_operation`.
6
+
3
7
  ## v0.1.0 to v0.2.0
4
8
 
5
- There is a breaking change between v0.1.0 and v0.2.0 regarding the configuration of graphql queries, variables and context.
9
+ There is a breaking change between v0.1.0 and v0.2.0 regarding the configuration of graphql queries, variables and context.
6
10
  Previously, you defined these three items with `let` in rspec:
7
11
 
8
12
  ```ruby
data/docs/add_helper.md CHANGED
@@ -23,7 +23,7 @@ it "does stuff" do
23
23
  end
24
24
  ```
25
25
 
26
- It's not a huge difference, but when you consider how well the `operation` method handles `nil` and
26
+ It's not a huge difference, but when you consider how well the `operation` method handles `nil` and
27
27
  operation results that are not found, it's well worth the few lines of savings.
28
28
 
29
29
  There are many other helpers available for your test suites, as well. Be sure to check the full
@@ -51,15 +51,14 @@ RSpec::GraphQLResponse.add_helper :operation do |operation_name|
51
51
  end
52
52
  ```
53
53
 
54
- In this example, the `response` helper is used, which guarantees the graphql has been executed and a response
54
+ In this example, the `response` helper is used, which guarantees the graphql has been executed and a response
55
55
  is available, assuming there were no exceptions preventing that.
56
56
 
57
57
  ## Add a Context Helper
58
58
 
59
59
  In addition to Spec level helpers, RSpec::GraphQLResponse allows you to add custom helpers at the context
60
60
  level. This means you can add configuration and other bits that can be called outside of an `it` block.
61
- The existing `graphql_query` and other DSL methods for configuring graphql calls are a great example of
62
- context level helpers.
61
+ The existing `graphql_operation` and other DSL methods for configuring graphql calls are a great example of context level helpers.
63
62
 
64
63
  To create a context helper, call `RSpec::GraphQLResponse.add_context_helper(name, &helper_block)`. The params
65
64
  are the same as `.add_helper`, but the resulting method will be made available in `describe` and `context`
@@ -73,7 +72,7 @@ end
73
72
 
74
73
  In this simple example, a method called `my_setting` is created, and it stores a value in the instance variable
75
74
  `@my_setting`. This takes advantage of RSpec's native ability to handle instance variables in describe and
76
- context blocks, allowing the variable to exist withing the hierarchy of objects for a given spec.
75
+ context blocks, allowing the variable to exist withing the hierarchy of objects for a given spec.
77
76
 
78
77
  With that defined, it can be used within a spec:
79
78
 
@@ -5,7 +5,10 @@ methods for configuring the query.
5
5
 
6
6
  ```ruby
7
7
  RSPec.describe Cool::Stuff, type: :graphql do
8
- graphql_query <<-GQL
8
+ let(:user) { create(:graphql_user) }
9
+ let(:search_name) { "Pet" }
10
+
11
+ graphql_operation <<-GQL
9
12
  query SomeThing($name: String) {
10
13
  characters(name: $name) {
11
14
  id
@@ -13,14 +16,18 @@ RSPec.describe Cool::Stuff, type: :graphql do
13
16
  }
14
17
  }
15
18
  GQL
16
-
17
- graphql_variables {
18
- name: "Jam"
19
- }
20
19
 
21
- grapql_context {
22
- current_user: "some user or whatever you need"
23
- }
20
+ graphql_variables do
21
+ {
22
+ name: search_name
23
+ }
24
+ end
25
+
26
+ grapql_context do
27
+ {
28
+ current_user: user
29
+ }
30
+ end
24
31
 
25
32
  it "executes and does the thing with the vars and context" do
26
33
  # ... expect things here
@@ -30,7 +37,7 @@ end
30
37
 
31
38
  ## Available Configuration Methods
32
39
 
33
- ### `graphql_query`
40
+ ### `graphql_operation`
34
41
 
35
42
  A string - most commonly a ruby heredoc - for the graphql query to execute
36
43
 
@@ -1,4 +1,4 @@
1
- # Validate a response operation with `have_operation(name)`
1
+ # Validate a response operation with `have_field(name)`
2
2
 
3
3
  Check for the presence of an operation's results. Useful when you want to ensure an operation exists before
4
4
  retrieving the operation's results.
@@ -7,7 +7,7 @@ retrieving the operation's results.
7
7
 
8
8
  ```ruby
9
9
  RSpec.describe My::Characters, type: :graphql do
10
- graphql_query <<-GQL
10
+ graphql_operation <<-GQL
11
11
  query CharacterList {
12
12
  characters {
13
13
  id
@@ -18,7 +18,7 @@ RSpec.describe My::Characters, type: :graphql do
18
18
 
19
19
  it "has the characters" do
20
20
 
21
- expect(response).to have_operation(:characters)
21
+ expect(response).to have_field(:characters)
22
22
 
23
23
  end
24
24
  end
@@ -28,7 +28,7 @@ end
28
28
 
29
29
  ```ruby
30
30
  RSpec.describe My::Characters, type: :graphql do
31
- graphql_query <<-GQL
31
+ graphql_operation <<-GQL
32
32
  query CharacterList {
33
33
  characters {
34
34
  id
@@ -39,7 +39,7 @@ RSpec.describe My::Characters, type: :graphql do
39
39
 
40
40
  it "does not have books" do
41
41
 
42
- expect(response).to_not have_operation(:books)
42
+ expect(response).to_not have_field(:books)
43
43
 
44
44
  end
45
45
  end
data/docs/operation.md CHANGED
@@ -1,38 +1,3 @@
1
1
  # Using the `operation` helper
2
2
 
3
- The `operation` helper will dig through a response to find a data
4
- structure that looks like,
5
-
6
- ```ruby
7
- {
8
- "data" => {
9
- operation_name
10
- }
11
- }
12
- ```
13
-
14
- ## Basic Use
15
-
16
- ```ruby
17
- it "has characters" do
18
- characters = operation(:characters)
19
-
20
- expect(character).to include(
21
- { id: 1, name: "Jam" },
22
- # ...
23
- )
24
- end
25
- ```
26
-
27
- ## Handling Nil
28
-
29
- If there is no `"data"` or no named operation for the name supplied, the
30
- `operation` helper will return `nil`
31
-
32
- ```ruby
33
- it "returns nil if operation doesn't exist" do
34
- character = operation(:something_that_does_not_exist)
35
-
36
- expect(operation).to be_nil
37
- end
38
- ```
3
+ Deprecated. See [response_data](response_data.md) instead.
data/docs/response.md CHANGED
@@ -1 +1 @@
1
- # Check the GraphQL Response with Helper `response`
1
+ # The GraphQL Response, via Helper `response`
@@ -0,0 +1,146 @@
1
+ # Using the `response_data` Helper
2
+
3
+ The `response_data` helper will dig through a graphql response, through
4
+ the outer hash, into the response data for an operation, and through any
5
+ and all layers of hash and array.
6
+
7
+ ## Syntax
8
+
9
+ ```ruby
10
+ response_data *[dig_pattern]
11
+ ```
12
+
13
+ Data returned via this helper will assume a `"data" => ` key at the root of
14
+ the `response` object. This root does not need to be specified in the list
15
+ of attributes for the `dig_pattern`.
16
+
17
+ ### Params
18
+
19
+ * `*[dig_pattern]` - an array of attributes (`:symbol`, `"string"`, or `key: :value` pair) that describes
20
+ the data structure to dig through, and the final data set to retrieve from the graphql response.
21
+
22
+ #### dig_pattern
23
+
24
+ Each attribute added to the `dig_pattern` represents an attribute at the given level of the
25
+ data structure, in numeric order from left to right. The first attribute provides will dig into
26
+ that attribute at the first level of data (just below the `"data" =>` key). The second attribute
27
+ will dig through data just below that first level, etc. etc. etc.
28
+
29
+ For example, with a data structure as shown below, in "Basic Use", you could specifiy these
30
+ attributes for the dig pattern:
31
+
32
+ * :characters
33
+ * :name
34
+
35
+ Like this:
36
+
37
+ ```ruby
38
+ response_data :characters, :name
39
+ ```
40
+
41
+ This dig pattern will find the `"characters"` key just below `"data"`, then iterate through
42
+ the array of characters and retrieve the `"name"` of each character.
43
+
44
+ For more details and options for the dig pattern, see the examples below.
45
+
46
+ ## Basic Use
47
+
48
+ A `response` data structure may look something like the following.
49
+
50
+ ```ruby
51
+ {
52
+ "data" => {
53
+ "characters" => [
54
+ { "id" => "1", "name" => "Jam" },
55
+ { "id" => "2", "name" => "Redemption" },
56
+ { "id" => "3", "name" => "Pet" }
57
+ ]
58
+ }
59
+ }
60
+ ```
61
+
62
+ The `response_data` helper will dig through to give you simplified
63
+ results that are easier to verify.
64
+
65
+ For example, if only the names of the characters need to be checked:
66
+
67
+ ```ruby
68
+ response_data :characters, :name
69
+
70
+ # => ["Jam", "Redemption", "Pet"]
71
+ ```
72
+
73
+ Or perhaps only the name for 2nd character is needed:
74
+
75
+ ```ruby
76
+ response_data {characters: [1]}, :name
77
+
78
+ # => "Redemption"
79
+ ```
80
+
81
+ ## List Every Item in an Array
82
+
83
+ Many responses from a graphql call will include an array of data somewhere
84
+ in the data structure. If you need to return all of the items in an array,
85
+ you only need to specify that array's key:
86
+
87
+ ```ruby
88
+ it "has characters" do
89
+ characters = response_data(:characters)
90
+
91
+ expect(character).to include(
92
+ { id: 1, name: "Jam" },
93
+ # ...
94
+ )
95
+ end
96
+ ```
97
+
98
+ ## Dig a Field From Every Item in an Array
99
+
100
+ When validation only needs to occur on a specific field for items found in
101
+ an array, there are two options.
102
+
103
+ 1. Specify a list of fields as already shown
104
+ 2. change the array's key to a hash and provide a `:symbol` wrapped in an array as the value
105
+
106
+ The first option was already shown in the Basic Use section above.
107
+
108
+ ```ruby
109
+ response_data :characters, :name
110
+
111
+ # => ["Jam", "Redemption", "Pet"]
112
+ ```
113
+
114
+ For the second option, the code would look like this:
115
+
116
+ ```ruby
117
+ response_data characters: [:name]
118
+
119
+ # => ["Jam", "Redemption", "Pet"]
120
+ ```
121
+
122
+ Both of these options are functionaly the same. The primary difference will be
123
+ how you wish to express the data structure in your code. Changing the list of
124
+ attributes to a hash with an array wrapping the value will provide a better
125
+ indication that an array is expected at that point in the data structure.
126
+
127
+ ## Dig Out an Item By Index, From an Array
128
+
129
+ There may be times when only a single piece of a returned array needs to be
130
+ validated. To handle this, switch the key of the array to a hash, as in the
131
+ previous example. Rather than specifying a child node's key in the value, though,
132
+ specify the index of the item you wish to extract.
133
+
134
+ ```ruby
135
+ response_data characters: [1]
136
+ ```
137
+
138
+ This will return the character at index 1, from the array of characters.
139
+
140
+ ## Handling Nil
141
+
142
+ If there is no data the key supplied, the helper will return `nil`
143
+
144
+ ```ruby
145
+ response_data(:something_that_does_not_exist) #=> nil
146
+ ```
@@ -1,5 +1,6 @@
1
1
  require "rspec"
2
2
 
3
+ require_relative "graphql_response/dig_dug/dig_dug"
3
4
  require_relative "graphql_response/version"
4
5
  require_relative "graphql_response/configuration"
5
6
  require_relative "graphql_response/validators"
@@ -0,0 +1,83 @@
1
+ module RSpec
2
+ module GraphQLResponse
3
+ class DigDug
4
+ attr_reader :dig_pattern
5
+
6
+ def initialize(*dig_pattern)
7
+ @dig_pattern = parse_dig_pattern(*dig_pattern)
8
+ end
9
+
10
+ def dig(data)
11
+ dig_data(data, dig_pattern)
12
+ end
13
+
14
+ private
15
+
16
+ def dig_data(data, patterns)
17
+ return data if patterns.nil?
18
+ return data if patterns.empty?
19
+
20
+ node = patterns[0]
21
+ node_key = node[:key]
22
+ node_key = node_key.to_s if node_key.is_a? Symbol
23
+ node_value = node[:value]
24
+
25
+ if node[:type] == :symbol
26
+ result = dig_symbol(data, node_key)
27
+ elsif node[:type] == :array
28
+ if data.is_a? Hash
29
+ child_data = data[node_key]
30
+ result = dig_symbol(child_data, node_value)
31
+ elsif data.is_a? Array
32
+ result = data.map { |value|
33
+ child_data = value[node_key]
34
+ dig_symbol(child_data, node_value)
35
+ }.compact
36
+ else
37
+ result = data
38
+ end
39
+ end
40
+
41
+ dig_data(result, patterns.drop(1))
42
+ end
43
+
44
+ def parse_dig_pattern(*pattern)
45
+ pattern_config = pattern.map do |pattern_item|
46
+ if pattern_item.is_a? Symbol
47
+ {
48
+ type: :symbol,
49
+ key: pattern_item
50
+ }
51
+ elsif pattern_item.is_a? Hash
52
+ pattern_item.map do |key, value|
53
+ {
54
+ type: :array,
55
+ key: key,
56
+ value: value[0]
57
+ }
58
+ end
59
+ end
60
+ end
61
+
62
+ pattern_config.flatten
63
+ end
64
+
65
+ def dig_symbol(data, key)
66
+ key = key.to_s if key.is_a? Symbol
67
+ return data[key] if data.is_a? Hash
68
+
69
+ if data.is_a? Array
70
+ if key.is_a? Numeric
71
+ mapped_data = data[key]
72
+ else
73
+ mapped_data = data.map { |value| value[key] }.flatten
74
+ end
75
+
76
+ return mapped_data
77
+ end
78
+
79
+ return data
80
+ end
81
+ end
82
+ end
83
+ end
@@ -6,13 +6,14 @@ module RSpec
6
6
 
7
7
  def self.add_helper(name, scope: :spec, &helper)
8
8
  helper_module = Module.new do |mod|
9
- mod.define_method(name) do |*args|
9
+ mod.define_method(name) do |*args, &block|
10
10
  instance_var = "@#{name}".to_sym
11
11
 
12
12
  if self.instance_variables.include? instance_var
13
13
  return self.instance_variable_get(instance_var)
14
14
  end
15
15
 
16
+ args << block
16
17
  result = self.instance_exec(*args, &helper)
17
18
  self.instance_variable_set(instance_var, result)
18
19
  end
@@ -20,7 +21,8 @@ module RSpec
20
21
 
21
22
  RSpec.configure do |config|
22
23
  config.after(:each) do
23
- helper_module.instance_variable_set(:@result, nil)
24
+ instance_var = "@#{name}".to_sym
25
+ helper_module.instance_variable_set(instance_var, nil)
24
26
  end
25
27
 
26
28
  module_method = if scope == :spec
@@ -38,11 +40,11 @@ module RSpec
38
40
  end
39
41
 
40
42
  # describe level helpers
41
- require_relative "helpers/graphql_query"
42
- require_relative "helpers/graphql_variables"
43
43
  require_relative "helpers/graphql_context"
44
+ require_relative "helpers/graphql_operation"
45
+ require_relative "helpers/graphql_variables"
44
46
 
45
47
  # spec level helpers
46
- require_relative "helpers/operation"
47
- require_relative "helpers/response"
48
48
  require_relative "helpers/execute_graphql"
49
+ require_relative "helpers/response"
50
+ require_relative "helpers/response_data"
@@ -1,12 +1,17 @@
1
1
  RSpec::GraphQLResponse.add_helper :execute_graphql do
2
2
  config = RSpec::GraphQLResponse.configuration
3
3
 
4
- query = get_graphql_query if respond_to? :get_graphql_query
5
- query_vars = get_graphql_variables if respond_to? :get_graphql_variables
6
- query_context = get_graphql_context if respond_to? :get_graphql_context
4
+ operation = graphql_operation if respond_to? :graphql_operation
5
+ operation = self.instance_eval(&graphql_operation) if operation.is_a? Proc
7
6
 
8
- config.graphql_schema.execute(query, {
9
- variables: query_vars,
10
- context: query_context
7
+ operation_vars = graphql_variables if respond_to? :graphql_variables
8
+ operation_vars = self.instance_eval(&graphql_variables) if operation_vars.is_a? Proc
9
+
10
+ operation_context = graphql_context if respond_to? :graphql_context
11
+ operation_context = self.instance_eval(&operation_context) if operation_context.is_a? Proc
12
+
13
+ config.graphql_schema.execute(operation, {
14
+ variables: operation_vars,
15
+ context: operation_context
11
16
  })
12
17
  end
@@ -1,3 +1,3 @@
1
1
  RSpec::GraphQLResponse.add_context_helper :graphql_context do |ctx|
2
- self.define_method(:get_graphql_context) { ctx }
2
+ self.define_method(:graphql_context) { ctx }
3
3
  end
@@ -0,0 +1,3 @@
1
+ RSpec::GraphQLResponse.add_context_helper :graphql_operation do |gql|
2
+ self.define_method(:graphql_operation) { gql }
3
+ end
@@ -1,3 +1,3 @@
1
1
  RSpec::GraphQLResponse.add_context_helper :graphql_variables do |vars|
2
- self.define_method(:get_graphql_variables) { vars }
2
+ self.define_method(:graphql_variables) { vars }
3
3
  end
@@ -0,0 +1,13 @@
1
+ RSpec::GraphQLResponse.add_helper :response_data do |*fields|
2
+ next nil unless response.is_a? Hash
3
+
4
+ response_data = response["data"]
5
+ next nil if response_data.nil?
6
+ next nil if response_data.empty?
7
+
8
+ fields = fields.compact
9
+ next response_data if fields.empty?
10
+
11
+ dig_dug = RSpec::GraphQLResponse::DigDug.new(*fields)
12
+ dig_dug.dig(response_data)
13
+ end
@@ -12,4 +12,4 @@ module RSpec
12
12
  end
13
13
 
14
14
  require_relative "matchers/have_errors"
15
- require_relative "matchers/have_operation"
15
+ require_relative "matchers/have_field"
@@ -1,6 +1,6 @@
1
- RSpec::GraphQLResponse.add_matcher :have_operation do |operation_name|
1
+ RSpec::GraphQLResponse.add_matcher :have_field do |operation_name|
2
2
  match do |response|
3
- validator = RSpec::GraphQLResponse.validator(:have_operation)
3
+ validator = RSpec::GraphQLResponse.validator(:have_field)
4
4
 
5
5
  @result = validator.validate(response, operation_name: operation_name)
6
6
  @result.valid?
@@ -11,7 +11,7 @@ RSpec::GraphQLResponse.add_matcher :have_operation do |operation_name|
11
11
  end
12
12
 
13
13
  match_when_negated do |response|
14
- validator = RSpec::GraphQLResponse.validator(:have_operation)
14
+ validator = RSpec::GraphQLResponse.validator(:have_field)
15
15
 
16
16
  @result = validator.validate_negated(response, operation_name: operation_name)
17
17
  @result.valid?
@@ -23,4 +23,4 @@ module RSpec
23
23
  end
24
24
 
25
25
  require_relative "validators/have_errors"
26
- require_relative "validators/have_operation"
26
+ require_relative "validators/have_field"
@@ -1,4 +1,4 @@
1
- RSpec::GraphQLResponse.add_validator :have_operation do
1
+ RSpec::GraphQLResponse.add_validator :have_field do
2
2
  failure_message :nil, "Cannot evaluate operations on nil"
3
3
  failure_message :not_found, ->(expected, actual) { "Expected to find operation result named #{expected}, but did not find it\n\t#{actual}" }
4
4
 
@@ -1,5 +1,5 @@
1
1
  module RSpec
2
2
  module GraphQLResponse
3
- VERSION = "0.2.0"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
@@ -26,10 +26,11 @@ Gem::Specification.new do |spec|
26
26
  spec.require_paths = ["lib"]
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 1.17"
29
- spec.add_development_dependency "graphql", "~> 1.12"
30
29
  spec.add_development_dependency "rake", ">= 12.0"
31
30
  spec.add_development_dependency "pry", "~> 0.14"
32
31
  spec.add_development_dependency "pry-byebug", "~> 3.8"
32
+ spec.add_development_dependency "super_diff", "~> 0.6"
33
33
 
34
- spec.add_runtime_dependency "rspec", "~>3.10"
34
+ spec.add_runtime_dependency "rspec", ">= 3.0"
35
+ spec.add_runtime_dependency "graphql", ">= 1.0"
35
36
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rspec-graphql_response
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - River Lynn Bailey
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-02 00:00:00.000000000 Z
11
+ date: 2021-04-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -24,20 +24,6 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.17'
27
- - !ruby/object:Gem::Dependency
28
- name: graphql
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '1.12'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '1.12'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -81,19 +67,47 @@ dependencies:
81
67
  - !ruby/object:Gem::Version
82
68
  version: '3.8'
83
69
  - !ruby/object:Gem::Dependency
84
- name: rspec
70
+ name: super_diff
85
71
  requirement: !ruby/object:Gem::Requirement
86
72
  requirements:
87
73
  - - "~>"
88
74
  - !ruby/object:Gem::Version
89
- version: '3.10'
90
- type: :runtime
75
+ version: '0.6'
76
+ type: :development
91
77
  prerelease: false
92
78
  version_requirements: !ruby/object:Gem::Requirement
93
79
  requirements:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
- version: '3.10'
82
+ version: '0.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: graphql
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '1.0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '1.0'
97
111
  description: Adds a :graphql rspec type with built-in helpers and matchers for ruby-graphql
98
112
  gem responses
99
113
  email:
@@ -126,24 +140,26 @@ files:
126
140
  - docs/execute_graphql.md
127
141
  - docs/graphql_spec_type.md
128
142
  - docs/have_errors.md
129
- - docs/have_operation.md
143
+ - docs/have_field.md
130
144
  - docs/operation.md
131
145
  - docs/response.md
146
+ - docs/response_data.md
132
147
  - lib/rspec/graphql_response.rb
133
148
  - lib/rspec/graphql_response/configuration.rb
149
+ - lib/rspec/graphql_response/dig_dug/dig_dug.rb
134
150
  - lib/rspec/graphql_response/helpers.rb
135
151
  - lib/rspec/graphql_response/helpers/execute_graphql.rb
136
152
  - lib/rspec/graphql_response/helpers/graphql_context.rb
137
- - lib/rspec/graphql_response/helpers/graphql_query.rb
153
+ - lib/rspec/graphql_response/helpers/graphql_operation.rb
138
154
  - lib/rspec/graphql_response/helpers/graphql_variables.rb
139
- - lib/rspec/graphql_response/helpers/operation.rb
140
155
  - lib/rspec/graphql_response/helpers/response.rb
156
+ - lib/rspec/graphql_response/helpers/response_data.rb
141
157
  - lib/rspec/graphql_response/matchers.rb
142
158
  - lib/rspec/graphql_response/matchers/have_errors.rb
143
- - lib/rspec/graphql_response/matchers/have_operation.rb
159
+ - lib/rspec/graphql_response/matchers/have_field.rb
144
160
  - lib/rspec/graphql_response/validators.rb
145
161
  - lib/rspec/graphql_response/validators/have_errors.rb
146
- - lib/rspec/graphql_response/validators/have_operation.rb
162
+ - lib/rspec/graphql_response/validators/have_field.rb
147
163
  - lib/rspec/graphql_response/validators/validation_base.rb
148
164
  - lib/rspec/graphql_response/validators/validation_result.rb
149
165
  - lib/rspec/graphql_response/validators/validation_runner.rb
@@ -1,3 +0,0 @@
1
- RSpec::GraphQLResponse.add_context_helper :graphql_query do |gql|
2
- self.define_method(:get_graphql_query) { gql }
3
- end
@@ -1,5 +0,0 @@
1
- RSpec::GraphQLResponse.add_helper :operation do |name|
2
- return nil unless response.is_a? Hash
3
-
4
- response.dig("data", name.to_s)
5
- end