brainstem 2.0.0 → 2.1.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +147 -0
  3. data/Gemfile.lock +68 -39
  4. data/lib/brainstem/api_docs.rb +9 -4
  5. data/lib/brainstem/api_docs/atlas.rb +3 -3
  6. data/lib/brainstem/api_docs/controller.rb +12 -4
  7. data/lib/brainstem/api_docs/controller_collection.rb +11 -2
  8. data/lib/brainstem/api_docs/endpoint.rb +17 -7
  9. data/lib/brainstem/api_docs/endpoint_collection.rb +9 -1
  10. data/lib/brainstem/api_docs/formatters/open_api_specification/helper.rb +19 -16
  11. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter.rb +52 -80
  12. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter.rb +64 -84
  13. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint_formatter.rb +1 -1
  14. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/endpoint_param_formatter.rb +39 -0
  15. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/presenter_field_formatter.rb +147 -0
  16. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/response_field_formatter.rb +146 -0
  17. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter.rb +53 -55
  18. data/lib/brainstem/api_docs/formatters/open_api_specification/version_2/tags_formatter.rb +1 -1
  19. data/lib/brainstem/api_docs/presenter.rb +16 -8
  20. data/lib/brainstem/api_docs/presenter_collection.rb +8 -5
  21. data/lib/brainstem/api_docs/sinks/open_api_specification_sink.rb +3 -1
  22. data/lib/brainstem/cli/generate_api_docs_command.rb +4 -0
  23. data/lib/brainstem/concerns/controller_dsl.rb +90 -20
  24. data/lib/brainstem/concerns/presenter_dsl.rb +16 -8
  25. data/lib/brainstem/dsl/association.rb +12 -0
  26. data/lib/brainstem/dsl/fields_block.rb +1 -1
  27. data/lib/brainstem/version.rb +1 -1
  28. data/spec/brainstem/api_docs/controller_spec.rb +127 -5
  29. data/spec/brainstem/api_docs/endpoint_spec.rb +489 -57
  30. data/spec/brainstem/api_docs/formatters/open_api_specification/helper_spec.rb +15 -4
  31. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/param_definitions_formatter_spec.rb +112 -66
  32. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/endpoint/response_definitions_formatter_spec.rb +404 -32
  33. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/endpoint_param_formatter_spec.rb +335 -0
  34. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/presenter_field_formatter_spec.rb +237 -0
  35. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/field_definitions/response_field_formatter_spec.rb +413 -0
  36. data/spec/brainstem/api_docs/formatters/open_api_specification/version_2/presenter_formatter_spec.rb +116 -4
  37. data/spec/brainstem/api_docs/presenter_spec.rb +406 -24
  38. data/spec/brainstem/cli/generate_api_docs_command_spec.rb +8 -0
  39. data/spec/brainstem/concerns/controller_dsl_spec.rb +606 -45
  40. data/spec/brainstem/concerns/presenter_dsl_spec.rb +34 -2
  41. data/spec/brainstem/dsl/association_spec.rb +54 -3
  42. metadata +11 -2
@@ -9,10 +9,12 @@ module Brainstem
9
9
  describe Presenter do
10
10
  subject { described_class.new(atlas, options) }
11
11
 
12
- let(:atlas) { Object.new }
13
- let(:target_class) { Class.new }
14
- let(:options) { { } }
15
- let(:nodoc) { false }
12
+ let(:atlas) { Object.new }
13
+ let(:target_class) { Class.new }
14
+ let(:options) { { include_internal: internal_flag } }
15
+ let(:internal_flag) { false }
16
+ let(:nodoc) { false }
17
+ let(:internal) { false }
16
18
 
17
19
  describe "#initialize" do
18
20
  it "yields self if given a block" do
@@ -25,7 +27,6 @@ module Brainstem
25
27
  let(:lorem) { "lorem ipsum dolor sit amet" }
26
28
  let(:const) { Object.new }
27
29
  let(:config) { {} }
28
- let(:options) { { const: const } }
29
30
 
