apiculture 0.1.7 → 0.2.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.
- checksums.yaml +4 -4
- data/.gitignore +3 -5
- data/.travis.yml +2 -0
- data/CHANGELOG.md +3 -0
- data/apiculture.gemspec +19 -20
- data/gemfiles/Gemfile.rack-1.x +2 -3
- data/gemfiles/Gemfile.rack-2.x +2 -3
- data/lib/apiculture/app.rb +4 -4
- data/lib/apiculture/sinatra_instance_methods.rb +5 -5
- data/lib/apiculture/version.rb +1 -1
- data/lib/apiculture.rb +39 -39
- metadata +38 -43
- data/spec/apiculture/action_spec.rb +0 -45
- data/spec/apiculture/app_documentation_spec.rb +0 -126
- data/spec/apiculture/method_documentation_spec.rb +0 -102
- data/spec/apiculture/openapi_documentation_spec.rb +0 -197
- data/spec/apiculture_spec.rb +0 -461
- data/spec/spec_helper.rb +0 -15
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apiculture
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julik Tarkhanov
|
@@ -9,24 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2023-02-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: builder
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
20
|
+
version: '3'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: '
|
27
|
+
version: '3'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: github-markup
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
@@ -40,21 +40,21 @@ dependencies:
|
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '3'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: mustache
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
46
|
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
|
-
version: '
|
48
|
+
version: '1'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
53
|
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
|
-
version: '
|
55
|
+
version: '1'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
57
|
+
name: mustermann
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
60
|
- - "~>"
|
@@ -68,61 +68,61 @@ dependencies:
|
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '3'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
|
-
name:
|
71
|
+
name: rdiscount
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: '
|
76
|
+
version: '2'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: '
|
83
|
+
version: '2'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
|
-
name:
|
85
|
+
name: bundler
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- - "
|
88
|
+
- - "~>"
|
89
89
|
- !ruby/object:Gem::Version
|
90
|
-
version: '0'
|
90
|
+
version: '2.0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- - "
|
95
|
+
- - "~>"
|
96
96
|
- !ruby/object:Gem::Version
|
97
|
-
version: '0'
|
97
|
+
version: '2.0'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
|
-
name:
|
99
|
+
name: cgi
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- - "
|
102
|
+
- - ">="
|
103
103
|
- !ruby/object:Gem::Version
|
104
|
-
version: '
|
104
|
+
version: '0'
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- - "
|
109
|
+
- - ">="
|
110
110
|
- !ruby/object:Gem::Version
|
111
|
-
version: '
|
111
|
+
version: '0'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
|
-
name:
|
113
|
+
name: rack-test
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- - "
|
116
|
+
- - ">="
|
117
117
|
- !ruby/object:Gem::Version
|
118
|
-
version: '
|
118
|
+
version: '0'
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- - "
|
123
|
+
- - ">="
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: '
|
125
|
+
version: '0'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rake
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -138,33 +138,33 @@ dependencies:
|
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '0'
|
140
140
|
- !ruby/object:Gem::Dependency
|
141
|
-
name:
|
141
|
+
name: rdoc
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
144
|
- - "~>"
|
145
145
|
- !ruby/object:Gem::Version
|
146
|
-
version: '
|
146
|
+
version: '6.0'
|
147
147
|
type: :development
|
148
148
|
prerelease: false
|
149
149
|
version_requirements: !ruby/object:Gem::Requirement
|
150
150
|
requirements:
|
151
151
|
- - "~>"
|
152
152
|
- !ruby/object:Gem::Version
|
153
|
-
version: '
|
153
|
+
version: '6.0'
|
154
154
|
- !ruby/object:Gem::Dependency
|
155
|
-
name:
|
155
|
+
name: rspec
|
156
156
|
requirement: !ruby/object:Gem::Requirement
|
157
157
|
requirements:
|
158
|
-
- - "
|
158
|
+
- - "~>"
|
159
159
|
- !ruby/object:Gem::Version
|
160
|
-
version: '
|
160
|
+
version: '3'
|
161
161
|
type: :development
|
162
162
|
prerelease: false
|
163
163
|
version_requirements: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
|
-
- - "
|
165
|
+
- - "~>"
|
166
166
|
- !ruby/object:Gem::Version
|
167
|
-
version: '
|
167
|
+
version: '3'
|
168
168
|
description: A toolkit for building REST APIs on top of Rack
|
169
169
|
email: me@julik.nl
|
170
170
|
executables: []
|
@@ -175,6 +175,7 @@ extra_rdoc_files:
|
|
175
175
|
files:
|
176
176
|
- ".gitignore"
|
177
177
|
- ".travis.yml"
|
178
|
+
- CHANGELOG.md
|
178
179
|
- Gemfile
|
179
180
|
- LICENSE.txt
|
180
181
|
- README.md
|
@@ -195,12 +196,6 @@ files:
|
|
195
196
|
- lib/apiculture/sinatra_instance_methods.rb
|
196
197
|
- lib/apiculture/timestamp_promise.rb
|
197
198
|
- lib/apiculture/version.rb
|
198
|
-
- spec/apiculture/action_spec.rb
|
199
|
-
- spec/apiculture/app_documentation_spec.rb
|
200
|
-
- spec/apiculture/method_documentation_spec.rb
|
201
|
-
- spec/apiculture/openapi_documentation_spec.rb
|
202
|
-
- spec/apiculture_spec.rb
|
203
|
-
- spec/spec_helper.rb
|
204
199
|
homepage: https://github.com/WeTransfer/apiculture
|
205
200
|
licenses:
|
206
201
|
- MIT
|
@@ -221,7 +216,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
221
216
|
- !ruby/object:Gem::Version
|
222
217
|
version: '0'
|
223
218
|
requirements: []
|
224
|
-
rubygems_version: 3.
|
219
|
+
rubygems_version: 3.2.33
|
225
220
|
signing_key:
|
226
221
|
specification_version: 4
|
227
222
|
summary: Sweet API sauce on top of Rack
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
describe Apiculture::Action do
|
4
|
-
context '.new' do
|
5
|
-
it 'exposes the methods of the object given as a first argument to initialize' do
|
6
|
-
action_class = Class.new(described_class)
|
7
|
-
fake_app = double('Apiculture::App', something: 'value')
|
8
|
-
action = action_class.new(fake_app)
|
9
|
-
expect(action).to respond_to(:something)
|
10
|
-
expect(action.something).to eq('value')
|
11
|
-
end
|
12
|
-
|
13
|
-
it 'converts keyword arguments to instance variables' do
|
14
|
-
action_class = Class.new(described_class)
|
15
|
-
action = action_class.new(nil, foo: 'a string')
|
16
|
-
expect(action.instance_variable_get('@foo')).to eq('a string')
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'responds to perform()' do
|
21
|
-
expect(described_class.new(nil)).to respond_to(:perform)
|
22
|
-
end
|
23
|
-
|
24
|
-
it 'can use bail() to throw a Sinatra halt' do
|
25
|
-
fake_app = double('Apiculture::App')
|
26
|
-
expect(fake_app).to receive(:json_halt).with('Failure', status: 400)
|
27
|
-
action_class = Class.new(described_class)
|
28
|
-
action_class.new(fake_app).bail "Failure"
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'can use bail() to throw a Sinatra halt with a custom status' do
|
32
|
-
fake_app = double('Apiculture::App')
|
33
|
-
expect(fake_app).to receive(:json_halt).with("Failure", status: 417)
|
34
|
-
|
35
|
-
action_class = Class.new(described_class)
|
36
|
-
action_class.new(fake_app).bail "Failure", status: 417
|
37
|
-
end
|
38
|
-
|
39
|
-
it 'can use bail() to throw a Sinatra halt with extra JSON attributes' do
|
40
|
-
fake_app = double('Apiculture::App')
|
41
|
-
expect(fake_app).to receive(:json_halt).with("Failure", status: 417, message: "Totale")
|
42
|
-
action_class = Class.new(described_class)
|
43
|
-
action_class.new(fake_app).bail "Failure", status: 417, message: 'Totale'
|
44
|
-
end
|
45
|
-
end
|
@@ -1,126 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
describe "Apiculture.api_documentation" do
|
4
|
-
let(:app) do
|
5
|
-
Class.new(Apiculture::App) do
|
6
|
-
extend Apiculture
|
7
|
-
|
8
|
-
markdown_string 'This API is very important. Because it has to do with pancakes.'
|
9
|
-
|
10
|
-
documentation_build_time!
|
11
|
-
|
12
|
-
desc 'Order a pancake'
|
13
|
-
required_param :diameter, "Diameter of the pancake. The pancake will be **bold**", Integer
|
14
|
-
param :topping, 'Type of topping', String
|
15
|
-
pancake_response_info = <<~EOS
|
16
|
-
When the pancake has been baked successfully
|
17
|
-
The pancake will have the following properties:
|
18
|
-
|
19
|
-
* It is going to be round
|
20
|
-
* It is going to be delicious
|
21
|
-
EOS
|
22
|
-
responds_with 200, pancake_response_info, { id: 'abdef..c21' }
|
23
|
-
api_method :post, '/pancakes' do
|
24
|
-
end
|
25
|
-
|
26
|
-
desc 'Check the pancake status'
|
27
|
-
route_param :id, 'Pancake ID to check status on'
|
28
|
-
responds_with 200, 'When the pancake is found', { status: 'Baking' }
|
29
|
-
responds_with 404, 'When no such pancake exists', { status: 'No such pancake' }
|
30
|
-
api_method :get, '/pancake/:id' do
|
31
|
-
end
|
32
|
-
|
33
|
-
desc 'Throw away the pancake'
|
34
|
-
route_param :id, 'Pancake ID to delete'
|
35
|
-
api_method :delete, '/pancake/:id' do
|
36
|
-
end
|
37
|
-
|
38
|
-
desc 'Pancake ingredients are in the URL'
|
39
|
-
route_param :topping_id, 'Pancake topping ID', Integer, cast: :to_i
|
40
|
-
api_method :get, '/pancake/with/:topping_id' do |topping_id|
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'generates app documentation as HTML without the body element' do
|
46
|
-
docco = app.api_documentation
|
47
|
-
generated_html = docco.to_html_fragment
|
48
|
-
|
49
|
-
expect(generated_html).not_to include('<body')
|
50
|
-
expect(generated_html).to include('Pancake ID to check status on')
|
51
|
-
expect(generated_html).to include('Pancake ID to delete')
|
52
|
-
end
|
53
|
-
|
54
|
-
it 'generates app documentation in HTML' do
|
55
|
-
docco = app.api_documentation
|
56
|
-
generated_html = docco.to_html
|
57
|
-
|
58
|
-
if ENV['SHOW_TEST_DOC']
|
59
|
-
File.open('t.html', 'w') do |f|
|
60
|
-
f.write(generated_html)
|
61
|
-
f.flush
|
62
|
-
`open #{f.path}`
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
expect(generated_html).to include('<body')
|
67
|
-
expect(generated_html).to include('Pancake ID to check status on')
|
68
|
-
expect(generated_html).to include('When the pancake has been baked successfully')
|
69
|
-
expect(generated_html).to include('"id": "abdef..c21"')
|
70
|
-
expect(generated_html).to end_with("\n")
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'generates app documentation in Markdown' do
|
74
|
-
docco = app.api_documentation
|
75
|
-
generated_markdown = docco.to_markdown
|
76
|
-
|
77
|
-
expect(generated_markdown).not_to include('<body')
|
78
|
-
expect(generated_markdown).to include('## POST /pancakes')
|
79
|
-
end
|
80
|
-
|
81
|
-
it 'generates app documentation honoring the mount point' do
|
82
|
-
overridden = Class.new(Apiculture::App) do
|
83
|
-
extend Apiculture
|
84
|
-
mounted_at '/api/v2/'
|
85
|
-
api_method :get, '/pancakes' do
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
generated_markdown = overridden.api_documentation.to_markdown
|
90
|
-
expect(generated_markdown).to include('## GET /api/v2/pancakes')
|
91
|
-
end
|
92
|
-
|
93
|
-
it 'generates app documentation injecting the inline Markdown strings' do
|
94
|
-
app_class = Class.new(Apiculture::App) do
|
95
|
-
extend Apiculture
|
96
|
-
markdown_string '# This describes important stuff'
|
97
|
-
api_method :get, '/pancakes' do
|
98
|
-
end
|
99
|
-
markdown_string '# This describes even more important stuff'
|
100
|
-
markdown_string 'This is a paragraph'
|
101
|
-
end
|
102
|
-
|
103
|
-
generated_html = app_class.api_documentation.to_html
|
104
|
-
expect(generated_html).to include('<h2>GET /pancakes</h2>')
|
105
|
-
expect(generated_html).to include('<h1>This describes even more important stuff')
|
106
|
-
expect(generated_html).to include('<h1>This describes important stuff')
|
107
|
-
expect(generated_html).to include('<p>This is a paragraph')
|
108
|
-
end
|
109
|
-
|
110
|
-
context 'with a file containing Markdown that has to be spliced into the docs' do
|
111
|
-
before(:each) { File.open('./TEST.md', 'w') { |f| f << "# This is an important header" } }
|
112
|
-
after(:each) { File.unlink('./TEST.md') }
|
113
|
-
it 'splices the contents of the file using markdown_file' do
|
114
|
-
app_class = Class.new(Apiculture::App) do
|
115
|
-
extend Apiculture
|
116
|
-
markdown_file './TEST.md'
|
117
|
-
api_method :get, '/pancakes' do
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
generated_html = app_class.api_documentation.to_html
|
122
|
-
expect(generated_html).to include('<h2>GET /pancakes</h2>')
|
123
|
-
expect(generated_html).to include('<h1>This is an important header')
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end
|
@@ -1,102 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
require_relative '../../lib/apiculture/method_documentation'
|
3
|
-
|
4
|
-
describe Apiculture::MethodDocumentation do
|
5
|
-
it 'generates HTML from an ActionDefinition with path, verb and both route and request params' do
|
6
|
-
definition = Apiculture::ActionDefinition.new
|
7
|
-
|
8
|
-
definition.description = "This action bakes pancakes"
|
9
|
-
definition.parameters << Apiculture::Parameter.new(:name, 'Pancake name', true, String, :to_s)
|
10
|
-
definition.parameters << Apiculture::Parameter.new(:thickness, 'Pancake **thick**ness', false, Float, :to_f)
|
11
|
-
definition.parameters << Apiculture::Parameter.new(:diameter, 'Pancake diameter', false, Integer, :to_i)
|
12
|
-
|
13
|
-
definition.route_parameters << Apiculture::RouteParameter.new(:pan_id, 'ID of the pancake frying pan')
|
14
|
-
definition.http_verb = 'get'
|
15
|
-
definition.path = '/pancake/:pan_id/bake'
|
16
|
-
definition.responses << Apiculture::PossibleResponse.new(200, "Pancake has been baked", {diameter: 10, unit: "cm"})
|
17
|
-
definition.responses << Apiculture::PossibleResponse.new(417, "Frying pan too cold", "ERR_NO_HEAT")
|
18
|
-
|
19
|
-
documenter = described_class.new(definition)
|
20
|
-
|
21
|
-
generated_html = documenter.to_html_fragment
|
22
|
-
generated_markdown = documenter.to_markdown
|
23
|
-
|
24
|
-
expect(generated_html).not_to include('<body>')
|
25
|
-
|
26
|
-
expect(generated_html).to include('<h2>GET /pancake/:pan_id/bake</h2>')
|
27
|
-
expect(generated_html).to include('<p>This action bakes pancakes</p>')
|
28
|
-
expect(generated_html).to include('<h3>URL parameters</h3>')
|
29
|
-
expect(generated_html).to include('ID of the pancake frying pan')
|
30
|
-
expect(generated_html).to include('<h3>Request parameters</h3>')
|
31
|
-
expect(generated_html).to include('<p>Pancake name</p>')
|
32
|
-
expect(generated_html).to include('<p>Pancake has been baked</p>')
|
33
|
-
expect(generated_html).to include('<p>Frying pan too cold</p>')
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'generates HTML from an ActionDefinition without route params' do
|
37
|
-
definition = Apiculture::ActionDefinition.new
|
38
|
-
|
39
|
-
definition.description = "This action bakes pancakes"
|
40
|
-
definition.parameters << Apiculture::Parameter.new(:name, 'Pancake name', true, String, :to_s)
|
41
|
-
definition.parameters << Apiculture::Parameter.new(:thickness, 'Pancake **thick**ness', false, Float, :to_f)
|
42
|
-
definition.parameters << Apiculture::Parameter.new(:diameter, 'Pancake diameter', false, Integer, :to_i)
|
43
|
-
|
44
|
-
definition.http_verb = 'get'
|
45
|
-
definition.path = '/pancake'
|
46
|
-
|
47
|
-
documenter = described_class.new(definition)
|
48
|
-
generated_html = documenter.to_html_fragment
|
49
|
-
|
50
|
-
expect(generated_html).not_to include('<h3>URL parameters</h3>')
|
51
|
-
end
|
52
|
-
|
53
|
-
it 'generates HTML from an ActionDefinition without request params' do
|
54
|
-
definition = Apiculture::ActionDefinition.new
|
55
|
-
|
56
|
-
definition.description = "This action bakes pancakes"
|
57
|
-
|
58
|
-
definition.route_parameters << Apiculture::RouteParameter.new(:pan_id, 'ID of the pancake frying pan')
|
59
|
-
definition.http_verb = 'get'
|
60
|
-
definition.path = '/pancake/:pan_id/bake'
|
61
|
-
|
62
|
-
documenter = described_class.new(definition)
|
63
|
-
|
64
|
-
generated_html = documenter.to_html_fragment
|
65
|
-
generated_markdown = documenter.to_markdown
|
66
|
-
|
67
|
-
expect(generated_html).not_to include('<h3>Request parameters</h3>')
|
68
|
-
end
|
69
|
-
|
70
|
-
it 'generates HTML from an ActionDefinition with a casted route param' do
|
71
|
-
definition = Apiculture::ActionDefinition.new
|
72
|
-
|
73
|
-
definition.description = "This adds a topping to a pancake"
|
74
|
-
|
75
|
-
definition.route_parameters << Apiculture::RouteParameter.new(:topping_id, 'ID of the pancake topping', Integer, cast: :to_i)
|
76
|
-
definition.http_verb = 'get'
|
77
|
-
definition.path = '/pancake/:topping_id'
|
78
|
-
|
79
|
-
documenter = described_class.new(definition)
|
80
|
-
|
81
|
-
generated_html = documenter.to_html_fragment
|
82
|
-
generated_markdown = documenter.to_markdown
|
83
|
-
expect(generated_html).to include('<h3>URL parameters</h3>')
|
84
|
-
expect(generated_html).to include('Type after cast')
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
it 'generates Markdown from an ActionDefinition with a mountpoint' do
|
89
|
-
definition = Apiculture::ActionDefinition.new
|
90
|
-
|
91
|
-
definition.description = "This action bakes pancakes"
|
92
|
-
|
93
|
-
definition.route_parameters << Apiculture::RouteParameter.new(:pan_id, 'ID of the pancake frying pan')
|
94
|
-
definition.http_verb = 'get'
|
95
|
-
definition.path = '/pancake/:pan_id/bake'
|
96
|
-
|
97
|
-
documenter = described_class.new(definition, '/api/v1')
|
98
|
-
|
99
|
-
generated_markdown = documenter.to_markdown
|
100
|
-
expect(generated_markdown).to include('## GET /api/v1/pancake/:pan_id')
|
101
|
-
end
|
102
|
-
end
|
@@ -1,197 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
describe 'Apiculture.api_documentation' do
|
4
|
-
let!(:test_class) do
|
5
|
-
class PancakeApi < Apiculture::App
|
6
|
-
extend Apiculture
|
7
|
-
|
8
|
-
documentation_build_time!
|
9
|
-
|
10
|
-
desc 'Order a pancake'
|
11
|
-
required_param :diameter, 'Diameter of the pancake. The pancake will be **bold**', Integer
|
12
|
-
param :topping, 'Type of topping', String
|
13
|
-
pancake_response_info = <<~EOS
|
14
|
-
When the pancake has been baked successfully
|
15
|
-
The pancake will have the following properties:
|
16
|
-
|
17
|
-
* It is going to be round
|
18
|
-
* It is going to be delicious
|
19
|
-
EOS
|
20
|
-
responds_with 200, pancake_response_info, { id: 'abdef..c21' }
|
21
|
-
api_method :post, '/pancakes' do
|
22
|
-
end
|
23
|
-
|
24
|
-
desc 'Check the pancake status'
|
25
|
-
route_param :id, 'Pancake ID to check status on'
|
26
|
-
responds_with 200, 'When the pancake is found', { status: 'Baking' }
|
27
|
-
responds_with 404, 'When no such pancake exists', { status: 'No such pancake' }
|
28
|
-
api_method :get, '/pancake/:id' do
|
29
|
-
end
|
30
|
-
|
31
|
-
desc 'Throw away the pancake'
|
32
|
-
route_param :id, 'Pancake ID to delete'
|
33
|
-
api_method :delete, '/pancake/:id' do
|
34
|
-
end
|
35
|
-
|
36
|
-
desc 'Pancake ingredients are in the URL'
|
37
|
-
route_param :topping_id, 'Pancake topping ID', Integer, cast: :to_i
|
38
|
-
api_method :get, '/pancake/with/:topping_id' do |topping_id|
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
let(:documentation) { PancakeApi.api_documentation }
|
44
|
-
let(:open_api_map) { documentation.to_openapi.spec }
|
45
|
-
|
46
|
-
describe '.to_openapi' do
|
47
|
-
it 'will have openapi version' do
|
48
|
-
expect(open_api_map).to include(openapi: '3.0.0')
|
49
|
-
end
|
50
|
-
|
51
|
-
describe 'info' do
|
52
|
-
let(:info) { open_api_map.fetch(:info) }
|
53
|
-
|
54
|
-
it 'will not to be empty' do
|
55
|
-
expect(info).not_to be_empty
|
56
|
-
end
|
57
|
-
|
58
|
-
it 'will have title' do
|
59
|
-
expect(info).to include(title: 'PancakeApi')
|
60
|
-
end
|
61
|
-
|
62
|
-
it 'will have version' do
|
63
|
-
expect(info).to include(version: '0.0.1')
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'will have description' do
|
67
|
-
expect(info).to include(:description)
|
68
|
-
expect(info[:description]).to include('PancakeApi Documentation built on')
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe 'paths' do
|
73
|
-
let(:paths) { open_api_map.fetch(:paths) }
|
74
|
-
|
75
|
-
it 'will have paths' do
|
76
|
-
expect(paths).not_to be_empty
|
77
|
-
end
|
78
|
-
|
79
|
-
it 'will have 4 paths' do
|
80
|
-
expect(paths.size).to eq(3)
|
81
|
-
end
|
82
|
-
|
83
|
-
context 'POST /pancakes' do
|
84
|
-
let(:post_pancakes) { paths.dig('/pancakes', :post) }
|
85
|
-
|
86
|
-
it 'will have route' do
|
87
|
-
expect(post_pancakes).not_to be_empty
|
88
|
-
end
|
89
|
-
|
90
|
-
describe 'request body content' do
|
91
|
-
let(:request_content) { post_pancakes.dig(:requestBody, :content) }
|
92
|
-
it 'will have correct JSON content type' do
|
93
|
-
expect(request_content).to have_key(:'application/json')
|
94
|
-
end
|
95
|
-
|
96
|
-
describe 'schema' do
|
97
|
-
let(:schema) { request_content.dig(:'application/json', :schema) }
|
98
|
-
it 'will have type' do
|
99
|
-
expect(schema).to include(type: :object)
|
100
|
-
end
|
101
|
-
|
102
|
-
it 'will have required parameters' do
|
103
|
-
expect(schema).to include(required: [:diameter])
|
104
|
-
end
|
105
|
-
|
106
|
-
describe 'properties' do
|
107
|
-
let(:properties) { schema.fetch(:properties) }
|
108
|
-
it 'will have all properties' do
|
109
|
-
expect(properties).to have_key :diameter
|
110
|
-
expect(properties).to have_key :topping
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context 'GET /pancake/:id' do
|
118
|
-
let(:get_pancake_by_id_path) { paths.dig('/pancake/{id}', :get) }
|
119
|
-
it 'will have route' do
|
120
|
-
expect(get_pancake_by_id_path).not_to be_empty
|
121
|
-
end
|
122
|
-
|
123
|
-
it 'will have summary' do
|
124
|
-
expect(get_pancake_by_id_path).to include(summary: 'Check the pancake status')
|
125
|
-
end
|
126
|
-
|
127
|
-
it 'will have a description' do
|
128
|
-
expect(get_pancake_by_id_path).to include(description: 'Check the pancake status')
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'will have operationId' do
|
132
|
-
expect(get_pancake_by_id_path).to have_key :operationId
|
133
|
-
end
|
134
|
-
|
135
|
-
describe 'parameters' do
|
136
|
-
let(:parameter) { get_pancake_by_id_path.fetch(:parameters).first }
|
137
|
-
|
138
|
-
it 'will contain parameter' do
|
139
|
-
expect(parameter).not_to be_empty
|
140
|
-
end
|
141
|
-
|
142
|
-
it 'will have required propertie' do
|
143
|
-
expect(parameter).to include(required: true)
|
144
|
-
end
|
145
|
-
|
146
|
-
it 'will indicate a path parameter' do
|
147
|
-
expect(parameter).to include(in: :path)
|
148
|
-
end
|
149
|
-
|
150
|
-
describe 'schema' do
|
151
|
-
let(:schema) { parameter.fetch(:schema) }
|
152
|
-
it 'will have object type' do
|
153
|
-
expect(schema).to include(type: 'string')
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'will have an example' do
|
157
|
-
expect(schema).to include(example: 'string')
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
describe 'responses' do
|
163
|
-
let(:responses) { get_pancake_by_id_path.fetch(:responses) }
|
164
|
-
|
165
|
-
it 'will contain all responses by response code' do
|
166
|
-
expect(responses).to have_key('200')
|
167
|
-
expect(responses).to have_key('404')
|
168
|
-
end
|
169
|
-
|
170
|
-
describe 'response 200' do
|
171
|
-
let(:response_200) { responses.fetch('200') }
|
172
|
-
|
173
|
-
it 'will have description' do
|
174
|
-
expect(response_200).to include(description: 'When the pancake is found')
|
175
|
-
end
|
176
|
-
|
177
|
-
it 'will have correct content type' do
|
178
|
-
expect(response_200.fetch(:content)).to have_key(:'application/json')
|
179
|
-
end
|
180
|
-
|
181
|
-
describe 'schema' do
|
182
|
-
let(:schema) { response_200.dig(:content, :'application/json', :schema) }
|
183
|
-
|
184
|
-
it 'will have object type' do
|
185
|
-
expect(schema).to include(type: 'object')
|
186
|
-
end
|
187
|
-
|
188
|
-
it 'will have properties' do
|
189
|
-
expect(schema).to have_key :properties
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
193
|
-
end
|
194
|
-
end
|
195
|
-
end
|
196
|
-
end
|
197
|
-
end
|