grape-swagger 0.30.1 → 0.31.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.
@@ -7,19 +7,6 @@ describe Grape::Endpoint do
7
7
  described_class.new(Grape::Util::InheritableSetting.new, path: '/', method: :get)
8
8
  end
9
9
 
10
- describe '#param_type_is_array?' do
11
- it 'returns true if the value passed represents an array' do
12
- expect(subject.send(:param_type_is_array?, 'Array')).to be_truthy
13
- expect(subject.send(:param_type_is_array?, '[String]')).to be_truthy
14
- expect(subject.send(:param_type_is_array?, 'Array[Integer]')).to be_truthy
15
- end
16
-
17
- it 'returns false if the value passed does not represent an array' do
18
- expect(subject.send(:param_type_is_array?, 'String')).to be_falsey
19
- expect(subject.send(:param_type_is_array?, '[String, Integer]')).to be_falsey
20
- end
21
- end
22
-
23
10
  describe '.content_types_for' do
24
11
  describe 'defined on target_class' do
25
12
  let(:own_json) { 'text/own-json' }
@@ -58,4 +45,109 @@ describe Grape::Endpoint do
58
45
  end
59
46
  end
60
47
  end
48
+
49
+ describe 'parse_request_params' do
50
+ let(:subject) { GrapeSwagger::Endpoint::ParamsParser }
51
+ before do
52
+ subject.send(:parse_request_params, params, {})
53
+ end
54
+
55
+ context 'when params do not contain an array' do
56
+ let(:params) do
57
+ [
58
+ ['id', { required: true, type: 'String' }],
59
+ ['description', { required: false, type: 'String' }]
60
+ ]
61
+ end
62
+
63
+ let(:expected_params) do
64
+ [
65
+ ['id', { required: true, type: 'String' }],
66
+ ['description', { required: false, type: 'String' }]
67
+ ]
68
+ end
69
+
70
+ it 'parses params correctly' do
71
+ expect(params).to eq expected_params
72
+ end
73
+ end
74
+
75
+ context 'when params contain a simple array' do
76
+ let(:params) do
77
+ [
78
+ ['id', { required: true, type: 'String' }],
79
+ ['description', { required: false, type: 'String' }],
80
+ ['stuffs', { required: true, type: 'Array[String]' }]
81
+ ]
82
+ end
83
+
84
+ let(:expected_params) do
85
+ [
86
+ ['id', { required: true, type: 'String' }],
87
+ ['description', { required: false, type: 'String' }],
88
+ ['stuffs', { required: true, type: 'Array[String]', is_array: true }]
89
+ ]
90
+ end
91
+
92
+ it 'parses params correctly and adds is_array to the array' do
93
+ expect(params).to eq expected_params
94
+ end
95
+ end
96
+
97
+ context 'when params contain a complex array' do
98
+ let(:params) do
99
+ [
100
+ ['id', { required: true, type: 'String' }],
101
+ ['description', { required: false, type: 'String' }],
102
+ ['stuffs', { required: true, type: 'Array' }],
103
+ ['stuffs[id]', { required: true, type: 'String' }]
104
+ ]
105
+ end
106
+
107
+ let(:expected_params) do
108
+ [
109
+ ['id', { required: true, type: 'String' }],
110
+ ['description', { required: false, type: 'String' }],
111
+ ['stuffs', { required: true, type: 'Array', is_array: true }],
112
+ ['stuffs[id]', { required: true, type: 'String', is_array: true }]
113
+ ]
114
+ end
115
+
116
+ it 'parses params correctly and adds is_array to the array and all elements' do
117
+ expect(params).to eq expected_params
118
+ end
119
+
120
+ context 'when array params are not contiguous with parent array' do
121
+ let(:params) do
122
+ [
123
+ ['id', { required: true, type: 'String' }],
124
+ ['description', { required: false, type: 'String' }],
125
+ ['stuffs', { required: true, type: 'Array' }],
126
+ ['stuffs[owners]', { required: true, type: 'Array' }],
127
+ ['stuffs[creators]', { required: true, type: 'Array' }],
128
+ ['stuffs[owners][id]', { required: true, type: 'String' }],
129
+ ['stuffs[creators][id]', { required: true, type: 'String' }],
130
+ ['stuffs_and_things', { required: true, type: 'String' }]
131
+ ]
132
+ end
133
+
134
+ let(:expected_params) do
135
+ [
136
+ ['id', { required: true, type: 'String' }],
137
+ ['description', { required: false, type: 'String' }],
138
+ ['stuffs', { required: true, type: 'Array', is_array: true }],
139
+ ['stuffs[owners]', { required: true, type: 'Array', is_array: true }],
140
+ ['stuffs[creators]', { required: true, type: 'Array', is_array: true }],
141
+ ['stuffs[owners][id]', { required: true, type: 'String', is_array: true }],
142
+ ['stuffs[creators][id]', { required: true, type: 'String', is_array: true }],
143
+ ['stuffs_and_things', { required: true, type: 'String' }]
144
+ ]
145
+ end
146
+
147
+ it 'parses params correctly and adds is_array to the array and all elements' do
148
+ expect(params).to eq expected_params
149
+ end
150
+ end
151
+ end
152
+ end
61
153
  end
