rspec-rails-api 0.3.4 → 0.5.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/.gitignore +0 -5
- data/.gitlab-ci.yml +1 -1
- data/.rubocop.yml +5 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +51 -0
- data/Gemfile.lock +98 -0
- data/README.md +39 -36
- data/Rakefile +3 -0
- data/lib/rspec/rails/api/dsl/example.rb +94 -18
- data/lib/rspec/rails/api/dsl/example_group.rb +134 -48
- data/lib/rspec/rails/api/entity_config.rb +28 -4
- data/lib/rspec/rails/api/field_config.rb +10 -2
- data/lib/rspec/rails/api/matchers.rb +26 -18
- data/lib/rspec/rails/api/metadata.rb +153 -21
- data/lib/rspec/rails/api/open_api_renderer.rb +189 -20
- data/lib/rspec/rails/api/utils.rb +28 -70
- data/lib/rspec/rails/api/validator.rb +211 -0
- data/lib/rspec/rails/api/version.rb +1 -1
- data/lib/rspec_rails_api.rb +4 -0
- data/rspec-rails-api.gemspec +10 -5
- metadata +68 -9
@@ -7,80 +7,38 @@ module RSpec
|
|
7
7
|
module Api
|
8
8
|
# Helper methods
|
9
9
|
class Utils
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
class << self
|
11
|
+
##
|
12
|
+
# Sets a value at given dotted path in a hash
|
13
|
+
#
|
14
|
+
# @param hash [Hash] The target hash
|
15
|
+
# @param path [Array] List of keys to access value
|
16
|
+
# @param value [*] Value to set
|
17
|
+
#
|
18
|
+
# @return [Hash] The modified hash
|
19
|
+
def deep_set(hash, path, value)
|
20
|
+
raise 'path should be an array' unless path.is_a? Array
|
21
|
+
|
22
|
+
return value if path.count.zero?
|
23
|
+
|
24
|
+
current_key = path.shift.to_s.to_sym
|
25
|
+
hash[current_key] = {} unless hash[current_key].is_a?(Hash)
|
26
|
+
hash[current_key] = deep_set(hash[current_key], path, value)
|
27
|
+
|
28
|
+
hash
|
15
29
|
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.deep_set(hash, path, value)
|
19
|
-
path = path.split('.') unless path.is_a? Array
|
20
|
-
|
21
|
-
return value if path.count.zero?
|
22
|
-
|
23
|
-
current_key = path.shift.to_sym
|
24
|
-
hash[current_key] = {} unless hash[current_key].is_a?(Hash)
|
25
|
-
hash[current_key] = deep_set(hash[current_key], path, value)
|
26
|
-
|
27
|
-
hash
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.check_value_type(type, value)
|
31
|
-
return true if type == :boolean && (value.is_a?(TrueClass) || value.is_a?(FalseClass))
|
32
|
-
return true if type == :array && value.is_a?(Array)
|
33
|
-
|
34
|
-
raise "Unknown type #{type}" unless PARAM_TYPES.key? type
|
35
|
-
|
36
|
-
value.is_a? PARAM_TYPES[type][:class]
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.validate_object_structure(actual, expected)
|
40
|
-
# Check keys
|
41
|
-
return false unless same_keys? actual, expected
|
42
30
|
|
43
|
-
|
44
|
-
|
31
|
+
##
|
32
|
+
# Returns a hash from an object
|
33
|
+
#
|
34
|
+
# @param value [Hash,Class] A hash or something with a "body" (as responses object in tests)
|
35
|
+
#
|
36
|
+
# @return [Hash]
|
37
|
+
def hash_from_response(value)
|
38
|
+
return JSON.parse(value.body) if value.respond_to? :body
|
45
39
|
|
46
|
-
|
47
|
-
expected_attributes = expected[key][:attributes]
|
48
|
-
|
49
|
-
# Type
|
50
|
-
return false unless check_value_type expected_type, actual[key.to_s]
|
51
|
-
|
52
|
-
# Deep object ?
|
53
|
-
return false unless validate_deep_object expected_type, expected_attributes, actual[key.to_s]
|
54
|
-
end
|
55
|
-
|
56
|
-
true
|
57
|
-
end
|
58
|
-
|
59
|
-
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
60
|
-
def self.validate_deep_object(expected_type, expected_attributes, actual)
|
61
|
-
if %i[object array].include?(expected_type) && expected_attributes.is_a?(Hash)
|
62
|
-
case expected_type
|
63
|
-
when :object
|
64
|
-
return false unless validate_object_structure actual, expected_attributes
|
65
|
-
when :array
|
66
|
-
actual.each do |array_entry|
|
67
|
-
return false unless validate_object_structure array_entry, expected_attributes
|
68
|
-
end
|
69
|
-
end
|
40
|
+
value
|
70
41
|
end
|
71
|
-
|
72
|
-
true
|
73
|
-
end
|
74
|
-
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength
|
75
|
-
|
76
|
-
def self.same_keys?(actual, expected)
|
77
|
-
optional = expected.reject { |_key, value| value[:required] }.keys
|
78
|
-
actual.symbolize_keys.keys.sort - optional == expected.keys.sort - optional
|
79
|
-
end
|
80
|
-
|
81
|
-
def self.check_attribute_type(type, except: [])
|
82
|
-
keys = PARAM_TYPES.keys.reject { |key| except.include? key }
|
83
|
-
keys.include?(type)
|
84
42
|
end
|
85
43
|
end
|
86
44
|
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/hash_with_indifferent_access'
|
4
|
+
require 'rspec_rails_api'
|
5
|
+
|
6
|
+
module RSpec
|
7
|
+
module Rails
|
8
|
+
module Api
|
9
|
+
# Set of method to validate data and data structures
|
10
|
+
class Validator
|
11
|
+
class << self
|
12
|
+
##
|
13
|
+
# Validates an object keys and values types
|
14
|
+
#
|
15
|
+
# @param actual [*] Value to compare
|
16
|
+
# @param expected [Hash, NilClass] Definition
|
17
|
+
#
|
18
|
+
# @return [String, Hash, NilClass] Nil when no error, string when not an object and dictionary of errors
|
19
|
+
# otherwise
|
20
|
+
def validate_object(actual, expected)
|
21
|
+
return 'is not a hash' unless actual.is_a? Hash
|
22
|
+
# Don't validate without a definition
|
23
|
+
return unless expected
|
24
|
+
|
25
|
+
keys_errors = validate_object_keys actual, expected
|
26
|
+
return keys_errors unless keys_errors.nil?
|
27
|
+
|
28
|
+
attributes_errors = validate_object_attributes(actual, expected)
|
29
|
+
|
30
|
+
attributes_errors unless attributes_errors.keys.empty?
|
31
|
+
end
|
32
|
+
|
33
|
+
##
|
34
|
+
# Validates each entry of an array
|
35
|
+
#
|
36
|
+
# @param array [*] The array to check
|
37
|
+
# @param expected [Symbol, Hash, NilClass] Attributes configuration
|
38
|
+
#
|
39
|
+
# @return [String, Hash, NilClass] Nil when no error, string when not an object and dictionary of errors
|
40
|
+
# otherwise
|
41
|
+
def validate_array(array, expected)
|
42
|
+
return 'is not an array' unless array.is_a? Array
|
43
|
+
# Arrays without an expected entry type
|
44
|
+
return unless expected
|
45
|
+
|
46
|
+
errors = {}
|
47
|
+
array.each_with_index do |array_entry, index|
|
48
|
+
value_error = validate_array_entry array_entry, expected
|
49
|
+
errors["##{index}"] = value_error if value_error
|
50
|
+
end
|
51
|
+
|
52
|
+
errors unless errors.keys.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
##
|
56
|
+
# Returns a human-readable string from matcher errors
|
57
|
+
#
|
58
|
+
# @param errors [String,Hash] Validation errors
|
59
|
+
# @param values [String] JSON string representing the value
|
60
|
+
#
|
61
|
+
# @return [String]
|
62
|
+
def format_failure_message(errors, values)
|
63
|
+
if errors.is_a? Hash
|
64
|
+
errors = errors.deep_stringify_keys.to_yaml.split("\n")
|
65
|
+
errors.shift
|
66
|
+
errors.map! do |line|
|
67
|
+
" #{line.sub(/^(\s+)"(#\d+)":(.*)$/, '\1\2:\3')}"
|
68
|
+
end
|
69
|
+
errors = errors.join("\n")
|
70
|
+
end
|
71
|
+
|
72
|
+
<<~TXT
|
73
|
+
expected object structure not to have these errors:
|
74
|
+
#{errors}
|
75
|
+
|
76
|
+
As a notice, here is the JSON object:
|
77
|
+
#{values}
|
78
|
+
TXT
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Checks if a given type is in the supported types list
|
83
|
+
#
|
84
|
+
# @param type [Symbol] Type to check
|
85
|
+
# @param except [[Symbol]] List of types to ignore
|
86
|
+
#
|
87
|
+
# @return [Boolean]
|
88
|
+
def valid_type?(type, except: [])
|
89
|
+
keys = PARAM_TYPES.keys.reject { |key| except.include? key }
|
90
|
+
keys.include?(type)
|
91
|
+
end
|
92
|
+
|
93
|
+
##
|
94
|
+
# Checks if a value is of the given type
|
95
|
+
#
|
96
|
+
# @param value [*] Value to test
|
97
|
+
# @param type [Symbol] Type to compare to
|
98
|
+
#
|
99
|
+
# @return [String,NilClass] True when the value corresponds to the given type
|
100
|
+
def validate_type(value, type)
|
101
|
+
if type == :boolean
|
102
|
+
return nil if value.is_a?(TrueClass) || value.is_a?(FalseClass)
|
103
|
+
|
104
|
+
return 'is not a "boolean"'
|
105
|
+
end
|
106
|
+
|
107
|
+
raise "Unknown type #{type}" unless PARAM_TYPES.key? type
|
108
|
+
|
109
|
+
return nil if value.is_a? PARAM_TYPES[type][:class]
|
110
|
+
|
111
|
+
"is not a \"#{type}\""
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
# Checks if a key should be skipped, whether it's missing and optional or nil
|
117
|
+
#
|
118
|
+
# @param key [Symbol] Key to check
|
119
|
+
# @param value [*] Associated value
|
120
|
+
# @param definition [Hash] Entity definitions
|
121
|
+
#
|
122
|
+
# @return [Boolean]
|
123
|
+
def skip_key_check?(key, value, definition)
|
124
|
+
# Ignore missing optional keys
|
125
|
+
return true unless value.key?(key.to_s) || definition[key][:required]
|
126
|
+
# Ignore null optional keys
|
127
|
+
return true if !definition[key][:required] && value[key.to_s].nil?
|
128
|
+
|
129
|
+
false
|
130
|
+
end
|
131
|
+
|
132
|
+
# Validates the keys of a hash
|
133
|
+
#
|
134
|
+
# @param actual [Hash] The hash to check
|
135
|
+
# @param definition [Hash] The object definition
|
136
|
+
#
|
137
|
+
# @return [String, Hash, NilClass] Nil when no error, string when not an object and dictionary of errors
|
138
|
+
# otherwise
|
139
|
+
def validate_object_keys(actual, definition)
|
140
|
+
# Hashes without an expected attributes type
|
141
|
+
return unless definition
|
142
|
+
|
143
|
+
errors = {}
|
144
|
+
actual.each_key do |key|
|
145
|
+
errors[key] = 'is not defined' unless definition.key?(key.to_sym)
|
146
|
+
end
|
147
|
+
|
148
|
+
errors unless errors.keys.empty?
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Validates the attributes of a Hash
|
153
|
+
#
|
154
|
+
# @param actual [Hash] Value to compare
|
155
|
+
# @param expected [Hash] Definition
|
156
|
+
#
|
157
|
+
# @return [String, Hash, NilClass] Nil when no error, string when not an object and dictionary of errors
|
158
|
+
# otherwise
|
159
|
+
def validate_object_attributes(actual, expected)
|
160
|
+
errors = {}
|
161
|
+
expected.each_key do |key|
|
162
|
+
next if skip_key_check? key, actual, expected
|
163
|
+
|
164
|
+
value_error = validate_object_attribute key, actual, expected[key][:type], expected[key][:attributes]
|
165
|
+
errors[key] = value_error unless value_error.nil?
|
166
|
+
end
|
167
|
+
|
168
|
+
errors unless errors.keys.nil?
|
169
|
+
end
|
170
|
+
|
171
|
+
# Checks the value of an entry in a Hash
|
172
|
+
#
|
173
|
+
# @param key [Symbol] Key to check
|
174
|
+
# @param actual [Hash] Hash to check
|
175
|
+
# @param expected_type [Symbol] Expected type
|
176
|
+
# @param definition [Symbol,Hash] Attribute definition
|
177
|
+
#
|
178
|
+
# @return [String,Hash,NilClass] Nil when no error is met, string when not a primitive and dictionary of
|
179
|
+
# errors otherwise
|
180
|
+
def validate_object_attribute(key, actual, expected_type, definition)
|
181
|
+
return 'is missing' unless actual.key? key.to_s
|
182
|
+
|
183
|
+
case expected_type
|
184
|
+
when :object
|
185
|
+
validate_object actual[key.to_s], definition
|
186
|
+
when :array
|
187
|
+
validate_array actual[key.to_s], definition
|
188
|
+
else
|
189
|
+
validate_type actual[key.to_s], expected_type
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
# Checks the validity of an array entry against a definition
|
194
|
+
#
|
195
|
+
# @param entry [*] Entry to check
|
196
|
+
# @param definition [Hash] Fields definition
|
197
|
+
#
|
198
|
+
# @return [String,Hash,NilClass] Nil when no error is met, string when not a primitive and dictionary of
|
199
|
+
# errors otherwise
|
200
|
+
def validate_array_entry(entry, definition)
|
201
|
+
if definition[:type].is_a? Symbol # Array of "simple" values
|
202
|
+
validate_type entry, definition[:type]
|
203
|
+
else # Objects
|
204
|
+
validate_object entry, definition
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
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,8 @@ 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
|
+
PRIMITIVES = PARAM_TYPES.keys
|
35
39
|
end
|
36
40
|
end
|
37
41
|
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.
|
@@ -32,14 +33,18 @@ Gem::Specification.new do |spec|
|
|
32
33
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
33
34
|
spec.require_paths = ['lib']
|
34
35
|
|
35
|
-
spec.required_ruby_version = '>= 2.
|
36
|
+
spec.required_ruby_version = '>= 2.7.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'
|
41
|
+
spec.add_development_dependency 'rack'
|
40
42
|
spec.add_development_dependency 'rake', '~> 10.0'
|
41
43
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
42
44
|
spec.add_development_dependency 'rubocop'
|
43
45
|
spec.add_development_dependency 'rubocop-performance'
|
46
|
+
spec.add_development_dependency 'rubocop-rake'
|
47
|
+
spec.add_development_dependency 'rubocop-rspec'
|
44
48
|
spec.add_development_dependency 'simplecov'
|
49
|
+
spec.add_development_dependency 'yard'
|
45
50
|
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.5.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: 2023-01-02 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
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rack
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: rake
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -108,6 +122,34 @@ dependencies:
|
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-rake
|
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: rubocop-rspec
|
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'
|
111
153
|
- !ruby/object:Gem::Dependency
|
112
154
|
name: simplecov
|
113
155
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,6 +164,20 @@ dependencies:
|
|
122
164
|
- - ">="
|
123
165
|
- !ruby/object:Gem::Version
|
124
166
|
version: '0'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: yard
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - ">="
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
174
|
+
type: :development
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
125
181
|
description: |
|
126
182
|
Create acceptance tests to check the Rails API responses and generate
|
127
183
|
documentation from it.
|
@@ -135,10 +191,12 @@ files:
|
|
135
191
|
- ".gitlab-ci.yml"
|
136
192
|
- ".rspec"
|
137
193
|
- ".rubocop.yml"
|
194
|
+
- ".ruby-version"
|
138
195
|
- ".travis.yml"
|
139
196
|
- CHANGELOG.md
|
140
197
|
- CODE_OF_CONDUCT.md
|
141
198
|
- Gemfile
|
199
|
+
- Gemfile.lock
|
142
200
|
- LICENSE.txt
|
143
201
|
- README.md
|
144
202
|
- Rakefile
|
@@ -152,6 +210,7 @@ files:
|
|
152
210
|
- lib/rspec/rails/api/metadata.rb
|
153
211
|
- lib/rspec/rails/api/open_api_renderer.rb
|
154
212
|
- lib/rspec/rails/api/utils.rb
|
213
|
+
- lib/rspec/rails/api/validator.rb
|
155
214
|
- lib/rspec/rails/api/version.rb
|
156
215
|
- lib/rspec_rails_api.rb
|
157
216
|
- rspec-rails-api.gemspec
|
@@ -162,6 +221,7 @@ metadata:
|
|
162
221
|
source_code_uri: https://gitlab.com/experimentslabs/rspec-rails-api
|
163
222
|
bug_tracker_uri: https://gitlab.com/experimentslabs/rspec-rails-api/issues
|
164
223
|
changelog_uri: https://gitlab.com/experimentslabs/rspec-rails-api/blob/master/CHANGELOG.md
|
224
|
+
rubygems_mfa_required: 'true'
|
165
225
|
post_install_message:
|
166
226
|
rdoc_options: []
|
167
227
|
require_paths:
|
@@ -170,15 +230,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
170
230
|
requirements:
|
171
231
|
- - ">="
|
172
232
|
- !ruby/object:Gem::Version
|
173
|
-
version: 2.
|
233
|
+
version: 2.7.0
|
174
234
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
235
|
requirements:
|
176
236
|
- - ">="
|
177
237
|
- !ruby/object:Gem::Version
|
178
238
|
version: '0'
|
179
239
|
requirements: []
|
180
|
-
|
181
|
-
rubygems_version: 2.7.6
|
240
|
+
rubygems_version: 3.4.1
|
182
241
|
signing_key:
|
183
242
|
specification_version: 4
|
184
243
|
summary: Tests standard Rails API responses and generate doc
|