grape 1.5.3 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/CONTRIBUTING.md +32 -1
  4. data/README.md +176 -25
  5. data/UPGRADING.md +61 -4
  6. data/grape.gemspec +6 -6
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +17 -12
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +4 -20
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +13 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +22 -37
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +3 -2
  28. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  29. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  30. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  31. data/lib/grape/exceptions/validation.rb +1 -6
  32. data/lib/grape/formatter/json.rb +1 -0
  33. data/lib/grape/formatter/serializable_hash.rb +2 -1
  34. data/lib/grape/formatter/xml.rb +1 -0
  35. data/lib/grape/locale/en.yml +9 -8
  36. data/lib/grape/middleware/auth/dsl.rb +7 -2
  37. data/lib/grape/middleware/base.rb +3 -1
  38. data/lib/grape/middleware/error.rb +2 -2
  39. data/lib/grape/middleware/formatter.rb +4 -4
  40. data/lib/grape/middleware/stack.rb +3 -3
  41. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  42. data/lib/grape/middleware/versioner/header.rb +6 -4
  43. data/lib/grape/middleware/versioner/param.rb +1 -0
  44. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  45. data/lib/grape/middleware/versioner/path.rb +2 -0
  46. data/lib/grape/path.rb +1 -0
  47. data/lib/grape/request.rb +4 -1
  48. data/lib/grape/router/attribute_translator.rb +1 -1
  49. data/lib/grape/router/pattern.rb +1 -1
  50. data/lib/grape/router/route.rb +2 -2
  51. data/lib/grape/router.rb +6 -0
  52. data/lib/grape/types/invalid_value.rb +8 -0
  53. data/lib/grape/util/cache.rb +1 -1
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +138 -79
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/invalid_value.rb +0 -7
  64. data/lib/grape/validations/types/json.rb +2 -1
  65. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  66. data/lib/grape/validations/types/set_coercer.rb +0 -2
  67. data/lib/grape/validations/types.rb +98 -30
  68. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  69. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  70. data/lib/grape/validations/validators/as_validator.rb +14 -0
  71. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  72. data/lib/grape/validations/validators/base.rb +82 -70
  73. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  74. data/lib/grape/validations/validators/default_validator.rb +51 -0
  75. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  76. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  77. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  78. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  79. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  80. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  81. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  82. data/lib/grape/validations/validators/values_validator.rb +88 -0
  83. data/lib/grape/validations.rb +16 -6
  84. data/lib/grape/version.rb +1 -1
  85. data/lib/grape.rb +77 -29
  86. data/spec/grape/api/custom_validations_spec.rb +116 -45
  87. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  88. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  89. data/spec/grape/api/documentation_spec.rb +59 -0
  90. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  91. data/spec/grape/api/instance_spec.rb +0 -1
  92. data/spec/grape/api/invalid_format_spec.rb +2 -2
  93. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  94. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  95. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  96. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  97. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  98. data/spec/grape/api/recognize_path_spec.rb +1 -3
  99. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  100. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  101. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  102. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  103. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  104. data/spec/grape/api_remount_spec.rb +16 -16
  105. data/spec/grape/api_spec.rb +462 -251
  106. data/spec/grape/config_spec.rb +0 -2
  107. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  108. data/spec/grape/dsl/desc_spec.rb +2 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +88 -59
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +64 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +6 -7
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +28 -19
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +33 -14
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  169. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  170. data/spec/grape/validations/params_scope_spec.rb +361 -96
  171. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  172. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  173. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  174. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  175. data/spec/grape/validations/types_spec.rb +36 -10
  176. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  177. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  178. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  179. data/spec/grape/validations/validators/coerce_spec.rb +23 -24
  180. data/spec/grape/validations/validators/default_spec.rb +72 -80
  181. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  182. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  183. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  184. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  185. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  186. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  187. data/spec/grape/validations/validators/values_spec.rb +201 -179
  188. data/spec/grape/validations_spec.rb +171 -79
  189. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  190. data/spec/integration/multi_json/json_spec.rb +1 -3
  191. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  192. data/spec/shared/versioning_examples.rb +12 -9
  193. data/spec/spec_helper.rb +21 -6
  194. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  195. metadata +41 -29
  196. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  197. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  198. data/lib/grape/validations/validators/as.rb +0 -16
  199. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  200. data/lib/grape/validations/validators/coerce.rb +0 -91
  201. data/lib/grape/validations/validators/default.rb +0 -48
  202. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  203. data/lib/grape/validations/validators/except_values.rb +0 -22
  204. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  205. data/lib/grape/validations/validators/presence.rb +0 -12
  206. data/lib/grape/validations/validators/regexp.rb +0 -13
  207. data/lib/grape/validations/validators/same_as.rb +0 -26
  208. data/lib/grape/validations/validators/values.rb +0 -83
  209. data/spec/grape/dsl/configuration_spec.rb +0 -16
  210. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  211. data/spec/support/eager_load.rb +0 -19