30
31
  subject { described_class.new(atlas, options) }
31
32
 
@@ -35,10 +36,12 @@ module Brainstem
35
36
  constant.to_s { "Namespaced::ClassName" }
36
37
  constant.possible_brainstem_keys { Set.new(%w(lorem ipsum)) }
37
38
  end
39
+
40
+ options[:const] = const
38
41
  end
39
42
 
40
43
  describe "#nodoc?" do
41
- let(:config) { { nodoc: nodoc } }
44
+ let(:config) { { nodoc: nodoc, internal: internal } }
42
45
 
43
46
  context "when nodoc in default" do
44
47
  let(:nodoc) { true }
@@ -48,6 +51,46 @@ module Brainstem
48
51
  end
49
52
  end
50
53
 
54
+ context "when internal flag is true" do
55
+ let(:internal_flag) { true }
56
+
57
+ context "when action config is internal" do
58
+ let(:internal) { true }
59
+
60
+ it "is false" do
61
+ expect(subject.nodoc?).to eq false
62
+ end
63
+ end
64
+
65
+ context "when action config is not internal" do
66
+ let(:internal) { false }
67
+
68
+ it "is false" do
69
+ expect(subject.nodoc?).to eq false
70
+ end
71
+ end
72
+ end
73
+
74
+ context "when internal flag is false" do
75
+ let(:internal_flag) { false }
76
+
77
+ context "when action config is internal" do
78
+ let(:internal) { true }
79
+
80
+ it "is true" do
81
+ expect(subject.nodoc?).to eq true
82
+ end
83
+ end
84
+
85
+ context "when action config is not internal" do
86
+ let(:internal) { false }
87
+
88
+ it "is false" do
89
+ expect(subject.nodoc?).to eq false
90
+ end
91
+ end
92
+ end
93
+
51
94
  context "when not nodoc in default" do
52
95
  it "is false" do
53
96
  expect(subject.nodoc?).to eq false
@@ -56,7 +99,7 @@ module Brainstem
56
99
  end
57
100
 
58
101
  describe "#title" do
59
- let(:config) { { title: { info: lorem, nodoc: nodoc } } }
102
+ let(:config) { { title: { info: lorem, nodoc: nodoc, internal: internal } } }
60
103
 
61
104
  context "when nodoc" do
62
105
  let(:nodoc) { true }
@@ -66,6 +109,46 @@ module Brainstem
66
109
  end
67
110
  end
68
111
 
112
+ context "when internal flag is true" do
113
+ let(:internal_flag) { true }
114
+
115
+ context "when title is internal" do
116
+ let(:internal) { true }
117
+
118
+ it "shows the title" do
119
+ expect(subject.title).to eq lorem
120
+ end
121
+ end
122
+
123
+ context "when title is not internal" do
124
+ let(:internal) { false }
125
+
126
+ it "shows the title" do
127
+ expect(subject.title).to eq lorem
128
+ end
129
+ end
130
+ end
131
+
132
+ context "when internal flag is false" do
133
+ let(:internal_flag) { false }
134
+
135
+ context "when title is internal" do
136
+ let(:internal) { true }
137
+
138
+ it "uses the last portion of the presenter's class" do
139
+ expect(subject.title).to eq "ClassName"
140
+ end
141
+ end
142
+
143
+ context "when title is not internal" do
144
+ let(:internal) { false }
145
+
146
+ it "shows the title" do
147
+ expect(subject.title).to eq lorem
148
+ end
149
+ end
150
+ end
151
+
69
152
  context "when not nodoc" do
70
153
  it "uses the presenter's title" do
71
154
  expect(subject.title).to eq lorem
@@ -81,7 +164,47 @@ module Brainstem
81
164
 
82
165
  describe "#description" do
83
166
  context "with description" do
