brainstem 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +77 -0
  3. data/README.md +119 -0
  4. data/docs/api_doc_generator.markdown +45 -4
  5. data/docs/brainstem_executable.markdown +1 -1
  6. data/docs/oas_2_docgen.png +0 -0
  7. data/docs/oas_2_docgen_ascii.txt +78 -0
  8. data/lib/brainstem/api_docs.rb +23 -9
  9. data/lib/brainstem/api_docs/abstract_collection.rb +0 -13
  10. data/lib/brainstem/api_docs/atlas.rb +0 -14
  11. data/lib/brainstem/api_docs/builder.rb +0 -14
  12. data/lib/brainstem/api_docs/controller.rb +7 -16
  13. data/lib/brainstem/api_docs/controller_collection.rb +0 -3
  14. data/lib/brainstem/api_docs/endpoint.rb +73 -19
  15. data/lib/brainstem/api_docs/endpoint_collection.rb +0 -7
  16. data/lib/brainstem/api_docs/formatters/abstract_formatter.rb +0 -2
  17. data/lib/brainstem/api_docs/formatters/markdown/controller_formatter.rb +1 -9
  18. data/lib/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter.rb +1 -9
  19. data/lib/brainstem/api_docs/formatters/markdown/endpoint_formatter.rb +39 -24
  20. data/lib/brainstem/api_docs/formatters/markdown/helper.rb +0 -13
  21. data/lib/brainstem/api_docs/formatters/markdown/presenter_formatter.rb +22 -35
  22. data/lib/brainstem/api_docs/formatters/open_api_specification/helper.rb +66 -0
  23. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/controller_formatter.rb +57 -0
  24. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter.rb +311 -0
  25. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter.rb +197 -0
  26. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_collection_formatter.rb +60 -0
  27. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_formatter.rb +162 -0
  28. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/info_formatter.rb +126 -0
  29. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter.rb +132 -0
  30. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/security_definitions_formatter.rb +99 -0
  31. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter.rb +123 -0
  32. data/lib/brainstem/api_docs/introspectors/abstract_introspector.rb +0 -7
  33. data/lib/brainstem/api_docs/introspectors/rails_introspector.rb +1 -20
  34. data/lib/brainstem/api_docs/presenter.rb +21 -27
  35. data/lib/brainstem/api_docs/presenter_collection.rb +1 -11
  36. data/lib/brainstem/api_docs/resolver.rb +1 -8
  37. data/lib/brainstem/api_docs/sinks/abstract_sink.rb +0 -4
  38. data/lib/brainstem/api_docs/sinks/controller_presenter_multifile_sink.rb +0 -9
  39. data/lib/brainstem/api_docs/sinks/open_api_specification_sink.rb +234 -0
  40. data/lib/brainstem/api_docs/sinks/stdout_sink.rb +0 -5
  41. data/lib/brainstem/cli.rb +0 -13
  42. data/lib/brainstem/cli/abstract_command.rb +0 -7
  43. data/lib/brainstem/cli/generate_api_docs_command.rb +48 -24
  44. data/lib/brainstem/concerns/controller_dsl.rb +288 -145
  45. data/lib/brainstem/concerns/formattable.rb +0 -5
  46. data/lib/brainstem/concerns/optional.rb +0 -1
  47. data/lib/brainstem/concerns/presenter_dsl.rb +2 -21
  48. data/lib/brainstem/dsl/configuration.rb +0 -11
  49. data/lib/brainstem/presenter.rb +0 -4
  50. data/lib/brainstem/version.rb +1 -1
  51. data/spec/brainstem/api_docs/abstract_collection_spec.rb +0 -11
  52. data/spec/brainstem/api_docs/atlas_spec.rb +0 -6
  53. data/spec/brainstem/api_docs/builder_spec.rb +0 -4
  54. data/spec/brainstem/api_docs/controller_collection_spec.rb +0 -2
  55. data/spec/brainstem/api_docs/controller_spec.rb +29 -18
  56. data/spec/brainstem/api_docs/endpoint_collection_spec.rb +0 -6
  57. data/spec/brainstem/api_docs/endpoint_spec.rb +343 -13
  58. data/spec/brainstem/api_docs/formatters/abstract_formatter_spec.rb +0 -2
  59. data/spec/brainstem/api_docs/formatters/markdown/controller_formatter_spec.rb +0 -1
  60. data/spec/brainstem/api_docs/formatters/markdown/endpoint_collection_formatter_spec.rb +0 -5
  61. data/spec/brainstem/api_docs/formatters/markdown/endpoint_formatter_spec.rb +94 -8
  62. data/spec/brainstem/api_docs/formatters/markdown/helper_spec.rb +0 -8
  63. data/spec/brainstem/api_docs/formatters/markdown/presenter_formatter_spec.rb +0 -7
  64. data/spec/brainstem/api_docs/formatters/open_api_specification/helper_spec.rb +210 -0
  65. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/controller_formatter_spec.rb +81 -0
  66. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter_spec.rb +672 -0
  67. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter_spec.rb +335 -0
  68. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_collection_formatter_spec.rb +59 -0
  69. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_formatter_spec.rb +308 -0
  70. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/info_formatter_spec.rb +89 -0
  71. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter_spec.rb +430 -0
  72. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/security_definitions_formatter_spec.rb +190 -0
  73. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter_spec.rb +217 -0
  74. data/spec/brainstem/api_docs/introspectors/abstract_introspector_spec.rb +0 -2
  75. data/spec/brainstem/api_docs/introspectors/rails_introspector_spec.rb +0 -2
  76. data/spec/brainstem/api_docs/presenter_collection_spec.rb +0 -2
  77. data/spec/brainstem/api_docs/presenter_spec.rb +58 -18
  78. data/spec/brainstem/api_docs/resolver_spec.rb +0 -1
  79. data/spec/brainstem/api_docs/sinks/controller_presenter_multifile_sink_spec.rb +0 -2
  80. data/spec/brainstem/api_docs/sinks/open_api_specification_sink_spec.rb +371 -0
  81. data/spec/brainstem/api_docs_spec.rb +2 -0
  82. data/spec/brainstem/cli/abstract_command_spec.rb +0 -4
  83. data/spec/brainstem/cli/generate_api_docs_command_spec.rb +53 -2
  84. data/spec/brainstem/concerns/controller_dsl_spec.rb +430 -64
  85. data/spec/brainstem/concerns/presenter_dsl_spec.rb +0 -20
  86. data/spec/brainstem/preloader_spec.rb +0 -7
  87. data/spec/brainstem/presenter_spec.rb +0 -1
  88. data/spec/dummy/rails.rb +0 -1
  89. data/spec/spec_helpers/db.rb +0 -1
  90. metadata +37 -2
