grape 1.5.2 → 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.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +33 -3
  5. data/UPGRADING.md +71 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +13 -17
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/desc.rb +3 -5
  11. data/lib/grape/dsl/headers.rb +5 -2
  12. data/lib/grape/dsl/helpers.rb +7 -5
  13. data/lib/grape/dsl/inside_route.rb +17 -8
  14. data/lib/grape/dsl/middleware.rb +4 -4
  15. data/lib/grape/dsl/parameters.rb +3 -3
  16. data/lib/grape/dsl/request_response.rb +9 -6
  17. data/lib/grape/dsl/routing.rb +2 -2
  18. data/lib/grape/dsl/settings.rb +5 -5
  19. data/lib/grape/endpoint.rb +21 -36
  20. data/lib/grape/error_formatter/json.rb +2 -6
  21. data/lib/grape/error_formatter/xml.rb +2 -6
  22. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  23. data/lib/grape/exceptions/validation.rb +1 -2
  24. data/lib/grape/formatter/json.rb +1 -0
  25. data/lib/grape/formatter/serializable_hash.rb +2 -1
  26. data/lib/grape/formatter/xml.rb +1 -0
  27. data/lib/grape/locale/en.yml +1 -1
  28. data/lib/grape/middleware/auth/dsl.rb +7 -1
  29. data/lib/grape/middleware/base.rb +3 -1
  30. data/lib/grape/middleware/formatter.rb +4 -4
  31. data/lib/grape/middleware/stack.rb +2 -2
  32. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  33. data/lib/grape/middleware/versioner/header.rb +6 -4
  34. data/lib/grape/middleware/versioner/param.rb +1 -0
  35. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  36. data/lib/grape/middleware/versioner/path.rb +2 -0
  37. data/lib/grape/parser/json.rb +1 -1
  38. data/lib/grape/parser/xml.rb +1 -1
  39. data/lib/grape/path.rb +1 -0
  40. data/lib/grape/request.rb +3 -0
  41. data/lib/grape/router/pattern.rb +1 -1
  42. data/lib/grape/router/route.rb +2 -2
  43. data/lib/grape/router.rb +6 -0
  44. data/lib/grape/util/inheritable_setting.rb +1 -3
  45. data/lib/grape/util/lazy_value.rb +3 -2
  46. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  47. data/lib/grape/validations/params_scope.rb +88 -55
  48. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  49. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  50. data/lib/grape/validations/types/json.rb +2 -1
  51. data/lib/grape/validations/types/primitive_coercer.rb +3 -3
  52. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  53. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  54. data/lib/grape/validations/validators/as.rb +6 -8
  55. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  56. data/lib/grape/validations/validators/base.rb +75 -70
  57. data/lib/grape/validations/validators/coerce.rb +63 -79
  58. data/lib/grape/validations/validators/default.rb +37 -34
  59. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  60. data/lib/grape/validations/validators/except_values.rb +13 -11
  61. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  62. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  63. data/lib/grape/validations/validators/presence.rb +7 -4
  64. data/lib/grape/validations/validators/regexp.rb +8 -5
  65. data/lib/grape/validations/validators/same_as.rb +18 -15
  66. data/lib/grape/validations/validators/values.rb +61 -56
  67. data/lib/grape/validations.rb +6 -0
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +4 -1
  70. data/spec/grape/api/custom_validations_spec.rb +77 -45
  71. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  72. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  73. data/spec/grape/api/invalid_format_spec.rb +2 -0
  74. data/spec/grape/api/recognize_path_spec.rb +1 -1
  75. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  76. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  77. data/spec/grape/api_remount_spec.rb +16 -15
  78. data/spec/grape/api_spec.rb +510 -220
  79. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  80. data/spec/grape/dsl/headers_spec.rb +39 -9
  81. data/spec/grape/dsl/helpers_spec.rb +3 -2
  82. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  83. data/spec/grape/dsl/logger_spec.rb +16 -18
  84. data/spec/grape/dsl/middleware_spec.rb +2 -1
  85. data/spec/grape/dsl/parameters_spec.rb +2 -0
  86. data/spec/grape/dsl/request_response_spec.rb +1 -0
  87. data/spec/grape/dsl/routing_spec.rb +10 -7
  88. data/spec/grape/endpoint/declared_spec.rb +259 -12
  89. data/spec/grape/endpoint_spec.rb +77 -55
  90. data/spec/grape/entity_spec.rb +22 -22
  91. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  92. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  93. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  94. data/spec/grape/exceptions/validation_spec.rb +5 -3
  95. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  96. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  97. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  98. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  99. data/spec/grape/loading_spec.rb +8 -8
  100. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  101. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  102. data/spec/grape/middleware/base_spec.rb +24 -15
  103. data/spec/grape/middleware/error_spec.rb +2 -2
  104. data/spec/grape/middleware/exception_spec.rb +111 -161
  105. data/spec/grape/middleware/formatter_spec.rb +27 -6
  106. data/spec/grape/middleware/globals_spec.rb +7 -4
  107. data/spec/grape/middleware/stack_spec.rb +14 -12
  108. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  109. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  110. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  111. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  112. data/spec/grape/middleware/versioner_spec.rb +1 -1
  113. data/spec/grape/parser_spec.rb +4 -0
  114. data/spec/grape/path_spec.rb +52 -52
  115. data/spec/grape/presenters/presenter_spec.rb +7 -6
  116. data/spec/grape/request_spec.rb +6 -4
  117. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  118. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  119. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  120. data/spec/grape/util/stackable_values_spec.rb +7 -5
  121. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  122. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  123. data/spec/grape/validations/params_scope_spec.rb +46 -10
  124. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
  125. data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
  126. data/spec/grape/validations/types_spec.rb +8 -8
  127. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  128. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  129. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  130. data/spec/grape/validations/validators/coerce_spec.rb +99 -22
  131. data/spec/grape/validations/validators/default_spec.rb +72 -78
  132. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  133. data/spec/grape/validations/validators/except_values_spec.rb +3 -3
  134. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  135. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  136. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  137. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  138. data/spec/grape/validations/validators/values_spec.rb +183 -178
  139. data/spec/grape/validations_spec.rb +99 -58
  140. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  141. data/spec/integration/multi_json/json_spec.rb +1 -1
  142. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  143. data/spec/shared/versioning_examples.rb +12 -9
  144. data/spec/spec_helper.rb +12 -2
  145. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  146. metadata +102 -101
