rspec-rails-api 0.3.1 → 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/.rubocop.yml +1 -0
- data/CHANGELOG.md +54 -0
- data/README.md +39 -36
- data/Rakefile +3 -0
- data/lib/rspec/rails/api/dsl/example.rb +94 -16
- data/lib/rspec/rails/api/dsl/example_group.rb +134 -48
- data/lib/rspec/rails/api/entity_config.rb +31 -4
- data/lib/rspec/rails/api/field_config.rb +12 -3
- data/lib/rspec/rails/api/matchers.rb +16 -3
- data/lib/rspec/rails/api/metadata.rb +149 -32
- data/lib/rspec/rails/api/open_api_renderer.rb +185 -25
- data/lib/rspec/rails/api/utils.rb +66 -7
- data/lib/rspec/rails/api/version.rb +1 -1
- data/lib/rspec_rails_api.rb +8 -0
- data/rspec-rails-api.gemspec +6 -4
- metadata +21 -6
@@ -27,6 +27,13 @@ module RSpec
|
|
27
27
|
@api_license = {}
|
28
28
|
end
|
29
29
|
|
30
|
+
##
|
31
|
+
# Merges example context definition with the renderer data
|
32
|
+
#
|
33
|
+
# @param context [Hash] Metadata hash
|
34
|
+
# @param dump_metadata [Boolean] Saves the raw metadata in `tmp/rra_metadata.yaml` for debugging
|
35
|
+
#
|
36
|
+
# @return [void
|
30
37
|
def merge_context(context, dump_metadata: false)
|
31
38
|
@metadata[:resources].deep_merge! context[:resources]
|
32
39
|
@metadata[:entities].deep_merge! context[:entities]
|
@@ -35,36 +42,64 @@ module RSpec
|
|
35
42
|
File.write ::Rails.root.join('tmp', 'rra_metadata.yaml'), context.to_yaml if dump_metadata
|
36
43
|
end
|
37
44
|
|
45
|
+
##
|
46
|
+
# Write OpenAPI files
|
47
|
+
#
|
48
|
+
# @param path [String, nil] Where to save the files. Defaults to `/tmp/rspec_api_rails.*` when unset
|
49
|
+
# @param only [[Symbol]] Formats to save the file to. Allowed values are `:yaml` and `:json`
|
50
|
+
#
|
51
|
+
# @return [void]
|
38
52
|
def write_files(path = nil, only: %i[yaml json])
|
39
|
-
content = prepare_metadata
|
40
53
|
path ||= ::Rails.root.join('tmp', 'rspec_api_rails')
|
41
54
|
|
55
|
+
file_types = %i[yaml json]
|
56
|
+
|
42
57
|
only.each do |type|
|
43
|
-
next unless
|
58
|
+
next unless file_types.include? type
|
44
59
|
|
45
|
-
File.write "#{path}.#{type}",
|
60
|
+
File.write "#{path}.#{type}", prepare_metadata.send("to_#{type}")
|
46
61
|
end
|
47
62
|
end
|
48
63
|
|
64
|
+
##
|
65
|
+
# Extracts metadata from context to generate an OpenAPI structure
|
66
|
+
#
|
67
|
+
# @return [Hash] The OpenAPI structure
|
49
68
|
def prepare_metadata
|
50
|
-
# Example: https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore-expanded.yaml
|
51
69
|
extract_metadatas
|
52
|
-
|
70
|
+
# Example: https://github.com/OAI/OpenAPI-Specification/blob/master/examples/v3.0/petstore-expanded.yaml
|
71
|
+
hash = {
|
53
72
|
openapi: '3.0.0',
|
54
73
|
info: @api_infos,
|
55
74
|
servers: @api_servers,
|
56
75
|
paths: @api_paths,
|
57
76
|
components: @api_components,
|
58
77
|
tags: @api_tags,
|
59
|
-
}
|
78
|
+
}
|
79
|
+
JSON.parse(JSON.pretty_generate(hash))
|
60
80
|
end
|
61
81
|
|
82
|
+
##
|
83
|
+
# Sets the contact field
|
84
|
+
#
|
85
|
+
# @param name [String, nil] Contact name
|
86
|
+
# @param email [String, nil] Contact Email
|
87
|
+
# @param url [String, nil] Contact URL
|
88
|
+
#
|
89
|
+
# @return [void]
|
62
90
|
def api_contact=(name: nil, email: nil, url: nil)
|
63
91
|
@api_contact[:name] = name if name
|
64
92
|
@api_contact[:email] = email if email
|
65
93
|
@api_contact[:url] = url if url
|
66
94
|
end
|
67
95
|
|
96
|
+
##
|
97
|
+
# Sets the license field
|
98
|
+
#
|
99
|
+
# @param name [String, nil] License name
|
100
|
+
# @param url [String, nil] License URL
|
101
|
+
#
|
102
|
+
# @return [void]
|
68
103
|
def api_license=(name: nil, url: nil)
|
69
104
|
@api_license[:name] = name if name
|
70
105
|
@api_license[:url] = url if url
|
@@ -72,14 +107,26 @@ module RSpec
|
|
72
107
|
|
73
108
|
private
|
74
109
|
|
110
|
+
##
|
111
|
+
# Extracts metadata for rendering
|
112
|
+
#
|
113
|
+
# @return [void]
|
75
114
|
def extract_metadatas
|
76
115
|
extract_from_resources
|
77
116
|
api_infos
|
78
117
|
api_servers
|
79
118
|
end
|
80
119
|
|
81
|
-
|
120
|
+
##
|
121
|
+
# Extracts metadata from resources for rendering
|
122
|
+
#
|
123
|
+
# @return [void]
|
124
|
+
def extract_from_resources # rubocop:disable Metrics/MethodLength
|
125
|
+
@api_components[:schemas] ||= {}
|
82
126
|
@metadata[:resources].each do |resource_key, resource|
|
127
|
+
resource[:entities].each do |name, entity|
|
128
|
+
@api_components[:schemas][name] = process_entity(entity)
|
129
|
+
end
|
83
130
|
@api_tags.push(
|
84
131
|
name: resource_key.to_s,
|
85
132
|
description: resource[:description]
|
@@ -88,14 +135,23 @@ module RSpec
|
|
88
135
|
end
|
89
136
|
end
|
90
137
|
|
138
|
+
##
|
139
|
+
# Processes a resource from metadata
|
140
|
+
#
|
141
|
+
# @param resource [Symbol, nil] Resource name
|
142
|
+
# @param resource_config [Hash, nil] Resource declaration
|
143
|
+
#
|
144
|
+
#
|
145
|
+
# @return [void]
|
91
146
|
def process_resource(resource: nil, resource_config: nil) # rubocop:disable Metrics/MethodLength
|
147
|
+
http_verbs = %i[get post put patch delete]
|
92
148
|
resource_config[:paths].each do |path_key, path|
|
93
149
|
url = path_with_params path_key.to_s
|
94
150
|
actions = {}
|
95
151
|
parameters = path.key?(:path_params) ? process_path_params(path[:path_params]) : []
|
96
152
|
|
97
153
|
path[:actions].each_key do |action|
|
98
|
-
next unless
|
154
|
+
next unless http_verbs.include? action
|
99
155
|
|
100
156
|
actions[action] = process_action resource: resource,
|
101
157
|
path: path_key,
|
@@ -108,6 +164,10 @@ module RSpec
|
|
108
164
|
end
|
109
165
|
end
|
110
166
|
|
167
|
+
##
|
168
|
+
# Processes path parameters for rendering
|
169
|
+
#
|
170
|
+
# @param params [Hash] Path parameters
|
111
171
|
def process_path_params(params)
|
112
172
|
parameters = []
|
113
173
|
params.each do |name, param|
|
@@ -117,7 +177,40 @@ module RSpec
|
|
117
177
|
parameters
|
118
178
|
end
|
119
179
|
|
120
|
-
def
|
180
|
+
def process_entity(entity) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
181
|
+
schema = {
|
182
|
+
properties: {},
|
183
|
+
}
|
184
|
+
required = []
|
185
|
+
entity.fields.each do |name, field|
|
186
|
+
property = {
|
187
|
+
description: field.description,
|
188
|
+
type: PARAM_TYPES[field.type][:type],
|
189
|
+
}
|
190
|
+
property[:format] = PARAM_TYPES[field.type][:format] if PARAM_TYPES[field.type][:format]
|
191
|
+
schema[:properties][name] = property
|
192
|
+
# Primitives support
|
193
|
+
if PRIMITIVES.include? field.attributes
|
194
|
+
property[:items] =
|
195
|
+
{ type: field.attributes.to_s.split('_').last.to_sym }
|
196
|
+
end
|
197
|
+
required.push name unless field.required == false
|
198
|
+
end
|
199
|
+
|
200
|
+
schema[:required] = required unless required.size.zero?
|
201
|
+
|
202
|
+
schema
|
203
|
+
end
|
204
|
+
|
205
|
+
##
|
206
|
+
# Processes a path parameter from metadata
|
207
|
+
#
|
208
|
+
# @param name [Symbol, nil] Parameter name
|
209
|
+
# @param param [Hash, nil] Parameter declaration
|
210
|
+
#
|
211
|
+
#
|
212
|
+
# @return [void]
|
213
|
+
def process_path_param(name, param) # rubocop:disable Metrics/MethodLength
|
121
214
|
parameter = {
|
122
215
|
name: name.to_s,
|
123
216
|
description: param[:description],
|
@@ -133,18 +226,30 @@ module RSpec
|
|
133
226
|
parameter
|
134
227
|
end
|
135
228
|
|
229
|
+
##
|
230
|
+
# Processes an action from metadata
|
231
|
+
#
|
232
|
+
# @param resource [Symbol, nil] Target resource
|
233
|
+
# @param path [Symbol, nil] Target path
|
234
|
+
# @param path_config [Hash, nil] Path configuraton
|
235
|
+
# @param action_config [Symbol, nil] Target action
|
236
|
+
# @param parameters [Array, nil] Path parameters
|
237
|
+
#
|
238
|
+
# @return [void]
|
239
|
+
#
|
240
|
+
# FIXME: Rename "action_config" to "action"
|
241
|
+
# FIXME: Rename "parameters" to "path_parameters"
|
136
242
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
137
243
|
def process_action(resource: nil, path: nil, path_config: nil, action_config: nil, parameters: nil)
|
138
244
|
responses = {}
|
139
245
|
request_body = nil
|
140
246
|
|
141
|
-
if %i[post put
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
247
|
+
if %i[post put
|
248
|
+
patch].include?(action_config) && path_config[:actions][action_config][:params].keys.count.positive?
|
249
|
+
schema = path_config[:actions][action_config][:params]
|
250
|
+
schema_ref = escape_operation_id("#{action_config}_#{path}")
|
251
|
+
examples = process_examples(path_config[:actions][action_config][:statuses])
|
252
|
+
request_body = process_request_body schema: schema, ref: schema_ref, examples: examples
|
148
253
|
end
|
149
254
|
|
150
255
|
path_config[:actions][action_config][:statuses].each do |status_key, status|
|
@@ -152,10 +257,11 @@ module RSpec
|
|
152
257
|
responses[status_key] = process_response status: status_key, status_config: status, content: content
|
153
258
|
end
|
154
259
|
|
155
|
-
|
156
|
-
action
|
157
|
-
|
158
|
-
|
260
|
+
summary = path_config[:actions][action_config][:summary]
|
261
|
+
action = {
|
262
|
+
summary: summary,
|
263
|
+
description: path_config[:actions][action_config][:description],
|
264
|
+
operationId: "#{resource} #{summary}".downcase.gsub(/[^\w]/, '_'),
|
159
265
|
parameters: parameters,
|
160
266
|
responses: responses,
|
161
267
|
tags: [resource.to_s],
|
@@ -167,6 +273,14 @@ module RSpec
|
|
167
273
|
end
|
168
274
|
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
169
275
|
|
276
|
+
##
|
277
|
+
# Processes a request body from metadata
|
278
|
+
#
|
279
|
+
# @param schema [Hash] Schema
|
280
|
+
# @param ref [String] Reference
|
281
|
+
# @param examples [Hash] Example
|
282
|
+
#
|
283
|
+
# @return [void]
|
170
284
|
def process_request_body(schema: nil, ref: nil, examples: {})
|
171
285
|
Utils.deep_set @api_components, "schemas.#{ref}", schema
|
172
286
|
{
|
@@ -181,22 +295,48 @@ module RSpec
|
|
181
295
|
}
|
182
296
|
end
|
183
297
|
|
298
|
+
##
|
299
|
+
# Process a response from metadata
|
300
|
+
#
|
301
|
+
# @param status [Symbol] Status code
|
302
|
+
# @param status_config [Hash] Configuration for status code
|
303
|
+
# @param content [String] Response content
|
304
|
+
#
|
305
|
+
# @return [void]
|
184
306
|
def process_response(status: nil, status_config: nil, content: nil)
|
185
|
-
response = {
|
186
|
-
description: status_config[:description],
|
187
|
-
}
|
307
|
+
response = { description: status_config[:description] }
|
188
308
|
|
189
309
|
return response if status.to_s == '204' && content # No content
|
190
310
|
|
191
311
|
response[:content] = {
|
192
312
|
'application/json': {
|
193
|
-
|
313
|
+
schema: response_schema(status_config[:expectations]),
|
314
|
+
examples: { default: { value: JSON.parse(content) } },
|
194
315
|
},
|
195
316
|
}
|
196
317
|
|
197
318
|
response
|
198
319
|
end
|
199
320
|
|
321
|
+
def response_schema(expectations)
|
322
|
+
if expectations[:many]
|
323
|
+
items = if PRIMITIVES.include?(expectations[:many])
|
324
|
+
{ type: expectations[:many].to_s.split('_').last }
|
325
|
+
else
|
326
|
+
{ '$ref' => "#/components/schemas/#{expectations[:many]}" }
|
327
|
+
end
|
328
|
+
{ type: 'array', items: items }
|
329
|
+
elsif expectations[:one]
|
330
|
+
{ '$ref' => "#/components/schemas/#{expectations[:one]}" }
|
331
|
+
end
|
332
|
+
end
|
333
|
+
|
334
|
+
##
|
335
|
+
# Processes examples from statuses
|
336
|
+
#
|
337
|
+
# @param statuses [Hash]
|
338
|
+
#
|
339
|
+
# @return [Hash] Request examples
|
200
340
|
def process_examples(statuses)
|
201
341
|
request_examples = {}
|
202
342
|
|
@@ -210,17 +350,33 @@ module RSpec
|
|
210
350
|
request_examples
|
211
351
|
end
|
212
352
|
|
353
|
+
##
|
354
|
+
# Converts path with params like ":id" to their OpenAPI representation
|
355
|
+
#
|
356
|
+
# @param string [String] The original path
|
357
|
+
#
|
358
|
+
# @return [String] OpenAPI path representation
|
213
359
|
def path_with_params(string)
|
214
360
|
string.gsub(/(?::(\w*))/) do |e|
|
215
361
|
"{#{e.sub(':', '')}}"
|
216
362
|
end
|
217
363
|
end
|
218
364
|
|
365
|
+
##
|
366
|
+
# Converts a string to a snake_cased string to use as operationId
|
367
|
+
#
|
368
|
+
# @param string [String] Original string
|
369
|
+
#
|
370
|
+
# @return [String] Snake_cased string
|
219
371
|
def escape_operation_id(string)
|
220
372
|
string.downcase.gsub(/[^\w]+/, '_')
|
221
373
|
end
|
222
374
|
|
223
|
-
|
375
|
+
##
|
376
|
+
# Fills the API general information sections
|
377
|
+
#
|
378
|
+
# @return [void]
|
379
|
+
def api_infos
|
224
380
|
@api_infos = {
|
225
381
|
title: @api_title || 'Some sample app',
|
226
382
|
version: @api_version || '1.0',
|
@@ -233,6 +389,10 @@ module RSpec
|
|
233
389
|
@api_infos
|
234
390
|
end
|
235
391
|
|
392
|
+
##
|
393
|
+
# Fills the API servers section
|
394
|
+
#
|
395
|
+
# @return [void]
|
236
396
|
def api_servers
|
237
397
|
@api_servers || [
|
238
398
|
{ url: 'http://api.example.com' },
|
@@ -7,14 +7,29 @@ module RSpec
|
|
7
7
|
module Api
|
8
8
|
# Helper methods
|
9
9
|
class Utils
|
10
|
+
##
|
11
|
+
# Gets a value in a hash by specifying a dotted path
|
12
|
+
#
|
13
|
+
# @param hash [Hash] The hash to search in
|
14
|
+
# @param path [String] The dotted path
|
15
|
+
#
|
16
|
+
# @return [*] The value or nil
|
10
17
|
def self.deep_get(hash, path)
|
11
18
|
path.split('.').inject(hash) do |sub_hash, key|
|
12
19
|
return nil unless sub_hash.is_a?(Hash) && sub_hash.key?(key.to_sym)
|
13
20
|
|
14
|
-
sub_hash[key.to_sym]
|
21
|
+
sub_hash[key.to_sym] # rubocop:disable Lint/UnmodifiedReduceAccumulator
|
15
22
|
end
|
16
23
|
end
|
17
24
|
|
25
|
+
##
|
26
|
+
# Sets a value at given dotted path in a hash
|
27
|
+
#
|
28
|
+
# @param hash [Hash] The target hash
|
29
|
+
# @param path [String] Dotted path
|
30
|
+
# @param value [*] Value to set
|
31
|
+
#
|
32
|
+
# @return [Hash] The modified hash
|
18
33
|
def self.deep_set(hash, path, value)
|
19
34
|
path = path.split('.') unless path.is_a? Array
|
20
35
|
|
@@ -27,7 +42,14 @@ module RSpec
|
|
27
42
|
hash
|
28
43
|
end
|
29
44
|
|
30
|
-
|
45
|
+
##
|
46
|
+
# Checks if a value is of the given parameter type
|
47
|
+
#
|
48
|
+
# @param type [Symbol] Type to compare to
|
49
|
+
# @param value [*] Value to test
|
50
|
+
#
|
51
|
+
# @return [Boolean] True when the value corresponds to the given type
|
52
|
+
def self.check_value_type(type, value)
|
31
53
|
return true if type == :boolean && (value.is_a?(TrueClass) || value.is_a?(FalseClass))
|
32
54
|
return true if type == :array && value.is_a?(Array)
|
33
55
|
|
@@ -36,6 +58,13 @@ module RSpec
|
|
36
58
|
value.is_a? PARAM_TYPES[type][:class]
|
37
59
|
end
|
38
60
|
|
61
|
+
##
|
62
|
+
# Validates an object keys and values types
|
63
|
+
#
|
64
|
+
# @param actual [Hash] Hash to compare
|
65
|
+
# @param expected [Hash] Structure to compare
|
66
|
+
#
|
67
|
+
# @return [Boolean] True when the object matches the structure
|
39
68
|
def self.validate_object_structure(actual, expected)
|
40
69
|
# Check keys
|
41
70
|
return false unless same_keys? actual, expected
|
@@ -56,23 +85,53 @@ module RSpec
|
|
56
85
|
true
|
57
86
|
end
|
58
87
|
|
59
|
-
|
88
|
+
##
|
89
|
+
# Validates an array or hash against a definition
|
90
|
+
#
|
91
|
+
# @param expected_type [:object, :array] The expected type
|
92
|
+
# @param expected_attributes [Hash] Attributes configuration
|
93
|
+
# @param actual [Array, Hash] Value to check
|
94
|
+
#
|
95
|
+
# @return [Boolean] True when `actual` is of the expected definition
|
60
96
|
def self.validate_deep_object(expected_type, expected_attributes, actual)
|
61
97
|
if %i[object array].include?(expected_type) && expected_attributes.is_a?(Hash)
|
62
98
|
case expected_type
|
63
99
|
when :object
|
64
100
|
return false unless validate_object_structure actual, expected_attributes
|
65
101
|
when :array
|
66
|
-
actual
|
67
|
-
return false unless validate_object_structure array_entry, expected_attributes
|
68
|
-
end
|
102
|
+
return false unless validate_deep_object_array actual, expected_attributes
|
69
103
|
end
|
70
104
|
end
|
71
105
|
|
72
106
|
true
|
73
107
|
end
|
74
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
75
108
|
|
109
|
+
##
|
110
|
+
# Validates each entry of an array
|
111
|
+
#
|
112
|
+
# @param array [Array] The array to check
|
113
|
+
# @param expected_attributes [Hash] Attributes configuration
|
114
|
+
#
|
115
|
+
# @return [Boolean] True when all values matches the attribute configuration
|
116
|
+
def self.validate_deep_object_array(array, expected_attributes)
|
117
|
+
array.each do |array_entry|
|
118
|
+
if expected_attributes[:type]
|
119
|
+
return false unless check_value_type expected_attributes[:type], array_entry
|
120
|
+
else
|
121
|
+
return false unless validate_object_structure array_entry, expected_attributes
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
true
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Checks if a hash have the required keys in it
|
130
|
+
#
|
131
|
+
# @param actual [Hash] The hash
|
132
|
+
# @param expected [Hash] Attributes definitions
|
133
|
+
#
|
134
|
+
# @return [Boolean] True when the object is valid
|
76
135
|
def self.same_keys?(actual, expected)
|
77
136
|
optional = expected.reject { |_key, value| value[:required] }.keys
|
78
137
|
actual.symbolize_keys.keys.sort - optional == expected.keys.sort - optional
|
data/lib/rspec_rails_api.rb
CHANGED
@@ -15,6 +15,8 @@ module RSpec
|
|
15
15
|
class Error < StandardError
|
16
16
|
end
|
17
17
|
|
18
|
+
##
|
19
|
+
# OpenAPI types, format and Ruby class correspondence
|
18
20
|
PARAM_TYPES = {
|
19
21
|
int32: { type: 'integer', format: 'int32', class: Integer },
|
20
22
|
int64: { type: 'integer', format: 'int64', class: Integer },
|
@@ -32,6 +34,12 @@ module RSpec
|
|
32
34
|
array: { type: 'array', format: nil, class: Array },
|
33
35
|
object: { type: 'object', format: nil, class: Hash },
|
34
36
|
}.freeze
|
37
|
+
|
38
|
+
EXCLUDED_PRIMITIVES = %i[array object].freeze
|
39
|
+
|
40
|
+
PRIMITIVES = PARAM_TYPES.keys
|
41
|
+
.reject { |key| EXCLUDED_PRIMITIVES.include? key }
|
42
|
+
.map { |key| "type_#{key}".to_sym }
|
35
43
|
end
|
36
44
|
end
|
37
45
|
end
|
data/rspec-rails-api.gemspec
CHANGED
@@ -18,9 +18,10 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.homepage = 'https://gitlab.com/experimentslabs/rspec-rails-api'
|
19
19
|
spec.license = 'MIT'
|
20
20
|
spec.metadata = {
|
21
|
-
'source_code_uri'
|
22
|
-
'bug_tracker_uri'
|
23
|
-
'changelog_uri'
|
21
|
+
'source_code_uri' => 'https://gitlab.com/experimentslabs/rspec-rails-api',
|
22
|
+
'bug_tracker_uri' => 'https://gitlab.com/experimentslabs/rspec-rails-api/issues',
|
23
|
+
'changelog_uri' => 'https://gitlab.com/experimentslabs/rspec-rails-api/blob/master/CHANGELOG.md',
|
24
|
+
'rubygems_mfa_required' => 'true',
|
24
25
|
}
|
25
26
|
|
26
27
|
# Specify which files should be added to the gem when it is released.
|
@@ -35,11 +36,12 @@ Gem::Specification.new do |spec|
|
|
35
36
|
spec.required_ruby_version = '>= 2.5.0'
|
36
37
|
|
37
38
|
spec.add_development_dependency 'activesupport', '~> 6.0'
|
38
|
-
spec.add_development_dependency 'bundler'
|
39
|
+
spec.add_development_dependency 'bundler'
|
39
40
|
spec.add_development_dependency 'byebug'
|
40
41
|
spec.add_development_dependency 'rake', '~> 10.0'
|
41
42
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
42
43
|
spec.add_development_dependency 'rubocop'
|
43
44
|
spec.add_development_dependency 'rubocop-performance'
|
44
45
|
spec.add_development_dependency 'simplecov'
|
46
|
+
spec.add_development_dependency 'yard'
|
45
47
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rspec-rails-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Manuel Tancoigne
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-12-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -28,16 +28,16 @@ dependencies:
|
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: byebug
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +122,20 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yard
|
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'
|
125
139
|
description: |
|
126
140
|
Create acceptance tests to check the Rails API responses and generate
|
127
141
|
documentation from it.
|
@@ -162,6 +176,7 @@ metadata:
|
|
162
176
|
source_code_uri: https://gitlab.com/experimentslabs/rspec-rails-api
|
163
177
|
bug_tracker_uri: https://gitlab.com/experimentslabs/rspec-rails-api/issues
|
164
178
|
changelog_uri: https://gitlab.com/experimentslabs/rspec-rails-api/blob/master/CHANGELOG.md
|
179
|
+
rubygems_mfa_required: 'true'
|
165
180
|
post_install_message:
|
166
181
|
rdoc_options: []
|
167
182
|
require_paths:
|