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
@@ -17,13 +17,11 @@ module Brainstem
17
17
  end
18
18
  end
19
19
 
20
-
21
20
  describe "#call" do
22
21
  it "is not implemented" do
23
22
  expect { subject.call }.to raise_error NotImplementedError
24
23
  end
25
24
  end
26
-
27
25
  end
28
26
  end
29
27
  end
@@ -56,7 +56,6 @@ module Brainstem
56
56
  let(:default_config) { {} }
57
57
  let(:configuration) { { _default: default_config } }
58
58
 
59
-
60
59
  describe "#format_title!" do
61
60
  it "outputs it as an h2" do
62
61
  stub(controller).title { lorem }
@@ -40,7 +40,6 @@ module Brainstem
40
40
  end
41
41
  end
42
42
 
43
-
44
43
  describe "formatting" do
45
44
  describe "#format_endpoints!" do
46
45
  it "joins each documentable endpoint" do
@@ -50,7 +49,6 @@ module Brainstem
50
49
  end
51
50
  end
52
51
 
53
-
54
52
  describe "#format_zero_text!" do
55
53
  it "appends the zero text" do
56
54
  subject.send(:format_zero_text!)
@@ -59,7 +57,6 @@ module Brainstem
59
57
  end
60
58
  end
61
59
 
62
-
63
60
  describe "#all_formatted_endpoints" do
64
61
  it "retrieves all formatted endpoints" do
65
62
  documentable_collection = Object.new
@@ -77,8 +74,6 @@ module Brainstem
77
74
  end
78
75
  end
79
76
  end
80
-
81
-
82
77
  end
83
78
  end
84
79
  end
@@ -18,6 +18,7 @@ module Brainstem
18
18
  describe "#call" do
19
19
  before do
20
20
  stub(endpoint).nodoc? { nodoc }
21
+ stub(endpoint).custom_response { {} }
21
22
  end
22
23
 
23
24
  context "when it is nodoc" do
@@ -78,7 +79,6 @@ module Brainstem
78
79
  end
79
80
  end
80
81
 
81
-
82
82
  describe "#format_description!" do
83
83
  context "when present" do
84
84
  before do
@@ -106,7 +106,6 @@ module Brainstem
106
106
  end
107
107
  end
108
108
 
109
-
110
109
  describe "#format_endpoint!" do
111
110
  let(:endpoint_args) { { http_methods: %w(get post), path: "/widgets(.:format)" } }
112
111
 
@@ -127,7 +126,6 @@ module Brainstem
127
126
  end
128
127
  end
129
128
 
130
-
131
129
  describe "#format_params!" do
132
130
  let(:const) do
133
131
  Class.new do
@@ -316,15 +314,103 @@ module Brainstem
316
314
  end
317
315
 
318
316
  describe "#format_presents!" do
319
- let(:presenter) { Object.new }
317
+ context "when has a custom response" do
318
+ before do
319
+ stub(endpoint).custom_response { true }
320
+ stub(endpoint).custom_response_configuration_tree { custom_response_configuration }
321
+ end
320
322
 