84
- let(:config) { { description: { info: lorem, nodoc: nodoc } } }
167
+ let(:config) { { description: { info: lorem, nodoc: nodoc, internal: internal } } }
168
+
169
+ context "when internal flag is true" do
170
+ let(:internal_flag) { true }
171
+
172
+ context "when description is internal" do
173
+ let(:internal) { true }
174
+
175
+ it "shows the description" do
176
+ expect(subject.description).to eq lorem
177
+ end
178
+ end
179
+
180
+ context "when description is not internal" do
181
+ let(:internal) { false }
182
+
183
+ it "shows the description" do
184
+ expect(subject.description).to eq lorem
185
+ end
186
+ end
187
+ end
188
+
189
+ context "when internal flag is false" do
190
+ let(:internal_flag) { false }
191
+
192
+ context "when description is internal" do
193
+ let(:internal) { true }
194
+
195
+ it "shows nothing" do
196
+ expect(subject.description).to eq ""
197
+ end
198
+ end
199
+
200
+ context "when description is not internal" do
201
+ let(:internal) { false }
202
+
203
+ it "shows the description" do
204
+ expect(subject.description).to eq lorem
205
+ end
206
+ end
207
+ end
85
208
 
86
209
  context "when nodoc" do
87
210
  let(:nodoc) { true }
@@ -112,13 +235,78 @@ module Brainstem
112
235
  end
113
236
  end
114
237
 
115
- subject { described_class.new(atlas, target_class: 'Workspace', const: presenter_class) }
238
+ subject { described_class.new(atlas, options) }
116
239
 
117
240
  before do
118
241
  stub(atlas).find_by_class(anything) { nil }
242
+ options[:target_class] = 'Workspace'
243
+ options[:const] = presenter_class
119
244
  end
120
245
 
121
246
  describe "leafs" do
247
+ context "when internal flag is true" do
248
+ let(:internal_flag) { true }
249
+
250
+ context "when field is internal" do
251
+ before do
252
+ presenter_class.fields do
253
+ field :new_field, :string, dynamic: lambda { "new_field value" }, nodoc: false
254
+ field :new_field2, :string, dynamic: lambda { "new_field2 value" }, internal: 'Only for internal docs'
255
+ field :new_field3, :string, dynamic: lambda { "new_field3 value" }
256
+ end
257
+ end
258
+
259
+ it "keeps the field" do
260
+ expect(subject.valid_fields.keys).to match_array(%w(new_field new_field2 new_field3))
261
+ end
262
+ end
263
+
264
+ context "when field is not internal" do
265
+ before do
266
+ presenter_class.fields do
267
+ field :new_field, :string, dynamic: lambda { "new_field value" }, nodoc: false
268
+ field :new_field2, :string, dynamic: lambda { "new_field2 value" }, internal: false
269
+ field :new_field3, :string, dynamic: lambda { "new_field3 value" }
270
+ end
271
+ end
272
+
273
+ it "keeps the field" do
274
+ expect(subject.valid_fields.keys).to match_array(%w(new_field new_field2 new_field3))
275
+ end
276
+ end
277
+ end
278
+
279
+ context "when internal flag is false" do
280
+ let(:internal_flag) { false }
281
+
282
+ context "when field is internal" do
283
+ before do
284
+ presenter_class.fields do
285
+ field :new_field2, :string, dynamic: lambda { "new_field2 value" }, internal: true
286
+ field :new_field3, :string, dynamic: lambda { "new_field3 value" }, internal: 'Only for internal docs'
287
+ end
288
+ end
289
+
290
+ it "rejects the field" do
291
+ expect(subject.valid_fields.count).to eq 0
292
+ end
293
+ end
294
+
295
+ context "when field is not internal" do
296
+ before do
297
+ presenter_class.fields do
298
+ field :new_field, :string, dynamic: lambda { "new_field value" }, nodoc: true
299
+ field :new_field2, :string, dynamic: lambda { "new_field2 value" }, internal: false
300
+ field :new_field3, :string, dynamic: lambda { "new_field3 value" }
301
+ end
302
+ end
303
+
304
+ it "keeps the field" do
305
+ expect(subject.valid_fields.keys).to match_array(%w(new_field2 new_field3))
306
+ end
307
+ end
308
+ end
309
+
122
310
  context "when nodoc" do