@@ -1,33 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::InvalidAcceptHeader do
6
4
  shared_examples_for 'a valid request' do
7
5
  it 'does return with status 200' do
8
6
  expect(last_response.status).to eq 200
9
7
  end
8
+
10
9
  it 'does return the expected result' do
11
10
  expect(last_response.body).to eq('beer received')
12
11
  end
13
12
  end
13
+
14
14
  shared_examples_for 'a cascaded request' do
15
15
  it 'does not find a matching route' do
16
16
  expect(last_response.status).to eq 404
17
17
  end
18
18
  end
19
+
19
20
  shared_examples_for 'a not-cascaded request' do
20
21
  it 'does not include the X-Cascade=pass header' do
21
22
  expect(last_response.headers['X-Cascade']).to be_nil
22
23
  end
24
+
23
25
  it 'does not accept the request' do
24
26
  expect(last_response.status).to eq 406
25
27
  end
26
28
  end
29
+
27
30
  shared_examples_for 'a rescued request' do
28
31
  it 'does not include the X-Cascade=pass header' do
29
32
  expect(last_response.headers['X-Cascade']).to be_nil
30
33
  end
34
+
31
35
  it 'does show rescue handler processing' do
32
36
  expect(last_response.status).to eq 400
33
37
  expect(last_response.body).to eq('message was processed')
@@ -36,6 +40,7 @@ describe Grape::Exceptions::InvalidAcceptHeader do
36
40
 
37
41
  context 'API with cascade=false and rescue_from :all handler' do
38
42
  subject { Class.new(Grape::API) }
43
+
39
44
  before do
40
45
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
41
46
  subject.rescue_from :all do |e|
@@ -52,7 +57,8 @@ describe Grape::Exceptions::InvalidAcceptHeader do
52
57
 
53
58
  context 'that received a request with correct vendor and version' do
54
59
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
55
- it_should_behave_like 'a valid request'
60
+
61
+ it_behaves_like 'a valid request'
56
62
  end
57
63
 
58
64
  context 'that receives' do
@@ -61,13 +67,15 @@ describe Grape::Exceptions::InvalidAcceptHeader do
61
67
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
62
68
  'CONTENT_TYPE' => 'application/json'
63
69
  end
64
- it_should_behave_like 'a rescued request'
70
+
71
+ it_behaves_like 'a rescued request'
65
72
  end
66
73
  end
67
74
  end
68
75
 
69
76
  context 'API with cascade=false and without a rescue handler' do
70
77
  subject { Class.new(Grape::API) }
78
+
71
79
  before do
72
80
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
73
81
  subject.get '/beer' do
@@ -81,23 +89,28 @@ describe Grape::Exceptions::InvalidAcceptHeader do
81
89
 
82
90
  context 'that received a request with correct vendor and version' do
83
91
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
84
- it_should_behave_like 'a valid request'
92
+
93
+ it_behaves_like 'a valid request'
85
94
  end
86
95
 
87
96
  context 'that receives' do
88
97
  context 'an invalid version in the request' do
89
98
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
90
- it_should_behave_like 'a not-cascaded request'
99
+
100
+ it_behaves_like 'a not-cascaded request'
91
101
  end
102
+
92
103
  context 'an invalid vendor in the request' do
93
104
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
94
- it_should_behave_like 'a not-cascaded request'
105
+
106
+ it_behaves_like 'a not-cascaded request'
95
107
  end
96
108
  end
97
109
  end
98
110
 
99
111
  context 'API with cascade=false and with rescue_from :all handler and http_codes' do
100
112
  subject { Class.new(Grape::API) }
113
+
101
114
  before do
102
115
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
103
116
  subject.rescue_from :all do |e|
@@ -119,7 +132,8 @@ describe Grape::Exceptions::InvalidAcceptHeader do
119
132
 