@@ -513,5 +513,180 @@ describe GrapeSwagger::DocMethods::MoveParams do
513
513
  end
514
514
  end
515
515
  end
516
+
517
+ describe 'recursive_call' do
518
+ before :each do
519
+ subject.send(:recursive_call, properties, 'test', nested_params)
520
+ end
521
+
522
+ let(:properties) { {} }
523
+
524
+ context 'when nested params is an array' do
525
+ let(:nested_params) do
526
+ [
527
+ {
528
+ in: 'body',
529
+ name: 'aliases',
530
+ description: 'The aliases of test.',
531
+ type: 'array',
532
+ items: { type: 'string' },
533
+ required: true
534
+ }
535
+ ]
536
+ end
537
+
538
+ let(:expected_properties) do
539
+ {
540
+ type: 'array',
541
+ items: {
542
+ type: 'object',
543
+ properties: {
544
+ aliases: {
545
+ type: 'string',
546
+ description: 'The aliases of test.'
547
+ }
548
+ },
549
+ required: [:aliases]
550
+ }
551
+ }
552
+ end
553
+
554
+ it 'adds property as symbol with array type and items' do
555
+ expect(properties[:test]).to eq expected_properties
556
+ end
557
+ end
558
+
559
+ context 'when nested params is not an array' do
560
+ let(:nested_params) do
561
+ [
562
+ {
563
+ in: 'body',
564
+ name: 'id',
565
+ description: 'The unique ID of test.',
566
+ type: 'string',
567
+ required: true
568
+ }
569
+ ]
570
+ end
571
+
572
+ let(:expected_properties) do
573
+ {
574
+ type: 'object',
575
+ required: [:id],
576
+ properties: {
577
+ id: {
578
+ type: 'string',
579
+ description: 'The unique ID of test.'
580
+ }
581
+ }
582
+ }
583
+ end
584
+
585
+ it 'adds property as symbol with object type' do
586
+ expect(properties[:test]).to eq expected_properties
587
+ end
588
+ end
589
+ end
590
+
591
+ describe 'add_properties_to_definition' do
592
+ before :each do
593
+ subject.send(:add_properties_to_definition, definition, properties, [])
594
+ end
595
+
596
+ context 'when definition has items key' do
597
+ let(:definition) do
598
+ {
599
+ type: 'array',
600
+ items: {
601
+ type: 'object',
602
+ properties: {
603
+ description: 'Test description'
604
+ }
605
+ }
606
+ }
607
+ end
608
+
609
+ let(:properties) do
610
+ {
611
+ strings: {
612
+ type: 'string',
613
+ description: 'string elements'
614
+ }
615
+ }
616
+ end
617
+
618
+ let(:expected_definition) do
619
+ {
620
+ type: 'array',
621
+ items: {
622
+ type: 'object',
623
+ properties: {
624
+ description: 'Test description',
625
+ strings: {
626
+ type: 'string',
627
+ description: 'string elements'
628
+ }
629
+ }
630
+ }
631
+ }
632
+ end
633
+
634
+ it 'deep merges properties into definition item properties' do
635
+ expect(definition).to eq expected_definition
636
+ end
637
+ end
638
+
639
+ context 'when definition does not have items key' do
640
+ let(:definition) do
641
+ {
642
+ type: 'object',
643
+ properties: {
644
+ parent: {
645
+ type: 'object',
646
+ description: 'Parent to child'
647
+ }
648
+ }
649
+ }
650
+ end
651
+
652
+ let(:properties) do
653
+ {
654
+ parent: {
655
+ type: 'object',
656
+ properties: {
657
+ id: {
658
+ type: 'string',
659
+ description: 'Parent ID'
660
+ }
661
+ },
662
+ required: [:id]
663
+ }
664
+ }
665
+ end
666
+
667
+ let(:expected_definition) do
668
+ {
669
+ type: 'object',
670
+ properties: {
671
+ parent: {
672
+ type: 'object',
673
+ description: 'Parent to child',
674
+ properties: {
675
+ id: {
676
+ type: 'string',
677
+ description: 'Parent ID'
678
+ }
679
+ },
680
+ required: [:id]
681
+ }
682
+ }
683
+ }
684
+ end
685
+
686
+ it 'deep merges properties into definition properties' do
687
+ expect(definition).to eq expected_definition
688
+ end
689
+ end
690
+ end
516
691
  end
