grape 1.5.3 → 1.6.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +39 -0
- data/CONTRIBUTING.md +2 -1
- data/README.md +31 -3
- data/UPGRADING.md +46 -4
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +13 -17
- data/lib/grape/api.rb +17 -12
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -5
- data/lib/grape/dsl/inside_route.rb +17 -8
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +3 -3
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +2 -2
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/endpoint.rb +20 -35
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/validation.rb +1 -2
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +2 -2
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +1 -0
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/params_scope.rb +88 -55
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +3 -3
- data/lib/grape/validations/validators/all_or_none.rb +8 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +6 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
- data/lib/grape/validations/validators/base.rb +75 -70
- data/lib/grape/validations/validators/coerce.rb +63 -79
- data/lib/grape/validations/validators/default.rb +37 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
- data/lib/grape/validations/validators/presence.rb +7 -4
- data/lib/grape/validations/validators/regexp.rb +8 -5
- data/lib/grape/validations/validators/same_as.rb +18 -15
- data/lib/grape/validations/validators/values.rb +61 -56
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +3 -1
- data/spec/grape/api/custom_validations_spec.rb +77 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +16 -15
- data/spec/grape/api_spec.rb +440 -227
- data/spec/grape/dsl/callbacks_spec.rb +2 -1
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +6 -4
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +2 -1
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +10 -7
- data/spec/grape/endpoint/declared_spec.rb +259 -12
- data/spec/grape/endpoint_spec.rb +64 -55
- data/spec/grape/entity_spec.rb +22 -22
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +2 -2
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +27 -6
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +14 -12
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
- data/spec/grape/validations/params_scope_spec.rb +46 -10
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
- data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +23 -22
- data/spec/grape/validations/validators/default_spec.rb +72 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +3 -3
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +183 -178
- data/spec/grape/validations_spec.rb +99 -58
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +12 -2
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +103 -103
data/spec/grape/path_spec.rb
CHANGED
@@ -6,63 +6,63 @@ module Grape
|
|
6
6
|
describe Path do
|
7
7
|
describe '#initialize' do
|
8
8
|
it 'remembers the path' do
|
9
|
-
path =
|
9
|
+
path = described_class.new('/:id', anything, anything)
|
10
10
|
expect(path.raw_path).to eql('/:id')
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'remembers the namespace' do
|
14
|
-
path =
|
14
|
+
path = described_class.new(anything, '/users', anything)
|
15
15
|
expect(path.namespace).to eql('/users')
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'remebers the settings' do
|
19
|
-
path =
|
19
|
+
path = described_class.new(anything, anything, foo: 'bar')
|
20
20
|
expect(path.settings).to eql(foo: 'bar')
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '#mount_path' do
|
25
25
|
it 'is nil when no mount path setting exists' do
|
26
|
-
path =
|
26
|
+
path = described_class.new(anything, anything, {})
|
27
27
|
expect(path.mount_path).to be_nil
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'is nil when the mount path is nil' do
|
31
|
-
path =
|
31
|
+
path = described_class.new(anything, anything, mount_path: nil)
|
32
32
|
expect(path.mount_path).to be_nil
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'splits the mount path' do
|
36
|
-
path =
|
36
|
+
path = described_class.new(anything, anything, mount_path: %w[foo bar])
|
37
37
|
expect(path.mount_path).to eql(%w[foo bar])
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe '#root_prefix' do
|
42
42
|
it 'is nil when no root prefix setting exists' do
|
43
|
-
path =
|
43
|
+
path = described_class.new(anything, anything, {})
|
44
44
|
expect(path.root_prefix).to be_nil
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'is nil when the mount path is nil' do
|
48
|
-
path =
|
48
|
+
path = described_class.new(anything, anything, root_prefix: nil)
|
49
49
|
expect(path.root_prefix).to be_nil
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'splits the mount path' do
|
53
|
-
path =
|
53
|
+
path = described_class.new(anything, anything, root_prefix: 'hello/world')
|
54
54
|
expect(path.root_prefix).to eql(%w[hello world])
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
describe '#uses_path_versioning?' do
|
59
59
|
it 'is false when the version setting is nil' do
|
60
|
-
path =
|
60
|
+
path = described_class.new(anything, anything, version: nil)
|
61
61
|
expect(path.uses_path_versioning?).to be false
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'is false when the version option is header' do
|
65
|
-
path =
|
65
|
+
path = described_class.new(
|
66
66
|
anything,
|
67
67
|
anything,
|
68
68
|
version: 'v1',
|
@@ -73,7 +73,7 @@ module Grape
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'is true when the version option is path' do
|
76
|
-
path =
|
76
|
+
path = described_class.new(
|
77
77
|
anything,
|
78
78
|
anything,
|
79
79
|
version: 'v1',
|
@@ -86,44 +86,44 @@ module Grape
|
|
86
86
|
|
87
87
|
describe '#namespace?' do
|
88
88
|
it 'is false when the namespace is nil' do
|
89
|
-
path =
|
90
|
-
expect(path
|
89
|
+
path = described_class.new(anything, nil, anything)
|
90
|
+
expect(path).not_to be_namespace
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'is false when the namespace starts with whitespace' do
|
94
|
-
path =
|
95
|
-
expect(path
|
94
|
+
path = described_class.new(anything, ' /foo', anything)
|
95
|
+
expect(path).not_to be_namespace
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'is false when the namespace is the root path' do
|
99
|
-
path =
|
99
|
+
path = described_class.new(anything, '/', anything)
|
100
100
|
expect(path.namespace?).to be false
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'is true otherwise' do
|
104
|
-
path =
|
104
|
+
path = described_class.new(anything, '/world', anything)
|
105
105
|
expect(path.namespace?).to be true
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
describe '#path?' do
|
110
110
|
it 'is false when the path is nil' do
|
111
|
-
path =
|
112
|
-
expect(path
|
111
|
+
path = described_class.new(nil, anything, anything)
|
112
|
+
expect(path).not_to be_path
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'is false when the path starts with whitespace' do
|
116
|
-
path =
|
117
|
-
expect(path
|
116
|
+
path = described_class.new(' /foo', anything, anything)
|
117
|
+
expect(path).not_to be_path
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'is false when the path is the root path' do
|
121
|
-
path =
|
121
|
+
path = described_class.new('/', anything, anything)
|
122
122
|
expect(path.path?).to be false
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'is true otherwise' do
|
126
|
-
path =
|
126
|
+
path = described_class.new('/hello', anything, anything)
|
127
127
|
expect(path.path?).to be true
|
128
128
|
end
|
129
129
|
end
|
@@ -131,24 +131,24 @@ module Grape
|
|
131
131
|
describe '#path' do
|
132
132
|
context 'mount_path' do
|
133
133
|
it 'is not included when it is nil' do
|
134
|
-
path =
|
134
|
+
path = described_class.new(nil, nil, mount_path: '/foo/bar')
|
135
135
|
expect(path.path).to eql '/foo/bar'
|
136
136
|
end
|
137
137
|
|
138
138
|
it 'is included when it is not nil' do
|
139
|
-
path =
|
139
|
+
path = described_class.new(nil, nil, {})
|
140
140
|
expect(path.path).to eql('/')
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
144
|
context 'root_prefix' do
|
145
145
|
it 'is not included when it is nil' do
|
146
|
-
path =
|
146
|
+
path = described_class.new(nil, nil, {})
|
147
147
|
expect(path.path).to eql('/')
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'is included after the mount path' do
|
151
|
-
path =
|
151
|
+
path = described_class.new(
|
152
152
|
nil,
|
153
153
|
nil,
|
154
154
|
mount_path: '/foo',
|
@@ -160,7 +160,7 @@ module Grape
|
|
160
160
|
end
|
161
161
|
|
162
162
|
it 'uses the namespace after the mount path and root prefix' do
|
163
|
-
path =
|
163
|
+
path = described_class.new(
|
164
164
|
nil,
|
165
165
|
'namespace',
|
166
166
|
mount_path: '/foo',
|
@@ -171,7 +171,7 @@ module Grape
|
|
171
171
|
end
|
172
172
|
|
173
173
|
it 'uses the raw path after the namespace' do
|
174
|
-
path =
|
174
|
+
path = described_class.new(
|
175
175
|
'raw_path',
|
176
176
|
'namespace',
|
177
177
|
mount_path: '/foo',
|
@@ -185,9 +185,9 @@ module Grape
|
|
185
185
|
describe '#suffix' do
|
186
186
|
context 'when using a specific format' do
|
187
187
|
it 'accepts specified format' do
|
188
|
-
path =
|
189
|
-
allow(path).to receive(:uses_specific_format?)
|
190
|
-
allow(path).to receive(:settings)
|
188
|
+
path = described_class.new(nil, nil, {})
|
189
|
+
allow(path).to receive(:uses_specific_format?).and_return(true)
|
190
|
+
allow(path).to receive(:settings).and_return({ format: :json })
|
191
191
|
|
192
192
|
expect(path.suffix).to eql('(.json)')
|
193
193
|
end
|
@@ -195,9 +195,9 @@ module Grape
|
|
195
195
|
|
196
196
|
context 'when path versioning is used' do
|
197
197
|
it "includes a '/'" do
|
198
|
-
path =
|
199
|
-
allow(path).to receive(:uses_specific_format?)
|
200
|
-
allow(path).to receive(:uses_path_versioning?)
|
198
|
+
path = described_class.new(nil, nil, {})
|
199
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
200
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
201
201
|
|
202
202
|
expect(path.suffix).to eql('(/.:format)')
|
203
203
|
end
|
@@ -205,25 +205,25 @@ module Grape
|
|
205
205
|
|
206
206
|
context 'when path versioning is not used' do
|
207
207
|
it "does not include a '/' when the path has a namespace" do
|
208
|
-
path =
|
209
|
-
allow(path).to receive(:uses_specific_format?)
|
210
|
-
allow(path).to receive(:uses_path_versioning?)
|
208
|
+
path = described_class.new(nil, 'namespace', {})
|
209
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
210
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
211
211
|
|
212
212
|
expect(path.suffix).to eql('(.:format)')
|
213
213
|
end
|
214
214
|
|
215
215
|
it "does not include a '/' when the path has a path" do
|
216
|
-
path =
|
217
|
-
allow(path).to receive(:uses_specific_format?)
|
218
|
-
allow(path).to receive(:uses_path_versioning?)
|
216
|
+
path = described_class.new('/path', nil, {})
|
217
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
218
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
219
219
|
|
220
220
|
expect(path.suffix).to eql('(.:format)')
|
221
221
|
end
|
222
222
|
|
223
223
|
it "includes a '/' otherwise" do
|
224
|
-
path =
|
225
|
-
allow(path).to receive(:uses_specific_format?)
|
226
|
-
allow(path).to receive(:uses_path_versioning?)
|
224
|
+
path = described_class.new(nil, nil, {})
|
225
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
226
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
227
227
|
|
228
228
|
expect(path.suffix).to eql('(/.:format)')
|
229
229
|
end
|
@@ -232,19 +232,19 @@ module Grape
|
|
232
232
|
|
233
233
|
describe '#path_with_suffix' do
|
234
234
|
it 'combines the path and suffix' do
|
235
|
-
path =
|
236
|
-
allow(path).to receive(:path)
|
237
|
-
allow(path).to receive(:suffix)
|
235
|
+
path = described_class.new(nil, nil, {})
|
236
|
+
allow(path).to receive(:path).and_return('/the/path')
|
237
|
+
allow(path).to receive(:suffix).and_return('suffix')
|
238
238
|
|
239
239
|
expect(path.path_with_suffix).to eql('/the/pathsuffix')
|
240
240
|
end
|
241
241
|
|
242
242
|
context 'when using a specific format' do
|
243
243
|
it 'might have a suffix with specified format' do
|
244
|
-
path =
|
245
|
-
allow(path).to receive(:path)
|
246
|
-
allow(path).to receive(:uses_specific_format?)
|
247
|
-
allow(path).to receive(:settings)
|
244
|
+
path = described_class.new(nil, nil, {})
|
245
|
+
allow(path).to receive(:path).and_return('/the/path')
|
246
|
+
allow(path).to receive(:uses_specific_format?).and_return(true)
|
247
|
+
allow(path).to receive(:settings).and_return({ format: :json })
|
248
248
|
|
249
249
|
expect(path.path_with_suffix).to eql('/the/path(.json)')
|
250
250
|
end
|
@@ -19,18 +19,18 @@ module Grape
|
|
19
19
|
end
|
20
20
|
|
21
21
|
describe Presenter do
|
22
|
+
subject { PresenterSpec::Dummy.new }
|
23
|
+
|
22
24
|
describe 'represent' do
|
23
25
|
let(:object_mock) do
|
24
26
|
Object.new
|
25
27
|
end
|
26
28
|
|
27
29
|
it 'represent object' do
|
28
|
-
expect(
|
30
|
+
expect(described_class.represent(object_mock)).to eq object_mock
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
subject { PresenterSpec::Dummy.new }
|
33
|
-
|
34
34
|
describe 'present' do
|
35
35
|
let(:hash_mock) do
|
36
36
|
{ key: :value }
|
@@ -38,8 +38,9 @@ module Grape
|
|
38
38
|
|
39
39
|
describe 'instance' do
|
40
40
|
before do
|
41
|
-
subject.present hash_mock, with:
|
41
|
+
subject.present hash_mock, with: described_class
|
42
42
|
end
|
43
|
+
|
43
44
|
it 'presents dummy hash' do
|
44
45
|
expect(subject.body).to eq hash_mock
|
45
46
|
end
|
@@ -56,8 +57,8 @@ module Grape
|
|
56
57
|
|
57
58
|
describe 'instance' do
|
58
59
|
before do
|
59
|
-
subject.present hash_mock1, with:
|
60
|
-
subject.present hash_mock2, with:
|
60
|
+
subject.present hash_mock1, with: described_class
|
61
|
+
subject.present hash_mock2, with: described_class
|
61
62
|
end
|
62
63
|
|
63
64
|
it 'presents both dummy presenter' do
|
data/spec/grape/request_spec.rb
CHANGED
@@ -21,7 +21,7 @@ module Grape
|
|
21
21
|
let(:env) { default_env }
|
22
22
|
|
23
23
|
let(:request) do
|
24
|
-
|
24
|
+
described_class.new(env)
|
25
25
|
end
|
26
26
|
|
27
27
|
describe '#params' do
|
@@ -38,7 +38,7 @@ module Grape
|
|
38
38
|
|
39
39
|
context 'when build_params_with: Grape::Extensions::Hash::ParamBuilder is specified' do
|
40
40
|
let(:request) do
|
41
|
-
|
41
|
+
described_class.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'returns symbolized params' do
|
@@ -65,6 +65,8 @@ module Grape
|
|
65
65
|
end
|
66
66
|
|
67
67
|
describe 'when the param_builder is set to Hashie' do
|
68
|
+
subject(:request_params) { described_class.new(env, **opts).params }
|
69
|
+
|
68
70
|
before do
|
69
71
|
Grape.configure do |config|
|
70
72
|
config.param_builder = Grape::Extensions::Hashie::Mash::ParamBuilder
|
@@ -75,15 +77,15 @@ module Grape
|
|
75
77
|
Grape.config.reset
|
76
78
|
end
|
77
79
|
|
78
|
-
subject(:request_params) { Grape::Request.new(env, **opts).params }
|
79
|
-
|
80
80
|
context 'when the API does not include a specific param builder' do
|
81
81
|
let(:opts) { {} }
|
82
|
+
|
82
83
|
it { is_expected.to be_a(Hashie::Mash) }
|
83
84
|
end
|
84
85
|
|
85
86
|
context 'when the API includes a specific param builder' do
|
86
87
|
let(:opts) { { build_params_with: Grape::Extensions::Hash::ParamBuilder } }
|
88
|
+
|
87
89
|
it { is_expected.to be_a(Hash) }
|
88
90
|
end
|
89
91
|
end
|
@@ -4,12 +4,12 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe InheritableSetting do
|
7
|
-
before
|
8
|
-
|
7
|
+
before do
|
8
|
+
described_class.reset_global!
|
9
9
|
end
|
10
10
|
|
11
11
|
let(:parent) do
|
12
|
-
|
12
|
+
described_class.new.tap do |settings|
|
13
13
|
settings.global[:global_thing] = :global_foo_bar
|
14
14
|
settings.namespace[:namespace_thing] = :namespace_foo_bar
|
15
15
|
settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
|
@@ -20,7 +20,7 @@ module Grape
|
|
20
20
|
end
|
21
21
|
|
22
22
|
let(:other_parent) do
|
23
|
-
|
23
|
+
described_class.new.tap do |settings|
|
24
24
|
settings.namespace[:namespace_thing] = :namespace_foo_bar_other
|
25
25
|
settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar_other
|
26
26
|
settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar_other
|
@@ -29,7 +29,7 @@ module Grape
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
before
|
32
|
+
before do
|
33
33
|
subject.inherit_from parent
|
34
34
|
end
|
35
35
|
|
@@ -50,7 +50,7 @@ module Grape
|
|
50
50
|
expect(parent.global[:global_thing]).to eq :global_new_foo_bar
|
51
51
|
end
|
52
52
|
|
53
|
-
it '
|
53
|
+
it 'handles different parents' do
|
54
54
|
subject.global[:global_thing] = :global_new_foo_bar
|
55
55
|
|
56
56
|
subject.inherit_from other_parent
|
@@ -89,7 +89,7 @@ module Grape
|
|
89
89
|
expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
|
90
90
|
end
|
91
91
|
|
92
|
-
it '
|
92
|
+
it 'handles different parents' do
|
93
93
|
expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
|
94
94
|
|
95
95
|
subject.inherit_from other_parent
|
@@ -4,8 +4,9 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe InheritableValues do
|
7
|
-
|
8
|
-
|
7
|
+
subject { described_class.new(parent) }
|
8
|
+
|
9
|
+
let(:parent) { described_class.new }
|
9
10
|
|
10
11
|
describe '#delete' do
|
11
12
|
it 'deletes a key' do
|
@@ -4,9 +4,10 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe ReverseStackableValues do
|
7
|
-
let(:parent) { described_class.new }
|
8
7
|
subject { described_class.new(parent) }
|
9
8
|
|
9
|
+
let(:parent) { described_class.new }
|
10
|
+
|
10
11
|
describe '#keys' do
|
11
12
|
it 'returns all keys' do
|
12
13
|
subject[:some_thing] = :foo_bar
|
@@ -102,6 +103,7 @@ module Grape
|
|
102
103
|
|
103
104
|
describe '#clone' do
|
104
105
|
let(:obj_cloned) { subject.clone }
|
106
|
+
|
105
107
|
it 'copies all values' do
|
106
108
|
parent = described_class.new
|
107
109
|
child = described_class.new parent
|
@@ -4,8 +4,9 @@ require 'spec_helper'
|
|
4
4
|
module Grape
|
5
5
|
module Util
|
6
6
|
describe StackableValues do
|
7
|
-
|
8
|
-
|
7
|
+
subject { described_class.new(parent) }
|
8
|
+
|
9
|
+
let(:parent) { described_class.new }
|
9
10
|
|
10
11
|
describe '#keys' do
|
11
12
|
it 'returns all keys' do
|
@@ -99,10 +100,11 @@ module Grape
|
|
99
100
|
|
100
101
|
describe '#clone' do
|
101
102
|
let(:obj_cloned) { subject.clone }
|
103
|
+
|
102
104
|
it 'copies all values' do
|
103
|
-
parent =
|
104
|
-
child =
|
105
|
-
grandchild =
|
105
|
+
parent = described_class.new
|
106
|
+
child = described_class.new parent
|
107
|
+
grandchild = described_class.new child
|
106
108
|
|
107
109
|
parent[:some_thing] = :foo
|
108
110
|
child[:some_thing] = %i[bar more]
|
@@ -4,7 +4,7 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe 'Validator with instance variables' do
|
6
6
|
let(:validator_type) do
|
7
|
-
Class.new(Grape::Validations::Base) do
|
7
|
+
Class.new(Grape::Validations::Validators::Base) do
|
8
8
|
def validate_param!(_attr_name, _params)
|
9
9
|
if instance_variable_defined?(:@instance_variable) && @instance_variable
|
10
10
|
raise Grape::Exceptions::Validation.new(params: ['params'],
|
@@ -14,15 +14,6 @@ describe 'Validator with instance variables' do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
17
|
-
|
18
|
-
before do
|
19
|
-
Grape::Validations.register_validator('instance_validator', validator_type)
|
20
|
-
end
|
21
|
-
|
22
|
-
after do
|
23
|
-
Grape::Validations.deregister_validator('instance_validator')
|
24
|
-
end
|
25
|
-
|
26
17
|
let(:app) do
|
27
18
|
Class.new(Grape::API) do
|
28
19
|
params do
|
@@ -35,6 +26,14 @@ describe 'Validator with instance variables' do
|
|
35
26
|
end
|
36
27
|
end
|
37
28
|
|
29
|
+
before do
|
30
|
+
Grape::Validations.register_validator('instance_validator', validator_type)
|
31
|
+
end
|
32
|
+
|
33
|
+
after do
|
34
|
+
Grape::Validations.deregister_validator('instance_validator')
|
35
|
+
end
|
36
|
+
|
38
37
|
it 'passes validation every time' do
|
39
38
|
expect(validator_type).to receive(:new).exactly(4).times.and_call_original
|
40
39
|
|
@@ -5,6 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Validations::MultipleAttributesIterator do
|
6
6
|
describe '#each' do
|
7
7
|
subject(:iterator) { described_class.new(validator, scope, params) }
|
8
|
+
|
8
9
|
let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
|
9
10
|
let(:validator) { double(attrs: %i[first second third]) }
|
10
11
|
|
@@ -98,6 +98,7 @@ describe Grape::Validations::ParamsScope do
|
|
98
98
|
|
99
99
|
def self.parse(value)
|
100
100
|
raise if value == 'invalid'
|
101
|
+
|
101
102
|
new(value)
|
102
103
|
end
|
103
104
|
|
@@ -144,7 +145,7 @@ describe Grape::Validations::ParamsScope do
|
|
144
145
|
get '/renaming-coerced', foo: ' there we go '
|
145
146
|
|
146
147
|
expect(last_response.status).to eq(200)
|
147
|
-
expect(last_response.body).to eq('there we go
|
148
|
+
expect(last_response.body).to eq('-there we go')
|
148
149
|
end
|
149
150
|
|
150
151
|
it do
|
@@ -180,6 +181,28 @@ describe Grape::Validations::ParamsScope do
|
|
180
181
|
expect(last_response.status).to eq(200)
|
181
182
|
expect(last_response.body).to eq('{"baz":{"qux":"any"}}')
|
182
183
|
end
|
184
|
+
|
185
|
+
it 'renaming can be defined before default' do
|
186
|
+
subject.params do
|
187
|
+
optional :foo, as: :bar, default: 'before'
|
188
|
+
end
|
189
|
+
subject.get('/rename-before-default') { declared(params)[:bar] }
|
190
|
+
get '/rename-before-default'
|
191
|
+
|
192
|
+
expect(last_response.status).to eq(200)
|
193
|
+
expect(last_response.body).to eq('before')
|
194
|
+
end
|
195
|
+
|
196
|
+
it 'renaming can be defined after default' do
|
197
|
+
subject.params do
|
198
|
+
optional :foo, default: 'after', as: :bar
|
199
|
+
end
|
200
|
+
subject.get('/rename-after-default') { declared(params)[:bar] }
|
201
|
+
get '/rename-after-default'
|
202
|
+
|
203
|
+
expect(last_response.status).to eq(200)
|
204
|
+
expect(last_response.body).to eq('after')
|
205
|
+
end
|
183
206
|
end
|
184
207
|
|
185
208
|
context 'array without coerce type explicitly given' do
|
@@ -269,7 +292,7 @@ describe Grape::Validations::ParamsScope do
|
|
269
292
|
it 'does not raise an exception' do
|
270
293
|
expect do
|
271
294
|
subject.params { optional :numbers, type: Array[Integer], values: 0..2, default: 0..2 }
|
272
|
-
end.
|
295
|
+
end.not_to raise_error
|
273
296
|
end
|
274
297
|
end
|
275
298
|
|
@@ -277,7 +300,7 @@ describe Grape::Validations::ParamsScope do
|
|
277
300
|
it 'does not raise an exception' do
|
278
301
|
expect do
|
279
302
|
subject.params { optional :numbers, type: Array[Integer], values: [0, 1, 2], default: [1, 0] }
|
280
|
-
end.
|
303
|
+
end.not_to raise_error
|
281
304
|
end
|
282
305
|
end
|
283
306
|
end
|
@@ -501,7 +524,7 @@ describe Grape::Validations::ParamsScope do
|
|
501
524
|
requires :c
|
502
525
|
end
|
503
526
|
end
|
504
|
-
end.
|
527
|
+
end.not_to raise_error
|
505
528
|
end
|
506
529
|
|
507
530
|
it 'does not raise an error if when using nested given' do
|
@@ -517,7 +540,7 @@ describe Grape::Validations::ParamsScope do
|
|
517
540
|
end
|
518
541
|
end
|
519
542
|
end
|
520
|
-
end.
|
543
|
+
end.not_to raise_error
|
521
544
|
end
|
522
545
|
|
523
546
|
it 'allows nested dependent parameters' do
|
@@ -562,13 +585,13 @@ describe Grape::Validations::ParamsScope do
|
|
562
585
|
body = JSON.parse(last_response.body)
|
563
586
|
|
564
587
|
expect(body.keys).to include('c')
|
565
|
-
expect(body.keys).
|
588
|
+
expect(body.keys).not_to include('b')
|
566
589
|
end
|
567
590
|
|
568
591
|
it 'allows renaming of dependent on parameter' do
|
569
592
|
subject.params do
|
570
593
|
optional :a, as: :b
|
571
|
-
given
|
594
|
+
given a: ->(val) { val == 'x' } do
|
572
595
|
requires :c
|
573
596
|
end
|
574
597
|
end
|
@@ -582,7 +605,7 @@ describe Grape::Validations::ParamsScope do
|
|
582
605
|
expect(last_response.status).to eq 200
|
583
606
|
end
|
584
607
|
|
585
|
-
it '
|
608
|
+
it 'does not raise if the dependent parameter is not the renamed one' do
|
586
609
|
expect do
|
587
610
|
subject.params do
|
588
611
|
optional :a, as: :b
|
@@ -590,6 +613,17 @@ describe Grape::Validations::ParamsScope do
|
|
590
613
|
requires :c
|
591
614
|
end
|
592
615
|
end
|
616
|
+
end.not_to raise_error
|
617
|
+
end
|
618
|
+
|
619
|
+
it 'raises an error if the dependent parameter is the renamed one' do
|
620
|
+
expect do
|
621
|
+
subject.params do
|
622
|
+
optional :a, as: :b
|
623
|
+
given :b do
|
624
|
+
requires :c
|
625
|
+
end
|
626
|
+
end
|
593
627
|
end.to raise_error(Grape::Exceptions::UnknownParameter)
|
594
628
|
end
|
595
629
|
|
@@ -753,7 +787,7 @@ describe Grape::Validations::ParamsScope do
|
|
753
787
|
subject.get('/test') { 'ok' }
|
754
788
|
end
|
755
789
|
|
756
|
-
it '
|
790
|
+
it 'passes none Hash params' do
|
757
791
|
get '/test', foos: ['']
|
758
792
|
expect(last_response.status).to eq(200)
|
759
793
|
expect(last_response.body).to eq('ok')
|
@@ -929,6 +963,7 @@ describe Grape::Validations::ParamsScope do
|
|
929
963
|
expect(last_response.body).to eq('one is missing, two is missing, three is missing')
|
930
964
|
end
|
931
965
|
end
|
966
|
+
|
932
967
|
context 'when fail_fast is defined it stops the validation' do
|
933
968
|
it 'of other params' do
|
934
969
|
subject.params do
|
@@ -941,6 +976,7 @@ describe Grape::Validations::ParamsScope do
|
|
941
976
|
expect(last_response.status).to eq(400)
|
942
977
|
expect(last_response.body).to eq('one is missing')
|
943
978
|
end
|
979
|
+
|
944
980
|
it 'for a single param' do
|
945
981
|
subject.params do
|
946
982
|
requires :one, allow_blank: false, regexp: /[0-9]+/, fail_fast: true
|
@@ -991,7 +1027,7 @@ describe Grape::Validations::ParamsScope do
|
|
991
1027
|
end
|
992
1028
|
|
993
1029
|
it 'prioritizes parameter validation over group validation' do
|
994
|
-
expect(last_response.body).
|
1030
|
+
expect(last_response.body).not_to include('address is empty')
|
995
1031
|
end
|
996
1032
|
end
|
997
1033
|
end
|