120
133
  context 'that received a request with correct vendor and version' do
121
134
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
122
- it_should_behave_like 'a valid request'
135
+
136
+ it_behaves_like 'a valid request'
123
137
  end
124
138
 
125
139
  context 'that receives' do
@@ -128,13 +142,15 @@ describe Grape::Exceptions::InvalidAcceptHeader do
128
142
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
129
143
  'CONTENT_TYPE' => 'application/json'
130
144
  end
131
- it_should_behave_like 'a rescued request'
145
+
146
+ it_behaves_like 'a rescued request'
132
147
  end
133
148
  end
134
149
  end
135
150
 
136
151
  context 'API with cascade=false, http_codes but without a rescue handler' do
137
152
  subject { Class.new(Grape::API) }
153
+
138
154
  before do
139
155
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: false
140
156
  subject.desc 'Get beer' do
@@ -153,23 +169,28 @@ describe Grape::Exceptions::InvalidAcceptHeader do
153
169
 
154
170
  context 'that received a request with correct vendor and version' do
155
171
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
156
- it_should_behave_like 'a valid request'
172
+
173
+ it_behaves_like 'a valid request'
157
174
  end
158
175
 
159
176
  context 'that receives' do
160
177
  context 'an invalid version in the request' do
161
178
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
162
- it_should_behave_like 'a not-cascaded request'
179
+
180
+ it_behaves_like 'a not-cascaded request'
163
181
  end
182
+
164
183
  context 'an invalid vendor in the request' do
165
184
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
166
- it_should_behave_like 'a not-cascaded request'
185
+
186
+ it_behaves_like 'a not-cascaded request'
167
187
  end
168
188
  end
169
189
  end
170
190
 
171
191
  context 'API with cascade=true and rescue_from :all handler' do
172
192
  subject { Class.new(Grape::API) }
193
+
173
194
  before do
174
195
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
175
196
  subject.rescue_from :all do |e|
@@ -186,7 +207,8 @@ describe Grape::Exceptions::InvalidAcceptHeader do
186
207
 
187
208
  context 'that received a request with correct vendor and version' do
188
209
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
189
- it_should_behave_like 'a valid request'
210
+
211
+ it_behaves_like 'a valid request'
190
212
  end
191
213
 
192
214
  context 'that receives' do
@@ -195,20 +217,24 @@ describe Grape::Exceptions::InvalidAcceptHeader do
195
217
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
196
218
  'CONTENT_TYPE' => 'application/json'
197
219
  end
198
- it_should_behave_like 'a cascaded request'
220
+
221
+ it_behaves_like 'a cascaded request'
199
222
  end
223
+
200
224
  context 'an invalid vendor in the request' do
201
225
  before do
202
226
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
203
227
  'CONTENT_TYPE' => 'application/json'
204
228
  end
205
- it_should_behave_like 'a cascaded request'
229
+
230
+ it_behaves_like 'a cascaded request'
206
231
  end
207
232
  end
208
233
  end
209
234
 
210
235
  context 'API with cascade=true and without a rescue handler' do
211
236
  subject { Class.new(Grape::API) }
237
+
212
238
  before do
213
239
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
214
240
  subject.get '/beer' do
@@ -222,23 +248,28 @@ describe Grape::Exceptions::InvalidAcceptHeader do
222
248
 
223
249
  context 'that received a request with correct vendor and version' do
224
250
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
225
- it_should_behave_like 'a valid request'
251
+
252
+ it_behaves_like 'a valid request'
226
253
  end
227
254
 
228
255
  context 'that receives' do
229
256
  context 'an invalid version in the request' do
230
257
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
231
- it_should_behave_like 'a cascaded request'
258
+
259
+ it_behaves_like 'a cascaded request'
232
260
  end
261
+
233
262
  context 'an invalid vendor in the request' do
234
263
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
235
- it_should_behave_like 'a cascaded request'
264
+
265
+ it_behaves_like 'a cascaded request'
236
266
  end
237
267
  end
238
268
  end
239
269
 
240
270
  context 'API with cascade=true and with rescue_from :all handler and http_codes' do
241
271
  subject { Class.new(Grape::API) }
272
+
242
273
  before do
243
274
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
244
275
  subject.rescue_from :all do |e|
@@ -260,7 +291,8 @@ describe Grape::Exceptions::InvalidAcceptHeader do
260
291
 
261
292
  context 'that received a request with correct vendor and version' do
