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
@@ -10,7 +10,6 @@ module Brainstem
10
10
 
11
11
  subject { described_class.new(atlas, options) }
12
12
 
13
-
14
13
  describe "#find_from_route" do
15
14
  let(:controller) { stub!.const { Object }.subject }
16
15
 
@@ -48,7 +47,6 @@ module Brainstem
48
47
  end
49
48
  end
50
49
 
51
-
52
50
  describe "#create_from_route" do
53
51
  it "creates a new endpoint, adding it to the members" do
54
52
  controller = Object.new
@@ -69,7 +67,6 @@ module Brainstem
69
67
  end
70
68
  end
71
69
 
72
-
73
70
  describe "#only_documentable" do
74
71
  let(:endpoint_2) { Object.new }
75
72
 
@@ -90,7 +87,6 @@ module Brainstem
90
87
  end
91
88
  end
92
89
 
93
-
94
90
  describe "#with_declared_presented_class" do
95
91
  let(:endpoint_2) { Object.new }
96
92
 
@@ -110,7 +106,6 @@ module Brainstem
110
106
  end
111
107
  end
112
108
 
113
-
114
109
  describe "#with_actions_in_controller" do
115
110
  let(:endpoint_2) { Object.new }
116
111
  let(:const) do
@@ -136,7 +131,6 @@ module Brainstem
136
131
  end
137
132
  end
138
133
 
139
-
140
134
  it_behaves_like "formattable"
141
135
  it_behaves_like "atlas taker"
142
136
  end
@@ -9,7 +9,6 @@ module Brainstem
9
9
  let(:options) { {} }
10
10
  subject { described_class.new(atlas, options) }
11
11
 
12
-
13
12
  describe "#initialize" do
14
13
  it "yields self if given a block" do
15
14
  block = Proc.new { |s| s.path = "bork bork" }
@@ -17,7 +16,6 @@ module Brainstem
17
16
  end
18
17
  end
19
18
 
20
-
21
19
  describe "#merge_http_methods!" do
22
20
  let(:options) { { http_methods: %w(GET) } }
23
21
 
@@ -29,7 +27,6 @@ module Brainstem
29
27
  end
30
28
  end
31
29
 
32
-
33
30
  describe "configured fields" do
34
31
  let(:const) do
35
32
  Class.new do
@@ -61,7 +58,6 @@ module Brainstem
61
58
  stub(controller).const { const }
62
59
  end
63
60
 
64
-
65
61
  describe "#nodoc?" do
66
62
  let(:show_config) { { nodoc: nodoc } }
67
63
 
@@ -80,7 +76,6 @@ module Brainstem
80
76
  end
81
77
  end
82
78
 
83
-
84
79
  describe "#title" do
85
80
  context "when present" do
86
81
  let(:show_config) { { title: { info: lorem, nodoc: nodoc } } }
@@ -107,7 +102,6 @@ module Brainstem
107
102
  end
108
103
  end
109
104
 
110
-
111
105
  describe "#description" do
112
106
  context "when present" do
113
107
  let(:show_config) { { description: { info: lorem, nodoc: nodoc } } }
@@ -134,7 +128,6 @@ module Brainstem
134
128
  end
135
129
  end
136
130
 
137
-
138
131
  describe "#valid_params" do
139
132
  it "returns the valid_params key from action or default" do
140
133
  mock(subject).key_with_default_fallback(:valid_params)
@@ -142,6 +135,65 @@ module Brainstem
142
135
  end
143
136
  end
144
137
 
