grape-swagger 0.21.0 → 0.22.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/.rubocop_todo.yml +1 -1
  4. data/CHANGELOG.md +24 -2
  5. data/Gemfile +5 -0
  6. data/README.md +105 -3
  7. data/example/api/endpoints.rb +16 -16
  8. data/lib/grape-swagger.rb +0 -1
  9. data/lib/grape-swagger/doc_methods.rb +1 -0
  10. data/lib/grape-swagger/doc_methods/data_type.rb +15 -3
  11. data/lib/grape-swagger/doc_methods/extensions.rb +16 -12
  12. data/lib/grape-swagger/doc_methods/move_params.rb +139 -94
  13. data/lib/grape-swagger/doc_methods/parse_params.rb +9 -7
  14. data/lib/grape-swagger/endpoint.rb +36 -17
  15. data/lib/grape-swagger/version.rb +1 -1
  16. data/spec/lib/data_type_spec.rb +24 -0
  17. data/spec/lib/endpoint_spec.rb +13 -0
  18. data/spec/lib/move_params_spec.rb +124 -116
  19. data/spec/support/model_parsers/entity_parser.rb +8 -2
  20. data/spec/support/model_parsers/mock_parser.rb +10 -0
  21. data/spec/support/model_parsers/representable_parser.rb +7 -0
  22. data/spec/support/the_paths_definitions.rb +1 -2
  23. data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +2 -1
  24. data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +1 -1
  25. data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +22 -1
  26. data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +4 -1
  27. data/spec/swagger_v2/api_swagger_v2_hash_and_array_spec.rb +60 -0
  28. data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +14 -9
  29. data/spec/swagger_v2/api_swagger_v2_hide_param_spec.rb +90 -0
  30. data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +185 -110
  31. data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +11 -13
  32. data/spec/swagger_v2/api_swagger_v2_response_spec.rb +5 -5
  33. data/spec/swagger_v2/endpoint_versioned_path_spec.rb +19 -18
  34. data/spec/swagger_v2/namespaced_api_spec.rb +20 -0
  35. data/spec/swagger_v2/param_multi_type_spec.rb +73 -0
  36. data/spec/swagger_v2/param_type_spec.rb +54 -27
  37. data/spec/swagger_v2/params_array_spec.rb +96 -6
  38. data/spec/swagger_v2/params_nested_spec.rb +2 -2
  39. metadata +9 -3
@@ -116,6 +116,11 @@ RSpec.shared_context 'entity swagger example' do
116
116
  expose :name, documentation: { type: String, desc: 'The name.' }
117
117
  expose :children, using: self, documentation: { type: 'RecursiveModel', is_array: true, desc: 'The child nodes.' }
118
118
  end
119
+
120
+ class DocumentedHashAndArrayModel < Grape::Entity
121
+ expose :raw_hash, documentation: { type: Hash, desc: 'Example Hash.', documentation: { in: 'body' } }
122
+ expose :raw_array, documentation: { type: Array, desc: 'Example Array', documentation: { in: 'body' } }
123
+ end
119
124
  end
120
125
  end
121
126
 
@@ -124,7 +129,8 @@ RSpec.shared_context 'entity swagger example' do
124
129
  'ApiError' => { 'type' => 'object', 'properties' => { 'code' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'status code' }, 'message' => { 'type' => 'string', 'description' => 'error message' } } },
125
130
  'ResponseItem' => { 'type' => 'object', 'properties' => { 'id' => { 'type' => 'integer', 'format' => 'int32' }, 'name' => { 'type' => 'string' } } },
