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
@@ -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"