@@ -0,0 +1,190 @@
1
+ require 'spec_helper'
2
+ require 'brainstem/api_docs/formatters/open_api_specification/version_2/security_definitions_formatter'
3
+
4
+ module Brainstem
5
+ module ApiDocs
6
+ module Formatters
7
+ module OpenApiSpecification
8
+ module Version2
9
+ describe SecurityDefinitionsFormatter do
10
+ subject { described_class.new }
11
+
12
+ describe 'call' do
13
+ before do
14
+ mock.proxy(subject).format_basic_auth_definitions!
15
+ mock.proxy(subject).format_apikey_auth_definitions!
16
+ mock.proxy(subject).format_oauth_definitions!
17
+ mock.proxy(subject).format_security_object!
18
+ end
19
+
20
+ it 'includes security definitions' do
21
+ output = subject.call
22
+ end
23
+ end
24
+
25
+ describe 'format_basic_auth_definitions!' do
26
+ context 'when definition exists' do
27
+ let(:basic_auth_definition) { { 'basic' => { 'type' => 'basic' } } }
28
+
29
+ before do
30
+ mock(subject).basic_auth_definitions { basic_auth_definition }
31
+ end
32
+
33
+ it 'includes the correct attributes' do
34
+ subject.send(:format_basic_auth_definitions!)
35
+
36
+ expect(subject.output.keys).to match_array(%w(securityDefinitions))
37
+ expect(subject.output['securityDefinitions']).to eq(basic_auth_definition)
38
+ end
39
+ end
40
+
41
+ context 'when definition is blank' do
42
+ before do
43
+ mock.proxy(subject).basic_auth_definitions
44
+ end
45
+
46
+ it 'does not add securityDefinitions key' do
47
+ subject.send(:format_basic_auth_definitions!)
48
+
49
+ expect(subject.output).to be_empty
50
+ end
51
+ end
52
+ end
53
+
54
+ describe 'format_apikey_auth_definitions!' do
55
+ context 'when definition exists' do
56
+ before do
57
+ mock.proxy(subject).apikey_auth_definitions
58
+ end
59
+
60
+ it 'includes the correct attributes' do
61
+ subject.send(:format_apikey_auth_definitions!)
62
+
63
+ expect(subject.output.keys).to match_array(%w(securityDefinitions))
64
+ expect(subject.output['securityDefinitions']).to eq({
65
+ 'api_key' => {
66
+ 'type' => 'apiKey',
67
+ 'name' => 'api_key',
68
+ 'in' => 'header'
69
+ }
70
+ })
71
+ end
72
+ end
73
+
74
+ context 'when definition is blank' do
75
+ before do
76
+ mock(subject).apikey_auth_definitions { {} }
77
+ end
78
+
79
+ it 'does not add securityDefinitions key' do
80
+ subject.send(:format_apikey_auth_definitions!)
81
+
82
+ expect(subject.output).to be_empty
83
+ end
84
+ end
85
+ end
86
+
87
+ describe 'format_apikey_auth_definitions!' do
88
+ context 'when definition exists' do
89
+ before do
90
+ mock.proxy(subject).apikey_auth_definitions
91
+ end
92
+
93
+ it 'includes the correct attributes' do
94
+ subject.send(:format_apikey_auth_definitions!)
95
+
96
+ expect(subject.output.keys).to match_array(%w(securityDefinitions))
97
+ expect(subject.output['securityDefinitions']).to eq({
98
+ 'api_key' => {
99
+ 'type' => 'apiKey',
100
+ 'name' => 'api_key',
101
+ 'in' => 'header'
102
+ }
103
+ })
104
+ end
105
+ end
106
+
107
+ context 'when definition is blank' do
108
+ before do
109
+ mock(subject).apikey_auth_definitions { {} }
110
+ end
111
+
112
+ it 'does not add securityDefinitions key' do
113
+ subject.send(:format_apikey_auth_definitions!)
114
+
115
+ expect(subject.output).to be_empty
116
+ end
117
+ end
118
+ end
119
+
120
+ describe 'format_oauth_definitions!' do
121
+ context 'when definition exists' do
122
+ before do
123
+ mock.proxy(subject).oauth_definitions
124
+ end
125
+
126
+ it 'includes the correct attributes' do
127
+ subject.send(:format_oauth_definitions!)
128
+
129
+ expect(subject.output.keys).to match_array(%w(securityDefinitions))
130
+ expect(subject.output['securityDefinitions']).to eq({
131
+ 'petstore_auth' => {
132
+ 'type' => 'oauth2',
133
+ 'authorizationUrl' => 'http://petstore.swagger.io/oauth/dialog',
134
+ 'flow' => 'implicit',
135
+ 'scopes' => {
136
+ 'write:pets' => 'modify pets in your account',
137
+ 'read:pets' => 'read your pets'
138
+ }
139
+ }
140
+ })
141
+ end
142
+ end
143
+
144
+ context 'when definition is blank' do
145
+ before do
146
+ mock(subject).oauth_definitions { {} }
147
+ end
148
+
149
+ it 'does not add securityDefinitions key' do
150
+ subject.send(:format_oauth_definitions!)
151
+
152
+ expect(subject.output).to be_empty
153
+ end
154
+ end
155
+ end
156
+
157
+ describe 'format_security_object!' do
158
+ context 'when definition exists' do
159
+ let(:security_object) { { 'petstore_auth' => ['write:pets', 'read:pets'] } }
160
+
161
+ before do
162
+ mock(subject).security_object { security_object }.times(2)
163
+ end
164
+
165
+ it 'includes the correct attributes' do
166
+ subject.send(:format_security_object!)
167
+
168
+ expect(subject.output.keys).to match_array(%w(security))
169
+ expect(subject.output['security']).to eq(security_object)
170
+ end
171
+ end
172
+
173
+ context 'when definition is blank' do
174
+ before do
175
+ mock.proxy(subject).security_object
176
+ end
177
+
178
+ it 'does not add security key' do
179
+ subject.send(:format_security_object!)
180
+
181
+ expect(subject.output).to be_empty
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
187
+ end
188
+ end
189
+ end
190
+ end
@@ -0,0 +1,217 @@
1
+ require 'spec_helper'
2
+ require 'brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter'
3
+ require 'brainstem/api_docs/controller'
4
+
5
+ module Brainstem
6
+ module ApiDocs
7
+ module Formatters
8
+ module OpenApiSpecification
9
+ module Version2
10
+ describe TagsFormatter do
11
+ let(:atlas) { Object.new }
12
+ let(:documentable_controller_Z) {
13
+ OpenStruct.new(
14
+ name: 'controller_Z',
15
+ description: 'controller_Z desc',
16
+ endpoints: OpenStruct.new(only_documentable: [1, 2]),
17
+ tag: 'Tag Z',
18
+ tag_groups: ['Group Z'],
19
+ )
20
+ }
21
+ let(:documentable_controller_A) {
22
+ OpenStruct.new(
23
+ name: 'controller_A',
24
+ description: 'controller_A desc',
25
+ endpoints: OpenStruct.new(only_documentable: [1, 2]),
26
+ tag: 'Tag A',
27
+ tag_groups: ['Group Z', 'Group A'],
28
+ )
29
+ }
30
+ let(:nodoc_controller) {
31
+ OpenStruct.new(
32
+ name: 'controller_nodoc',
33
+ description: 'controller_nodoc desc',
34
+ endpoints: OpenStruct.new(only_documentable: [1, 2]),
35
+ tag: 'No Doc',
36
+ tag_groups: ['No Doc Group'],
37
+ )
38
+ }
39
+ let(:no_endpoint_controller) {
40
+ OpenStruct.new(
41
+ name: 'controller_no_endpoint',
42
+ description: 'controller_no_endpoint desc',
43
+ endpoints: OpenStruct.new(only_documentable: []),
44
+ tag: 'No Endpoint',
45
+ tag_groups: ['No Endpoint Group'],
46
+ )
47
+ }
48
+ let(:no_tag_controller) {
49
+ OpenStruct.new(
50
+ name: 'no_tag_controller',
51
+ description: 'no_tag_controller desc',
52
+ endpoints: OpenStruct.new(only_documentable: [1])
53
+ )
54
+ }
55
+ let(:controllers) {
56
+ [
57
+ documentable_controller_Z,
58
+ documentable_controller_A,
59
+ nodoc_controller,
60
+ no_endpoint_controller,
61
+ no_tag_controller
62
+ ]
63
+ }
64
+ let(:ignore_tagging) { false }
65
+ let(:options) { { ignore_tagging: ignore_tagging } }
66
+
67
+ def extract_tag_names(tags)
68
+ tags.map { |tag| tag['name'] }
69
+ end
70
+
71
+ subject { described_class.new(controllers, options) }
72
+
73
+ before do
74
+ stub(nodoc_controller).nodoc? { true }
75
+ end
76
+
77
+ describe 'call' do
78
+ describe 'when ignore tags option is selected' do
79
+ let(:ignore_tagging) { true }
80
+
81
+ before do
82
+ dont_allow(subject).format_tags!
83
+ dont_allow(subject).format_tag_groups!
84
+ end
85
+
86
+ it 'returns empty object' do
87
+ expect(subject.call).to be_empty
88
+ end
89
+ end
90
+
91
+ describe 'when no controllers are passed in' do
92
+ let(:controllers) { [] }
93
+
94
+ before do
95
+ dont_allow(subject).format_tags!
96
+ dont_allow(subject).format_tag_groups!
97
+ end
98
+
99
+ it 'returns empty object' do
100
+ expect(subject.call).to be_empty
101
+ end
102
+ end
103
+
104
+ describe 'when controllers are present and ignore tags is false' do
105
+ before do
106
+ mock(subject).format_tags!
107
+ mock(subject).format_tag_groups!
108
+ end
109
+
110
+ it 'includes tag definitions' do
111
+ subject.call
112
+ end
113
+ end
114
+ end
115
+
116
+ describe '#format_tags!' do
117
+ it 'excludes no doc controllers' do
118
+ subject.send(:format_tags!)
119
+
120
+ expect(subject.output).to have_key('tags')
121
+ expect(extract_tag_names(subject.output['tags'])).to_not include('No Doc')
122
+ end
123
+
124
+ it 'excludes controllers with no documentable endpoints' do
125
+ subject.send(:format_tags!)
126
+
127
+ expect(subject.output).to have_key('tags')
128
+ expect(extract_tag_names(subject.output['tags'])).to_not include('No Endpoint')
129
+ end
130
+
131
+ it 'returns a array of tags sorted by name of the tag' do
132
+ subject.send(:format_tags!)
133
+
134
+ expect(subject.output).to have_key('tags')
135
+ expect(subject.output['tags']).to eq([
136
+ {
137
+ 'name' => 'No Tag Controller',
138
+ 'description' => 'No_tag_controller desc.'
139
+ },
140
+ {
141
+ 'name' => 'Tag A',
142
+ 'description' => 'Controller_A desc.'
143
+ },
144
+ {
145
+ 'name' => 'Tag Z',
146
+ 'description' => 'Controller_Z desc.'
147
+ },
148
+ ])
149
+ end
150
+ end
151
+
152
+ describe '#format_tag_groups!!' do
153
+ it 'excludes no doc controllers' do
154
+ subject.send(:format_tag_groups!)
155
+
156
+ expect(subject.output).to have_key('x-tagGroups')
157
+ expect(extract_tag_names(subject.output['x-tagGroups'])).to_not include('No Doc Group')
158
+ end
159
+
160
+ it 'excludes controllers with no documentable endpoints' do
161
+ subject.send(:format_tag_groups!)
162
+
163
+ expect(subject.output).to have_key('x-tagGroups')
164
+ expect(extract_tag_names(subject.output['x-tagGroups'])).to_not include('No Endpoint Group')
165
+ end
166
+
167
+ it 'returns a array of tag groups sorted by name of the group name' do
168
+ subject.send(:format_tag_groups!)
169
+
170
+ expect(subject.output).to have_key('x-tagGroups')
171
+ expect(subject.output['x-tagGroups']).to eq([
172
+ {
173
+ 'name' => 'Group A',
174
+ 'tags' => ['Tag A']
175
+ },
176
+ {
177
+ 'name' => 'Group Z',
178
+ 'tags' => ['Tag A', 'Tag Z']
179
+ },
180
+ {
181
+ 'name' => 'No Tag Controller',
182
+ 'tags' => ['No Tag Controller']
183
+ },
184
+ ])
185
+ end
186
+
187
+ context 'when none of the controllers have tag groups specified' do
188
+ let(:documentable_controller_Z) {
189
+ OpenStruct.new(
190
+ name: 'controller_Z',
191
+ description: 'controller_Z desc',
192
+ endpoints: OpenStruct.new(only_documentable: [1, 2]),
193
+ tag: 'Tag Z',
194
+ )
195
+ }
196
+ let(:documentable_controller_A) {
197
+ OpenStruct.new(
198
+ name: 'controller_A',
199
+ description: 'controller_A desc',
200
+ endpoints: OpenStruct.new(only_documentable: [1, 2]),
201
+ tag: 'Tag A',
202
+ )
203
+ }
204
+
205
+ it 'does not add tag groups to the output' do
206
+ subject.send(:format_tag_groups!)
207
+
208
+ expect(subject.output).to_not have_key('x-tagGroups')
209
+ end
210
+ end
211
+ end
212
+ end
213
+ end
214
+ end
215
+ end
216
+ end
217
+ end
@@ -43,7 +43,6 @@ module Brainstem
43
43
  end
