grape-swagger 0.21.0 → 0.22.0

Sign up to get free protection for your applications and to get access to all the features.
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