262
293
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
263
- it_should_behave_like 'a valid request'
294
+
295
+ it_behaves_like 'a valid request'
264
296
  end
265
297
 
266
298
  context 'that receives' do
@@ -269,20 +301,24 @@ describe Grape::Exceptions::InvalidAcceptHeader do
269
301
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77',
270
302
  'CONTENT_TYPE' => 'application/json'
271
303
  end
272
- it_should_behave_like 'a cascaded request'
304
+
305
+ it_behaves_like 'a cascaded request'
273
306
  end
307
+
274
308
  context 'an invalid vendor in the request' do
275
309
  before do
276
310
  get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99',
277
311
  'CONTENT_TYPE' => 'application/json'
278
312
  end
279
- it_should_behave_like 'a cascaded request'
313
+
314
+ it_behaves_like 'a cascaded request'
280
315
  end
281
316
  end
282
317
  end
283
318
 
284
319
  context 'API with cascade=true, http_codes but without a rescue handler' do
285
320
  subject { Class.new(Grape::API) }
321
+
286
322
  before do
287
323
  subject.version 'v99', using: :header, vendor: 'vendorname', format: :json, cascade: true
288
324
  subject.desc 'Get beer' do
@@ -301,17 +337,21 @@ describe Grape::Exceptions::InvalidAcceptHeader do
301
337
 
302
338
  context 'that received a request with correct vendor and version' do
303
339
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v99' }
304
- it_should_behave_like 'a valid request'
340
+
341
+ it_behaves_like 'a valid request'
305
342
  end
306
343
 
307
344
  context 'that receives' do
308
345
  context 'an invalid version in the request' do
309
346
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.vendorname-v77' }
310
- it_should_behave_like 'a cascaded request'
347
+
348
+ it_behaves_like 'a cascaded request'
311
349
  end
350
+
312
351
  context 'an invalid vendor in the request' do
313
352
  before { get '/beer', {}, 'HTTP_ACCEPT' => 'application/vnd.invalidvendor-v99' }
314
- it_should_behave_like 'a cascaded request'
353
+
354
+ it_behaves_like 'a cascaded request'
315
355
  end
316
356
  end
317
357
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::InvalidFormatter do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::InvalidResponse do
6
4
  describe '#message' do
7
5
  let(:error) { described_class.new }
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::InvalidVersionerOption do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -10,7 +8,7 @@ describe Grape::Exceptions::InvalidVersionerOption do
10
8
 
11
9
  it 'contains the problem in the message' do
12
10
  expect(error.message).to include(
13
- 'Unknown :using for versioner: headers'
11
+ 'unknown :using for versioner: headers'
14
12
  )
15
13
  end
16
14
  end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Grape::Exceptions::MissingGroupType do
4
+ describe '#message' do
5
+ subject { described_class.new.message }
6
+
7
+ it { is_expected.to include 'group type is required' }
8
+ end
9
+
10
+ describe 'deprecated Grape::Exceptions::MissingGroupTypeError' do
11
+ subject { Grape::Exceptions::MissingGroupTypeError.new }
12
+
13
+ it 'puts a deprecation warning' do
14
+ expect(Warning).to receive(:warn) do |message|
15
+ expect(message).to include('`Grape::Exceptions::MissingGroupTypeError` is deprecated')
16
+ end
17
+
18
+ subject
19
+ end
20
+ end
21
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::MissingMimeType do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::MissingOption do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -10,7 +8,7 @@ describe Grape::Exceptions::MissingOption do
10
8
 
11
9
  it 'contains the problem in the message' do
12
10
  expect(error.message).to include(
13
- 'You must specify :path options.'
11
+ 'you must specify :path options'
14
12
  )
15
13
  end
16
14
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::UnknownOptions do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::UnknownValidator do
6
4
  describe '#message' do
7
5
  let(:error) do
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe Grape::Exceptions::UnsupportedGroupType do
4
+ subject { described_class.new }
5
+
6
+ describe '#message' do
7
+ subject { described_class.new.message }
8
+
9
+ it { is_expected.to include 'group type must be Array, Hash, JSON or Array[JSON]' }
10
+ end
11
+
12
+ describe 'deprecated Grape::Exceptions::UnsupportedGroupTypeError' do
13
+ subject { Grape::Exceptions::UnsupportedGroupTypeError.new }
14
+
15
+ it 'puts a deprecation warning' do
16
+ expect(Warning).to receive(:warn) do |message|
17
+ expect(message).to include('`Grape::Exceptions::UnsupportedGroupTypeError` is deprecated')
18
+ end
19
+
20
+ subject
21
+ end
22
+ end
23
+ end
@@ -1,34 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  require 'ostruct'
5
4
 
