grape-swagger 0.11.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +8 -1
  3. data/.rubocop.yml +3 -0
  4. data/.rubocop_todo.yml +14 -22
  5. data/.travis.yml +7 -4
  6. data/CHANGELOG.md +53 -26
  7. data/Gemfile +1 -1
  8. data/README.md +414 -327
  9. data/RELEASING.md +3 -4
  10. data/example/api/endpoints.rb +132 -0
  11. data/example/api/entities.rb +18 -0
  12. data/example/config.ru +36 -2
  13. data/example/example_requests.postman_collection +146 -0
  14. data/example/swagger-example.png +0 -0
  15. data/grape-swagger.gemspec +9 -6
  16. data/lib/grape-swagger.rb +69 -99
  17. data/lib/grape-swagger/doc_methods.rb +69 -544
  18. data/lib/grape-swagger/doc_methods/data_type.rb +77 -0
  19. data/lib/grape-swagger/doc_methods/extensions.rb +75 -0
  20. data/lib/grape-swagger/doc_methods/move_params.rb +153 -0
  21. data/lib/grape-swagger/doc_methods/operation_id.rb +27 -0
  22. data/lib/grape-swagger/doc_methods/optional_object.rb +15 -0
  23. data/lib/grape-swagger/doc_methods/parse_params.rb +113 -0
  24. data/lib/grape-swagger/doc_methods/path_string.rb +29 -0
  25. data/lib/grape-swagger/doc_methods/produces_consumes.rb +12 -0
  26. data/lib/grape-swagger/doc_methods/status_codes.rb +17 -0
  27. data/lib/grape-swagger/doc_methods/tag_name_description.rb +26 -0
  28. data/lib/grape-swagger/endpoint.rb +317 -0
  29. data/lib/grape-swagger/version.rb +1 -1
  30. data/spec/lib/data_type_spec.rb +57 -0
  31. data/spec/lib/endpoint_spec.rb +6 -0
  32. data/spec/lib/extensions_spec.rb +127 -0
  33. data/spec/lib/move_params_spec.rb +298 -0
  34. data/spec/lib/operation_id_spec.rb +24 -0
  35. data/spec/lib/optional_object_spec.rb +40 -0
  36. data/spec/lib/path_string_spec.rb +38 -0
  37. data/spec/lib/produces_consumes_spec.rb +98 -0
  38. data/spec/markdown/kramdown_adapter_spec.rb +2 -9
  39. data/spec/markdown/redcarpet_adapter_spec.rb +2 -16
  40. data/spec/spec_helper.rb +7 -13
  41. data/spec/support/api_swagger_v2_result.rb +204 -0
  42. data/spec/support/namespace_tags.rb +73 -0
  43. data/spec/support/the_api_entities.rb +52 -0
  44. data/spec/support/the_paths_definitions.rb +94 -0
  45. data/spec/swagger_v2/api_swagger_v2_definitions-models_spec.rb +32 -0
  46. data/spec/swagger_v2/api_swagger_v2_detail_spec.rb +151 -0
  47. data/spec/swagger_v2/api_swagger_v2_extensions_spec.rb +109 -0
  48. data/spec/swagger_v2/api_swagger_v2_format-content_type_spec.rb +124 -0
  49. data/spec/swagger_v2/api_swagger_v2_global_configuration_spec.rb +51 -0
  50. data/spec/swagger_v2/api_swagger_v2_headers_spec.rb +44 -0
  51. data/spec/swagger_v2/api_swagger_v2_hide_documentation_path_spec.rb +56 -0
  52. data/spec/swagger_v2/api_swagger_v2_mounted_spec.rb +146 -0
  53. data/spec/swagger_v2/api_swagger_v2_param_type_body_nested_spec.rb +197 -0
  54. data/spec/swagger_v2/api_swagger_v2_param_type_body_spec.rb +151 -0
  55. data/spec/swagger_v2/api_swagger_v2_param_type_spec.rb +217 -0
  56. data/spec/swagger_v2/api_swagger_v2_request_params_fix_spec.rb +64 -0
  57. data/spec/swagger_v2/api_swagger_v2_response_spec.rb +184 -0
  58. data/spec/swagger_v2/api_swagger_v2_spec.rb +207 -0
  59. data/spec/swagger_v2/api_swagger_v2_type-format_spec.rb +121 -0
  60. data/spec/{boolean_params_spec.rb → swagger_v2/boolean_params_spec.rb} +2 -2
  61. data/spec/{default_api_spec.rb → swagger_v2/default_api_spec.rb} +40 -36
  62. data/spec/swagger_v2/description_not_initialized.rb +39 -0
  63. data/spec/{float_api_spec.rb → swagger_v2/float_api_spec.rb} +2 -2
  64. data/spec/{form_params_spec.rb → swagger_v2/form_params_spec.rb} +9 -9
  65. data/spec/{grape-swagger_spec.rb → swagger_v2/grape-swagger_spec.rb} +0 -0
  66. data/spec/swagger_v2/hide_api_spec.rb +131 -0
  67. data/spec/swagger_v2/mounted_target_class_spec.rb +76 -0
  68. data/spec/swagger_v2/namespace_tags_prefix_spec.rb +84 -0
  69. data/spec/swagger_v2/namespace_tags_spec.rb +76 -0
  70. data/spec/{namespaced_api_spec.rb → swagger_v2/namespaced_api_spec.rb} +6 -26
  71. data/spec/{param_type_spec.rb → swagger_v2/param_type_spec.rb} +10 -8
  72. data/spec/{param_values_spec.rb → swagger_v2/param_values_spec.rb} +52 -22
  73. data/spec/swagger_v2/params_array_spec.rb +63 -0
  74. data/spec/swagger_v2/params_hash_spec.rb +65 -0
  75. data/spec/swagger_v2/params_nested_spec.rb +63 -0
  76. data/spec/{reference_entity.rb → swagger_v2/reference_entity.rb} +18 -23
  77. data/spec/swagger_v2/response_model_spec.rb +212 -0
  78. data/spec/swagger_v2/simple_mounted_api_spec.rb +264 -0
  79. metadata +175 -90
  80. data/example/api.rb +0 -66
  81. data/lib/grape-swagger/markdown.rb +0 -23
  82. data/spec/api_description_spec.rb +0 -43
  83. data/spec/api_global_models_spec.rb +0 -77
  84. data/spec/api_models_spec.rb +0 -364
  85. data/spec/api_paths_spec.rb +0 -128
  86. data/spec/api_root_spec.rb +0 -30
  87. data/spec/api_with_nil_types.rb +0 -50
  88. data/spec/api_with_path_versioning_spec.rb +0 -33
  89. data/spec/api_with_prefix_and_namespace_spec.rb +0 -32
  90. data/spec/api_with_standalone_namespace_spec.rb +0 -215
  91. data/spec/array_entity_spec.rb +0 -34
  92. data/spec/array_params_spec.rb +0 -85
  93. data/spec/grape-swagger_helper_spec.rb +0 -152
  94. data/spec/group_params_spec.rb +0 -31
  95. data/spec/hash_params_spec.rb +0 -30
  96. data/spec/hide_api_spec.rb +0 -124
  97. data/spec/i18n_spec.rb +0 -364
  98. data/spec/markdown/markdown_spec.rb +0 -27
  99. data/spec/mounted_target_class_spec.rb +0 -63
  100. data/spec/mutually_exclusive_spec.rb +0 -36
  101. data/spec/non_default_api_spec.rb +0 -733
  102. data/spec/response_model_spec.rb +0 -121
  103. data/spec/simple_mounted_api_spec.rb +0 -213
  104. data/spec/support/i18n_helper.rb +0 -8
