grape-swagger 0.7.2 → 0.8.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 (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.rubocop.yml +36 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.travis.yml +3 -0
  7. data/CHANGELOG.md +90 -0
  8. data/CONTRIBUTING.md +126 -0
  9. data/Gemfile +1 -21
  10. data/LICENSE.txt +1 -1
  11. data/README.md +397 -0
  12. data/RELEASING.md +80 -0
  13. data/Rakefile +6 -23
  14. data/UPGRADING.md +47 -0
  15. data/grape-swagger.gemspec +26 -84
  16. data/lib/grape-swagger.rb +237 -111
  17. data/lib/grape-swagger/errors.rb +9 -0
  18. data/lib/grape-swagger/markdown.rb +23 -0
  19. data/lib/grape-swagger/markdown/kramdown_adapter.rb +37 -0
  20. data/lib/grape-swagger/markdown/redcarpet_adapter.rb +89 -0
  21. data/lib/grape-swagger/version.rb +3 -0
  22. data/spec/api_description_spec.rb +41 -0
  23. data/spec/api_global_models_spec.rb +76 -0
  24. data/spec/api_models_spec.rb +190 -93
  25. data/spec/default_api_spec.rb +31 -36
  26. data/spec/form_params_spec.rb +56 -53
  27. data/spec/grape-swagger_helper_spec.rb +88 -49
  28. data/spec/grape-swagger_spec.rb +7 -5
  29. data/spec/hide_api_spec.rb +58 -55
  30. data/spec/markdown/kramdown_adapter_spec.rb +38 -0
  31. data/spec/markdown/markdown_spec.rb +27 -0
  32. data/spec/markdown/redcarpet_adapter_spec.rb +81 -0
  33. data/spec/namespaced_api_spec.rb +47 -0
  34. data/spec/non_default_api_spec.rb +372 -222
  35. data/spec/response_model_spec.rb +80 -0
  36. data/spec/simple_mounted_api_spec.rb +113 -118
  37. data/spec/spec_helper.rb +0 -1
  38. data/spec/version_spec.rb +8 -0
  39. data/test/api.rb +62 -0
  40. data/test/config.ru +10 -2
  41. data/test/splines.png +0 -0
  42. metadata +145 -91
  43. data/.rvmrc +0 -48
  44. data/CHANGELOG.markdown +0 -55
  45. data/Gemfile.lock +0 -94
  46. data/README.markdown +0 -168
  47. data/VERSION +0 -1
  48. data/test/nested_api.rb +0 -30
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'responseModel' do
4
+ before :all do
5
+ module MyAPI
6
+ module Entities
7
+ class BaseEntity < Grape::Entity
8
+ def self.entity_name
9
+ name.sub(/^MyAPI::Entities::/, '')
10
+ end
11
+ end
12
+
13
+ class Something < BaseEntity
14
+ expose :text, documentation: { type: 'string', desc: 'Content of something.' }
15
+ end
16
+
17
+ class Error < BaseEntity
18
+ expose :code, documentation: { type: 'string', desc: 'Error code' }
19
+ expose :message, documentation: { type: 'string', desc: 'Error message' }
20
+ end
21
+ end
22
+
23
+ class ResponseModelApi < Grape::API
24
+ format :json
25
+ desc 'This returns something or an error',
26
+ entity: Entities::Something,
27
+ http_codes: [
28
+ [200, 'OK', Entities::Something],
29
+ [403, 'Refused to return something', Entities::Error]
30
+ ]
31
+
32
+ get '/something/:id' do
33
+ if params[:id] == 1
34
+ something = OpenStruct.new text: 'something'
35
+ present something, with: Entities::Something
36
+ else
37
+ error = OpenStruct.new code: 'some_error', message: 'Some error'
38
+ present error, with: Entities::Error
39
+ end
40
+ end
41
+
42
+ add_swagger_documentation
43
+ end
44
+ end
45
+ end
46
+
47
+ def app
48
+ MyAPI::ResponseModelApi
49
+ end
50
+
51
+ subject do
52
+ get '/swagger_doc/something'
53
+ JSON.parse(last_response.body)
54
+ end
55
+
56
+ it 'should document specified models' do
57
+ expect(subject['apis'][0]['operations'][0]['responseMessages']).to eq(
58
+ [
59
+ {
60
+ 'code' => 200,
61
+ 'message' => 'OK',
62
+ 'responseModel' => 'Something'
63
+ },
64
+ {
65
+ 'code' => 403,
66
+ 'message' => 'Refused to return something',
67
+ 'responseModel' => 'Error'
68
+ }
69
+ ]
70
+ )
71
+ expect(subject['models'].keys).to include 'Error'
72
+ expect(subject['models']['Error']).to eq(
73
+ 'id' => 'Error',
74
+ 'properties' => {
75
+ 'code' => { 'type' => 'string', 'description' => 'Error code' },
76
+ 'message' => { 'type' => 'string', 'description' => 'Error message' }
77
+ }
78
+ )
79
+ end
80
+ end
@@ -1,58 +1,56 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "a simple mounted api" do
3
+ describe 'a simple mounted api' do
4
4
  before :all do
5
5
  class CustomType; end
6
6
 
7
7
  class SimpleMountedApi < Grape::API
8
- desc "Document root"
8
+ desc 'Document root'
9
9
  get do
10
10
  end
11
11
 
12
- desc 'This gets something.', {
13
- :notes => '_test_'
14
- }
12
+ desc 'This gets something.',
13
+ notes: '_test_'
15
14
 
16
15
  get '/simple' do
17
16
  { bla: 'something' }
18
17
  end
19
18
 
20
- desc 'This gets something for URL using - separator.', {
21
- :notes => '_test_'
22
- }
19
+ desc 'This gets something for URL using - separator.',
20
+ notes: '_test_'
23
21
 
24
22
  get '/simple-test' do
25
23
  { bla: 'something' }
26
24
  end
27
25
 
28
- desc 'this gets something else', {
29
- :headers => {
30
- "XAuthToken" => { description: "A required header.", required: true },
31
- "XOtherHeader" => { description: "An optional header.", required: false }
32
- },
33
- :http_codes => {
34
- 403 => "invalid pony",
35
- 405 => "no ponies left!"
36
- }
37
- }
26
+ desc 'this gets something else',
27
+ headers: {
28
+ 'XAuthToken' => { description: 'A required header.', required: true },
29
+ 'XOtherHeader' => { description: 'An optional header.', required: false }
30
+ },
31
+ http_codes: {
32
+ 403 => 'invalid pony',
33
+ 405 => 'no ponies left!'
34
+ }
35
+
38
36
  get '/simple_with_headers' do
39
- {:bla => 'something_else'}
37
+ { bla: 'something_else' }
40
38
  end
41
39
 
42
- desc 'this takes an array of parameters', {
43
- :params => {
44
- "items[]" => { description: "array of items" }
45
- }
46
- }
40
+ desc 'this takes an array of parameters',
41
+ params: {
42
+ 'items[]' => { description: 'array of items' }
43
+ }
44
+
47
45
  post '/items' do
48
46
  {}
49
47
  end
50
48
 
51
- desc 'this uses a custom parameter', {
52
- :params => {
53
- "custom" => { type: CustomType, description: "array of items" }
54
- }
55
- }
49
+ desc 'this uses a custom parameter',
50
+ params: {
51
+ 'custom' => { type: CustomType, description: 'array of items' }
52
+ }
53
+
56
54
  get '/custom' do
57
55
  {}
58
56
  end
@@ -64,126 +62,123 @@ describe "a simple mounted api" do
64
62
  end
65
63
  end
66
64
 
67
- def app; SimpleApi end
65
+ def app
66
+ SimpleApi
67
+ end
68
68
 
69
- it "retrieves swagger-documentation on /swagger_doc" do
69
+ it 'retrieves swagger-documentation on /swagger_doc' do
70
70
  get '/swagger_doc.json'
71
- JSON.parse(last_response.body).should == {
72
- "apiVersion" => "0.1",
73
- "swaggerVersion" => "1.2",
74
- "basePath" => "http://example.org",
75
- "info" => {},
76
- "produces" => ["application/xml", "application/json", "text/plain"],
77
- "operations" => [],
78
- "apis" => [
79
- { "path" => "/swagger_doc/simple.{format}" },
80
- { "path" => "/swagger_doc/simple-test.{format}" },
81
- { "path" => "/swagger_doc/simple_with_headers.{format}" },
82
- { "path" => "/swagger_doc/items.{format}" },
83
- { "path" => "/swagger_doc/custom.{format}" },
84
- { "path" => "/swagger_doc/swagger_doc.{format}" }
71
+ expect(JSON.parse(last_response.body)).to eq(
72
+ 'apiVersion' => '0.1',
73
+ 'swaggerVersion' => '1.2',
74
+ 'info' => {},
75
+ 'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
76
+ 'apis' => [
77
+ { 'path' => '/simple.{format}', 'description' => 'Operations about simples' },
78
+ { 'path' => '/simple-test.{format}', 'description' => 'Operations about simple-tests' },
79
+ { 'path' => '/simple_with_headers.{format}', 'description' => 'Operations about simple_with_headers' },
80
+ { 'path' => '/items.{format}', 'description' => 'Operations about items' },
81
+ { 'path' => '/custom.{format}', 'description' => 'Operations about customs' },
82
+ { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
85
83
  ]
86
- }
84
+ )
87
85
  end
88
86
 
89
- it "retrieves the documentation for mounted-api" do
87
+ it 'retrieves the documentation for mounted-api' do
90
88
  get '/swagger_doc/simple.json'
91
- JSON.parse(last_response.body).should == {
92
- "apiVersion" => "0.1",
93
- "swaggerVersion" => "1.2",
94
- "basePath" => "http://example.org",
95
- "resourcePath" => "",
96
- "apis" => [{
97
- "path" => "/simple.{format}",
98
- "operations" => [{
99
- "produces" => ["application/xml", "application/json", "text/plain"],
100
- "notes" => "_test_",
101
- "summary" => "This gets something.",
102
- "nickname" => "GET-simple---format-",
103
- "httpMethod" => "GET",
104
- "parameters" => []
89
+ expect(JSON.parse(last_response.body)).to eq(
90
+ 'apiVersion' => '0.1',
91
+ 'swaggerVersion' => '1.2',
92
+ 'basePath' => 'http://example.org',
93
+ 'resourcePath' => '/simple',
94
+ 'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
95
+ 'apis' => [{
96
+ 'path' => '/simple.{format}',
97
+ 'operations' => [{
98
+ 'notes' => '_test_',
99
+ 'summary' => 'This gets something.',
100
+ 'nickname' => 'GET-simple---format-',
101
+ 'method' => 'GET',
102
+ 'parameters' => [],
103
+ 'type' => 'void'
105
104
  }]
106
105
  }]
107
- }
106
+ )
108
107
  end
109
108
 
110
- context "retrieves the documentation for mounted-api that" do
109
+ context 'retrieves the documentation for mounted-api that' do
111
110
  it "contains '-' in URL" do
112
111
  get '/swagger_doc/simple-test.json'
113
- JSON.parse(last_response.body).should == {
114
- "apiVersion" => "0.1",
115
- "swaggerVersion" => "1.2",
116
- "basePath" => "http://example.org",
117
- "resourcePath" => "",
118
- "apis" => [{
119
- "path" => "/simple-test.{format}",
120
- "operations" => [{
121
- "produces" => ["application/xml", "application/json", "text/plain"],
122
- "notes" => "_test_",
123
- "summary" => "This gets something for URL using - separator.",
124
- "nickname" => "GET-simple-test---format-",
125
- "httpMethod" => "GET",
126
- "parameters" => []
112
+ expect(JSON.parse(last_response.body)).to eq(
113
+ 'apiVersion' => '0.1',
114
+ 'swaggerVersion' => '1.2',
115
+ 'basePath' => 'http://example.org',
116
+ 'resourcePath' => '/simple-test',
117
+ 'produces' => ['application/xml', 'application/json', 'application/vnd.api+json', 'text/plain'],
118
+ 'apis' => [{
119
+ 'path' => '/simple-test.{format}',
120
+ 'operations' => [{
121
+ 'notes' => '_test_',
122
+ 'summary' => 'This gets something for URL using - separator.',
123
+ 'nickname' => 'GET-simple-test---format-',
124
+ 'method' => 'GET',
125
+ 'parameters' => [],
126
+ 'type' => 'void'
127
127
  }]
128
128
  }]
129
- }
129
+ )
130
130
  end
131
131
 
132
- it "includes headers" do
132
+ it 'includes headers' do
133
133
  get '/swagger_doc/simple_with_headers.json'
134
- JSON.parse(last_response.body)["apis"].should == [{
135
- "path" => "/simple_with_headers.{format}",
136
- "operations" => [{
137
- "produces" => ["application/xml", "application/json", "text/plain"],
138
- "notes" => nil,
139
- "notes" => "",
140
- "summary" => "this gets something else",
141
- "nickname" => "GET-simple_with_headers---format-",
142
- "httpMethod" => "GET",
143
- "parameters" => [
144
- { "paramType" => "header", "name" => "XAuthToken", "description" => "A required header.", "type" => "String", "dataType" => "String", "required" => true },
145
- { "paramType" => "header", "name" => "XOtherHeader", "description" => "An optional header.", "type" => "String", "dataType" => "String", "required" => false }
134
+ expect(JSON.parse(last_response.body)['apis']).to eq [{
135
+ 'path' => '/simple_with_headers.{format}',
136
+ 'operations' => [{
137
+ 'notes' => '',
138
+ 'summary' => 'this gets something else',
139
+ 'nickname' => 'GET-simple_with_headers---format-',
140
+ 'method' => 'GET',
141
+ 'parameters' => [
142
+ { 'paramType' => 'header', 'name' => 'XAuthToken', 'description' => 'A required header.', 'type' => 'String', 'required' => true },
143
+ { 'paramType' => 'header', 'name' => 'XOtherHeader', 'description' => 'An optional header.', 'type' => 'String', 'required' => false }
146
144
  ],
147
- "responseMessages" => [
148
- { "code" => 403, "message" => "invalid pony" },
149
- { "code" => 405, "message" => "no ponies left!" }
145
+ 'type' => 'void',
146
+ 'responseMessages' => [
147
+ { 'code' => 403, 'message' => 'invalid pony' },
148
+ { 'code' => 405, 'message' => 'no ponies left!' }
150
149
  ]
151
150
  }]
152
151
  }]
153
152
  end
154
153
 
155
- it "supports multiple parameters" do
154
+ it 'supports multiple parameters' do
156
155
  get '/swagger_doc/items.json'
157
- JSON.parse(last_response.body)["apis"].should == [{
158
- "path" => "/items.{format}",
159
- "operations" => [{
160
- "produces" => ["application/xml", "application/json", "text/plain"],
161
- "notes" => nil,
162
- "notes" => "",
163
- "summary" => "this takes an array of parameters",
164
- "nickname" => "POST-items---format-",
165
- "httpMethod" => "POST",
166
- "parameters" => [ { "paramType" => "form", "name" => "items[]", "description" => "array of items", "type" => "String", "dataType" => "String", "required" => false } ]
156
+ expect(JSON.parse(last_response.body)['apis']).to eq [{
157
+ 'path' => '/items.{format}',
158
+ 'operations' => [{
159
+ 'notes' => '',
160
+ 'summary' => 'this takes an array of parameters',
161
+ 'nickname' => 'POST-items---format-',
162
+ 'method' => 'POST',
163
+ 'parameters' => [{ 'paramType' => 'form', 'name' => 'items[]', 'description' => 'array of items', 'type' => 'string', 'required' => false, 'allowMultiple' => false }],
164
+ 'type' => 'void'
167
165
  }]
168
166
  }]
169
167
  end
170
168
 
171
- it "supports custom types" do
169
+ it 'supports custom types' do
172
170
  get '/swagger_doc/custom.json'
173
- JSON.parse(last_response.body)["apis"].should == [{
174
- "path" => "/custom.{format}",
175
- "operations" => [{
176
- "produces" => ["application/xml", "application/json", "text/plain"],
177
- "notes" => nil,
178
- "notes" => "",
179
- "summary" => "this uses a custom parameter",
180
- "nickname" => "GET-custom---format-",
181
- "httpMethod" => "GET",
182
- "parameters" => [ { "paramType" => "query", "name" => "custom", "description" => "array of items", "type" => "CustomType", "dataType" => "CustomType", "required" => false } ]
171
+ expect(JSON.parse(last_response.body)['apis']).to eq [{
172
+ 'path' => '/custom.{format}',
173
+ 'operations' => [{
174
+ 'notes' => '',
175
+ 'summary' => 'this uses a custom parameter',
176
+ 'nickname' => 'GET-custom---format-',
177
+ 'method' => 'GET',
178
+ 'parameters' => [{ 'paramType' => 'query', 'name' => 'custom', 'description' => 'array of items', 'type' => 'CustomType', 'required' => false, 'allowMultiple' => false }],
179
+ 'type' => 'void'
183
180
  }]
184
181
  }]
185
182
  end
186
-
187
183
  end
188
-
189
184
  end
data/spec/spec_helper.rb CHANGED
@@ -9,7 +9,6 @@ require 'grape-entity'
9
9
  require 'rubygems'
10
10
  require 'bundler'
11
11
 
12
- require 'pry'
13
12
  require 'json'
14
13
 
15
14
  Bundler.setup :default, :test
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe GrapeSwagger do
4
+ it '#version' do
5
+ expect(GrapeSwagger::VERSION).to_not be_nil
6
+ expect(GrapeSwagger::VERSION.split('.').count).to eq 3
7
+ end
8
+ end
data/test/api.rb ADDED
@@ -0,0 +1,62 @@
1
+ require 'grape'
2
+ require '../lib/grape-swagger'
3
+
4
+ @@splines = {}
5
+
6
+ class Api < Grape::API
7
+ format :json
8
+
9
+ desc 'API Root'
10
+ get do
11
+ { splines_url: '/splines' }
12
+ end
13
+
14
+ namespace :splines do
15
+ desc 'Return a spline.'
16
+ params do
17
+ requires :id, type: Integer, desc: 'Spline id.'
18
+ end
19
+ get ':id' do
20
+ @@splines[params[:id]] || error!('Not Found', 404)
21
+ end
22
+
23
+ desc 'Update a spline.'
24
+ params do
25
+ requires :id, type: Integer, desc: 'Spline id.'
26
+ optional :reticulated, type: Boolean, default: true, desc: 'True if the spline is reticulated.'
27
+ end
28
+ put ':id' do
29
+ spline = (@@splines[params[:id]] || error!('Not Found', 404))
30
+ spline[:reticulated] = params[:reticulated]
31
+ spline
32
+ end
33
+
34
+ desc 'Create a spline.'
35
+ params do
36
+ optional :reticulated, type: Boolean, default: true, desc: 'True if the spline is reticulated.'
37
+ end
38
+ post do
39
+ spline = { id: @@splines.size + 1, reticulated: params[:reticulated] }
40
+ @@splines[@@splines.size + 1] = spline
41
+ spline
42
+ end
43
+
44
+ desc 'Return all splines.'
45
+ get do
46
+ @@splines.values
47
+ end
48
+
49
+ # TEST api for testing uploading
50
+ # curl --form file=@splines.png http://localhost:9292/splines/upload
51
+ desc 'Update image'
52
+ post 'upload' do
53
+ filename = params[:file][:filename]
54
+ content_type 'application/octet-stream'
55
+ env['api.format'] = :binary # there's no formatter for :binary, data will be returned "as is"
56
+ header 'Content-Disposition', "attachment; filename*=UTF-8''#{URI.escape(filename)}"
57
+ params[:file][:tempfile].read
58
+ end
59
+ end
60
+
61
+ add_swagger_documentation
62
+ end