6
5
  describe Grape::Exceptions::ValidationErrors do
7
6
  let(:validation_message) { 'FooBar is invalid' }
8
- let(:validation_error) { OpenStruct.new(params: [validation_message]) }
7
+ let(:validation_error) { instance_double Grape::Exceptions::Validation, params: [validation_message], message: '' }
9
8
 
10
9
  context 'initialize' do
10
+ subject do
11
+ described_class.new(errors: [validation_error], headers: headers)
12
+ end
13
+
11
14
  let(:headers) do
12
15
  {
13
16
  'A-Header-Key' => 'A-Header-Value'
14
17
  }
15
18
  end
16
19
 
17
- subject do
18
- described_class.new(errors: [validation_error], headers: headers)
19
- end
20
-
21
- it 'should assign headers through base class' do
20
+ it 'assigns headers through base class' do
22
21
  expect(subject.headers).to eq(headers)
23
22
  end
24
23
  end
25
24
 
26
25
  context 'message' do
27
26
  context 'is not repeated' do
27
+ subject(:message) { error.message.split(',').map(&:strip) }
28
+
28
29
  let(:error) do
29
30
  described_class.new(errors: [validation_error, validation_error])
30
31
  end
31
- subject(:message) { error.message.split(',').map(&:strip) }
32
32
 
33
33
  it { expect(message).to include validation_message }
34
34
  it { expect(message.size).to eq 1 }
@@ -37,9 +37,10 @@ describe Grape::Exceptions::ValidationErrors do
37
37
 
38
38
  describe '#full_messages' do
39
39
  context 'with errors' do
40
+ subject { described_class.new(errors: [validation_error_1, validation_error_2]).full_messages }
41
+
40
42
  let(:validation_error_1) { Grape::Exceptions::Validation.new(params: ['id'], message: :presence) }
41
43
  let(:validation_error_2) { Grape::Exceptions::Validation.new(params: ['name'], message: :presence) }
42
- subject { described_class.new(errors: [validation_error_1, validation_error_2]).full_messages }
43
44
 
44
45
  it 'returns an array with each errors full message' do
45
46
  expect(subject).to contain_exactly('id is missing', 'name is missing')
@@ -47,9 +48,10 @@ describe Grape::Exceptions::ValidationErrors do
47
48
  end
48
49
 
49
50
  context 'when attributes is an array of symbols' do
50
- let(:validation_error) { Grape::Exceptions::Validation.new(params: [:admin_field], message: 'Can not set admin-only field') }
51
51
  subject { described_class.new(errors: [validation_error]).full_messages }
52
52
 
53
+ let(:validation_error) { Grape::Exceptions::Validation.new(params: [:admin_field], message: 'Can not set admin-only field') }
54
+
53
55
  it 'returns an array with an error full message' do
54
56
  expect(subject.first).to eq('admin_field Can not set admin-only field')
55
57
  end
@@ -65,7 +67,7 @@ describe Grape::Exceptions::ValidationErrors do
65
67
 
66
68
  it 'can return structured json with separate fields' do
67
69
  subject.format :json
68
- subject.rescue_from Grape::Exceptions::ValidationErrors do |e|
70
+ subject.rescue_from described_class do |e|
69
71
  error!(e, 400)
70
72
  end
71
73
  subject.params do
@@ -1,19 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::Validation do
6
4
  it 'fails when params are missing' do
7
- expect { Grape::Exceptions::Validation.new(message: 'presence') }.to raise_error(ArgumentError, /missing keyword:.+?params/)
5
+ expect { described_class.new(message: 'presence') }.to raise_error(ArgumentError, /missing keyword:.+?params/)
8
6
  end
7
+
9
8
  context 'when message is a symbol' do
10
9
  it 'stores message_key' do
11
- expect(Grape::Exceptions::Validation.new(params: ['id'], message: :presence).message_key).to eq(:presence)
10
+ expect(described_class.new(params: ['id'], message: :presence).message_key).to eq(:presence)
12
11
  end
13
12
  end
13
+
14
14
  context 'when message is a String' do
15
15
  it 'does not store the message_key' do