@@ -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 = Path.new('/:id', anything, anything)
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 = Path.new(anything, '/users', anything)
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 = Path.new(anything, anything, foo: 'bar')
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 = Path.new(anything, anything, {})
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 = Path.new(anything, anything, mount_path: nil)
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 = Path.new(anything, anything, mount_path: %w[foo bar])
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 = Path.new(anything, anything, {})
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 = Path.new(anything, anything, root_prefix: nil)
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 = Path.new(anything, anything, root_prefix: 'hello/world')
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 = Path.new(anything, anything, version: nil)
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 = Path.new(
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 = Path.new(
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 = Path.new(anything, nil, anything)
90
- expect(path.namespace?).to be_falsey
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 = Path.new(anything, ' /foo', anything)
95
- expect(path.namespace?).to be_falsey
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 = Path.new(anything, '/', anything)
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 = Path.new(anything, '/world', anything)
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 = Path.new(nil, anything, anything)
112
- expect(path.path?).to be_falsey
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 = Path.new(' /foo', anything, anything)
117
- expect(path.path?).to be_falsey
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 = Path.new('/', anything, anything)
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 = Path.new('/hello', anything, anything)
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 = Path.new(nil, nil, mount_path: '/foo/bar')
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 = Path.new(nil, nil, {})
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 = Path.new(nil, nil, {})
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 = Path.new(
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 = Path.new(
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 = Path.new(
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 = Path.new(nil, nil, {})
189
- allow(path).to receive(:uses_specific_format?) { true }
190
- allow(path).to receive(:settings) { { format: :json } }
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 = Path.new(nil, nil, {})
199
- allow(path).to receive(:uses_specific_format?) { false }
200
- allow(path).to receive(:uses_path_versioning?) { true }
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 = Path.new(nil, 'namespace', {})
209
- allow(path).to receive(:uses_specific_format?) { false }
210
- allow(path).to receive(:uses_path_versioning?) { true }
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 = Path.new('/path', nil, {})
217
- allow(path).to receive(:uses_specific_format?) { false }
218
- allow(path).to receive(:uses_path_versioning?) { true }
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 = Path.new(nil, nil, {})
225
- allow(path).to receive(:uses_specific_format?) { false }
226
- allow(path).to receive(:uses_path_versioning?) { true }
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 = Path.new(nil, nil, {})
236
- allow(path).to receive(:path) { '/the/path' }
237
- allow(path).to receive(:suffix) { '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 = Path.new(nil, nil, {})
245
- allow(path).to receive(:path) { '/the/path' }
246
- allow(path).to receive(:uses_specific_format?) { true }
247
- allow(path).to receive(:settings) { { format: :json } }
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(Presenter.represent(object_mock)).to eq object_mock
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: Grape::Presenters::Presenter
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: Grape::Presenters::Presenter
60
- subject.present hash_mock2, with: Grape::Presenters::Presenter
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
@@ -21,7 +21,7 @@ module Grape
21
21
  let(:env) { default_env }
22
22
 
23
23
  let(:request) do
24
- Grape::Request.new(env)
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
- Grape::Request.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
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 :each do
8
- InheritableSetting.reset_global!
7
+ before do
8
+ described_class.reset_global!
9
9
  end
10
10
 
11
11
  let(:parent) do
12
- Grape::Util::InheritableSetting.new.tap do |settings|
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
- Grape::Util::InheritableSetting.new.tap do |settings|
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 :each do
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 'should handle different parents' do
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 'should handle different parents' do
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
- let(:parent) { InheritableValues.new }
8
- subject { InheritableValues.new(parent) }
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
- let(:parent) { StackableValues.new }
8
- subject { StackableValues.new(parent) }
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 = StackableValues.new
104
- child = StackableValues.new parent
105
- grandchild = StackableValues.new child
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.to_not raise_error
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.to_not raise_error
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.to_not raise_error
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.to_not raise_error
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).to_not include('b')
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 b: ->(val) { val == 'x' } do
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 'raises an error if the dependent parameter is not the renamed one' do
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 'should pass none Hash params' do
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).to_not include('address is empty')
1030
+ expect(last_response.body).not_to include('address is empty')
995
1031
  end
996
1032
  end
997
1033
  end