rspec-graphql-integration 0.1.0 → 0.2.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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c741c1c9dcf41ac20bad890effdfde5ffa121b63b60f6704f07c0638a6001e6e
|
4
|
+
data.tar.gz: 74742a1424ec5ff2587bf945eab4cc5bf8ea059552da4f9b61ef01676b284477
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1dc6131393b96403f4054cb9a75c9d44c00a23dc6e5b101525290f1ba9f55d05b8ac4e3d071df262c14f53c4508d7a6f72357a10ca30eb611e1ad760fa3aa7bd
|
7
|
+
data.tar.gz: c6ed7377e513b4e12589f0ae8f1986bbedfbe8c43c31e773427e7b96926089ecac242b930cab4c858994b001776625e34af078b2fb56e2fed42931884b8acebb
|
@@ -4,6 +4,7 @@ module RSpec
|
|
4
4
|
module GraphqlIntegration
|
5
5
|
def self.initialize_configuration(config) # rubocop:disable Metrics/MethodLength
|
6
6
|
config.add_setting(:graphql_schema_class, default: nil)
|
7
|
+
config.add_setting(:graphql_put_files_in_folder, default: false)
|
7
8
|
|
8
9
|
config.include(RSpec::GraphqlIntegration::Matchers::DeepEq, type: :graphql)
|
9
10
|
config.include(RSpec::GraphqlIntegration::Matchers::MatchGraphqlResponse, type: :graphql)
|
@@ -2,12 +2,10 @@ module RSpec
|
|
2
2
|
module GraphqlIntegration
|
3
3
|
module Matchers
|
4
4
|
##
|
5
|
-
# This
|
5
|
+
# This helper method recursively compares nested Ruby Hashes and Arrays while ignoring
|
6
6
|
# the order of elements in Arrays.
|
7
7
|
module DeepEq
|
8
|
-
|
9
|
-
|
10
|
-
matcher(:deep_eq) { |expected| match { |actual| deep_eq?(actual, expected) } }
|
8
|
+
module_function
|
11
9
|
|
12
10
|
def deep_eq?(actual, expected)
|
13
11
|
return arrays_deep_eq?(actual, expected) if expected.is_a?(Array) && actual.is_a?(Array)
|
@@ -20,8 +18,8 @@ module RSpec
|
|
20
18
|
def arrays_deep_eq?(actual, expected)
|
21
19
|
expected = expected.clone
|
22
20
|
|
23
|
-
actual.each do |
|
24
|
-
index = expected.find_index { |
|
21
|
+
actual.each do |actual_array|
|
22
|
+
index = expected.find_index { |expected_array| deep_eq?(actual_array, expected_array) }
|
25
23
|
return false if index.nil?
|
26
24
|
|
27
25
|
expected.delete_at(index)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "json"
|
2
|
+
|
1
3
|
module RSpec
|
2
4
|
module GraphqlIntegration
|
3
5
|
module Matchers
|
@@ -7,104 +9,239 @@ module RSpec
|
|
7
9
|
extend RSpec::Matchers::DSL
|
8
10
|
|
9
11
|
##
|
10
|
-
# This error is
|
11
|
-
|
12
|
-
|
13
|
-
def initialize(variable_name, example_value)
|
12
|
+
# This error is raised when the schema class is not set in the RSpec configuration.
|
13
|
+
class SchemaNotSetError < StandardError
|
14
|
+
def initialize
|
14
15
|
super <<~TEXT
|
15
|
-
|
16
|
+
Please define
|
17
|
+
|
18
|
+
config.graphql_schema_class
|
16
19
|
|
17
|
-
|
18
|
-
let(:#{variable_name}) { #{example_value} }
|
20
|
+
in your spec_helper.rb
|
19
21
|
TEXT
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
##
|
24
|
-
#
|
25
|
-
# the
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
# This error is thrown if neither the default request file is present nor
|
27
|
+
# the request_file_overwrite variable is set in a test.
|
28
|
+
class DefaultRequestFileMissing < StandardError
|
29
|
+
def initialize(default_request_file)
|
30
|
+
super <<~TEXT
|
31
|
+
No default request file found for this test.
|
32
|
+
|
33
|
+
Please create either a default request file:
|
34
|
+
#{default_request_file}
|
35
|
+
|
36
|
+
or define a file with the request_file_overwrite variable:
|
37
|
+
let(:request_file_overwrite) { File.join(File.dirname(__FILE__), "my_request_file.graphql") }
|
38
|
+
TEXT
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
##
|
43
|
+
# This error is thrown if neither the default request file is present nor
|
44
|
+
# the response_file_overwrite variable is set in a test.
|
45
|
+
class DefaultResponseFileMissing < StandardError
|
46
|
+
def initialize(default_response_file)
|
47
|
+
super <<~TEXT
|
48
|
+
No default response file found for this test.
|
49
|
+
|
50
|
+
Please create either a default response file:
|
51
|
+
#{default_response_file}
|
52
|
+
|
53
|
+
or define a file with the response_file_overwrite variable:
|
54
|
+
let(:response_file_overwrite) { File.join(File.dirname(__FILE__), "my_response_file.graphql") }
|
55
|
+
TEXT
|
56
|
+
end
|
57
|
+
end
|
29
58
|
|
30
59
|
matcher(:match_graphql_response) do |_expected| # rubocop:disable Metrics/BlockLength
|
31
60
|
match do |_actual|
|
32
|
-
|
61
|
+
# expected_response needs to be loaded first because it might contain variables
|
62
|
+
# that are required in the request and that aren't loaded yet. Such variables
|
63
|
+
# could be database objects that could be created while loading the response.
|
64
|
+
expected_response
|
33
65
|
|
34
|
-
# We need to test the responses with
|
66
|
+
# We need to test the responses with DeepEq so that we ignore
|
35
67
|
# the order in nested hashes.
|
36
|
-
|
37
|
-
rescue RSpec::Expectations::ExpectationNotMetError => e
|
38
|
-
@error = e
|
39
|
-
raise
|
68
|
+
DeepEq.deep_eq?(actual_response, expected_response)
|
40
69
|
end
|
41
70
|
|
42
71
|
# For the failure message, we want to show the diff between the actual and
|
43
72
|
# the expected response and the standard eq matcher from RSpec does that best.
|
44
73
|
failure_message { expect(actual_response).to eq(expected_response) }
|
45
74
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
75
|
+
##
|
76
|
+
# Loads the response file and substitutes the variables in the response file.
|
77
|
+
def expected_response
|
78
|
+
@expected_response ||=
|
79
|
+
begin
|
80
|
+
expected_response =
|
81
|
+
load_response(
|
82
|
+
response_file,
|
83
|
+
defined?(response_variables) ? response_variables : {},
|
84
|
+
)
|
85
|
+
|
86
|
+
expected_response = [expected_response] unless expected_response.is_a?(Array)
|
87
|
+
|
88
|
+
expected_response
|
50
89
|
end
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Executes the query with the context and the variables against the schema and
|
94
|
+
# returns the response.
|
95
|
+
def actual_response
|
96
|
+
@actual_response ||=
|
97
|
+
begin
|
98
|
+
response =
|
99
|
+
schema_class.execute(
|
100
|
+
File.read(request_file),
|
101
|
+
context: defined?(context) ? context : {},
|
102
|
+
variables: defined?(request_variables) ? request_variables : {},
|
103
|
+
)
|
104
|
+
|
105
|
+
response.values
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# This method tries to get the file path for the file that is running the tests.
|
111
|
+
#
|
112
|
+
# The magic of this method can be overwritten by defining:
|
113
|
+
# let(:test_file_overwrite) { __FILE__ }
|
114
|
+
def test_file
|
115
|
+
return test_file_overwrite if defined?(test_file_overwrite)
|
116
|
+
|
117
|
+
caller_location =
|
118
|
+
caller_locations.find { |location| location.path.include?("/spec/graphql") }
|
119
|
+
|
120
|
+
caller_location.path
|
121
|
+
end
|
122
|
+
|
123
|
+
##
|
124
|
+
# This method defines the folder where the request and response files are stored.
|
125
|
+
#
|
126
|
+
# It's either the folder of the file that is running the tests or a subfolder
|
127
|
+
# named like the test file.
|
128
|
+
def files_folder
|
129
|
+
if RSpec.configuration.graphql_put_files_in_folder
|
130
|
+
test_file.gsub("_spec.rb", "")
|
131
|
+
else
|
132
|
+
File.dirname(test_file)
|
51
133
|
end
|
52
134
|
end
|
53
135
|
|
54
|
-
|
55
|
-
|
136
|
+
##
|
137
|
+
# This method tries to get the file path for the request file.
|
138
|
+
#
|
139
|
+
# If the request_file_overwrite variable is set, it uses that.
|
140
|
+
#
|
141
|
+
# raises DefaultRequestFileMissing if no request file is found.
|
142
|
+
def request_file
|
143
|
+
if defined?(request_file_overwrite)
|
144
|
+
return File.join(files_folder, request_file_overwrite)
|
145
|
+
end
|
56
146
|
|
57
|
-
|
147
|
+
default_request_file = File.join(files_folder, default_request_file_name)
|
58
148
|
|
59
|
-
|
149
|
+
unless File.exist?(default_request_file)
|
150
|
+
raise DefaultRequestFileMissing, default_request_file
|
151
|
+
end
|
152
|
+
|
153
|
+
default_request_file
|
60
154
|
end
|
61
155
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
156
|
+
##
|
157
|
+
# The default request file is either called like the test file without _spec
|
158
|
+
# but with .graphql or it's in the subfolder of the test file called "request.graphql".
|
159
|
+
def default_request_file_name
|
160
|
+
if RSpec.configuration.graphql_put_files_in_folder
|
161
|
+
"request.graphql"
|
162
|
+
else
|
163
|
+
test_file.split("/").last.gsub("_spec.rb", ".graphql")
|
164
|
+
end
|
71
165
|
end
|
72
166
|
|
167
|
+
##
|
168
|
+
# This method tries to get the file path for the response file.
|
169
|
+
#
|
170
|
+
# If the response_file_overwrite variable is set, it uses that.
|
171
|
+
#
|
172
|
+
# raises DefaultRequestFileMissing if no response file is found.
|
173
|
+
def response_file
|
174
|
+
if defined?(response_file_overwrite)
|
175
|
+
return File.join(files_folder, response_file_overwrite)
|
176
|
+
end
|
177
|
+
|
178
|
+
default_response_file = File.join(files_folder, default_response_file_name)
|
179
|
+
|
180
|
+
unless File.exist?(default_response_file)
|
181
|
+
raise DefaultResponseFileMissing, default_response_file
|
182
|
+
end
|
183
|
+
|
184
|
+
default_response_file
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# The default response file is either called like the test file without _spec
|
189
|
+
# but with .json or it's in the subfolder of the test file called "response.json".
|
190
|
+
def default_response_file_name
|
191
|
+
if RSpec.configuration.graphql_put_files_in_folder
|
192
|
+
"response.json"
|
193
|
+
else
|
194
|
+
test_file.split("/").last.gsub("_spec.rb", ".json")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
##
|
199
|
+
# This method gets the schema class from the RSpec configuration.
|
200
|
+
#
|
201
|
+
# If schema_class_overwrite is set, it uses that.
|
202
|
+
#
|
203
|
+
# raises SchemaNotSetError if the schema class is not set.
|
73
204
|
def schema_class
|
74
205
|
# It's possible to overwrite the schema class if an app has multiple schemas.
|
75
206
|
return schema_class_overwrite if defined?(schema_class_overwrite)
|
76
207
|
|
77
|
-
if RSpec.configuration.graphql_schema_class.nil?
|
78
|
-
raise "Please define config.graphql_schema_class in your rails_helper.rb"
|
79
|
-
end
|
208
|
+
raise SchemaNotSetError if RSpec.configuration.graphql_schema_class.nil?
|
80
209
|
|
81
210
|
RSpec.configuration.graphql_schema_class
|
82
211
|
end
|
83
212
|
end
|
84
213
|
|
85
|
-
##
|
86
|
-
# Loads a query in a GraphQL file.
|
87
|
-
#
|
88
|
-
# Example:
|
89
|
-
# load_query(__FILE__, 'current_user/query.graphql'),
|
90
|
-
def load_query(dir, filename)
|
91
|
-
File.read(File.join(File.dirname(dir), filename))
|
92
|
-
end
|
93
|
-
|
94
214
|
##
|
95
215
|
# Loads a response in a JSON file and substitute the passed variables that
|
96
216
|
# are surrounded by {{...}} in the file.
|
97
217
|
#
|
98
218
|
# Example:
|
99
219
|
# load_response(
|
100
|
-
#
|
101
|
-
# 'current_user/response.json',
|
220
|
+
# "current_user.json",
|
102
221
|
# {
|
103
|
-
# user_id:
|
222
|
+
# user_id: 1,
|
104
223
|
# },
|
105
224
|
# )
|
106
|
-
|
107
|
-
|
225
|
+
#
|
226
|
+
# current_user.json:
|
227
|
+
# {
|
228
|
+
# "data": {
|
229
|
+
# "currentUser": {
|
230
|
+
# "id": "{{user_id}}",
|
231
|
+
# }
|
232
|
+
# }
|
233
|
+
# }
|
234
|
+
#
|
235
|
+
# Result:
|
236
|
+
# {
|
237
|
+
# "data": {
|
238
|
+
# "currentUser": {
|
239
|
+
# "id": "1",
|
240
|
+
# }
|
241
|
+
# }
|
242
|
+
# }
|
243
|
+
def load_response(filename, variables = {})
|
244
|
+
json_file = File.read(filename)
|
108
245
|
variables.each { |key, value| json_file.gsub!("\"{{#{key}}}\"", JSON.dump(value)) }
|
109
246
|
|
110
247
|
JSON.parse(json_file)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-graphql-integration
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Gundel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: graphql
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: byebug
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: prettier
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +66,48 @@ dependencies:
|
|
52
66
|
- - ">="
|
53
67
|
- !ruby/object:Gem::Version
|
54
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rspec
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
55
111
|
- !ruby/object:Gem::Dependency
|
56
112
|
name: rubocop
|
57
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,6 +122,34 @@ dependencies:
|
|
66
122
|
- - ">="
|
67
123
|
- !ruby/object:Gem::Version
|
68
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-rspec
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
69
153
|
description:
|
70
154
|
email:
|
71
155
|
- gundel.peter@gmail.com
|
@@ -91,14 +175,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
91
175
|
requirements:
|
92
176
|
- - ">="
|
93
177
|
- !ruby/object:Gem::Version
|
94
|
-
version: '2.
|
178
|
+
version: '2.7'
|
95
179
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
180
|
requirements:
|
97
181
|
- - ">="
|
98
182
|
- !ruby/object:Gem::Version
|
99
183
|
version: '0'
|
100
184
|
requirements: []
|
101
|
-
rubygems_version: 3.
|
185
|
+
rubygems_version: 3.1.6
|
102
186
|
signing_key:
|
103
187
|
specification_version: 4
|
104
188
|
summary: An RSpec plugin to simplify integration tests for GraphQL
|