126
131
  'UseResponse' => { 'type' => 'object', 'properties' => { 'description' => { 'type' => 'string' }, '$responses' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/ResponseItem' } } } },
127
- 'RecursiveModel' => { 'type' => 'object', 'properties' => { 'name' => { 'type' => 'string', 'description' => 'The name.' }, 'children' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/RecursiveModel' }, 'description' => 'The child nodes.' } } }
132
+ 'RecursiveModel' => { 'type' => 'object', 'properties' => { 'name' => { 'type' => 'string', 'description' => 'The name.' }, 'children' => { 'type' => 'array', 'items' => { '$ref' => '#/definitions/RecursiveModel' }, 'description' => 'The child nodes.' } } },
133
+ 'DocumentedHashAndArrayModel' => { 'type' => 'object', 'properties' => { 'raw_hash' => { 'type' => 'object', 'description' => 'Example Hash.' }, 'raw_array' => { 'type' => 'array', 'description' => 'Example Array' } } }
128
134
  }
129
135
  end
130
136
 
@@ -308,7 +314,7 @@ RSpec.shared_context 'entity swagger example' do
308
314
  'properties' => {
309
315
  'id' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'Identity of Something' },
310
316
  'text' => { 'type' => 'string', 'description' => 'Content of something.' },
311
- 'links' => { 'type' => 'link' },
317
+ 'links' => { 'type' => 'array', 'items' => { 'type' => 'link' } },
312
318
  'others' => { 'type' => 'text' }
313
319
  },
314
320
  'description' => 'This gets Things.'
@@ -52,6 +52,7 @@ RSpec.shared_context 'mock swagger example' do
52
52
  class ApiError < OpenStruct; end
53
53
  class SecondApiError < OpenStruct; end
54
54
  class RecursiveModel < OpenStruct; end
55
+ class DocumentedHashAndArrayModel < OpenStruct; end
55
56
  end
56
57
  end
57
58
 
@@ -83,6 +84,15 @@ RSpec.shared_context 'mock swagger example' do
83
84
  'description' => "it's a mock"
84
85
  }
85
86
  }
87
+ },
88
+ 'DocumentedHashAndArrayModel' => {
89
+ 'type' => 'object',
90
+ 'properties' => {
91
+ 'mock_data' => {
92
+ 'type' => 'string',
93
+ 'description' => "it's a mock"
94
+ }
95
+ }
86
96
  }
87
97
  }
88
98
  end
@@ -186,6 +186,13 @@ RSpec.shared_context 'representable swagger example' do
186
186
  property :name, documentation: { type: String, desc: 'The name.' }
187
187
  property :children, decorator: self, documentation: { type: 'RecursiveModel', is_array: true, desc: 'The child nodes.' }
188
188
  end
189
+
190
+ class DocumentedHashAndArrayModel < Representable::Decorator
191
+ include Representable::JSON
192
+
193
+ property :raw_hash, documentation: { type: Hash, desc: 'Example Hash.' }
194
+ property :raw_array, documentation: { type: Array, desc: 'Example Array' }
195
+ end
189
196
  end
190
197
  end
191
198
 
@@ -97,8 +97,7 @@ RSpec.shared_context 'the api paths/defs' do
97
97
  properties: {
98
98
  in_body_1: { type: 'integer', format: 'int32', description: 'in_body_1' },
99
99
  in_body_2: { type: 'string', description: 'in_body_2' },
100
- in_body_3: { type: 'string', description: 'in_body_3' },
101
- key: { type: 'integer', format: 'int32', readOnly: true }
100
+ in_body_3: { type: 'string', description: 'in_body_3' }
102
101
  },
103
102
  required: [:in_body_1]
104
103
  }
@@ -11,7 +11,8 @@ describe 'definitions/models' do
11
11
  add_swagger_documentation models: [
12
12
  ::Entities::UseResponse,
13
13
  ::Entities::ApiError,
14
- ::Entities::RecursiveModel
14
+ ::Entities::RecursiveModel,
15
+ ::Entities::DocumentedHashAndArrayModel
15
16
  ]
16
17
  end
17
18
  end
@@ -144,7 +144,7 @@ describe 'details' do
144
144
  specify do
145
145
  expect(subject['paths']['/use_gfm_rc_detail']['get']).to include('description')