321
- before do
322
- stub(endpoint).presenter_title { "Sprocket Widget" }
323
- stub(endpoint).relative_presenter_path_from_controller(:markdown) { "../../sprocket_widget.markdown" }
323
+ context "when the response type is a hash" do
324
+ let(:custom_response_configuration) do
325
+ {
326
+ '_config' => {
327
+ 'type' => 'hash',
328
+ },
329
+ 'widget_name' => {
330
+ '_config' => {
331
+ 'type' => 'string',
332
+ 'info' => 'the name of the widget',
333
+ 'nodoc' => false
334
+ },
335
+ },
336
+ 'widget_permission' => {
337
+ '_config' => {
338
+ 'type' => 'hash',
339
+ 'nodoc' => false
340
+ },
341
+ 'can_edit' => {
342
+ '_config' => {
343
+ 'type' => 'boolean',
344
+ 'info' => 'can edit the widget',
345
+ 'nodoc' => false
346
+ },
347
+ }
348
+ },
349
+ }.with_indifferent_access
350
+ end
351
+
352
+ it "formats the custom response" do
353
+ subject.send(:format_presents!)
354
+
355
+ output = subject.output
356
+ expect(output).to include("The resulting JSON is a hash with the following properties\n\n")
357
+ expect(output).to include("- `widget_name` (`String`) - the name of the widget\n")
358
+ expect(output).to include("- `widget_permission` (`Hash`)\n")
359
+ expect(output).to include(" - `can_edit` (`Boolean`) - can edit the widget\n")
360
+ end
361
+ end
362
+
363
+ context "when the response is an array" do
364
+ let(:custom_response_configuration) do
365
+ {
366
+ '_config' => {
367
+ 'type' => 'array',
368
+ 'item_type' => 'hash',
369
+ },
370
+ 'widget_name' => {
371
+ '_config' => {
372
+ 'type' => 'string',
373
+ 'info' => 'the name of the widget',
374
+ 'nodoc' => false
375
+ },
376
+ },
377
+ 'widget_permissions' => {
378
+ '_config' => {
379
+ 'type' => 'array',
380
+ 'item_type' => 'hash',
381
+ 'info' => 'the permissions of the widget',
382
+ 'nodoc' => false
383
+ },
384
+ 'can_edit' => {
385
+ '_config' => {
386
+ 'type' => 'boolean',
387
+ 'info' => 'can edit the widget',
388
+ 'nodoc' => false
389
+ },
390
+ }
391
+ },
392
+ }.with_indifferent_access
393
+ end
394
+
395
+ it "formats the custom response" do
396
+ subject.send(:format_presents!)
397
+
398
+ output = subject.output
399
+ expect(output).to include "The resulting JSON is an array of objects with the following properties\n\n"
400
+ expect(output).to include("- `widget_name` (`String`) - the name of the widget\n")
401
+ expect(output).to include("- `widget_permissions` (`Array<Hash>`) - the permissions of the widget\n")
402
+ expect(output).to include(" - `can_edit` (`Boolean`) - can edit the widget\n")
403
+ end
404
+ end
324
405
  end
325
406
 
326
- context "when present" do
407
+ context "when custom response is absent and presenter is present" do
408
+ let(:presenter) { Object.new }
409
+
327
410
  before do
411
+ stub(endpoint).custom_response { false }
412
+ stub(endpoint).presenter_title { "Sprocket Widget" }
413
+ stub(endpoint).relative_presenter_path_from_controller(:markdown) { "../../sprocket_widget.markdown" }
328
414
  stub(endpoint).presenter { presenter }
329
415
  end
330
416
 
@@ -32,21 +32,18 @@ module Brainstem
32
32
  end
33
33
  end
34
34
 
35
-
36
35
  describe "#md_p" do
37
36
  it "appends two newlines" do
38
37
  expect(subject.md_p(lipsum)).to eq(lipsum + "\n\n")
39
38
  end
40
39
  end
41
40
 
42
-
43
41
  describe "#md_strong" do
44
42
  it "wraps the text in asterisk pairs" do
45
43
  expect(subject.md_strong("Popeye")).to eq "**Popeye**"
46
44
  end
47
45
  end
48
46
 
49
-
50
47
  describe "#md_code" do
51
48
  it "renders the code between backtick blocks" do
52
49
  expect(subject.md_code('var my_var = 1;')).to eq "```\nvar my_var = 1;\n```\n\n"
@@ -57,14 +54,12 @@ module Brainstem
57
54
  end
58
55
  end
59
56
 
60
-
61
57
  describe "#md_inline_code" do
62
58
  it "renders the code between single backticks" do
63
59
  expect(subject.md_inline_code('my_var')).to eq "`my_var`"
64
60
  end
65
61
  end
66
62
 
67
-
68
63
  describe "#md_ul" do
69
64
  it "evaluates the block given to it in the instance's context" do
70
65
  mock(subject).md_h1('hello') { }
@@ -76,7 +71,6 @@ module Brainstem
76
71
  end
77
72
  end
78
73
 
79
-
80
74
  describe "#md_li" do
81
75
  it "renders the text after a dash-space with a newline" do
82
76
  expect(subject.md_li("text")).to eq "- text\n"
@@ -87,14 +81,12 @@ module Brainstem
87
81
  end
88
82
  end
89
83
 
90
-
91
84
  describe "#md_a" do
92
85
  it "renders the text in a bracket and includes a link in parens" do
93
86
  expect(subject.md_a("text", "link.md")).to eq "[text](link.md)"
94
87
  end
95
88
  end
96
89
 
97
-
98
90
  describe "#md_inline_type" do
99
91
  it "renders the code between single backticks" do
100
92
  expect(subject.md_inline_type("string")).to eq " (`String`)"
@@ -68,7 +68,6 @@ module Brainstem
68
68
  end
69
69
  end
70
70
 
71
-
72
71
  describe "#format_brainstem_keys!" do