517
692
  end
@@ -5,193 +5,199 @@ require 'spec_helper'
5
5
  describe 'Group Params as Array' do
6
6
  include_context "#{MODEL_PARSER} swagger example"
7
7
 
8
- def app
9
- Class.new(Grape::API) do
10
- format :json
11
-
12
- params do
13
- requires :required_group, type: Array do
14
- requires :required_param_1
15
- requires :required_param_2
8
+ [true, false].each do |array_use_braces|
9
+ context "when array_use_braces option is set to #{array_use_braces}" do
10
+ let(:braces) { array_use_braces ? '[]' : '' }
11
+
12
+ let(:app) do
13
+ Class.new(Grape::API) do
14
+ format :json
15
+
16
+ params do
17
+ requires :required_group, type: Array do
18
+ requires :required_param_1
19
+ requires :required_param_2
20
+ end
21
+ end
22
+ post '/groups' do
23
+ { 'declared_params' => declared(params) }
24
+ end
25
+
26
+ params do
27
+ requires :typed_group, type: Array do
28
+ requires :id, type: Integer, desc: 'integer given'
29
+ requires :name, type: String, desc: 'string given'
30
+ optional :email, type: String, desc: 'email given'
31
+ optional :others, type: Integer, values: [1, 2, 3]
32
+ end
33
+ end
34
+ post '/type_given' do
35
+ { 'declared_params' => declared(params) }
36
+ end
37
+
38
+ # as body parameters it would be interpreted a bit different,
39
+ # cause it could not be distinguished anymore, so this would be translated to one array,
40
+ # see also next example for the difference
41
+ params do
42
+ requires :array_of_string, type: Array[String], documentation: { param_type: 'body', desc: 'nested array of strings' }
43
+ requires :array_of_integer, type: Array[Integer], documentation: { param_type: 'body', desc: 'nested array of integers' }
44
+ end
45
+
46
+ post '/array_of_type' do
47
+ { 'declared_params' => declared(params) }
48
+ end
49
+
50
+ params do
51
+ requires :array_of_string, type: Array[String], documentation: { param_type: 'body', desc: 'array of strings' }
52
+ requires :integer_value, type: Integer, documentation: { param_type: 'body', desc: 'integer value' }
53
+ end
54
+
55
+ post '/object_and_array' do
56
+ { 'declared_params' => declared(params) }
57
+ end
58
+
59
+ params do
60
+ requires :array_of_string, type: Array[String]
61
+ requires :array_of_integer, type: Array[Integer]
62
+ end
63
+
64
+ post '/array_of_type_in_form' do
65
+ { 'declared_params' => declared(params) }
66
+ end
67
+
68
+ params do
69
+ requires :array_of_entities, type: Array[Entities::ApiError]
70
+ end
71
+
72
+ post '/array_of_entities' do
73
+ { 'declared_params' => declared(params) }
74
+ end
75
+
76
+ add_swagger_documentation array_use_braces: array_use_braces
16
77
  end
