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
@@ -9,99 +9,185 @@ module RSpec
|
|
9
9
|
# All these methods will be available in example groups
|
10
10
|
# (anything but 'it', 'example', 'for_code')
|
11
11
|
module ExampleGroup
|
12
|
-
|
13
|
-
# as it will initialize the
|
12
|
+
##
|
13
|
+
# First method to be called in a spec file # as it will initialize the
|
14
|
+
# metadata.
|
15
|
+
#
|
16
|
+
# @param name [String] Resource name
|
17
|
+
# @param description [String] Resource description
|
14
18
|
def resource(name, description = '')
|
15
|
-
metadata[:
|
16
|
-
metadata[:
|
19
|
+
metadata[:rra] ||= Metadata.new
|
20
|
+
metadata[:rra].add_resource name, description
|
17
21
|
end
|
18
22
|
|
19
|
-
|
23
|
+
##
|
24
|
+
# Describes an entity
|
25
|
+
#
|
26
|
+
# @param type [Symbol] Name of the entity for reference
|
27
|
+
# @param fields [Hash] Fields declarations
|
28
|
+
#
|
29
|
+
# @return [void]
|
20
30
|
def entity(type, fields)
|
21
|
-
metadata[:
|
31
|
+
metadata[:rra].add_entity type, fields
|
22
32
|
end
|
23
33
|
|
24
|
-
|
34
|
+
##
|
35
|
+
# Describes request or path parameters
|
36
|
+
#
|
37
|
+
# @param type [Symbol] Name of the parameters set for reference
|
38
|
+
# @param fields [Hash] Fields declarations
|
39
|
+
#
|
40
|
+
# @return [void]
|
25
41
|
def parameters(type, fields)
|
26
|
-
metadata[:
|
42
|
+
metadata[:rra].add_parameter type, fields
|
27
43
|
end
|
28
44
|
|
29
|
-
|
45
|
+
##
|
46
|
+
# Declares parameters used in URLS (_path_)
|
47
|
+
# Use `fields` or `defined` but not both.
|
48
|
+
#
|
49
|
+
# @param [Hash, nil] fields An attributes declaration
|
50
|
+
# @param [Symbol, nil] defined An entity reference
|
51
|
+
#
|
52
|
+
# @return [void]
|
30
53
|
def path_params(fields: nil, defined: nil)
|
31
|
-
if defined && !metadata[:
|
54
|
+
if defined && !metadata[:rra].parameters[defined]
|
32
55
|
raise "Parameter #{defined} was not defined with the 'parameters' method"
|
33
56
|
end
|
34
57
|
|
35
|
-
fields ||= metadata[:
|
58
|
+
fields ||= metadata[:rra].parameters[defined]
|
36
59
|
|
37
|
-
metadata[:
|
60
|
+
metadata[:rra].add_path_params fields
|
38
61
|
end
|
39
62
|
|
63
|
+
##
|
64
|
+
# Declares parameters for a request body
|
65
|
+
# Use `attributes` or `defined` but not both.
|
66
|
+
#
|
67
|
+
# @param [Hash, nil] attributes An attributes declaration
|
68
|
+
# @param [Symbol, nil] defined An entity reference.
|
69
|
+
#
|
70
|
+
# @return [void]
|
40
71
|
def request_params(attributes: nil, defined: nil)
|
41
|
-
if defined && !metadata[:
|
72
|
+
if defined && !metadata[:rra].parameters[defined]
|
42
73
|
raise "Parameter #{defined} was not defined with the 'parameters' method"
|
43
74
|
end
|
44
75
|
|
45
|
-
attributes ||= metadata[:
|
76
|
+
attributes ||= metadata[:rra].parameters[defined]
|
46
77
|
|
47
|
-
metadata[:
|
78
|
+
metadata[:rra].add_request_params attributes
|
48
79
|
end
|
49
80
|
|
50
|
-
|
51
|
-
|
81
|
+
##
|
82
|
+
# Defines a GET action
|
83
|
+
#
|
84
|
+
# @param [String] url URL to test
|
85
|
+
# @param [String] summary What the action does
|
86
|
+
# @param [String] description Longer description
|
87
|
+
#
|
88
|
+
# @return [void]
|
89
|
+
def on_get(url, summary = nil, description = nil, &block)
|
90
|
+
on_action(:get, url, summary, description, &block)
|
52
91
|
end
|
53
92
|
|
54
|
-
|
55
|
-
|
93
|
+
##
|
94
|
+
# Defines a POST action
|
95
|
+
#
|
96
|
+
# @param [String] url URL to test
|
97
|
+
# @param [String] summary What the action does
|
98
|
+
# @param [String] description Longer description
|
99
|
+
#
|
100
|
+
# @return [void]
|
101
|
+
def on_post(url, summary = nil, description = nil, &block)
|
102
|
+
on_action(:post, url, summary, description, &block)
|
56
103
|
end
|
57
104
|
|
58
|
-
|
59
|
-
|
105
|
+
##
|
106
|
+
# Defines a PUT action
|
107
|
+
#
|
108
|
+
# @param [String] url URL to test
|
109
|
+
# @param [String] summary What the action does
|
110
|
+
# @param [String] description Longer description
|
111
|
+
#
|
112
|
+
# @return [void]
|
113
|
+
def on_put(url, summary = nil, description = nil, &block)
|
114
|
+
on_action(:put, url, summary, description, &block)
|
60
115
|
end
|
61
116
|
|
62
|
-
|
63
|
-
|
117
|
+
##
|
118
|
+
# Defines a PATCH action
|
119
|
+
#
|
120
|
+
# @param [String] url URL to test
|
121
|
+
# @param [String] summary What the action does
|
122
|
+
# @param [String] description Longer description
|
123
|
+
#
|
124
|
+
# @return [void]
|
125
|
+
def on_patch(url, summary = nil, description = nil, &block)
|
126
|
+
on_action(:patch, url, summary, description, &block)
|
64
127
|
end
|
65
128
|
|
66
|
-
|
67
|
-
|
129
|
+
##
|
130
|
+
# Defines a DELETE action
|
131
|
+
#
|
132
|
+
# @param [String] url URL to test
|
133
|
+
# @param [String] summary What the action does
|
134
|
+
# @param [String] description Longer description
|
135
|
+
#
|
136
|
+
# @return [void]
|
137
|
+
def on_delete(url, summary = nil, description = nil, &block)
|
138
|
+
on_action(:delete, url, summary, description, &block)
|
68
139
|
end
|
69
140
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
141
|
+
##
|
142
|
+
# Adds an HTTP code declaration to metadata, with expected result
|
143
|
+
# If no expectation is provided, the response will be expected to be empty
|
144
|
+
#
|
145
|
+
# @param status_code [Number] Status code to test for
|
146
|
+
# @param description [String] Description of the route/status pair
|
147
|
+
# @param expect_many [Symbol] Check the response for a list of given entity
|
148
|
+
# @param expect_one [Symbol] Check the response for a given entity
|
149
|
+
# @param test_only [Boolean] When true, test the response without filling the documentation
|
150
|
+
#
|
151
|
+
# @return [void]
|
152
|
+
#
|
153
|
+
def for_code(status_code, description = nil, expect_many: nil, expect_one: false, test_only: false, &block)
|
78
154
|
description ||= Rack::Utils::HTTP_STATUS_CODES[status_code]
|
79
155
|
|
80
|
-
metadata[:
|
156
|
+
metadata[:rra].add_status_code(status_code, description) unless test_only
|
157
|
+
metadata[:rra].add_expectations(expect_one, expect_many)
|
158
|
+
metadata[:rra_current_example] = metadata[:rra].current_example
|
81
159
|
|
82
160
|
describe "->#{test_only ? ' test' : ''} #{status_code} - #{description}" do
|
83
|
-
execute_for_code_block(
|
161
|
+
execute_for_code_block(block)
|
84
162
|
end
|
85
163
|
end
|
86
164
|
|
87
165
|
private
|
88
166
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
167
|
+
##
|
168
|
+
# Currently fill metadata with the action
|
169
|
+
#
|
170
|
+
# @param [Symbol] action HTTP verb
|
171
|
+
# @param [String] url URL to test
|
172
|
+
# @param [String, nil] summary What the action does
|
173
|
+
# @param [String, nil] description Longer description
|
174
|
+
#
|
175
|
+
# @return [void]
|
176
|
+
def on_action(action, url, summary, description, &block)
|
177
|
+
metadata[:rra].add_action(action, url, summary, description)
|
93
178
|
|
94
|
-
|
95
|
-
end
|
179
|
+
describe("#{action.upcase} #{url}", &block)
|
96
180
|
end
|
97
181
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
182
|
+
##
|
183
|
+
# Visit the URL and test response
|
184
|
+
#
|
185
|
+
# @param callback_block [block] Block to execute for testing the response
|
186
|
+
#
|
187
|
+
# @return [void]
|
188
|
+
def execute_for_code_block(callback_block)
|
189
|
+
example 'Test and create documentation', caller: callback_block.send(:caller) do
|
190
|
+
instance_eval(&callback_block) if callback_block
|
105
191
|
end
|
106
192
|
end
|
107
193
|
end
|
@@ -18,6 +18,8 @@ module RSpec
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
+
##
|
22
|
+
# @return [Hash] Entity configuration
|
21
23
|
def to_h
|
22
24
|
out = {}
|
23
25
|
@fields.each_key do |key|
|
@@ -26,16 +28,41 @@ module RSpec
|
|
26
28
|
out
|
27
29
|
end
|
28
30
|
|
31
|
+
##
|
32
|
+
# Replaces the arrays 'of' and objects 'attributes' with the corresponding
|
33
|
+
# entities, recursively
|
34
|
+
#
|
35
|
+
# @param entities [Hash] List of entities
|
36
|
+
#
|
37
|
+
# @return [Hash]
|
29
38
|
def expand_with(entities)
|
30
39
|
hash = to_h
|
31
40
|
hash.each_pair do |field, config|
|
32
41
|
next unless %i[array object].include? config[:type]
|
33
42
|
|
34
|
-
|
35
|
-
next unless
|
36
|
-
raise "Entity #{attributes} not found for entity completion." unless entities[attributes]
|
43
|
+
attribute = config[:attributes]
|
44
|
+
next unless attribute.is_a? Symbol
|
37
45
|
|
38
|
-
hash[field][:attributes] = entities
|
46
|
+
hash[field][:attributes] = expand_attribute attribute, entities
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
##
|
53
|
+
# Expands an attribute for "for" and "attributes" keys
|
54
|
+
#
|
55
|
+
# @param attribute [Symbol] Attribute name
|
56
|
+
# @param entities [Hash] List of entities
|
57
|
+
def expand_attribute(attribute, entities)
|
58
|
+
if PRIMITIVES.include? attribute
|
59
|
+
# Primitives support
|
60
|
+
{ type: attribute.to_s.split('_').last.to_sym }
|
61
|
+
else
|
62
|
+
# Defined attribute
|
63
|
+
raise "Entity #{attribute} not found for entity completion." unless entities[attribute]
|
64
|
+
|
65
|
+
entities[attribute].expand_with(entities)
|
39
66
|
end
|
40
67
|
end
|
41
68
|
end
|
@@ -11,7 +11,7 @@ module RSpec
|
|
11
11
|
class FieldConfig
|
12
12
|
attr_accessor :required, :type, :attributes, :description
|
13
13
|
|
14
|
-
def initialize(type:, required: true,
|
14
|
+
def initialize(type:, description:, required: true, attributes: nil, of: nil)
|
15
15
|
@required = required
|
16
16
|
@description = description
|
17
17
|
raise "Field type not allowed: '#{type}'" unless Utils.check_attribute_type(type)
|
@@ -22,6 +22,8 @@ module RSpec
|
|
22
22
|
@type = type
|
23
23
|
end
|
24
24
|
|
25
|
+
##
|
26
|
+
# @return [Hash] Field configuration
|
25
27
|
def to_h
|
26
28
|
out = { required: @required, type: @type }
|
27
29
|
out[:description] = @description unless @description.nil?
|
@@ -39,10 +41,17 @@ module RSpec
|
|
39
41
|
|
40
42
|
private
|
41
43
|
|
44
|
+
##
|
45
|
+
# Sets @attributes of the field when it's an Array or Hash
|
46
|
+
#
|
47
|
+
# @param attributes [Hash, Symbol] The attributes definition or reference
|
48
|
+
#
|
49
|
+
# @return [void]
|
42
50
|
def define_attributes(attributes)
|
43
|
-
@attributes =
|
51
|
+
@attributes = case attributes
|
52
|
+
when Hash
|
44
53
|
@attributes = EntityConfig.new attributes
|
45
|
-
|
54
|
+
when Symbol
|
46
55
|
attributes
|
47
56
|
end
|
48
57
|
end
|
@@ -4,6 +4,9 @@ require 'active_support/hash_with_indifferent_access'
|
|
4
4
|
|
5
5
|
require 'rspec/rails/api/utils'
|
6
6
|
|
7
|
+
##
|
8
|
+
# RSpec matcher to check something against an array of `expected`
|
9
|
+
#
|
7
10
|
# FIXME: Split the matcher in something else; it's too messy.
|
8
11
|
RSpec::Matchers.define :have_many do |expected|
|
9
12
|
match do |actual|
|
@@ -13,18 +16,28 @@ RSpec::Matchers.define :have_many do |expected|
|
|
13
16
|
raise "Response is not an array: #{@actual.class}" unless @actual.is_a? Array
|
14
17
|
raise 'Response has no item to compare with' unless @actual.count.positive?
|
15
18
|
|
19
|
+
# Primitive type
|
20
|
+
if expected[:type].is_a?(Symbol)
|
21
|
+
@actual.each do |item|
|
22
|
+
return false unless RSpec::Rails::Api::Utils.check_value_type(expected[:type], item)
|
23
|
+
end
|
24
|
+
|
25
|
+
return true
|
26
|
+
end
|
27
|
+
|
16
28
|
# Check every entry
|
17
|
-
ok = true
|
18
29
|
@actual.each do |item|
|
19
|
-
|
30
|
+
return false unless RSpec::Rails::Api::Utils.validate_object_structure item, expected
|
20
31
|
end
|
21
32
|
|
22
|
-
|
33
|
+
true
|
23
34
|
end
|
24
35
|
|
25
36
|
diffable
|
26
37
|
end
|
27
38
|
|
39
|
+
##
|
40
|
+
# RSpec matcher to check something against the `expected` definition
|
28
41
|
# FIXME: Split the matcher in something else; it's too messy.
|
29
42
|
RSpec::Matchers.define :have_one do |expected|
|
30
43
|
match do |actual|
|
@@ -9,7 +9,7 @@ module RSpec
|
|
9
9
|
module Api
|
10
10
|
# Handles contexts and examples metadatas.
|
11
11
|
class Metadata # rubocop:disable Metrics/ClassLength
|
12
|
-
attr_reader :entities, :resources, :current_resource, :
|
12
|
+
attr_reader :entities, :resources, :parameters, :current_resource, :current_url, :current_method, :current_code
|
13
13
|
|
14
14
|
def initialize
|
15
15
|
@resources = {}
|
@@ -22,23 +22,54 @@ module RSpec
|
|
22
22
|
@current_code = nil
|
23
23
|
end
|
24
24
|
|
25
|
+
##
|
26
|
+
# Adds a resource to metadata
|
27
|
+
#
|
28
|
+
# @param name [String] Resource name
|
29
|
+
# @param description [String] Resource description
|
30
|
+
#
|
31
|
+
# @return [void]
|
25
32
|
def add_resource(name, description)
|
26
33
|
@resources[name.to_sym] = { description: description, paths: {} }
|
27
34
|
@current_resource = name.to_sym
|
28
35
|
end
|
29
36
|
|
30
|
-
|
37
|
+
##
|
38
|
+
# Adds an entity definition
|
39
|
+
#
|
40
|
+
# @param name [Symbol] Entity name
|
41
|
+
# @param fields [Hash] Fields definitions
|
42
|
+
#
|
43
|
+
#
|
44
|
+
# @return [void]
|
45
|
+
def add_entity(name, fields)
|
31
46
|
Utils.deep_set(@resources,
|
32
|
-
"#{@current_resource}.entities.#{
|
47
|
+
"#{@current_resource}.entities.#{name}",
|
33
48
|
EntityConfig.new(fields))
|
34
49
|
end
|
35
50
|
|
36
|
-
|
37
|
-
|
51
|
+
##
|
52
|
+
# Adds a parameter definition
|
53
|
+
#
|
54
|
+
# @param name [Symbol] Parameter definition name
|
55
|
+
# @param fields [Hash] Fields definitions
|
56
|
+
#
|
57
|
+
# @return [void]
|
58
|
+
def add_parameter(name, fields)
|
59
|
+
raise "Parameter #{name} is already defined" if @parameters[name]
|
38
60
|
|
39
|
-
|
61
|
+
fields.each_value do |field|
|
62
|
+
field[:required] = true unless field[:required] == false
|
63
|
+
end
|
64
|
+
@parameters[name] = fields
|
40
65
|
end
|
41
66
|
|
67
|
+
##
|
68
|
+
# Adds path parameters definition
|
69
|
+
#
|
70
|
+
# @param fields [Hash] Parameters definitions
|
71
|
+
#
|
72
|
+
# @return [void]
|
42
73
|
def add_path_params(fields) # rubocop:disable Metrics/MethodLength
|
43
74
|
check_current_context :resource, :url
|
44
75
|
|
@@ -57,6 +88,9 @@ module RSpec
|
|
57
88
|
end
|
58
89
|
end
|
59
90
|
|
91
|
+
##
|
92
|
+
# Add request parameters (_body_)
|
93
|
+
#
|
60
94
|
# Fields should be something like:
|
61
95
|
# id: {type: :number, description: 'Something'},
|
62
96
|
# name: {type: string, description: 'Something'}
|
@@ -66,6 +100,10 @@ module RSpec
|
|
66
100
|
# property: {type: :string, description: 'Something'},
|
67
101
|
# ...
|
68
102
|
# }}
|
103
|
+
#
|
104
|
+
# @param fields [Hash] Parameters definitions
|
105
|
+
#
|
106
|
+
# @return [void]
|
69
107
|
def add_request_params(fields)
|
70
108
|
check_current_context :resource, :url, :method
|
71
109
|
|
@@ -75,11 +113,21 @@ module RSpec
|
|
75
113
|
params)
|
76
114
|
end
|
77
115
|
|
78
|
-
|
116
|
+
##
|
117
|
+
# Adds an action and sets `@current_url` and `@current_method`
|
118
|
+
#
|
119
|
+
# @param method [:get, :post, :put, :patch, delete] Method name
|
120
|
+
# @param url [String] Associated URL
|
121
|
+
# @param summary [String] What the route does for given method
|
122
|
+
# @param description [String] Longer description of this action
|
123
|
+
#
|
124
|
+
# @return [void]
|
125
|
+
def add_action(method, url, summary, description = '')
|
79
126
|
check_current_context :resource
|
80
127
|
|
81
128
|
Utils.deep_set(@resources, "#{@current_resource}.paths.#{url}.actions.#{method}",
|
82
|
-
description: description,
|
129
|
+
description: description || '',
|
130
|
+
summary: summary,
|
83
131
|
statuses: {},
|
84
132
|
params: {})
|
85
133
|
|
@@ -87,7 +135,15 @@ module RSpec
|
|
87
135
|
@current_method = method
|
88
136
|
end
|
89
137
|
|
90
|
-
|
138
|
+
##
|
139
|
+
# Adds a status code to metadata and sets `@current_code`
|
140
|
+
#
|
141
|
+
# @param status_code [Integer] The status code
|
142
|
+
# @param description [String] Code description
|
143
|
+
#
|
144
|
+
# @return [void]
|
145
|
+
#
|
146
|
+
# rubocop:disable Layout/LineLength
|
91
147
|
def add_status_code(status_code, description)
|
92
148
|
check_current_context :resource, :url, :method
|
93
149
|
|
@@ -97,8 +153,51 @@ module RSpec
|
|
97
153
|
example: { response: nil })
|
98
154
|
@current_code = status_code
|
99
155
|
end
|
100
|
-
# rubocop:enable
|
156
|
+
# rubocop:enable Layout/LineLength
|
157
|
+
|
158
|
+
##
|
159
|
+
# Gets the current example
|
160
|
+
#
|
161
|
+
# @return [Hash] Current example metadata
|
162
|
+
def current_example
|
163
|
+
# rubocop:disable Layout/LineLength
|
164
|
+
Utils.deep_get @resources,
|
165
|
+
"#{@current_resource}.paths.#{@current_url}.actions.#{@current_method}.statuses.#{@current_code}"
|
166
|
+
# rubocop:enable Layout/LineLength
|
167
|
+
end
|
101
168
|
|
169
|
+
##
|
170
|
+
# Adds expectations for current example
|
171
|
+
#
|
172
|
+
# @param one [Hash, nil] Entity definition
|
173
|
+
# @param many [Hash, nil] Entity definition
|
174
|
+
#
|
175
|
+
# @return [void]
|
176
|
+
def add_expectations(one, many)
|
177
|
+
check_current_context :resource, :url, :method, :code
|
178
|
+
none = !many && !one
|
179
|
+
|
180
|
+
# rubocop:disable Layout/LineLength
|
181
|
+
Utils.deep_set(@resources,
|
182
|
+
"#{@current_resource}.paths.#{@current_url}.actions.#{@current_method}.statuses.#{@current_code}.expectations",
|
183
|
+
{
|
184
|
+
one: one,
|
185
|
+
many: many,
|
186
|
+
none: none,
|
187
|
+
})
|
188
|
+
# rubocop:enable Layout/LineLength
|
189
|
+
end
|
190
|
+
|
191
|
+
##
|
192
|
+
# Adds a request example
|
193
|
+
#
|
194
|
+
# @param url [String, nil] Visited URL
|
195
|
+
# @param action [String, nil] HTTP verb
|
196
|
+
# @param status_code [Integer, nil] Status code
|
197
|
+
# @param response [String, nil] Response body
|
198
|
+
# @param path_params [Hash, nil] Used path parameterss
|
199
|
+
# @param params [Hash, nil] Used body parameters
|
200
|
+
#
|
102
201
|
# rubocop:disable Metrics/ParameterLists
|
103
202
|
def add_request_example(url: nil, action: nil, status_code: nil, response: nil, path_params: nil, params: nil)
|
104
203
|
resource = nil
|
@@ -116,6 +215,8 @@ module RSpec
|
|
116
215
|
end
|
117
216
|
# rubocop:enable Metrics/ParameterLists
|
118
217
|
|
218
|
+
##
|
219
|
+
# @return [Hash] Hash representation of the metadata
|
119
220
|
def to_h
|
120
221
|
{
|
121
222
|
resources: @resources,
|
@@ -125,25 +226,28 @@ module RSpec
|
|
125
226
|
|
126
227
|
private
|
127
228
|
|
128
|
-
|
129
|
-
|
229
|
+
##
|
230
|
+
# Checks for the definition of given scopes.
|
231
|
+
# This is useful to verify if all metadata is set for the current example
|
232
|
+
#
|
233
|
+
# @param scope [Symbol[]] List of scope to check for
|
234
|
+
#
|
235
|
+
# @return [Boolean]
|
236
|
+
def check_current_context(*scope) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
130
237
|
scope ||= []
|
131
|
-
if scope.include?(:resource)
|
132
|
-
|
133
|
-
|
134
|
-
if scope.include?(:
|
135
|
-
raise 'No action declared' unless @current_method
|
136
|
-
end
|
137
|
-
if scope.include?(:url)
|
138
|
-
raise 'No url declared' unless @current_url
|
139
|
-
end
|
140
|
-
if scope.include?(:code)
|
141
|
-
raise 'No status code declared' unless @current_code
|
142
|
-
end
|
238
|
+
raise 'No resource declared' if scope.include?(:resource) && !@current_resource
|
239
|
+
raise 'No action declared' if scope.include?(:method) && !@current_method
|
240
|
+
raise 'No url declared' if scope.include?(:url) && !@current_url
|
241
|
+
raise 'No status code declared' if scope.include?(:code) && !@current_code
|
143
242
|
end
|
144
243
|
|
145
|
-
|
146
|
-
|
244
|
+
##
|
245
|
+
# Checks if a given parameter is used in the URL (_path_) or querystring (query)
|
246
|
+
#
|
247
|
+
# @param url_chunks [String[]] Chunks of an url splitted on the query separator (`?`)
|
248
|
+
# @param name [Symbol] Name of the parameter
|
249
|
+
#
|
250
|
+
# @return [:path, :query]
|
147
251
|
def path_param_scope(url_chunks, name)
|
148
252
|
if /:#{name}/.match?(url_chunks[0])
|
149
253
|
:path
|
@@ -154,14 +258,21 @@ module RSpec
|
|
154
258
|
end
|
155
259
|
end
|
156
260
|
|
157
|
-
|
261
|
+
##
|
262
|
+
# Checks and complete a field definition
|
263
|
+
#
|
264
|
+
# @param fields [Hash] Fields definitions
|
265
|
+
#
|
266
|
+
# @return [Hash] Completed field definition
|
267
|
+
def organize_params(fields) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
158
268
|
out = { properties: {} }
|
159
269
|
required = []
|
270
|
+
allowed_types = %i[array object]
|
160
271
|
fields.each do |name, field|
|
161
|
-
allowed_type =
|
272
|
+
allowed_type = allowed_types.include?(field[:type]) || PARAM_TYPES.key?(field[:type])
|
162
273
|
raise "Field type not allowed: #{field[:type]}" unless allowed_type
|
163
274
|
|
164
|
-
required.push name.to_s if field[:required]
|
275
|
+
required.push name.to_s if field[:required] != false
|
165
276
|
|
166
277
|
out[:properties][name] = fill_request_param field
|
167
278
|
end
|
@@ -169,12 +280,18 @@ module RSpec
|
|
169
280
|
out
|
170
281
|
end
|
171
282
|
|
283
|
+
##
|
284
|
+
# Checks and completes a request parameter definition
|
285
|
+
#
|
286
|
+
# @param field [Hash] Parameter definition
|
287
|
+
#
|
288
|
+
# @return [Hash] Completed parameter
|
172
289
|
def fill_request_param(field)
|
173
|
-
if field[:type] == :object && field[:
|
174
|
-
organize_params field[:
|
290
|
+
if field[:type] == :object && field[:attributes]
|
291
|
+
organize_params field[:attributes]
|
175
292
|
else
|
176
293
|
properties = {
|
177
|
-
type: field[:type]
|
294
|
+
type: PARAM_TYPES[field[:type]][:type],
|
178
295
|
description: field[:description] || nil,
|
179
296
|
}
|
180
297
|
|