73
72
  before do
74
73
  stub(presenter).brainstem_keys { [ "sprockets", "widgets" ] }
@@ -80,7 +79,6 @@ module Brainstem
80
79
  end
81
80
  end
82
81
 
83
-
84
82
  describe "#format_description!" do
85
83
  context "when present" do
86
84
  before do
@@ -107,7 +105,6 @@ module Brainstem
107
105
  end
108
106
  end
109
107
 
110
-
111
108
  describe "#format_fields!" do
112
109
  let(:presenter_class) do
113
110
  Class.new(Brainstem::Presenter) do
@@ -315,7 +312,6 @@ module Brainstem
315
312
  end
316
313
  end
317
314
 
318
-
319
315
  context "if it is conditional" do
320
316
  before do
321
317
  presenter_class.fields do
@@ -383,7 +379,6 @@ module Brainstem
383
379
  end
384
380
  end
385
381
 
386
-
387
382
  describe "#format_filters!" do
388
383
  let(:valid_filters) { {} }
389
384
 
@@ -440,7 +435,6 @@ module Brainstem
440
435
  end
441
436
  end
442
437
 
443
-
444
438
  describe "format_sort_orders!" do
445
439
  before do
446
440
  stub(presenter).valid_sort_orders { sort_orders }
@@ -492,7 +486,6 @@ module Brainstem
492
486
  end
493
487
  end
494
488
 
495
-
496
489
  describe "format_associations!" do
497
490
  let(:associations) { {} }
498
491
  let(:link) { nil }