123
311
  before do
124
312
  presenter_class.fields do
@@ -243,6 +431,7 @@ module Brainstem
243
431
  field :mandatory_field, :string, dynamic: lambda { "new_field value" }
244
432
  field :optional_top_field, :string, dynamic: lambda { "new_field value" }, optional: true
245
433
  field :nodoc_optional_top_field, :string, dynamic: lambda { "new_field value" }, optional: true, nodoc: true
434
+ field :internal_optional_top_field, :string, dynamic: lambda { "new_field value" }, optional: true, internal: true
246
435
 
247
436
  fields :optional_block_field, :hash, optional: true do
248
437
  field :leaf_field_1, :string
@@ -256,6 +445,14 @@ module Brainstem
256
445
  field :optional_field_nodoc_block_field, :string, optional: true
257
446
  end
258
447
 
448
+ fields :internal_optional_block_field, :hash, internal: 'Only for internal docs', optional: true do
449
+ field :optional_field_internal_block_field, :string, optional: true
450
+ end
451
+
452
+ fields :internal_block_field, :hash, internal: true do
453
+ field :optional_field_internal_block_field, :string, optional: true
454
+ end
455
+
259
456
  fields :block_field_with_optional_fields, :hash do
260
457
  fields :optional_double_nested_field, :hash, optional: true do
261
458
  field :leaf_field_3, :string
@@ -263,6 +460,8 @@ module Brainstem
263
460
 
264
461
  fields :double_nested_field, :hash do
265
462
  field :leaf_field_4, :string
463
+ field :internal_optional_leaf_field, :string, internal: 'Only for internal docs', optional: true
464
+ field :internal_leaf_field, :string, internal: true
266
465
  field :optional_leaf_field, :string, optional: true
267
466
  field :nodoc_optional_leaf_field, :string, optional: true, nodoc: true
268
467
  end
@@ -271,25 +470,45 @@ module Brainstem
271
470
  end
272
471
  end
273
472
 
274
- subject { described_class.new(atlas, target_class: 'Workspace', const: presenter_class).optional_field_names }
473
+ subject { described_class.new(atlas, options).optional_field_names }
275
474
 
276
475
  before do
277
476
  stub(atlas).find_by_class(anything) { nil }
477
+ options[:target_class] = 'Workspace'
478
+ options[:const] = presenter_class
278
479
  end
279
480
 
280
481
  it 'includes optional top level fields if nodoc is false' do
281
482
  expect(subject).to include('optional_top_field')
282
- expect(subject).to_not include('nodoc_optional_top_field')
483
+ expect(subject).to_not include('nodoc_optional_top_field', 'internal_optional_top_field')
283
484
  end
284
485
 
285
486
  it 'includes optional block fields if nodoc is false' do
286
487
  expect(subject).to include('optional_block_field', 'optional_double_nested_field')
287
- expect(subject).to_not include('nodoc_optional_block_field')
488
+ expect(subject).to_not include('nodoc_optional_block_field', 'internal_block_field')
288
489
  end
289
490
 
290
491
  it 'includes optional leaf fields of block fields if nodoc is false' do
291
492
  expect(subject).to include('optional_leaf_field')
292
- expect(subject).to_not include('nodoc_optional_leaf_field', 'optional_field_nodoc_block_field')
493
+ expect(subject).to_not include('nodoc_optional_leaf_field', 'optional_field_nodoc_block_field', 'internal_leaf_field')
494
+ end
495
+
496
+ context "when internal flag is true" do
497
+ let(:internal_flag) { true }
498
+
499
+ it 'includes optional top level fields' do
500
+ expect(subject).to include('internal_optional_top_field')
501
+ end
502
+
503
+ it 'includes optional block fields' do
504
+ expect(subject).to include('internal_optional_block_field')
505
+ expect(subject).to_not include('internal_block_field')
506
+ end
507
+
508
+ it 'includes optional leaf fields of block fields' do
509
+ expect(subject).to include('internal_optional_leaf_field')
510
+ expect(subject).to_not include('internal_leaf_field')
511
+ end
293
512
  end