146
146
  expect(subject['paths']['/use_gfm_rc_detail']['get']['description']).to eql(
147
- "<h1>This returns something</h1>\n\n<p># Burgers in Heaven</p>\n\n<blockquote>\n<p>A burger doesn&#39;t come for free</p>\n</blockquote>\n\n<p>If you want to reserve a burger in heaven, you have to do\nsome crazy stuff on earth.</p>\n<pre class=\"highlight plaintext\"><code>def do_good\nputs 'help people'\nend\n</code></pre>\n\n<ul>\n<li><em>Will go to Heaven:</em> Probably</li>\n<li><em>Will go to Hell:</em> Probably not</li>\n</ul>"
147
+ "<h1>This returns something</h1>\n\n<p># Burgers in Heaven</p>\n\n<blockquote>\n<p>A burger doesn&#39;t come for free</p>\n</blockquote>\n\n<p>If you want to reserve a burger in heaven, you have to do\nsome crazy stuff on earth.</p>\n<pre class=\"highlight plaintext\"><code>def do_good\nputs 'help people'\nend\n</code></pre>\n<ul>\n<li><em>Will go to Heaven:</em> Probably</li>\n<li><em>Will go to Hell:</em> Probably not</li>\n</ul>"
148
148
  )
149
149
  end
150
150
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'extension' do
3
+ describe 'extensions' do
4
4
  include_context "#{MODEL_PARSER} swagger example"
5
5
 
6
6
  before :all do
@@ -40,6 +40,14 @@ describe 'extension' do
40
40
 
41
41
  route_setting :x_def, [{ for: 422, other: 'stuff' }, { for: 200, some: 'stuff' }]
42
42
 
43
+ desc 'This returns something with extension on definition level',
44
+ success: Entities::OtherItem
45
+ get '/non_existend_status_definitions_extension' do
46
+ { 'declared_params' => declared(params) }
47
+ end
48
+
49
+ route_setting :x_def, [{ for: 422, other: 'stuff' }, { for: 200, some: 'stuff' }]
50
+
43
51
  desc 'This returns something with extension on definition level',
44
52
  success: Entities::OtherItem,
45
53
  failure: [{ code: 422, message: 'NotFound', model: Entities::SecondApiError }]
@@ -106,4 +114,17 @@ describe 'extension' do
106
114
  expect(subject['definitions']['SecondApiError']['x-other']).to eql 'stuff'
107
115
  end
108
116
  end
117
+
118
+ describe 'extension on definition level' do
119
+ subject do
120
+ get '/swagger_doc/non_existend_status_definitions_extension'
121
+ JSON.parse(last_response.body)
122
+ end
123
+
124
+ specify do
125
+ expect(subject['definitions'].length).to eql 1
126
+ expect(subject['definitions']['OtherItem']).to include 'x-some'
127
+ expect(subject['definitions']['OtherItem']['x-some']).to eql 'stuff'
128
+ end
129
+ end
109
130
  end
@@ -23,7 +23,8 @@ describe 'global configuration stuff' do
23
23
  base_path: -> { 'somewhere/over/the/rainbow' },
24
24
  mount_path: 'documentation',
25
25
  add_base_path: true,
26
- add_version: true
26
+ add_version: true,
27
+ security_definitions: { api_key: { foo: 'bar' } }
27
28
  end
28
29
  end
29
30
  end
@@ -44,6 +45,8 @@ describe 'global configuration stuff' do
44
45
  expect(subject['basePath']).to eql 'somewhere/over/the/rainbow'
45
46
  expect(subject['paths'].keys.first).to eql '/somewhere/over/the/rainbow/v3/configuration'
46
47
  expect(subject['schemes']).to eql ['https']
48
+ expect(subject['securityDefinitions'].keys).to include('api_key')
49
+ expect(subject['securityDefinitions']['api_key']).to include('foo' => 'bar')
47
50
  end
48
51
  end
49
52
  end