44
44
  end
45
45
 
46
-
47
46
  describe "#load_environment!" do
48
47
  it "is not implemented" do
49
48
  expect { subject.send(:load_environment!) }.to raise_error NotImplementedError
@@ -131,7 +130,6 @@ module Brainstem
131
130
  end
132
131
  end
133
132
 
134
-
135
133
  describe "#valid_presenters?" do
136
134
  it "is valid when a collection of zero or more classes" do
137
135
  stub(subject).presenters { [ Integer ] }
@@ -81,7 +81,6 @@ module Brainstem
81
81
  )
82
82
  end
83
83
 
84
-
85
84
  it "allows the specification of a custom base_presenter_class" do
86
85
  expect(subject.send(:base_presenter_class).to_s)
87
86
  .to eq "::FakeBasePresenter"
@@ -103,7 +102,6 @@ module Brainstem
103
102
  )
104
103
  end
105
104
 
106
-
107
105
  it "allows the specification of a custom base_controller_class" do
108
106
  expect(subject.send(:base_controller_class).to_s)
109
107
  .to eq "::FakeBaseController"
@@ -33,7 +33,6 @@ module Brainstem
33
33
  end
34
34
  end
35
35
 
36
-
37
36
  describe "#create_from_target_class" do
38
37
  let(:pclm) { Object.new }
39
38
  let(:options) { { presenter_constant_lookup_method: pclm } }
@@ -66,7 +65,6 @@ module Brainstem
66
65
  end
67
66
  end
68
67
 
69
-
70
68
  describe "#create_from_presenter_collection" do
71
69
  let(:const) { Class.new }
72
70