17
78
  end
18
- post '/groups' do
19
- { 'declared_params' => declared(params) }
20
- end
21
79
 
22
- params do
23
- requires :typed_group, type: Array do
24
- requires :id, type: Integer, desc: 'integer given'
25
- requires :name, type: String, desc: 'string given'
26
- optional :email, type: String, desc: 'email given'
27
- optional :others, type: Integer, values: [1, 2, 3]
80
+ describe 'retrieves the documentation for grouped parameters' do
81
+ subject do
82
+ get '/swagger_doc/groups'
83
+ JSON.parse(last_response.body)
28
84
  end
29
- end
30
- post '/type_given' do
31
- { 'declared_params' => declared(params) }
32
- end
33
85
 
34
- # as body parameters it would be interpreted a bit different,
35
- # cause it could not be distinguished anymore, so this would be translated to one array,
36
- # see also next example for the difference
37
- params do
38
- requires :array_of_string, type: Array[String], documentation: { param_type: 'body', desc: 'nested array of strings' }
39
- requires :array_of_integer, type: Array[Integer], documentation: { param_type: 'body', desc: 'nested array of integers' }
40
- end
41
-
42
- post '/array_of_type' do
43
- { 'declared_params' => declared(params) }
86
+ specify do
87
+ expect(subject['paths']['/groups']['post']['parameters']).to eql(
88
+ [
89
+ { 'in' => 'formData', 'name' => "required_group#{braces}[required_param_1]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
90
+ { 'in' => 'formData', 'name' => "required_group#{braces}[required_param_2]", 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } }
91
+ ]
92
+ )
93
+ end
44
94
  end
45
95
 
46
- params do
47
- requires :array_of_string, type: Array[String], documentation: { param_type: 'body', desc: 'array of strings' }
48
- requires :integer_value, type: Integer, documentation: { param_type: 'body', desc: 'integer value' }
49
- end
96
+ describe 'retrieves the documentation for typed group parameters' do
97
+ subject do
98
+ get '/swagger_doc/type_given'
99
+ JSON.parse(last_response.body)
100
+ end
50
101
 