@@ -0,0 +1,60 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'document hash and array' do
4
+ include_context "#{MODEL_PARSER} swagger example"
5
+
6
+ before :all do
7
+ module TheApi
8
+ class TestApi < Grape::API
9
+ format :json
10
+
11
+ documentation = ::Entities::DocumentedHashAndArrayModel.documentation if ::Entities::DocumentedHashAndArrayModel.respond_to?(:documentation)
12
+
13
+ desc 'This returns something'
14
+ namespace :arbitrary do
15
+ params do
16
+ requires :id, type: Integer
17
+ end
18
+ route_param :id do
19
+ desc 'Timeless treasure'
20
+ params do
21
+ requires :body, using: documentation unless documentation.nil?
22
+ requires :raw_hash, type: Hash, documentation: { param_type: 'body' } if documentation.nil?
23
+ requires :raw_array, type: Array, documentation: { param_type: 'body' } if documentation.nil?
24
+ end
25
+ put '/id_and_hash' do
26
+ {}
27
+ end
28
+ end
29
+ end
30
+
31
+ add_swagger_documentation
32
+ end
33
+ end
34
+ end
35
+
36
+ def app
37
+ TheApi::TestApi
38
+ end
39
+
40
+ subject do
41
+ get '/swagger_doc'
42
+ JSON.parse(last_response.body)
43
+ end
44
+ describe 'generated request definition' do
45
+ it 'has hash' do
46
+ expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
47
+ expect(subject['definitions']['putArbitraryIdIdAndHash']['properties'].keys).to include('raw_hash')
48
+ end
49
+
50
+ it 'has array' do
51
+ expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
52
+ expect(subject['definitions']['putArbitraryIdIdAndHash']['properties'].keys).to include('raw_array')
53
+ end
54
+
55
+ it 'does not have the path parameter' do
56
+ expect(subject['definitions'].keys).to include('putArbitraryIdIdAndHash')
57
+ expect(subject['definitions']['putArbitraryIdIdAndHash']).to_not include('id')
58
+ end
59
+ end
60
+ end
@@ -18,6 +18,9 @@ describe 'headers' do
18
18
  },
19
19
 
20
20
  entity: Entities::UseResponse
21
+ params do
22
+ optional :param_x, type: String, desc: 'This is a parameter', documentation: { param_type: 'query' }
23
+ end
21
24
  get '/use_headers' do
22
25
  { 'declared_params' => declared(params) }
23
26
  end
@@ -37,15 +40,17 @@ describe 'headers' do
37
40
  end
38
41
 
39
42
  specify do
