brainstem 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
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