294
513
  end
295
514
 
@@ -320,8 +539,47 @@ module Brainstem
320
539
  end
321
540
 
322
541
  describe "#documentable_filter?" do
323
- let(:info) { lorem }
324
- let(:filter) { { nodoc: nodoc, info: info } }
542
+ let(:info) { lorem }
543
+ let(:filter) { { nodoc: nodoc, info: info, internal: internal } }
544
+
545
+ context "when internal flag is true" do
546
+ let(:internal_flag) { true }
547
+
548
+ context "when field is internal" do
549
+ let(:internal) { true }
550
+
551
+ it "is true" do
552
+ expect(subject.documentable_filter?(:filter, filter)).to eq true
553
+ end
554
+ end
555
+
556
+ context "when field is not internal" do
557
+ let(:internal) { false }
558
+
559
+ it "is true" do
560
+ expect(subject.documentable_filter?(:filter, filter)).to eq true
561
+ end
562
+ end
563
+ end
564
+
565
+ context "when internal flag is false" do
566
+ let(:internal_flag) { false }
567
+
568
+ context "when field is internal" do
569
+ let(:internal) { true }
570
+
571
+ it "is false" do
572
+ expect(subject.documentable_filter?(:filter, filter)).to eq false
573
+ end
574
+ end
575
+
576
+ context "when field is not internal" do
577
+ let(:internal) { false }
578
+ it "is true" do
579
+ expect(subject.documentable_filter?(:filter, filter)).to eq true
580
+ end
581
+ end
582
+ end
325
583
 
326
584
  context "when nodoc" do
327
585
  let(:nodoc) { true }
@@ -361,11 +619,55 @@ module Brainstem
361
619
  end
362
620
 
363
621
  describe "#valid_sort_orders" do
364
- let(:config) { { sort_orders: { title: { nodoc: true }, date: {} } } }
622
+ let(:config) { { sort_orders: { title: { nodoc: nodoc, internal: internal }, date: {} } } }
623
+
624
+ context 'nodoc is true' do
625
+ let(:nodoc) { true }
365
626
 
366
- it "returns all pairs not marked nodoc" do
367
- expect(subject.valid_sort_orders).to have_key(:date)
368
- expect(subject.valid_sort_orders).not_to have_key(:title)
627
+ it "returns all pairs not marked nodoc" do
628
+ expect(subject.valid_sort_orders).to have_key(:date)
629
+ expect(subject.valid_sort_orders).not_to have_key(:title)
630
+ end
631
+ end
632
+
633
+ context "when internal flag is true" do
634
+ let(:internal_flag) { true }
635
+
636
+ context "when field is internal" do
637
+ let(:internal) { true }
638
+
639
+ it "returns all pairs marked internal" do
640
+ expect(subject.valid_sort_orders).to have_key(:title)
641
+ end
642
+ end
643
+
644
+ context "when field is not internal" do
645
+ let(:internal) { false }
646
+
647
+ it "returns all pairs not marked internal" do
648
+ expect(subject.valid_sort_orders).to have_key(:title)
649
+ end
650
+ end
651
+ end
652
+
653
+ context "when internal flag is false" do
654
+ let(:internal_flag) { false }
655
+
656
+ context "when field is internal" do
657
+ let(:internal) { true }
658
+
659
+ it "doesnt return all pairs not marked internal" do
660
+ expect(subject.valid_sort_orders).to_not have_key(:title)
661
+ end
662
+ end
663
+
664
+ context "when field is not internal" do
665
+ let(:internal) { false }
666
+
667
+ it "returns all pairs not marked internal" do
668
+ expect(subject.valid_sort_orders).to have_key(:title)
669
+ end
670
+ end
369
671
  end
370
672
  end
371
673
 