40
- expect(subject['paths']['/use_headers']['get']['parameters']).to eql(
41
- [
42
- { 'in' => 'header',
43
- 'name' => 'X-Rate-Limit-Limit',
44
- 'description' => 'The number of allowed requests in the current period',
45
- 'type' => 'integer',
46
- 'format' => 'int32',
47
- 'required' => false }
48
- ]
43
+ parameters = subject['paths']['/use_headers']['get']['parameters']
44
+ expect(parameters).to include(
45
+ 'in' => 'header',
46
+ 'name' => 'X-Rate-Limit-Limit',
47
+ 'description' => 'The number of allowed requests in the current period',
48
+ 'type' => 'integer',
49
+ 'format' => 'int32',
50
+ 'required' => false
49
51
  )
52
+ expect(parameters.size).to eq(2)
53
+ expect(parameters.first['in']).to eq('header')
54
+ expect(parameters.last['in']).to eq('query')
50
55
  end
51
56
  end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'hidden flag enables a single endpoint parameter to be excluded from the documentation' do
4
+ include_context "#{MODEL_PARSER} swagger example"
5
+ before :all do
6
+ module TheApi
7
+ class HideParamsApi < Grape::API
8
+ namespace :flat_params_endpoint do
9
+ desc 'This is a endpoint with a flat parameter hierarchy'
10
+ params do
11
+ requires :name, type: String, documentation: { desc: 'name' }
12
+ optional :favourite_color, type: String, documentation: { desc: 'I should not be anywhere', hidden: true }
13
+ optional :proc_param, type: String, documentation: { desc: 'I should not be anywhere', hidden: -> { true } }
14
+ end
15
+
16
+ post do
17
+ { 'declared_params' => declared(params) }
18
+ end
19
+ end
20
+
21
+ namespace :nested_params_endpoint do
22
+ desc 'This is a endpoint with a nested parameter hierarchy'
23
+ params do
24
+ optional :name, type: String, documentation: { desc: 'name' }
25
+ optional :hidden_attribute, type: Hash do
26
+ optional :favourite_color, type: String, documentation: { desc: 'I should not be anywhere', hidden: true }
27
+ end
28
+
29
+ optional :attributes, type: Hash do
30
+ optional :attribute_1, type: String, documentation: { desc: 'Attribute one' }
31
+ optional :hidden_attribute, type: String, documentation: { desc: 'I should not be anywhere', hidden: true }
32
+ end
33
+ end
34
+
35
+ post do
36
+ { 'declared_params' => declared(params) }
37
+ end
38
+ end
39
+
40
+ namespace :required_param_endpoint do
41
+ desc 'This endpoint has hidden defined for a required parameter'
42
+ params do
43
+ requires :name, type: String, documentation: { desc: 'name', hidden: true }
44
+ end
45
+
46
+ post do
47
+ { 'declared_params' => declared(params) }
48
+ end
49
+ end
50
+
51
+ add_swagger_documentation
52
+ end
53
+ end
54
+ end
55
+
56
+ let(:app) { TheApi::HideParamsApi }
57
+
58
+ describe 'simple flat parameter hierarchy' do
59
+ subject do
60
+ get '/swagger_doc/flat_params_endpoint'
61
+ JSON.parse(last_response.body)
62
+ end
63
+
64
+ specify do
65
+ expect(subject['paths']['/flat_params_endpoint']['post']['parameters'].map { |p| p['name'] }).not_to include('favourite_color', 'proc_param')
66
+ end
67
+ end
68
+
69
+ describe 'nested parameter hierarchy' do
70
+ subject do
71
+ get '/swagger_doc/nested_params_endpoint'
72
+ JSON.parse(last_response.body)
73
+ end
74
+
75
+ specify do
76
+ expect(subject['paths']['/nested_params_endpoint']['post']['parameters'].map { |p| p['name'] }).not_to include(/hidden_attribute/)
77
+ end
78
+ end
79
+
80
+ describe 'hidden defined for required parameter' do
81
+ subject do
82
+ get '/swagger_doc/required_param_endpoint'
83
+ JSON.parse(last_response.body)
84
+ end
85
+
86
+ specify do
87
+ expect(subject['paths']['/required_param_endpoint']['post']['parameters'].map { |p| p['name'] }).to include('name')
88
+ end
89
+ end
90
+ end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `header`' do
3
+ describe 'moving body/formData Params to definitions' do
4
4
  include_context "#{MODEL_PARSER} swagger example"
5
5
 
6
6
  before :all do
@@ -11,12 +11,14 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
11
11
  detail: 'more details description',
12
12
  success: Entities::UseNestedWithAddress
13
13
  params do
14
- requires :name, type: String, documentation: { desc: 'name', in: 'body' }
15
- optional :address, type: Hash do
16
- requires :street, type: String, documentation: { desc: 'street', in: 'body' }
17
- requires :postcode, type: String, documentation: { desc: 'postcode', in: 'body' }
18
- requires :city, type: String, documentation: { desc: 'city', in: 'body' }
19
- optional :country, type: String, documentation: { desc: 'country', in: 'body' }
14
+ optional :contact, type: Hash do
15
+ requires :name, type: String, documentation: { desc: 'name', in: 'body' }
16
+ optional :addresses, type: Array do
17
+ requires :street, type: String, documentation: { desc: 'street', in: 'body' }
18
+ requires :postcode, type: String, documentation: { desc: 'postcode', in: 'body' }
19
+ requires :city, type: String, documentation: { desc: 'city', in: 'body' }
20
+ optional :country, type: String, documentation: { desc: 'country', in: 'body' }
21
+ end
20
22
  end
21
23
  end
22
24
 
@@ -44,6 +46,30 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
44
46
  end
45
47
 
46
48
  namespace :multiple_nested_params do
49
+ desc 'put in body with multiple nested parameters',
50
+ success: Entities::UseNestedWithAddress
51
+ params do
52
+ optional :contact, type: Hash do
53
+ requires :name, type: String, documentation: { desc: 'name', in: 'body' }
54
+ optional :addresses, type: Array do
55
+ optional :street, type: String, documentation: { desc: 'street', in: 'body' }
56
+ requires :postcode, type: Integer, documentation: { desc: 'postcode', in: 'formData' }
57
+ optional :city, type: String, documentation: { desc: 'city', in: 'body' }
58
+ optional :country, type: String, documentation: { desc: 'country', in: 'body' }
59
+ end
60
+ optional :delivery_address, type: Hash do
61
+ optional :street, type: String, documentation: { desc: 'street', in: 'body' }
62
+ optional :postcode, type: String, documentation: { desc: 'postcode', in: 'formData' }
63
+ optional :city, type: String, documentation: { desc: 'city', in: 'body' }
64
+ optional :country, type: String, documentation: { desc: 'country', in: 'body' }
65
+ end
66
+ end
67
+ end
68
+
69
+ post '/in_body' do
70
+ { 'declared_params' => declared(params) }
71
+ end
72
+
47
73
  desc 'put in body with multiple nested parameters',
48
74
  success: Entities::UseNestedWithAddress
49
75
  params do
@@ -83,74 +109,73 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
83
109
  JSON.parse(last_response.body)
84
110
  end
85
111
 
86
- specify do
87
- expect(subject['paths']['/simple_nested_params/in_body']['post']['parameters']).to eql(
88
- [{
89
- 'name' => 'UseNestedWithAddress',
90
- 'in' => 'body',
91
- 'required' => true,
92
- 'schema' => { '$ref' => '#/definitions/postRequestUseNestedWithAddress' }
93
- }]
94
- )
95
- end
112
+ describe 'POST' do
113
+ specify do
114
+ expect(subject['paths']['/simple_nested_params/in_body']['post']['parameters']).to eql(
115
+ [
116
+ { 'name' => 'SimpleNestedParamsInBody', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/postSimpleNestedParamsInBody' } }
117
+ ]
118
+ )
119
+ end
96
120
 
97
- specify do
98
- expect(subject['definitions']['postRequestUseNestedWithAddress']).to eql(
99
- 'description' => "post in body with nested parameters\n more details description",
100
- 'type' => 'object',
101
- 'properties' => {
102
- 'address' => { '$ref' => '#/definitions/postRequestUseNestedWithAddressAddress' },
103
- 'name' => { 'type' => 'string', 'description' => 'name' }
104
- },
105
- 'required' => ['name']
106
- )
107
- expect(subject['definitions']['postRequestUseNestedWithAddressAddress']).to eql(
108
- 'description' => 'postRequestUseNestedWithAddress - address',
109
- 'type' => 'object',
110
- 'properties' => {
111
- 'street' => { 'type' => 'string', 'description' => 'street' },
112
- 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
113
- 'city' => { 'type' => 'string', 'description' => 'city' },
114
- 'country' => { 'type' => 'string', 'description' => 'country' }
115
- },
116
- 'required' => %w(street postcode city)
117
- )
121
+ specify do
122
+ expect(subject['definitions']['postSimpleNestedParamsInBody']).to eql(
123
+ 'type' => 'object',
124
+ 'properties' => {
125
+ 'contact' => {
126
+ 'type' => 'object',
127
+ 'properties' => {
128
+ 'name' => { 'type' => 'string', 'description' => 'name' },
129
+ 'addresses' => {
130
+ 'type' => 'array',
131
+ 'items' => {
132
+ 'type' => 'object',
133
+ 'properties' => {
134
+ 'street' => { 'type' => 'string', 'description' => 'street' },
135
+ 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
136
+ 'city' => { 'type' => 'string', 'description' => 'city' },
137
+ 'country' => { 'type' => 'string', 'description' => 'country' }
138
+ },
139
+ 'required' => %w(street postcode city)
140
+ }
141
+ }
142
+ },
143
+ 'required' => %w(name)
144
+ }
145
+ },
146
+ 'description' => 'post in body with nested parameters'
147
+ )
148
+ end
118
149
  end
119
150
 
120
- specify do
121
- expect(subject['paths']['/simple_nested_params/in_body/{id}']['put']['parameters']).to eql(
122
- [
123
- { 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true },
124
- {
125
- 'name' => 'UseNestedWithAddress',
126
- 'in' => 'body',
127
- 'required' => true,
128
- 'schema' => { '$ref' => '#/definitions/putRequestUseNestedWithAddress' }
129
- }
130
- ]
131
- )
132
- end
151
+ describe 'PUT' do
152
+ specify do
153
+ expect(subject['paths']['/simple_nested_params/in_body/{id}']['put']['parameters']).to eql(
154
+ [
155
+ { 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true },
156
+ { 'name' => 'SimpleNestedParamsInBody', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/putSimpleNestedParamsInBody' } }
157
+ ]
158
+ )
159
+ end
133
160
 
134
- specify do
135
- expect(subject['definitions']['putRequestUseNestedWithAddress']).to eql(
136
- 'description' => "put in body with nested parameters\n more details description",
137
- 'type' => 'object',
138
- 'properties' => {
139
- 'address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressAddress' },
140
- 'id' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
141
- 'name' => { 'type' => 'string', 'description' => 'name' }
142
- }
143
- )
144
- expect(subject['definitions']['putRequestUseNestedWithAddressAddress']).to eql(
145
- 'description' => 'putRequestUseNestedWithAddress - address',
146
- 'type' => 'object',
147
- 'properties' => {
148
- 'street' => { 'type' => 'string', 'description' => 'street' },
149
- 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
150
- 'city' => { 'type' => 'string', 'description' => 'city' },
151
- 'country' => { 'type' => 'string', 'description' => 'country' }
152
- }
153
- )
161
+ specify do
162
+ expect(subject['definitions']['putSimpleNestedParamsInBody']).to eql(
163
+ 'type' => 'object',
164
+ 'properties' => {
165
+ 'name' => { 'type' => 'string', 'description' => 'name' },
166
+ 'address' => {
167
+ 'type' => 'object',
168
+ 'properties' => {
169
+ 'street' => { 'type' => 'string', 'description' => 'street' },
170
+ 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
171
+ 'city' => { 'type' => 'string', 'description' => 'city' },
172
+ 'country' => { 'type' => 'string', 'description' => 'country' }
173
+ }
174
+ }
175
+ },
176
+ 'description' => 'put in body with nested parameters'
177
+ )
178
+ end
154
179
  end
155
180
  end
156
181
 
@@ -160,47 +185,97 @@ describe 'setting of param type, such as `query`, `path`, `formData`, `body`, `h
160
185
  JSON.parse(last_response.body)
161
186
  end
162
187
 
163
- specify do
164
- expect(subject['paths']['/multiple_nested_params/in_body/{id}']['put']['parameters']).to eql(
165
- [
166
- { 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true },
167
- { 'name' => 'UseNestedWithAddress', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/putRequestUseNestedWithAddress' } }
168
- ]
169
- )
188
+ describe 'POST' do
189
+ specify do
190
+ expect(subject['paths']['/multiple_nested_params/in_body']['post']['parameters']).to eql(
191
+ [
192
+ {
193
+ 'name' => 'MultipleNestedParamsInBody',
194
+ 'in' => 'body',
195
+ 'required' => true,
196
+ 'schema' => { '$ref' => '#/definitions/postMultipleNestedParamsInBody' }
197
+ }
198
+ ]
199
+ )
200
+ end
201
+
202
+ specify do
203
+ expect(subject['definitions']['postMultipleNestedParamsInBody']).to eql(
204
+ 'type' => 'object',
205
+ 'properties' => {
206
+ 'contact' => {
207
+ 'type' => 'object',
208
+ 'properties' => {
209
+ 'name' => { 'type' => 'string', 'description' => 'name' },
210
+ 'addresses' => {
211
+ 'type' => 'array',
212
+ 'items' => {
213
+ 'type' => 'object',
214
+ 'properties' => {
215
+ 'street' => { 'type' => 'string', 'description' => 'street' },
216
+ 'postcode' => { 'type' => 'integer', 'format' => 'int32', 'description' => 'postcode' },
217
+ 'city' => { 'type' => 'string', 'description' => 'city' },
218
+ 'country' => { 'type' => 'string', 'description' => 'country' }
219
+ },
220
+ 'required' => ['postcode']
221
+ }
222
+ },
223
+ 'delivery_address' => {
224
+ 'type' => 'object',
225
+ 'properties' => {
226
+ 'street' => { 'type' => 'string', 'description' => 'street' },
227
+ 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
228
+ 'city' => { 'type' => 'string', 'description' => 'city' },
229
+ 'country' => { 'type' => 'string', 'description' => 'country' }
230
+ }
231
+ }
232
+ },
233
+ 'required' => %w(name)
234
+ }
235
+ },
236
+ 'description' => 'put in body with multiple nested parameters'
237
+ )
238
+ end
170
239
  end
171
240
 
172
- specify do
173
- expect(subject['definitions']['putRequestUseNestedWithAddress']).to eql(
174
- 'description' => 'put in body with multiple nested parameters',
175
- 'type' => 'object',
176
- 'properties' => {
177
- 'address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressAddress' },
178
- 'delivery_address' => { '$ref' => '#/definitions/putRequestUseNestedWithAddressDeliveryAddress' },
179
- 'id' => { 'type' => 'integer', 'format' => 'int32', 'readOnly' => true },
180
- 'name' => { 'type' => 'string', 'description' => 'name' }
181
- }
182
- )
183
- expect(subject['definitions']['putRequestUseNestedWithAddressAddress']).to eql(
184
- 'description' => 'putRequestUseNestedWithAddress - address',
185
- 'type' => 'object',
186
- 'properties' => {
187
- 'street' => { 'type' => 'string', 'description' => 'street' },
188
- 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
189
- 'city' => { 'type' => 'string', 'description' => 'city' },
190
- 'country' => { 'type' => 'string', 'description' => 'country' }
191
- },
192
- 'required' => ['postcode']
193
- )
194
- expect(subject['definitions']['putRequestUseNestedWithAddressDeliveryAddress']).to eql(
195
- 'description' => 'putRequestUseNestedWithAddress - delivery_address',
196
- 'type' => 'object',
197
- 'properties' => {
198
- 'street' => { 'type' => 'string', 'description' => 'street' },
199
- 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
200
- 'city' => { 'type' => 'string', 'description' => 'city' },
201
- 'country' => { 'type' => 'string', 'description' => 'country' }
202
- }
203
- )
241
+ describe 'PUT' do
242
+ specify do
243
+ expect(subject['paths']['/multiple_nested_params/in_body/{id}']['put']['parameters']).to eql(
244
+ [
245
+ { 'in' => 'path', 'name' => 'id', 'type' => 'integer', 'format' => 'int32', 'required' => true },
246
+ { 'name' => 'MultipleNestedParamsInBody', 'in' => 'body', 'required' => true, 'schema' => { '$ref' => '#/definitions/putMultipleNestedParamsInBody' } }
247
+ ]
248
+ )
249
+ end
250
+
251
+ specify do
252
+ expect(subject['definitions']['putMultipleNestedParamsInBody']).to eql(
253
+ 'type' => 'object',
254
+ 'properties' => {
255
+ 'name' => { 'type' => 'string', 'description' => 'name' },
256
+ 'address' => {
257
+ 'type' => 'object',
258
+ 'properties' => {
259
+ 'street' => { 'type' => 'string', 'description' => 'street' },
260
+ 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
261
+ 'city' => { 'type' => 'string', 'description' => 'city' },
262
+ 'country' => { 'type' => 'string', 'description' => 'country' }
263
+ },
264
+ 'required' => ['postcode']
265
+ },
266
+ 'delivery_address' => {
267
+ 'type' => 'object',
268
+ 'properties' => {
269
+ 'street' => { 'type' => 'string', 'description' => 'street' },
270
+ 'postcode' => { 'type' => 'string', 'description' => 'postcode' },
271
+ 'city' => { 'type' => 'string', 'description' => 'city' },
272
+ 'country' => { 'type' => 'string', 'description' => 'country' }
273
+ }
274
+ }
275
+ },
276
+ 'description' => 'put in body with multiple nested parameters'
277
+ )
278
+ end
204
279
  end
205
280
  end
206
281
  end