@@ -0,0 +1,73 @@
1
+ RSpec.shared_context "namespace example" do
2
+ before :all do
3
+ module TheApi
4
+
5
+ class CustomType; end
6
+
7
+ class NamespaceApi < Grape::API
8
+
9
+ namespace :hudson do
10
+ desc 'Document root'
11
+ get '/' do
12
+ end
13
+ end
14
+
15
+ namespace :colorado do
16
+ desc 'This gets something.',
17
+ notes: '_test_'
18
+
19
+ get '/simple' do
20
+ { bla: 'something' }
21
+ end
22
+ end
23
+
24
+ namespace :colorado do
25
+ desc 'This gets something for URL using - separator.',
26
+ notes: '_test_'
27
+
28
+ get '/simple-test' do
29
+ { bla: 'something' }
30
+ end
31
+ end
32
+
33
+ namespace :thames do
34
+ desc 'this gets something else',
35
+ headers: {
36
+ 'XAuthToken' => { description: 'A required header.', required: true },
37
+ 'XOtherHeader' => { description: 'An optional header.', required: false }
38
+ },
39
+ http_codes: [
40
+ { code: 403, message: 'invalid pony' },
41
+ { code: 405, message: 'no ponies left!' }
42
+ ]
43
+
44
+ get '/simple_with_headers' do
45
+ { bla: 'something_else' }
46
+ end
47
+ end
48
+
49
+ namespace :niles do
50
+ desc 'this takes an array of parameters',
51
+ params: {
52
+ 'items[]' => { description: 'array of items', is_array: true }
53
+ }
54
+
55
+ post '/items' do
56
+ {}
57
+ end
58
+ end
59
+
60
+ namespace :niles do
61
+ desc 'this uses a custom parameter',
62
+ params: {
63
+ 'custom' => { type: CustomType, description: 'array of items', is_array: true }
64
+ }
65
+
66
+ get '/custom' do
67
+ {}
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,52 @@
1
+ RSpec.shared_context "the api entities" do
2
+ before :all do
3
+ module TheApi
4
+ module Entities
5
+ class ApiError < Grape::Entity
6
+ expose :code, documentation: { type: Integer }
7
+ expose :message, documentation: { type: String }
8
+ end
9
+
10
+ class SecondApiError < Grape::Entity
11
+ expose :code, documentation: { type: Integer }
12
+ expose :severity, documentation: { type: String }
13
+ expose :message, documentation: { type: String }
14
+ end
15
+
16
+ class ResponseItem < Grape::Entity
17
+ expose :id, documentation: { type: Integer }
18
+ expose :name, documentation: { type: String }
19
+ end
20
+
21
+ class OtherItem < Grape::Entity
22
+ expose :key, documentation: { type: Integer }
23
+ expose :symbol, documentation: { type: String }
24
+ end
25
+
26
+ class UseResponse < Grape::Entity
27
+ expose :description, documentation: { type: String }
28
+ expose :items, as: '$responses', using: Entities::ResponseItem, documentation: { is_array: true }
29
+ end
30
+
31
+ class UseItemResponseAsType < Grape::Entity
32
+ expose :description, documentation: { type: String }
33
+ expose :responses, documentation: { type: Entities::ResponseItem, is_array: false }
34
+ end
35
+
36
+ class UseAddress < Grape::Entity
37
+ expose :street, documentation: { type: String, desc: 'street' }
38
+ expose :postcode, documentation: { type: String, desc: 'postcode' }
39
+ expose :city, documentation: { type: String, desc: 'city' }
40
+ expose :country, documentation: { type: String, desc: 'country' }
41
+ end
42
+
43
+ class UseNestedWithAddress < Grape::Entity
44
+ expose :name, documentation: { type: String }
45
+ expose :address, using: Entities::UseAddress
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+
52
+ end
@@ -0,0 +1,94 @@
1
+ RSpec.shared_context "the api paths/defs" do
2
+ let(:paths) {{
3
+ "/in_body" => {
4
+ post: {
5
+ produces: ["application/json"],
6
+ consumes: ["application/json"],
7
+ parameters: [
8
+ {in: "body", name: "in_body_1", description: "in_body_1", type: "integer", format: "int32", required: true},
9
+ {in: "body", name: "in_body_2", description: "in_body_2", type: "string", required: false},
10
+ {in: "body", name: "in_body_3", description: "in_body_3", type: "string", required: false}
11
+ ],
12
+ responses: {201 => {description: "post in body /wo entity", schema: {"$ref" => "#/definitions/InBody"}}},
13
+ tags: ["in_body"],
14
+ operationId: "postInBody"
15
+ },
16
+ get: {
17
+ produces: ["application/json"],
18
+ responses: {200 => {description: "get in path /wo entity", schema: {"$ref" => "#/definitions/InBody"}}},
19
+ tags: ["in_body"],
20
+ operationId: "getInBody"
21
+ }
22
+ },
23
+ "/in_body/{key}" => {
24
+ put: {
25
+ produces: ["application/json"],
26
+ consumes: ["application/json"],
27
+ parameters: [
28
+ {in: "path", name: "key", description: nil, type: "integer", format: "int32", required: true},
29
+ {in: "body", name: "in_body_1", description: "in_body_1", type: "integer", format: "int32", required: true},
30
+ {in: "body", name: "in_body_2", description: "in_body_2", type: "string", required: false},
31
+ {in: "body", name: "in_body_3", description: "in_body_3", type: "string", required: false}
32
+ ],
33
+ responses: {200 => {description: "put in body /wo entity", schema: {"$ref" => "#/definitions/InBody"}}},
34
+ tags: ["in_body"],
35
+ operationId: "putInBodyKey"
36
+ },
37
+ get: {
38
+ produces: ["application/json"],
39
+ parameters: [
40
+ {in: "path", name: "key", description: nil, type: "integer", format: "int32", required: true}
41
+ ],
42
+ responses: {200 => {description: "get in path /wo entity", schema: {"$ref" => "#/definitions/InBody"}}},
43
+ tags: ["in_body"],
44
+ operationId: "getInBodyKey"
45
+ }}
46
+ }}
47
+
48
+ let(:found_path) {{
49
+ post: {
50
+ produces: ["application/json"],
51
+ consumes: ["application/json"],
52
+ parameters: [
53
+ {in: "body", name: "in_body_1", description: "in_body_1", type: "integer", format: "int32", required: true},
54
+ {in: "body", name: "in_body_2", description: "in_body_2", type: "string", required: false},
55
+ {in: "body", name: "in_body_3", description: "in_body_3", type: "string", required: false}
56
+ ],
57
+ responses: {201 => {description: "post in body /wo entity", schema: {"$ref"=>"#/definitions/InBody"}}},
58
+ tags: ["in_body"],
59
+ operationId: "postInBody"
60
+ }}}
61
+
62
+ let(:definitions) {{
63
+ "InBody" => {
64
+ type: "object",
65
+ properties: {
66
+ in_body_1: {type: "integer", format: "int32"},
67
+ in_body_2: {type: "string"},
68
+ in_body_3: {type: "string"},
69
+ key: {type: "integer", format: "int32"}
70
+ }}}}
71
+
72
+ let(:expected_post_defs) {{
73
+ type: "object",
74
+ properties: {
75
+ in_body_1: {type: "integer", format: "int32", description: "in_body_1"},
76
+ in_body_2: {type: "string", description: "in_body_2"},
77
+ in_body_3: {type: "string", description: "in_body_3"}
78
+ },
79
+ :required=>[:in_body_1]
80
+ }}
81
+
82
+ let(:expected_put_defs) {{
83
+ type: "object",
84
+ properties: {
85
+ in_body_1: {type: "integer", format: "int32", description: "in_body_1"},
86
+ in_body_2: {type: "string", description: "in_body_2"},
87
+ in_body_3: {type: "string", description: "in_body_3"},
88
+ key: {type: "integer", format: "int32", readOnly: true}
89
+ },
90
+ :required=>[:in_body_1]
91
+ }}
92
+
93
+ let(:expected_path) {[]}
94
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'definitions/models' do
4
+ include_context "the api entities"
5
+
6
+ before :all do
7
+ module TheApi
8
+ class ModelApi < Grape::API
9
+ format :json
10
+
11
+ add_swagger_documentation models: [
12
+ TheApi::Entities::UseResponse,
13
+ TheApi::Entities::ApiError
14
+ ]
15
+ end
16
+ end
17
+ end
18
+
19
+ def app
20
+ TheApi::ModelApi
21
+ end
22
+
23
+ subject do
24
+ get '/swagger_doc'
25
+ JSON.parse(last_response.body)
26
+ end
27
+
28
+ specify do
29
+ expect(subject).to include 'definitions'
30
+ expect(subject['definitions']).to include 'ResponseItem', 'UseResponse', 'ApiError'
31
+ end
32
+ end
@@ -0,0 +1,151 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'spec_helper'
4
+
5
+ def details
6
+ <<-DETAILS
7
+ # Burgers in Heaven
8
+
9
+ > A burger doesn't come for free
10
+
11
+ If you want to reserve a burger in heaven, you have to do
12
+ some crazy stuff on earth.
13
+
14
+ ```
15
+ def do_good
16
+ puts 'help people'
17
+ end
18
+ ```
19
+
20
+ * _Will go to Heaven:_ Probably
21
+ * _Will go to Hell:_ Probably not
22
+ DETAILS
23
+ end
24
+
25
+ describe 'details' do
26
+ describe "take deatils as it is" do
27
+ include_context "the api entities"
28
+
29
+ before :all do
30
+ module TheApi
31
+ class DetailApi < Grape::API
32
+ format :json
33
+
34
+ desc 'This returns something',
35
+ detail: 'detailed description of the route',
36
+ entity: Entities::UseResponse,
37
+ failure: [{code: 400, model: Entities::ApiError}]
38
+ get '/use_detail' do
39
+ { "declared_params" => declared(params) }
40
+ end
41
+
42
+ desc 'This returns something' do
43
+ detail 'detailed description of the route inside the `desc` block'
44
+ entity Entities::UseResponse
45
+ failure [{code: 400, model: Entities::ApiError}]
46
+ end
47
+ get '/use_detail_block' do
48
+ { "declared_params" => declared(params) }
49
+ end
50
+
51
+ add_swagger_documentation
52
+ end
53
+ end
54
+ end
55
+
56
+ def app
57
+ TheApi::DetailApi
58
+ end
59
+
60
+ subject do
61
+ get '/swagger_doc'
62
+ JSON.parse(last_response.body)
63
+ end
64
+
65
+ specify do
66
+ expect(subject['paths']['/use_detail']['get']).to include('description')
67
+ expect(subject['paths']['/use_detail']['get']['description']).to eql "This returns something\n detailed description of the route"
68
+ end
69
+
70
+ specify do
71
+ expect(subject['paths']['/use_detail_block']['get']).to include('description')
72
+ expect(subject['paths']['/use_detail_block']['get']['description']).to eql "This returns something\n detailed description of the route inside the `desc` block"
73
+ end
74
+ end
75
+
76
+ describe 'details, convert markdown with kramdown' do
77
+ include_context "the api entities"
78
+
79
+ before :all do
80
+ module TheApi
81
+ class GfmDetailApi < Grape::API
82
+ format :json
83
+
84
+ desc 'This returns something',
85
+ detail: details,
86
+ entity: Entities::UseResponse,
87
+ failure: [{code: 400, model: Entities::ApiError}]
88
+ get '/use_gfm_detail' do
89
+ { "declared_params" => declared(params) }
90
+ end
91
+
92
+ add_swagger_documentation markdown: GrapeSwagger::Markdown::KramdownAdapter.new
93
+ end
94
+ end
95
+ end
96
+
97
+ def app
98
+ TheApi::GfmDetailApi
99
+ end
100
+
101
+ subject do
102
+ get '/swagger_doc'
103
+ JSON.parse(last_response.body)
104
+ end
105
+
106
+ specify do
107
+ expect(subject['paths']['/use_gfm_detail']['get']).to include('description')
108
+ expect(subject['paths']['/use_gfm_detail']['get']['description']).to eql(
109
+ "<h1 id=\"this-returns-something\">This returns something</h1>\n<p># Burgers in Heaven</p>\n\n<blockquote>\n <p>A burger doesn’t come for free</p>\n</blockquote>\n\n<p>If you want to reserve a burger in heaven, you have to do<br />\nsome crazy stuff on earth.</p>\n\n<pre><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>"
110
+ )
111
+ end
112
+ end
113
+
114
+ describe 'details, convert markdown with redcarpet', unless: RUBY_PLATFORM.eql?('java') do
115
+ include_context "the api entities"
116
+
117
+ before :all do
118
+ module TheApi
119
+ class GfmRcDetailApi < Grape::API
120
+ format :json
121
+
122
+ desc 'This returns something',
123
+ detail: details,
124
+ entity: Entities::UseResponse,
125
+ failure: [{code: 400, model: Entities::ApiError}]
126
+ get '/use_gfm_rc_detail' do
127
+ { "declared_params" => declared(params) }
128
+ end
129
+
130
+ add_swagger_documentation markdown: GrapeSwagger::Markdown::RedcarpetAdapter.new
131
+ end
132
+ end
133
+ end
134
+
135
+ def app
136
+ TheApi::GfmRcDetailApi
137
+ end
138
+
139
+ subject do
140
+ get '/swagger_doc'
141
+ JSON.parse(last_response.body)
142
+ end
143
+
144
+ specify do
145
+ expect(subject['paths']['/use_gfm_rc_detail']['get']).to include('description')
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>"
148
+ )
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,109 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'extension' do
4
+ include_context "the api entities"
5
+
6
+ before :all do
7
+ module TheApi
8
+ class ExtensionsApi < Grape::API
9
+ format :json
10
+
11
+ route_setting :x_path, { some: 'stuff' }
12
+
13
+ desc 'This returns something with extension on path level',
14
+ params: Entities::UseResponse.documentation,
15
+ failure: [{code: 400, message: 'NotFound', model: Entities::ApiError}]
16
+ get '/path_extension' do
17
+ { "declared_params" => declared(params) }
18
+ end
19
+
20
+ desc 'This returns something with extension on verb level',
21
+ params: Entities::UseResponse.documentation,
22
+ failure: [{code: 400, message: 'NotFound', model: Entities::ApiError}],
23
+ x: { some: 'stuff' }
24
+ params do
25
+ requires :id, type: Integer
26
+ end
27
+ get '/verb_extension' do
28
+ { "declared_params" => declared(params) }
29
+ end
30
+
31
+ route_setting :x_def, { for: 200, some: 'stuff' }
32
+
33
+ desc 'This returns something with extension on definition level',
34
+ params: Entities::ResponseItem.documentation,
35
+ success: Entities::ResponseItem,
36
+ failure: [{code: 400, message: 'NotFound', model: Entities::ApiError}]
37
+ get '/definitions_extension' do
38
+ { "declared_params" => declared(params) }
39
+ end
40
+
41
+ route_setting :x_def, [{ for: 422, other: 'stuff' }, { for: 200, some: 'stuff' }]
42
+
43
+ desc 'This returns something with extension on definition level',
44
+ success: Entities::OtherItem,
45
+ failure: [{code: 422, message: 'NotFound', model: Entities::SecondApiError}]
46
+ get '/multiple_definitions_extension' do
47
+ { "declared_params" => declared(params) }
48
+ end
49
+
50
+ add_swagger_documentation
51
+ end
52
+ end
53
+ end
54
+
55
+ def app
56
+ TheApi::ExtensionsApi
57
+ end
58
+
59
+ describe "extension on path level" do
60
+ subject do
61
+ get '/swagger_doc/path_extension'
62
+ JSON.parse(last_response.body)
63
+ end
64
+
65
+ specify do
66
+ expect(subject['paths']['/path_extension']).to include 'x-some'
67
+ expect(subject['paths']['/path_extension']['x-some']).to eql 'stuff'
68
+ end
69
+ end
70
+
71
+ describe "extension on verb level" do
72
+ subject do
73
+ get '/swagger_doc/verb_extension'
74
+ JSON.parse(last_response.body)
75
+ end
76
+
77
+ specify do
78
+ expect(subject['paths']['/verb_extension']['get']).to include 'x-some'
79
+ expect(subject['paths']['/verb_extension']['get']['x-some']).to eql 'stuff'
80
+ end
81
+ end
82
+
83
+ describe "extension on definition level" do
84
+ subject do
85
+ get '/swagger_doc/definitions_extension'
86
+ JSON.parse(last_response.body)
87
+ end
88
+
89
+ specify do
90
+ expect(subject['definitions']['ResponseItem']).to include 'x-some'
91
+ expect(subject['definitions']['ResponseItem']['x-some']).to eql 'stuff'
92
+ expect(subject['definitions']['ApiError']).not_to include 'x-some'
93
+ end
94
+ end
95
+
96
+ describe "extension on definition level" do
97
+ subject do
98
+ get '/swagger_doc/multiple_definitions_extension'
99
+ JSON.parse(last_response.body)
100
+ end
101
+
102
+ specify do
103
+ expect(subject['definitions']['OtherItem']).to include 'x-some'
104
+ expect(subject['definitions']['OtherItem']['x-some']).to eql 'stuff'
105
+ expect(subject['definitions']['SecondApiError']).to include 'x-other'
106
+ expect(subject['definitions']['SecondApiError']['x-other']).to eql 'stuff'
107
+ end
108
+ end
109
+ end