grape-swagger 0.30.1 → 0.31.0

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