138
+ describe "#operation_id" do
139
+ context "when present" do
140
+ let(:show_config) { { operation_id: "blah" } }
141
+
142
+ it "returns the operation ID" do
143
+ expect(subject.operation_id).to eq("blah")
144
+ end
145
+ end
146
+
147
+ context "when not present" do
148
+ let(:show_config) { { title: "Blah" } }
149
+
150
+ it "returns nothing" do
151
+ expect(subject.operation_id).to be_nil
152
+ end
153
+ end
154
+ end
155
+
156
+ describe "#produces" do
157
+ it "returns the produces key from action or default" do
158
+ mock(subject).key_with_default_fallback(:produces)
159
+ subject.produces
160
+ end
161
+ end
162
+
163
+ describe "#consumes" do
164
+ it "returns the consumes key from action or default" do
165
+ mock(subject).key_with_default_fallback(:consumes)
166
+ subject.consumes
167
+ end
168
+ end
169
+
170
+ describe "#security" do
171
+ it "returns the security key from action or default" do
172
+ mock(subject).key_with_default_fallback(:security)
173
+ subject.security
174
+ end
175
+ end
176
+
177
+ describe "#schemes" do
178
+ it "returns the schemes key from action or default" do
179
+ mock(subject).key_with_default_fallback(:schemes)
180
+ subject.schemes
181
+ end
182
+ end
183
+
184
+ describe "#external_docs" do
185
+ it "returns the external_docs key from action or default" do
186
+ mock(subject).key_with_default_fallback(:external_docs)
187
+ subject.external_docs
188
+ end
189
+ end
190
+
191
+ describe "#deprecated" do
192
+ it "returns the deprecated key from action or default" do
193
+ mock(subject).key_with_default_fallback(:deprecated)
194
+ subject.deprecated
195
+ end
196
+ end
145
197
 
146
198
  describe "#params_configuration_tree" do
147
199
  let(:default_config) { { valid_params: which_param } }
@@ -540,7 +592,6 @@ module Brainstem
540
592
  end
541
593
  end
542
594
 
543
-
544
595
  describe "#valid_presents" do
545
596
  it "returns the presents key from action or default" do
546
597
  mock(subject).key_with_default_fallback(:presents)
@@ -548,7 +599,6 @@ module Brainstem
548
599
  end
549
600
  end
550
601
 
551
-
552
602
  describe "#contextual_documentation" do
553
603
  let(:show_config) { { title: { info: info, nodoc: nodoc } } }
554
604
  let(:info) { lorem }
@@ -594,7 +644,6 @@ module Brainstem
594
644
  end
595
645
  end
596
646
 
597
-
598
647
  describe "#key_with_default_fallback" do
599
648
  let(:default_config) { { info: "default" } }
600
649
 
@@ -614,7 +663,6 @@ module Brainstem
614
663
  end
615
664
  end
616
665
 
617
-
618
666
  describe "#sort" do
619
667
  actions = %w(index show create update delete articuno zapdos moltres)
620
668
 
@@ -637,7 +685,6 @@ module Brainstem
637
685
  end
638
686
  end
639
687
 
640
-
641
688
  describe "#presenter_title" do
642
689
  let(:presenter) { mock!.title.returns(lorem).subject }
643
690
  let(:options) { { presenter: presenter } }
@@ -647,7 +694,6 @@ module Brainstem
647
694
  end
648
695
  end
649
696
 
650
-
651
697
  describe "#relative_presenter_path_from_controller" do