@@ -396,8 +698,48 @@ module Brainstem
396
698
  end
397
699
 
398
700
  describe "#documentable_association?" do
399
- let(:desc) { lorem }
400
- let(:association) { OpenStruct.new(options: { nodoc: nodoc }, description: desc ) }
701
+ let(:desc) { lorem }
702
+ let(:association) { OpenStruct.new(options: { nodoc: nodoc, internal: internal }, description: desc) }
703
+
704
+ context "when internal flag is true" do
705
+ let(:internal_flag) { true }
706
+
707
+ context "when field is internal" do
708
+ let(:internal) { true }
709
+
710
+ it "is true" do
711
+ expect(subject.documentable_association?(:assoc, association)).to eq true
712
+ end
713
+ end
714
+
715
+ context "when field is not internal" do
716
+ let(:internal) { false }
717
+
718
+ it "is true" do
719
+ expect(subject.documentable_association?(:assoc, association)).to eq true
720
+ end
721
+ end
722
+ end
723
+
724
+ context "when internal flag is false" do
725
+ let(:internal_flag) { false }
726
+
727
+ context "when field is internal" do
728
+ let(:internal) { true }
729
+
730
+ it "is false" do
731
+ expect(subject.documentable_association?(:assoc, association)).to eq false
732
+ end
733
+ end
734
+
735
+ context "when field is not internal" do
736
+ let(:internal) { false }
737
+
738
+ it "is true" do
739
+ expect(subject.documentable_association?(:assoc, association)).to eq true
740
+ end
741
+ end
742
+ end
401
743
 
402
744
  context "when nodoc" do
403
745
  let(:nodoc) { true }
@@ -485,7 +827,7 @@ module Brainstem
485
827
  end
486
828
 
487
829
  describe "#contextual_documentation" do
488
- let(:config) { { title: { info: info, nodoc: nodoc } } }
830
+ let(:config) { { title: { info: info, nodoc: nodoc, internal: internal } } }
489
831
  let(:info) { lorem }
490
832
 
491
833
  context "when has the key" do
@@ -511,6 +853,46 @@ module Brainstem
511
853
  end
512
854
  end
513
855
 
856
+ context "when internal flag is true" do
857
+ let(:internal_flag) { true }
858
+
859
+ context "when field is internal" do
860
+ let(:internal) { true }
861
+
862
+ it "is truthy" do
863
+ expect(subject.contextual_documentation(key)).to be_truthy
864
+ end
865
+ end
866
+
867
+ context "when field is not internal" do
868
+ let(:internal) { false }
869
+
870
+ it "is truthy" do
871
+ expect(subject.contextual_documentation(key)).to be_truthy
872
+ end
873
+ end
874
+ end
875
+
876
+ context "when internal flag is false" do
877
+ let(:internal_flag) { false }
878
+
879
+ context "when field is internal" do
880
+ let(:internal) { true }
881
+
882
+ it "is falsey" do
883
+ expect(subject.contextual_documentation(key)).to be_falsey
884
+ end
885
+ end
886
+
887
+ context "when field is not internal" do
888
+ let(:internal) { false }
889
+
890
+ it "is truthy" do
891
+ expect(subject.contextual_documentation(key)).to be_truthy
892
+ end
893
+ end
894
+ end
895
+
514
896
  context "when nodoc" do
515
897
  let(:nodoc) { true }
516
898
 
@@ -592,7 +974,7 @@ module Brainstem
592
974
  stub(presenter).nodoc? { nodoc }
593
975
  end
594
976
 
595
- context "when nodoc" do
977
+ context "when nodoc? returns true" do
596
978
  let(:nodoc) { true }
597
979
 
598
980
  it "is nil" do
@@ -600,7 +982,7 @@ module Brainstem
600
982
  end
601
983
  end
602
984
 
603
- context "when not nodoc" do
985
+ context "when nodoc? returns false" do
604
986
  it "is the path" do
605
987
  expect(subject.link_for_association(association)).to eq "./path"
606
988
  end