grape-swagger 0.7.2 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,10 +1,9 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Default API" do
4
-
3
+ describe 'Default API' do
5
4
  context 'with no additional options' do
6
- before :all do
7
- class NotAMountedApi < Grape::API
5
+ def app
6
+ Class.new(Grape::API) do
8
7
  format :json
9
8
  desc 'This gets something.'
10
9
  get '/something' do
@@ -14,37 +13,36 @@ describe "Default API" do
14
13
  end
15
14
  end
16
15
 
17
- def app; NotAMountedApi; end
18
-
19
- it "should document something" do
16
+ subject do
20
17
  get '/swagger_doc'
21
- JSON.parse(last_response.body).should == {
22
- "apiVersion" => "0.1",
23
- "swaggerVersion" => "1.2",
24
- "basePath" => "http://example.org",
25
- "info" => {},
26
- "produces" => ["application/json"],
27
- "operations" => [],
28
- "apis" => [
29
- { "path" => "/swagger_doc/something.{format}" },
30
- { "path" => "/swagger_doc/swagger_doc.{format}" }
18
+ JSON.parse(last_response.body)
19
+ end
20
+
21
+ it 'documents api' do
22
+ expect(subject).to eq(
23
+ 'apiVersion' => '0.1',
24
+ 'swaggerVersion' => '1.2',
25
+ 'info' => {},
26
+ 'produces' => ['application/json'],
27
+ 'apis' => [
28
+ { 'path' => '/something.{format}', 'description' => 'Operations about somethings' },
29
+ { 'path' => '/swagger_doc.{format}', 'description' => 'Operations about swagger_docs' }
31
30
  ]
32
- }
31
+ )
33
32
  end
34
-
35
- context "path inside the apis array" do
36
- it "should start with a forward slash" do
37
- get '/swagger_doc'
38
- JSON.parse(last_response.body)['apis'].each do |api|
39
- api['path'].should start_with "/"
33
+
34
+ context 'path inside the apis array' do
35
+ it 'starts with a forward slash' do
36
+ subject['apis'].each do |api|
37
+ expect(api['path']).to start_with '/'
40
38
  end
41
39
  end
42
40
  end
43
41
  end
44
42
 
45
- context 'with API info' do
46
- before :all do
47
- class ApiInfoTest < Grape::API
43
+ context 'with additional info' do
44
+ def app
45
+ Class.new(Grape::API) do
48
46
  format :json
49
47
  add_swagger_documentation info: {
50
48
  title: 'My API Title',
@@ -55,20 +53,18 @@ describe "Default API" do
55
53
  contact: 'support@test.com'
56
54
  }
57
55
  end
58
- get '/swagger_doc'
59
56
  end
60
57
 
61
- def app; ApiInfoTest; end
62
-
63
58
  subject do
59
+ get '/swagger_doc'
64
60
  JSON.parse(last_response.body)['info']
65
61
  end
66
62
 
67
- it 'should document API title' do
63
+ it 'documents API title' do
68
64
  expect(subject['title']).to eql('My API Title')
69
65
  end
70
66
 
71
- it 'should document API description' do
67
+ it 'documents API description' do
72
68
  expect(subject['description']).to eql('A description of my API')
73
69
  end
74
70
 
@@ -76,17 +72,16 @@ describe "Default API" do
76
72
  expect(subject['license']).to eql('Apache 2')
77
73
  end
78
74
 
79
- it 'should document the license url' do
75
+ it 'documents the license url' do
80
76
  expect(subject['licenseUrl']).to eql('http://test.com')
81
77
  end
82
78
 
83
- it 'should document the terms of service url' do
79
+ it 'documents the terms of service url' do
84
80
  expect(subject['termsOfServiceUrl']).to eql('http://terms.com')
85
81
  end
86
82
 
87
- it 'should document the contact email' do
83
+ it 'documents the contact email' do
88
84
  expect(subject['contact']).to eql('support@test.com')
89
85
  end
90
86
  end
91
-
92
87
  end
@@ -1,29 +1,30 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "Form Params" do
4
-
5
- before :all do
6
- class FormParamApi < Grape::API
3
+ describe 'Form Params' do
4
+ def app
5
+ Class.new(Grape::API) do
7
6
  format :json
8
7
 
9
8
  params do
10
- requires :name, type: String, desc: "name of item"
9
+ requires :name, type: String, desc: 'name of item'
11
10
  end
12
11
  post '/items' do
13
12
  {}
14
13
  end
15
14
 
16
15
  params do
17
- requires :id, type: Integer, desc: "id of item"
18
- requires :name, type: String, desc: "name of item"
16
+ requires :id, type: Integer, desc: 'id of item'
17
+ requires :name, type: String, desc: 'name of item'
18
+ requires :conditions, type: Integer, desc: 'conditions of item', values: [1, 2, 3]
19
19
  end
20
20
  put '/items/:id' do
21
21
  {}
22
22
  end
23
23
 
24
24
  params do
25
- requires :id, type: Integer, desc: "id of item"
26
- requires :name, type: String, desc: "name of item"
25
+ requires :id, type: Integer, desc: 'id of item'
26
+ requires :name, type: String, desc: 'name of item'
27
+ optional :conditions, type: String, desc: 'conditions of item', values: proc { %w(1 2) }
27
28
  end
28
29
  patch '/items/:id' do
29
30
  {}
@@ -33,51 +34,53 @@ describe "Form Params" do
33
34
  end
34
35
  end
35
36
 
36
- def app; FormParamApi; end
37
-
38
- it "retrieves the documentation form params" do
37
+ subject do
39
38
  get '/swagger_doc/items.json'
39
+ JSON.parse(last_response.body)
40
+ end
40
41
 
41
- JSON.parse(last_response.body).should == {
42
- "apiVersion" => "0.1",
43
- "swaggerVersion" => "1.2",
44
- "resourcePath" => "",
45
- "basePath"=>"http://example.org",
46
- "apis" => [
47
- {
48
- "path" => "/items.{format}",
49
- "operations" => [
50
- {
51
- "produces" => ["application/json"],
52
- "notes" => "",
53
- "summary" => "",
54
- "nickname" => "POST-items---format-",
55
- "httpMethod" => "POST",
56
- "parameters" => [ { "paramType" => "form", "name" => "name", "description" => "name of item", "type" => "String", "dataType" => "String", "required" => true } ]
57
- }
58
- ]
59
- }, {
60
- "path" => "/items/{id}.{format}",
61
- "operations" => [
62
- {
63
- "produces" => ["application/json"],
64
- "notes" => "",
65
- "summary" => "",
66
- "nickname" => "PUT-items--id---format-",
67
- "httpMethod" => "PUT",
68
- "parameters" => [ { "paramType" => "path", "name" => "id", "description" => "id of item", "type" => "Integer", "dataType" => "Integer", "required" => true }, { "paramType" => "form", "name" => "name", "description" => "name of item", "type" => "String", "dataType" => "String", "required" => true } ]
69
- },
70
- {
71
- "produces" => ["application/json"],
72
- "notes" => "",
73
- "summary" => "",
74
- "nickname" => "PATCH-items--id---format-",
75
- "httpMethod" => "PATCH",
76
- "parameters" => [ { "paramType" => "path", "name" => "id", "description" => "id of item", "type" => "Integer", "dataType" => "Integer", "required" => true }, { "paramType" => "form", "name" => "name", "description" => "name of item", "type" => "String", "dataType" => "String", "required" => true } ]
77
- }
78
- ]
79
- }
80
- ]
81
- }
42
+ it 'retrieves the documentation form params' do
43
+ expect(subject['apis']).to eq([
44
+ {
45
+ 'path' => '/items.{format}',
46
+ 'operations' => [
47
+ {
48
+ 'notes' => '',
49
+ 'summary' => '',
50
+ 'nickname' => 'POST-items---format-',
51
+ 'method' => 'POST',
52
+ 'parameters' => [{ 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false }],
53
+ 'type' => 'void'
54
+ }
55
+ ]
56
+ }, {
57
+ 'path' => '/items/{id}.{format}',
58
+ 'operations' => [
59
+ {
60
+ 'notes' => '',
61
+ 'summary' => '',
62
+ 'nickname' => 'PUT-items--id---format-',
63
+ 'method' => 'PUT',
64
+ 'parameters' => [
65
+ { 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
66
+ { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
67
+ { 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32', 'enum' => [1, 2, 3] }
68
+ ],
69
+ 'type' => 'void'
70
+ },
71
+ {
72
+ 'notes' => '',
73
+ 'summary' => '',
74
+ 'nickname' => 'PATCH-items--id---format-',
75
+ 'method' => 'PATCH',
76
+ 'parameters' => [
77
+ { 'paramType' => 'path', 'name' => 'id', 'description' => 'id of item', 'type' => 'integer', 'required' => true, 'allowMultiple' => false, 'format' => 'int32' },
78
+ { 'paramType' => 'form', 'name' => 'name', 'description' => 'name of item', 'type' => 'string', 'required' => true, 'allowMultiple' => false },
79
+ { 'paramType' => 'form', 'name' => 'conditions', 'description' => 'conditions of item', 'type' => 'string', 'required' => false, 'allowMultiple' => false, 'enum' => %w(1 2) }
80
+ ],
81
+ 'type' => 'void'
82
+ }
83
+ ]
84
+ }])
82
85
  end
83
86
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe "helpers" do
3
+ describe 'helpers' do
4
4
 
5
5
  before :all do
6
6
  class HelperTestAPI < Grape::API
@@ -8,98 +8,137 @@ describe "helpers" do
8
8
  end
9
9
  end
10
10
 
11
- before :each do
12
- @api = Object.new
11
+ subject do
12
+ api = Object.new
13
13
 
14
14
  # after injecting grape-swagger into the Test API we get the helper methods
15
15
  # back from the first endpoint's class (the API mounted by grape-swagger
16
16
  # to serve the swagger_doc
17
17
 
18
- @api.extend HelperTestAPI.endpoints.first.options[:app].helpers
18
+ api.extend HelperTestAPI.endpoints.first.options[:app].helpers
19
+ api
19
20
  end
20
21
 
21
- context "parsing parameters" do
22
- it "parses params as query strings for a GET" do
22
+ context 'parsing parameters' do
23
+ it 'parses params as query strings for a GET' do
23
24
  params = {
24
- name: { type: 'String', desc: "A name", required: true, defaultValue: 'default' },
25
+ name: { type: 'String', desc: 'A name', required: true, default: 'default' },
25
26
  level: 'max'
26
27
  }
27
- path = "/coolness"
28
- method = "GET"
29
- @api.parse_params(params, path, method).should == [
30
- { paramType: "query", name: :name, description: "A name", type: "String", dataType: "String", required: true, defaultValue: 'default' },
31
- { paramType: "query", name: :level, description: "", type: "String", dataType: "String", required: false }
28
+ path = '/coolness'
29
+ method = 'GET'
30
+ expect(subject.parse_params(params, path, method)).to eq [
31
+ { paramType: 'query', name: :name, description: 'A name', type: 'string', required: true, allowMultiple: false, defaultValue: 'default' },
32
+ { paramType: 'query', name: :level, description: '', type: 'string', required: false, allowMultiple: false }
32
33
  ]
33
34
  end
34
35
 
35
- it "parses params as form for a POST" do
36
+ it 'parses params as form for a POST' do
36
37
  params = {
37
- name: { type: 'String', :desc => "A name", required: true },
38
+ name: { type: 'String', desc: 'A name', required: true },
38
39
  level: 'max'
39
40
  }
40
- path = "/coolness"
41
- method = "POST"
42
- @api.parse_params(params, path, method).should == [
43
- { paramType: "form", name: :name, description: "A name", type: "String", dataType: "String", required: true },
44
- { paramType: "form", name: :level, description: "", type: "String", dataType: "String", required: false }
41
+ path = '/coolness'
42
+ method = 'POST'
43
+ expect(subject.parse_params(params, path, method)).to eq [
44
+ { paramType: 'form', name: :name, description: 'A name', type: 'string', required: true, allowMultiple: false },
45
+ { paramType: 'form', name: :level, description: '', type: 'string', required: false, allowMultiple: false }
45
46
  ]
46
47
  end
47
48
 
48
- context "custom type" do
49
+ it 'parses file param' do
50
+ params = {
51
+ rack: {
52
+ type: 'Rack::Multipart::UploadedFile',
53
+ desc: 'rack file',
54
+ datafile: 'content',
55
+ required: true
56
+ },
57
+ rails: {
58
+ type: 'Hash',
59
+ desc: 'rails file',
60
+ datafile: 'content',
61
+ required: true
62
+ }
63
+ }
64
+ path = '/coolness'
65
+ method = 'POST'
66
+ expect(subject.parse_params(params, path, method)).to eq [
67
+ {
68
+ paramType: 'body',
69
+ name: :rack,
70
+ description: 'rack file',
71
+ type: 'File',
72
+ required: true,
73
+ allowMultiple: false
74
+ },
75
+ {
76
+ paramType: 'body',
77
+ name: :rails,
78
+ description: 'rails file',
79
+ type: 'File',
80
+ required: true,
81
+ allowMultiple: false
82
+ }
83
+ ]
84
+
85
+ end
86
+
87
+ context 'custom type' do
49
88
  before :all do
50
89
  class CustomType
51
90
  end
52
91
  end
53
- it "parses a custom parameters" do
92
+ it 'parses a custom parameters' do
54
93
  params = {
55
- option: { type: CustomType, desc: "Custom option" }
94
+ option: { type: CustomType, desc: 'Custom option' }
56
95
  }
57
- path = "/coolness"
58
- method = "GET"
59
- @api.parse_params(params, path, method).should == [
60
- { paramType: "query", name: :option, description: "Custom option", type: "CustomType", dataType: "CustomType", required: false }
96
+ path = '/coolness'
97
+ method = 'GET'
98
+ expect(subject.parse_params(params, path, method)).to eq [
99
+ { paramType: 'query', name: :option, description: 'Custom option', type: 'CustomType', required: false, allowMultiple: false }
61
100
  ]
62
101
  end
63
102
  end
64
103
 
65
104
  end
66
105
 
67
- context "parsing the path" do
68
- it "parses the path" do
69
- path = ":abc/def(.:format)"
70
- @api.parse_path(path, nil).should == "{abc}/def.{format}"
106
+ context 'parsing the path' do
107
+ it 'parses the path' do
108
+ path = ':abc/def(.:format)'
109
+ expect(subject.parse_path(path, nil)).to eq '{abc}/def.{format}'
71
110
  end
72
111
 
73
- it "parses a path that has vars with underscores in the name" do
74
- path = "abc/:def_g(.:format)"
75
- @api.parse_path(path, nil).should == "abc/{def_g}.{format}"
112
+ it 'parses a path that has vars with underscores in the name' do
113
+ path = 'abc/:def_g(.:format)'
114
+ expect(subject.parse_path(path, nil)).to eq 'abc/{def_g}.{format}'
76
115
  end
77
116
 
78
- it "parses a path that has vars with numbers in the name" do
79
- path = "abc/:sha1(.:format)"
80
- @api.parse_path(path, nil).should == "abc/{sha1}.{format}"
117
+ it 'parses a path that has vars with numbers in the name' do
118
+ path = 'abc/:sha1(.:format)'
119
+ expect(subject.parse_path(path, nil)).to eq 'abc/{sha1}.{format}'
81
120
  end
82
121
 
83
- it "parses a path that has multiple variables" do
84
- path1 = "abc/:def/:geh(.:format)"
85
- path2 = "abc/:def:geh(.:format)"
86
- @api.parse_path(path1, nil).should == "abc/{def}/{geh}.{format}"
87
- @api.parse_path(path2, nil).should == "abc/{def}{geh}.{format}"
122
+ it 'parses a path that has multiple variables' do
123
+ path1 = 'abc/:def/:geh(.:format)'
124
+ path2 = 'abc/:def:geh(.:format)'
125
+ expect(subject.parse_path(path1, nil)).to eq 'abc/{def}/{geh}.{format}'
126
+ expect(subject.parse_path(path2, nil)).to eq 'abc/{def}{geh}.{format}'
88
127
  end
89
128
 
90
- it "parses the path with a specified version" do
91
- path = ":abc/{version}/def(.:format)"
92
- @api.parse_path(path, 'v1').should == "{abc}/v1/def.{format}"
129
+ it 'parses the path with a specified version' do
130
+ path = ':abc/{version}/def(.:format)'
131
+ expect(subject.parse_path(path, 'v1')).to eq '{abc}/v1/def.{format}'
93
132
  end
94
133
  end
95
134
 
96
- context "parsing header parameters" do
97
- it "parses params for the header" do
135
+ context 'parsing header parameters' do
136
+ it 'parses params for the header' do
98
137
  params = {
99
- "XAuthToken" => { description: "A required header.", required: true, defaultValue: 'default' }
138
+ 'XAuthToken' => { description: 'A required header.', required: true, default: 'default' }
100
139
  }
101
- @api.parse_header_params(params).should == [
102
- { paramType: "header", name: "XAuthToken", description: "A required header.", type: "String", dataType: "String", required: true, defaultValue: 'default' }
140
+ expect(subject.parse_header_params(params)).to eq [
141
+ { paramType: 'header', name: 'XAuthToken', description: 'A required header.', type: 'String', required: true, defaultValue: 'default' }
103
142
  ]
104
143
  end
105
144
  end
@@ -1,13 +1,15 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Grape::API do
4
-
5
- it "added combined-routes" do
6
- Grape::API.should respond_to :combined_routes
4
+ it 'added combined-routes' do
5
+ expect(Grape::API).to respond_to :combined_routes
7
6
  end
8
7
 
9
- it "added add_swagger_documentation" do
10
- Grape::API.should respond_to :add_swagger_documentation
8
+ it 'added add_swagger_documentation' do
9
+ expect(Grape::API).to respond_to :add_swagger_documentation
11
10
  end
12
11
 
12
+ it 'added combined-namespaces' do
13
+ expect(Grape::API).to respond_to :combined_namespaces
14
+ end
13
15
  end