652
698
  let(:presenter) {
653
699
  mock!
@@ -671,6 +717,290 @@ module Brainstem
671
717
  end
672
718
  end
673
719
 
720
+ describe "custom response" do
721
+ let(:const) do
722
+ Class.new do
723
+ def self.brainstem_model_name
724
+ :widget
725
+ end
726
+ end
727
+ end
728
+
729
+ let(:controller) { Object.new }
730
+ let(:action) { :show }
731
+ let(:show_config) { {} }
732
+ let(:nodoc) { false }
733
+ let(:configuration) { { :show => show_config } }
734
+
735
+ let(:options) { { controller: controller, action: action } }
736
+
737
+ before do
738
+ stub(controller).configuration { configuration }
739
+ stub(controller).const { const }
740
+ end
741
+
742
+ describe "#custom_response_configuration_tree" do
743
+ let(:default_response_config) { { nodoc: nodoc, type: 'array', item_type: 'hash' } }
744
+
745
+ context "when no custom response is present" do
746
+ let(:show_config) { {} }
747
+
748
+ it "returns empty object" do
749
+ expect(subject.custom_response_configuration_tree).to be_empty
750
+ end
751
+ end
752
+
753
+ context "when custom response is present" do
754
+ let(:show_config) do
755
+ {
756
+ custom_response: { _config: default_response_config }.merge(other_response_fields)
757
+ }
758
+ end
759
+
760
+ context "non-nested params" do
761
+ let(:other_response_fields) do
762
+ { Proc.new { 'title' } => { nodoc: nodoc, type: 'string' } }
763
+ end
764
+
765
+ context "when nodoc" do
766
+ let(:nodoc) { true }
767
+
768
+ it "rejects the key" do
769
+ expect(subject.custom_response_configuration_tree).to eq(
770
+ {
771
+ _config: default_response_config
772
+ }.with_indifferent_access
773
+ )
774
+ end
775
+ end
776
+
777
+ context "when not nodoc" do
778
+ let(:nodoc) { false }
779
+
780
+ it "lists it as a root param" do
781
+ expect(subject.custom_response_configuration_tree).to eq(
782
+ {
783
+ _config: default_response_config,
784
+ title: {
785
+ _config: { nodoc: nodoc, type: 'string' }
786
+ }
787
+ }.with_indifferent_access
788
+ )
789
+ end
790
+
791
+ context "when param has an item" do
792
+ let(:other_response_fields) do
793
+ { Proc.new { 'only' } => { nodoc: nodoc, type: 'array', item: 'integer' } }
794
+ end
795
+
796
+ it "lists it as a root param" do
797
+ expect(subject.custom_response_configuration_tree).to eq(
798
+ {
799
+ _config: default_response_config,
800
+ only: {
801
+ _config: { nodoc: nodoc, type: 'array', item: 'integer' }
802
+ }
803
+ }.with_indifferent_access
804
+ )
805
+ end
806
+ end
807
+ end
808
+ end
809
+
810
+ context "nested params" do
811
+ let(:parent_proc) { Proc.new { 'sprocket' } }
812
+ let(:other_response_fields) do
813
+ {
814
+ parent_proc => { nodoc: nodoc, type: 'array', item_type: 'hash' },
815
+ Proc.new { 'title' } => { nodoc: nodoc, type: 'string', ancestors: [parent_proc] }
816
+ }
817
+ end
818
+
819
+ context "when nodoc" do
820
+ let(:nodoc) { true }
821
+
822
+ it "rejects the key" do
823
+ expect(subject.custom_response_configuration_tree).to eq(
824
+ {
825
+ _config: default_response_config,
826
+ }.with_indifferent_access
827
+ )
828
+ end
829
+ end
830
+
831
+ context "when not nodoc" do
832
+ it "lists it as a nested param" do
833
+ expect(subject.custom_response_configuration_tree).to eq(
834
+ {
835
+ _config: default_response_config,
836
+ sprocket: {
837
+ _config: {
838
+ nodoc: nodoc,
839
+ type: 'array',
840
+ item_type: 'hash'
841
+ },
842
+ title: {
843
+ _config: {
844
+ nodoc: nodoc,
845
+ type: 'string'
846
+ }
847
+ }
848
+ }
849
+ }.with_indifferent_access
850
+ )
851
+ end
852
+
853
+ context "when nested param has an item" do
854
+ let(:other_response_fields) do
855
+ {
856
+ parent_proc => { nodoc: nodoc, type: 'array', item_type: 'hash' },
857
+ Proc.new { 'ids' } => { nodoc: nodoc, type: 'array', item: 'integer', ancestors: [parent_proc] }
858
+ }
859
+ end
860
+
861
+ it "lists it as a nested param" do
862
+ expect(subject.custom_response_configuration_tree).to eq(
863
+ {
864
+ _config: default_response_config,
865
+ sprocket: {
866
+ _config: {
867
+ nodoc: nodoc,
868
+ type: 'array',
869
+ item_type: 'hash'
870
+ },
871
+ ids: {
872
+ _config: {
873
+ nodoc: nodoc,
874
+ type: 'array',
875
+ item: 'integer'
876
+ }
877
+ }
878
+ }
879
+ }.with_indifferent_access
880
+ )
881
+ end
882
+ end
883
+ end
884
+ end
885
+
886
+ context "multi nested params" do
887
+ let(:project_proc) { Proc.new { 'project' } }
888
+ let(:id_proc) { Proc.new { 'id' } }
889
+ let(:task_proc) { Proc.new { 'task' } }
890
+ let(:title_proc) { Proc.new { 'title' } }
891
+ let(:checklist_proc) { Proc.new { 'checklist' } }
892
+ let(:name_proc) { Proc.new { 'name' } }
893
+ let(:other_response_fields) do
894
+ {
895
+ task_proc => {
896
+ type: 'hash',
897
+ },
898
+ title_proc => {
899
+ type: 'string',
900
+ ancestors: [task_proc]
901
+ },
902
+ checklist_proc => {
903
+ type: 'array',
904
+ item: 'hash',
905
+ ancestors: [task_proc]
906
+ },
907
+ name_proc => {
908
+ type: 'string',
909
+ ancestors: [task_proc, checklist_proc]
910
+ }
911
+ }
912
+ end
913
+
914
+ context "when a leaf param has no doc" do
915
+ before do
916
+ other_response_fields[name_proc][:nodoc] = true
917
+ end
918
+
919
+ it "rejects the key" do
920
+ expect(subject.custom_response_configuration_tree).to eq(
921
+ {
922
+ _config: default_response_config,
923
+ task: {
924
+ _config: {
925
+ type: 'hash'
926
+ },
927
+ title: {
928
+ _config: {
929
+ type: 'string'
930
+ }
931
+ },
932
+ checklist: {
933
+ _config: {
934
+ type: 'array',
935
+ item: 'hash'
936
+ }
937
+ },
938
+ },
939
+ }.with_indifferent_access
940
+ )
941
+ end
942
+ end
943
+
944
+ context "when parent param has nodoc" do
945
+ before do
946
+ other_response_fields[checklist_proc][:nodoc] = true
947
+ # The nested field will be inherit the nodoc property from its parent.
948
+ other_response_fields[name_proc][:nodoc] = true
949
+ end
950
+
951
+ it "rejects the parent key and its children" do
952
+ expect(subject.custom_response_configuration_tree).to eq(
953
+ {
954
+ _config: default_response_config,
955
+ task: {
956
+ _config: {
957
+ type: 'hash'
958
+ },
959
+ title: {
960
+ _config: {
961
+ type: 'string'
962
+ }
963
+ }
964
+ }
965
+ }.with_indifferent_access
966
+ )
967
+ end
968
+ end
969
+
970
+ context "when not nodoc" do
971
+ it "evaluates the proc in the controller's context and lists it as a nested param" do
972
+ expect(subject.custom_response_configuration_tree).to eq(
973
+ {
974
+ _config: default_response_config,
975
+ task: {
976
+ _config: {
977
+ type: 'hash'
978
+ },
979
+ title: {
980
+ _config: {
981
+ type: 'string'
982
+ }
983
+ },
984
+ checklist: {
985
+ _config: {
986
+ type: 'array',
987
+ item: 'hash',
988
+ },
989
+ name: {
990
+ _config: {
991
+ type: 'string',
992
+ }
993
+ },
994
+ },
995
+ },
996
+ }.with_indifferent_access
997
+ )
998
+ end
999
+ end
1000
+ end
1001
+ end
1002
+ end
1003
+ end
674
1004
 
675
1005
  it_behaves_like "formattable"
676
1006
  it_behaves_like "atlas taker"