@@ -0,0 +1,210 @@
1
+ require 'spec_helper'
2
+ require 'brainstem/api_docs/formatters/open_api_specification/helper'
3
+
4
+ module Brainstem
5
+ module ApiDocs
6
+ module Formatters
7
+ module OpenApiSpecification
8
+ describe Helper do
9
+ let(:klass) { Class.new { include Helper } }
10
+
11
+ subject { klass.new }
12
+
13
+ describe "presenter_title" do
14
+ let(:presenter) { Presenter }
15
+ let(:target_class) { "cool_stuff" }
16
+
17
+ before do
18
+ mock(presenter).contextual_documentation(:title) { title }
19
+ stub(presenter).target_class { target_class }
20
+ end
21
+
22
+ context "when presenter has a title" do
23
+ let(:title) { "Awesome Sauce!" }
24
+
25
+ it "returns the title" do
26
+ expect(subject.presenter_title(presenter)).to eq(title)
27
+ end
28
+ end
29
+
30
+ context "when presenter does not have a title" do
31
+ let(:title) { nil }
32
+
33
+ it "returns the formatted target class of the presenter" do
34
+ expect(subject.presenter_title(presenter)).to eq("Cool Stuff")
35
+ end
36
+ end
37
+ end
38
+
39
+ describe "format_tag_name" do
40
+ context "when name is given" do
41
+ let(:title) { "awesome_sauce" }
42
+
43
+ it "returns the formatted name" do
44
+ expect(subject.format_tag_name(title)).to eq("Awesome Sauce")
45
+ end
46
+ end
47
+
48
+ context "when name is nil" do
49
+ let(:title) { nil }
50
+
51
+ it "returns nil" do
52
+ expect(subject.format_tag_name(title)).to be_nil
53
+ end
54
+ end
55
+ end
56
+
57
+ describe "format_description" do
58
+ context "when description is given" do
59
+ let(:description) { " lorem ipsum dolor sit amet " }
60
+
61
+ it "returns the formatted description" do
62
+ expect(subject.format_description(description)).to eq("Lorem ipsum dolor sit amet.")
63
+ end
64
+ end
65
+
66
+ context "when description is nil" do
67
+ let(:description) { "" }
68
+
69
+ it "returns nil" do
70
+ expect(subject.format_description(description)).to eq('')
71
+ end
72
+ end
73
+ end
74
+
75
+ describe "uncapitalize" do
76
+ context "when description is given" do
77
+ let(:description) { " Lorem ipsum dolor sit amet " }
78
+
79
+ it "returns the formatted description" do
80
+ expect(subject.uncapitalize(description)).to eq("lorem ipsum dolor sit amet")
81
+ end
82
+ end
83
+
84
+ context "when description is nil" do
85
+ let(:description) { "" }
86
+
87
+ it "returns nil" do
88
+ expect(subject.uncapitalize(description)).to eq("")
89
+ end
90
+ end
91
+ end
92
+
93
+ describe "format_http_method" do
94
+ let(:endpoint) { OpenStruct.new(http_methods: %w(PATCH PUT)) }
95
+
96
+ it "returns the first downcased http method" do
97
+ expect(subject.format_http_method(endpoint)).to eq("patch")
98
+ end
99
+ end
100
+
101
+ describe "type_and_format" do
102
+ context "when type is 'string'" do
103
+ it "returns the correct type and format" do
104
+ expect(subject.type_and_format('string')).to eq({ 'type' => 'string' })
105
+ end
106
+ end
107
+
108
+ context "when type is 'boolean'" do
109
+ it "returns the correct type and format" do
110
+ expect(subject.send(:type_and_format, 'boolean')).to eq({ 'type' => 'boolean' })
111
+ end
112
+ end
113
+
114
+ context "when type is 'integer'" do
115
+ it "returns the correct type and format" do
116
+ expect(subject.send(:type_and_format, 'integer')).to eq({ 'type' => 'integer', 'format' => 'int32' })
117
+ end
118
+ end
119
+
120
+ context "when type is 'long'" do
121
+ it "returns the correct type and format" do
122
+ expect(subject.send(:type_and_format, 'long')).to eq({ 'type' => 'integer', 'format' => 'int64' })
123
+ end
124
+ end
125
+
126
+ context "when type is 'float'" do
127
+ it "returns the correct type and format" do
128
+ expect(subject.send(:type_and_format, 'float')).to eq({ 'type' => 'number', 'format' => 'float' })
129
+ end
130
+ end
131
+
132
+ context "when type is 'double'" do
133
+ it "returns the correct type and format" do
134
+ expect(subject.send(:type_and_format, 'double')).to eq({ 'type' => 'number', 'format' => 'double' })
135
+ end
136
+ end
137
+
138
+ context "when type is 'byte'" do
139
+ it "returns the correct type and format" do
140
+ expect(subject.send(:type_and_format, 'byte')).to eq({ 'type' => 'string', 'format' => 'byte' })
141
+ end
142
+ end
143
+
144
+ context "when type is 'binary'" do
145
+ it "returns the correct type and format" do
146
+ expect(subject.send(:type_and_format, 'binary')).to eq({ 'type' => 'string', 'format' => 'binary' })
147
+ end
148
+ end
149
+
150
+ context "when type is 'date'" do
151
+ it "returns the correct type and format" do
152
+ expect(subject.send(:type_and_format, 'date')).to eq({ 'type' => 'string', 'format' => 'date' })
153
+ end
154
+ end
155
+
156
+ context "when type is 'datetime'" do
157
+ it "returns the correct type and format" do
158
+ expect(subject.send(:type_and_format, 'datetime')).to eq({ 'type' => 'string', 'format' => 'date-time' })
159
+ end
160
+ end
161
+
162
+ context "when type is 'password'" do
163
+ it "returns the correct type and format" do
164
+ expect(subject.send(:type_and_format, 'password')).to eq({ 'type' => 'string', 'format' => 'password' })
165
+ end
166
+ end
167
+
168
+ context "when type is 'id'" do
169
+ it "returns the correct type and format" do
170
+ expect(subject.send(:type_and_format, 'id')).to eq({ 'type' => 'integer', 'format' => 'int32' })
171
+ end
172
+ end
173
+
174
+ context "when type is 'decimal'" do
175
+ it "returns the correct type and format" do
176
+ expect(subject.send(:type_and_format, 'decimal')).to eq({ 'type' => 'number', 'format' => 'float' })
177
+ end
178
+ end
179
+
180
+ context "when type is array" do
181
+ context "when item type is not specified" do
182
+ it "returns type as `array` and item type as `string`" do
183
+ expect(subject.send(:type_and_format, 'array')).to eq({
184
+ 'type' => 'array',
185
+ 'items' => { 'type' => 'string' }
186
+ })
187
+ end
188
+ end
189
+
190
+ context "when item type is specified" do
191
+ it "returns type as `array` and given item type" do
192
+ expect(subject.send(:type_and_format, 'array', 'integer')).to eq({
193
+ 'type' => 'array',
194
+ 'items' => { 'type' => 'integer' }
195
+ })
196
+ end
197
+ end
198
+ end
199
+
200
+ context "when type is unknown" do
201
+ it "returns nil" do
202
+ expect(subject.send(:type_and_format, 'invalid')).to be_nil
203
+ end
204
+ end
205
+ end
206
+ end
207
+ end
208
+ end
209
+ end
210
+ end