51
- post '/object_and_array' do
52
- { 'declared_params' => declared(params) }
102
+ specify do
103
+ expect(subject['paths']['/type_given']['post']['parameters']).to eql(
104
+ [
105
+ { 'in' => 'formData', 'name' => "typed_group#{braces}[id]", 'description' => 'integer given', 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' }, 'required' => true },
106
+ { 'in' => 'formData', 'name' => "typed_group#{braces}[name]", 'description' => 'string given', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true },
107
+ { 'in' => 'formData', 'name' => "typed_group#{braces}[email]", 'description' => 'email given', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false },
108
+ { 'in' => 'formData', 'name' => "typed_group#{braces}[others]", 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32', 'enum' => [1, 2, 3] }, 'required' => false }
109
+ ]
110
+ )
111
+ end
53
112
  end
54
113
 
55
- params do
56
- requires :array_of_string, type: Array[String]
57
- requires :array_of_integer, type: Array[Integer]
58
- end
114
+ describe 'retrieves the documentation for parameters that are arrays of primitive types' do
115
+ subject do
116
+ get '/swagger_doc/array_of_type'
117
+ JSON.parse(last_response.body)
118
+ end
59
119
 
60
- post '/array_of_type_in_form' do
61
- { 'declared_params' => declared(params) }
120
+ specify do
121
+ expect(subject['definitions']['postArrayOfType']['type']).to eql 'array'
122
+ expect(subject['definitions']['postArrayOfType']['items']).to eql(
123
+ 'type' => 'object',
124
+ 'properties' => {
125
+ 'array_of_string' => {
126
+ 'type' => 'string', 'description' => 'nested array of strings'
127
+ },
128
+ 'array_of_integer' => {
129
+ 'type' => 'integer', 'format' => 'int32', 'description' => 'nested array of integers'
130
+ }
131
+ },
132
+ 'required' => %w[array_of_string array_of_integer]
133
+ )
134
+ end
62
135
  end
63
136
 
64
- params do
65
- requires :array_of_entities, type: Array[Entities::ApiError]
66
- end
137
+ describe 'documentation for simple and array parameters' do
138
+ subject do
139
+ get '/swagger_doc/object_and_array'
140
+ JSON.parse(last_response.body)
141
+ end
67
142
 
68
- post '/array_of_entities' do
69
- { 'declared_params' => declared(params) }
143
+ specify do
144
+ expect(subject['definitions']['postObjectAndArray']['type']).to eql 'object'
145
+ expect(subject['definitions']['postObjectAndArray']['properties']).to eql(
146
+ 'array_of_string' => {
147
+ 'type' => 'array',
148
+ 'description' => 'array of strings',
149
+ 'items' => {
150
+ 'type' => 'string'
151
+ }
152
+ },
153
+ 'integer_value' => {
154
+ 'type' => 'integer', 'format' => 'int32', 'description' => 'integer value'
155
+ }
156
+ )
157
+ end
70
158
  end
71
159
 
72
- add_swagger_documentation
73
- end
74
- end
75
-
76
- describe 'retrieves the documentation for grouped parameters' do
77
- subject do
78
- get '/swagger_doc/groups'
79
- JSON.parse(last_response.body)
80
- end
81
-
82
- specify do
83
- expect(subject['paths']['/groups']['post']['parameters']).to eql(
84
- [
85
- { 'in' => 'formData', 'name' => 'required_group[required_param_1]', 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } },
86
- { 'in' => 'formData', 'name' => 'required_group[required_param_2]', 'required' => true, 'type' => 'array', 'items' => { 'type' => 'string' } }
87
- ]
88
- )
89
- end
90
- end
91
-
92
- describe 'retrieves the documentation for typed group parameters' do
93
- subject do
94
- get '/swagger_doc/type_given'
95
- JSON.parse(last_response.body)
96
- end
97
-
98
- specify do
99
- expect(subject['paths']['/type_given']['post']['parameters']).to eql(
100
- [
101
- { 'in' => 'formData', 'name' => 'typed_group[id]', 'description' => 'integer given', 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' }, 'required' => true },
102
- { 'in' => 'formData', 'name' => 'typed_group[name]', 'description' => 'string given', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true },
103
- { 'in' => 'formData', 'name' => 'typed_group[email]', 'description' => 'email given', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => false },
104
- { 'in' => 'formData', 'name' => 'typed_group[others]', 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32', 'enum' => [1, 2, 3] }, 'required' => false }
105
- ]
106
- )
107
- end
108
- end
109
-
110
- describe 'retrieves the documentation for parameters that are arrays of primitive types' do
111
- subject do
112
- get '/swagger_doc/array_of_type'
113
- JSON.parse(last_response.body)
114
- end
115
-
116
- specify do
117
- expect(subject['definitions']['postArrayOfType']['type']).to eql 'array'
118
- expect(subject['definitions']['postArrayOfType']['items']).to eql(
119
- 'type' => 'object',
120
- 'properties' => {
121
- 'array_of_string' => {
122
- 'type' => 'string', 'description' => 'nested array of strings'
123
- },
124
- 'array_of_integer' => {
125
- 'type' => 'integer', 'format' => 'int32', 'description' => 'nested array of integers'
126
- }
127
- },
128
- 'required' => %w[array_of_string array_of_integer]
129
- )
130
- end
131
- end
132
-
133
- describe 'documentation for simple and array parameters' do
134
- subject do
135
- get '/swagger_doc/object_and_array'
136
- JSON.parse(last_response.body)
137
- end
138
-
139
- specify do
140
- expect(subject['definitions']['postObjectAndArray']['type']).to eql 'object'
141
- expect(subject['definitions']['postObjectAndArray']['properties']).to eql(
142
- 'array_of_string' => {
143
- 'type' => 'array',
144
- 'description' => 'array of strings',
145
- 'items' => {
146
- 'type' => 'string'
147
- }
148
- },
149
- 'integer_value' => {
150
- 'type' => 'integer', 'format' => 'int32', 'description' => 'integer value'
151
- }
152
- )
153
- end
154
- end
155
-
156
- describe 'retrieves the documentation for typed group parameters' do
157
- subject do
158
- get '/swagger_doc/array_of_type_in_form'
159
- JSON.parse(last_response.body)
160
- end
160
+ describe 'retrieves the documentation for typed group parameters' do
161
+ subject do
162
+ get '/swagger_doc/array_of_type_in_form'
163
+ JSON.parse(last_response.body)
164
+ end
161
165
 
162
- specify do
163
- expect(subject['paths']['/array_of_type_in_form']['post']['parameters']).to eql(
164
- [
165
- { 'in' => 'formData', 'name' => 'array_of_string', 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true },
166
- { 'in' => 'formData', 'name' => 'array_of_integer', 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' }, 'required' => true }
167
- ]
168
- )
169
- end
170
- end
166
+ specify do
167
+ expect(subject['paths']['/array_of_type_in_form']['post']['parameters']).to eql(
168
+ [
169
+ { 'in' => 'formData', 'name' => "array_of_string#{braces}", 'type' => 'array', 'items' => { 'type' => 'string' }, 'required' => true },
170
+ { 'in' => 'formData', 'name' => "array_of_integer#{braces}", 'type' => 'array', 'items' => { 'type' => 'integer', 'format' => 'int32' }, 'required' => true }
171
+ ]
172
+ )
173
+ end
174
+ end
171
175
 
172
- describe 'documentation for entity array parameters' do
173
- let(:parameters) do
174
- [
175
- {
176
- 'in' => 'formData',
177
- 'name' => 'array_of_entities',
178
- 'type' => 'array',
179
- 'items' => {
180
- '$ref' => '#/definitions/ApiError'
181
- },
182
- 'required' => true
183
- }
184
- ]
185
- end
176
+ describe 'documentation for entity array parameters' do
177
+ let(:parameters) do
178
+ [
179
+ {
180
+ 'in' => 'formData',
181
+ 'name' => "array_of_entities#{braces}",
182
+ 'type' => 'array',
183
+ 'items' => {
184
+ '$ref' => '#/definitions/ApiError'
185
+ },
186
+ 'required' => true
187
+ }
188
+ ]
189
+ end
186
190
 
187
- subject do
188
- get '/swagger_doc/array_of_entities'
189
- JSON.parse(last_response.body)
190
- end
191
+ subject do
192
+ get '/swagger_doc/array_of_entities'
193
+ JSON.parse(last_response.body)
194
+ end
191
195
 
192
- specify do
193
- expect(subject['definitions']['ApiError']).not_to be_blank
194
- expect(subject['paths']['/array_of_entities']['post']['parameters']).to eql(parameters)
196
+ specify do
197
+ expect(subject['definitions']['ApiError']).not_to be_blank
198
+ expect(subject['paths']['/array_of_entities']['post']['parameters']).to eql(parameters)
199
+ end
200
+ end
195
201
  end
196
202
  end
197
203
  end