16
- expect(Grape::Exceptions::Validation.new(params: ['id'], message: 'presence').message_key).to eq(nil)
16
+ expect(described_class.new(params: ['id'], message: 'presence').message_key).to be_nil
17
17
  end
18
18
  end
19
19
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Extensions::Hash::ParamBuilder do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -10,10 +8,10 @@ describe Grape::Extensions::Hash::ParamBuilder do
10
8
  end
11
9
 
12
10
  describe 'in an endpoint' do
13
- context '#params' do
11
+ describe '#params' do
14
12
  before do
15
13
  subject.params do
16
- build_with Grape::Extensions::Hash::ParamBuilder
14
+ build_with Grape::Extensions::Hash::ParamBuilder # rubocop:disable RSpec/DescribedClass
17
15
  end
18
16
 
19
17
  subject.get do
@@ -21,7 +19,7 @@ describe Grape::Extensions::Hash::ParamBuilder do
21
19
  end
22
20
  end
23
21
 
24
- it 'should be of type Hash' do
22
+ it 'is of type Hash' do
25
23
  get '/'
26
24
  expect(last_response.status).to eq(200)
27
25
  expect(last_response.body).to eq('Hash')
@@ -31,17 +29,17 @@ describe Grape::Extensions::Hash::ParamBuilder do
31
29
 
32
30
  describe 'in an api' do
33
31
  before do
34
- subject.send(:include, Grape::Extensions::Hash::ParamBuilder)
32
+ subject.send(:include, Grape::Extensions::Hash::ParamBuilder) # rubocop:disable RSpec/DescribedClass
35
33
  end
36
34
 
37
- context '#params' do
35
+ describe '#params' do
38
36
  before do
39
37
  subject.get do
40
38
  params.class
41
39
  end
42
40
  end
43
41
 
44
- it 'should be Hash' do
42
+ it 'is Hash' do
45
43
  get '/'
46
44
  expect(last_response.status).to eq(200)
47
45
  expect(last_response.body).to eq('Hash')
@@ -69,7 +67,7 @@ describe Grape::Extensions::Hash::ParamBuilder do
69
67
 
70
68
  it 'symbolizes the params' do
71
69
  subject.params do
72
- build_with Grape::Extensions::Hash::ParamBuilder
70
+ build_with Grape::Extensions::Hash::ParamBuilder # rubocop:disable RSpec/DescribedClass
73
71
  requires :a, type: String
74
72
  end
75
73
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -10,10 +8,10 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
10
8
  end
11
9
 
12
10
  describe 'in an endpoint' do
13
- context '#params' do
11
+ describe '#params' do
14
12
  before do
15
13
  subject.params do
16
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
14
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
17
15
  end
18
16
 
19
17
  subject.get do
@@ -21,7 +19,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
21
19
  end
22
20
  end
23
21
 
24
- it 'should be of type Hash' do
22
+ it 'is of type Hash' do
25
23
  get '/'
26
24
  expect(last_response.status).to eq(200)
27
25
  expect(last_response.body).to eq('ActiveSupport::HashWithIndifferentAccess')
@@ -31,10 +29,10 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
31
29
 
32
30
  describe 'in an api' do
33
31
  before do
34
- subject.send(:include, Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder)
32
+ subject.send(:include, Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder) # rubocop:disable RSpec/DescribedClass
35
33
  end
36
34
 
37
- context '#params' do
35
+ describe '#params' do
38
36
  before do
39
37
  subject.get do
40
38
  params.class
@@ -49,7 +47,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
49
47
 
50
48
  it 'parses sub hash params' do
51
49
  subject.params do
52
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
50
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
53
51
 
54
52
  optional :a, type: Hash do
55
53
  optional :b, type: Hash do
@@ -70,7 +68,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
70
68
 
71
69
  it 'params are indifferent to symbol or string keys' do
72
70
  subject.params do
73
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
71
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
74
72
  optional :a, type: Hash do
75
73
  optional :b, type: Hash do
76
74
  optional :c, type: String
@@ -90,7 +88,7 @@ describe Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuild
90
88
 
91
89
  it 'responds to string keys' do
92
90
  subject.params do
93
- build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder
91
+ build_with Grape::Extensions::ActiveSupport::HashWithIndifferentAccess::ParamBuilder # rubocop:disable RSpec/DescribedClass
94
92
  requires :a, type: String
95
93
  end
96
94