brainstem 1.4.1 → 2.0.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 (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