grape 1.5.3 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +150 -21
  5. data/UPGRADING.md +61 -4
  6. data/grape.gemspec +5 -5
  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 +2 -19
  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 +8 -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 +20 -35
  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 +2 -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 +2 -2
  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 +3 -0
  48. data/lib/grape/router/pattern.rb +1 -1
  49. data/lib/grape/router/route.rb +2 -2
  50. data/lib/grape/router.rb +6 -0
  51. data/lib/grape/util/inheritable_setting.rb +1 -3
  52. data/lib/grape/util/json.rb +2 -0
  53. data/lib/grape/util/lazy_value.rb +3 -2
  54. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  55. data/lib/grape/validations/attributes_doc.rb +58 -0
  56. data/lib/grape/validations/params_scope.rb +137 -78
  57. data/lib/grape/validations/types/array_coercer.rb +0 -2
  58. data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
  59. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  60. data/lib/grape/validations/types/json.rb +2 -1
  61. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  62. data/lib/grape/validations/types/set_coercer.rb +0 -2
  63. data/lib/grape/validations/types.rb +98 -30
  64. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  65. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  66. data/lib/grape/validations/validators/as_validator.rb +14 -0
  67. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  68. data/lib/grape/validations/validators/base.rb +82 -70
  69. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  70. data/lib/grape/validations/validators/default_validator.rb +51 -0
  71. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  72. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  73. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  74. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  75. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  76. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  77. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  78. data/lib/grape/validations/validators/values_validator.rb +88 -0
  79. data/lib/grape/validations.rb +16 -6
  80. data/lib/grape/version.rb +1 -1
  81. data/lib/grape.rb +69 -29
  82. data/spec/grape/api/custom_validations_spec.rb +116 -45
  83. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  84. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  85. data/spec/grape/api/documentation_spec.rb +59 -0
  86. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  87. data/spec/grape/api/instance_spec.rb +0 -1
  88. data/spec/grape/api/invalid_format_spec.rb +2 -2
  89. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  90. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  91. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  92. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  93. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  94. data/spec/grape/api/recognize_path_spec.rb +1 -3
  95. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  96. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  97. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  98. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  99. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  100. data/spec/grape/api_remount_spec.rb +16 -16
  101. data/spec/grape/api_spec.rb +457 -231
  102. data/spec/grape/config_spec.rb +0 -2
  103. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  104. data/spec/grape/dsl/configuration_spec.rb +0 -2
  105. data/spec/grape/dsl/desc_spec.rb +0 -2
  106. data/spec/grape/dsl/headers_spec.rb +39 -11
  107. data/spec/grape/dsl/helpers_spec.rb +3 -4
  108. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  109. data/spec/grape/dsl/logger_spec.rb +15 -19
  110. data/spec/grape/dsl/middleware_spec.rb +2 -3
  111. data/spec/grape/dsl/parameters_spec.rb +2 -2
  112. data/spec/grape/dsl/request_response_spec.rb +7 -8
  113. data/spec/grape/dsl/routing_spec.rb +11 -10
  114. data/spec/grape/dsl/settings_spec.rb +0 -2
  115. data/spec/grape/dsl/validations_spec.rb +0 -17
  116. data/spec/grape/endpoint/declared_spec.rb +261 -16
  117. data/spec/grape/endpoint_spec.rb +86 -58
  118. data/spec/grape/entity_spec.rb +22 -23
  119. data/spec/grape/exceptions/base_spec.rb +16 -2
  120. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  121. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
  122. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  123. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  124. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  125. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  126. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  127. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  129. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  130. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  131. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  132. data/spec/grape/exceptions/validation_spec.rb +5 -5
  133. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  134. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  135. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  136. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  137. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  138. data/spec/grape/integration/rack_spec.rb +0 -2
  139. data/spec/grape/loading_spec.rb +8 -10
  140. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  141. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  142. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  143. data/spec/grape/middleware/base_spec.rb +24 -17
  144. data/spec/grape/middleware/error_spec.rb +8 -3
  145. data/spec/grape/middleware/exception_spec.rb +111 -163
  146. data/spec/grape/middleware/formatter_spec.rb +27 -8
  147. data/spec/grape/middleware/globals_spec.rb +7 -6
  148. data/spec/grape/middleware/stack_spec.rb +14 -14
  149. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  150. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  151. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  152. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  153. data/spec/grape/middleware/versioner_spec.rb +1 -3
  154. data/spec/grape/named_api_spec.rb +0 -2
  155. data/spec/grape/parser_spec.rb +4 -2
  156. data/spec/grape/path_spec.rb +52 -54
  157. data/spec/grape/presenters/presenter_spec.rb +7 -8
  158. data/spec/grape/request_spec.rb +6 -6
  159. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  160. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  161. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  162. data/spec/grape/util/stackable_values_spec.rb +7 -6
  163. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  164. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  165. data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
  166. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  167. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  168. data/spec/grape/validations/params_scope_spec.rb +361 -96
  169. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  170. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  171. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  172. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  173. data/spec/grape/validations/types_spec.rb +36 -10
  174. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  175. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  176. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  177. data/spec/grape/validations/validators/coerce_spec.rb +23 -24
  178. data/spec/grape/validations/validators/default_spec.rb +72 -80
  179. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  180. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  181. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  182. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  183. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  184. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  185. data/spec/grape/validations/validators/values_spec.rb +182 -179
  186. data/spec/grape/validations_spec.rb +149 -80
  187. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  188. data/spec/integration/multi_json/json_spec.rb +1 -3
  189. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  190. data/spec/shared/versioning_examples.rb +12 -9
  191. data/spec/spec_helper.rb +21 -6
  192. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  193. metadata +126 -117
  194. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  195. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  196. data/lib/grape/validations/validators/as.rb +0 -16
  197. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  198. data/lib/grape/validations/validators/coerce.rb +0 -91
  199. data/lib/grape/validations/validators/default.rb +0 -48
  200. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  201. data/lib/grape/validations/validators/except_values.rb +0 -22
  202. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  203. data/lib/grape/validations/validators/presence.rb +0 -12
  204. data/lib/grape/validations/validators/regexp.rb +0 -13
  205. data/lib/grape/validations/validators/same_as.rb +0 -26
  206. data/lib/grape/validations/validators/values.rb +0 -83
  207. data/spec/support/eager_load.rb +0 -19
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Endpoint do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -10,32 +8,32 @@ describe Grape::Endpoint do
10
8
  end
11
9
 
12
10
  describe '.before_each' do
13
- after { Grape::Endpoint.before_each.clear }
11
+ after { described_class.before_each.clear }
14
12
 
15
13
  it 'is settable via block' do
16
14
  block = ->(_endpoint) { 'noop' }
17
- Grape::Endpoint.before_each(&block)
18
- expect(Grape::Endpoint.before_each.first).to eq(block)
15
+ described_class.before_each(&block)
16
+ expect(described_class.before_each.first).to eq(block)
19
17
  end
20
18
 
21
19
  it 'is settable via reference' do
22
20
  block = ->(_endpoint) { 'noop' }
23
- Grape::Endpoint.before_each block
24
- expect(Grape::Endpoint.before_each.first).to eq(block)
21
+ described_class.before_each block
22
+ expect(described_class.before_each.first).to eq(block)
25
23
  end
26
24
 
27
25
  it 'is able to override a helper' do
28
26
  subject.get('/') { current_user }
29
27
  expect { get '/' }.to raise_error(NameError)
30
28
 
31
- Grape::Endpoint.before_each do |endpoint|
29
+ described_class.before_each do |endpoint|
32
30
  allow(endpoint).to receive(:current_user).and_return('Bob')
33
31
  end
34
32
 
35
33
  get '/'
36
34
  expect(last_response.body).to eq('Bob')
37
35
 
38
- Grape::Endpoint.before_each(nil)
36
+ described_class.before_each(nil)
39
37
  expect { get '/' }.to raise_error(NameError)
40
38
  end
41
39
 
@@ -46,18 +44,18 @@ describe Grape::Endpoint do
46
44
  end
47
45
  expect { get '/' }.to raise_error(NameError)
48
46
 
49
- Grape::Endpoint.before_each do |endpoint|
47
+ described_class.before_each do |endpoint|
50
48
  allow(endpoint).to receive(:current_user).and_return('Bob')
51
49
  end
52
50
 
53
- Grape::Endpoint.before_each do |endpoint|
51
+ described_class.before_each do |endpoint|
54
52
  allow(endpoint).to receive(:authenticate_user!).and_return(true)
55
53
  end
56
54
 
57
55
  get '/'
58
56
  expect(last_response.body).to eq('Bob')
59
57
 
60
- Grape::Endpoint.before_each(nil)
58
+ described_class.before_each(nil)
61
59
  expect { get '/' }.to raise_error(NameError)
62
60
  end
63
61
  end
@@ -66,7 +64,7 @@ describe Grape::Endpoint do
66
64
  it 'takes a settings stack, options, and a block' do
67
65
  p = proc {}
68
66
  expect do
69
- Grape::Endpoint.new(Grape::Util::InheritableSetting.new, {
67
+ described_class.new(Grape::Util::InheritableSetting.new, {
70
68
  path: '/',
71
69
  method: :get
72
70
  }, &p)
@@ -77,7 +75,7 @@ describe Grape::Endpoint do
77
75
  it 'sets itself in the env upon call' do
78
76
  subject.get('/') { 'Hello world.' }
79
77
  get '/'
80
- expect(last_request.env['api.endpoint']).to be_kind_of(Grape::Endpoint)
78
+ expect(last_request.env['api.endpoint']).to be_kind_of(described_class)
81
79
  end
82
80
 
83
81
  describe '#status' do
@@ -137,6 +135,7 @@ describe Grape::Endpoint do
137
135
  headers.to_json
138
136
  end
139
137
  end
138
+
140
139
  it 'includes request headers' do
141
140
  get '/headers'
142
141
  expect(JSON.parse(last_response.body)).to eq(
@@ -144,13 +143,15 @@ describe Grape::Endpoint do
144
143
  'Cookie' => ''
145
144
  )
146
145
  end
146
+
147
147
  it 'includes additional request headers' do
148
148
  get '/headers', nil, 'HTTP_X_GRAPE_CLIENT' => '1'
149
149
  expect(JSON.parse(last_response.body)['X-Grape-Client']).to eq('1')
150
150
  end
151
+
151
152
  it 'includes headers passed as symbols' do
152
153
  env = Rack::MockRequest.env_for('/headers')
153
- env['HTTP_SYMBOL_HEADER'.to_sym] = 'Goliath passes symbols'
154
+ env[:HTTP_SYMBOL_HEADER] = 'Goliath passes symbols'
154
155
  body = read_chunks(subject.call(env)[2]).join
155
156
  expect(JSON.parse(body)['Symbol-Header']).to eq('Goliath passes symbols')
156
157
  end
@@ -212,10 +213,10 @@ describe Grape::Endpoint do
212
213
  end
213
214
  get '/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2'
214
215
  expect(last_response.body).to eq('3')
215
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
216
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
216
217
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
217
218
  [cookie.name, cookie]
218
- end]
219
+ end.to_h
219
220
  expect(cookies.size).to eq(2)
220
221
  %w[and_this delete_this_cookie].each do |cookie_name|
221
222
  cookie = cookies[cookie_name]
@@ -236,10 +237,10 @@ describe Grape::Endpoint do
236
237
  end
237
238
  get('/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2')
238
239
  expect(last_response.body).to eq('3')
239
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
240
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
240
241
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
241
242
  [cookie.name, cookie]
242
- end]
243
+ end.to_h
243
244
  expect(cookies.size).to eq(2)
244
245
  %w[and_this delete_this_cookie].each do |cookie_name|
245
246
  cookie = cookies[cookie_name]
@@ -253,7 +254,7 @@ describe Grape::Endpoint do
253
254
 
254
255
  describe '#params' do
255
256
  context 'default class' do
256
- it 'should be a ActiveSupport::HashWithIndifferentAccess' do
257
+ it 'is a ActiveSupport::HashWithIndifferentAccess' do
257
258
  subject.get '/foo' do
258
259
  params.class
259
260
  end
@@ -339,7 +340,7 @@ describe Grape::Endpoint do
339
340
  end
340
341
 
341
342
  context 'namespace requirements' do
342
- before :each do
343
+ before do
343
344
  subject.namespace :outer, requirements: { person_email: /abc@(.*).com/ } do
344
345
  get('/:person_email') do
345
346
  params[:person_email]
@@ -358,7 +359,7 @@ describe Grape::Endpoint do
358
359
  expect(last_response.body).to eq('abc@example.com')
359
360
  end
360
361
 
361
- it "should override outer namespace's requirements" do
362
+ it "overrides outer namespace's requirements" do
362
363
  get '/outer/inner/someone@testing.wrong/test/1'
363
364
  expect(last_response.status).to eq(404)
364
365
 
@@ -370,7 +371,7 @@ describe Grape::Endpoint do
370
371
  end
371
372
 
372
373
  context 'from body parameters' do
373
- before(:each) do
374
+ before do
374
375
  subject.post '/request_body' do
375
376
  params[:user]
376
377
  end
@@ -431,7 +432,28 @@ describe Grape::Endpoint do
431
432
  end
432
433
  post '/upload', { file: '' }, 'CONTENT_TYPE' => 'multipart/form-data; boundary=foobar'
433
434
  expect(last_response.status).to eq(400)
434
- expect(last_response.body).to eq('Empty message body supplied with multipart/form-data; boundary=foobar content-type')
435
+ expect(last_response.body).to eq('empty message body supplied with multipart/form-data; boundary=foobar content-type')
436
+ end
437
+ end
438
+
439
+ context 'when the limit on multipart files is exceeded' do
440
+ around do |example|
441
+ limit = Rack::Utils.multipart_part_limit
442
+ Rack::Utils.multipart_part_limit = 1
443
+ example.run
444
+ Rack::Utils.multipart_part_limit = limit
445
+ end
446
+
447
+ it 'returns a 413 if given too many multipart files' do
448
+ subject.params do
449
+ requires :file, type: Rack::Multipart::UploadedFile
450
+ end
451
+ subject.post '/upload' do
452
+ params[:file][:filename]
453
+ end
454
+ post '/upload', { file: Rack::Test::UploadedFile.new(__FILE__, 'text/plain'), extra: Rack::Test::UploadedFile.new(__FILE__, 'text/plain') }
455
+ expect(last_response.status).to eq(413)
456
+ expect(last_response.body).to eq("the number of uploaded files exceeded the system's configured limit (1)")
435
457
  end
436
458
  end
437
459
 
@@ -469,11 +491,11 @@ describe Grape::Endpoint do
469
491
  post '/', ::Grape::Json.dump(data: { some: 'payload' }), 'CONTENT_TYPE' => 'application/json'
470
492
  end
471
493
 
472
- it 'should not response with 406 for same type without params' do
494
+ it 'does not response with 406 for same type without params' do
473
495
  expect(last_response.status).not_to be 406
474
496
  end
475
497
 
476
- it 'should response with given content type in headers' do
498
+ it 'responses with given content type in headers' do
477
499
  expect(last_response.headers['Content-Type']).to eq 'application/json; charset=utf-8'
478
500
  end
479
501
  end
@@ -709,16 +731,18 @@ describe Grape::Endpoint do
709
731
  describe '.generate_api_method' do
710
732
  it 'raises NameError if the method name is already in use' do
711
733
  expect do
712
- Grape::Endpoint.generate_api_method('version', &proc {})
734
+ described_class.generate_api_method('version', &proc {})
713
735
  end.to raise_error(NameError)
714
736
  end
737
+
715
738
  it 'raises ArgumentError if a block is not given' do
716
739
  expect do
717
- Grape::Endpoint.generate_api_method('GET without a block method')
740
+ described_class.generate_api_method('GET without a block method')
718
741
  end.to raise_error(ArgumentError)
719
742
  end
743
+
720
744
  it 'returns a Proc' do
721
- expect(Grape::Endpoint.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
745
+ expect(described_class.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
722
746
  end
723
747
  end
724
748
 
@@ -777,7 +801,7 @@ describe Grape::Endpoint do
777
801
  end
778
802
 
779
803
  get '/error_filters'
780
- expect(last_response.status).to eql 500
804
+ expect(last_response.status).to be 500
781
805
  expect(called).to match_array %w[before before_validation]
782
806
  end
783
807
 
@@ -786,8 +810,11 @@ describe Grape::Endpoint do
786
810
  subject.before { called << 'parent' }
787
811
  subject.namespace :parent do
788
812
  before { called << 'prior' }
813
+
789
814
  before { error! :oops, 500 }
815
+
790
816
  before { called << 'subsequent' }
817
+
791
818
  get :hello do
792
819
  called << :endpoint
793
820
  'Hello!'
@@ -795,7 +822,7 @@ describe Grape::Endpoint do
795
822
  end
796
823
 
797
824
  get '/parent/hello'
798
- expect(last_response.status).to eql 500
825
+ expect(last_response.status).to be 500
799
826
  expect(called).to match_array %w[parent prior]
800
827
  end
801
828
  end
@@ -806,19 +833,19 @@ describe Grape::Endpoint do
806
833
  it 'allows for the anchoring option with a delete method' do
807
834
  subject.send(:delete, '/example', anchor: true) {}
808
835
  send(:delete, '/example/and/some/more')
809
- expect(last_response.status).to eql 404
836
+ expect(last_response.status).to be 404
810
837
  end
811
838
 
812
839
  it 'anchors paths by default for the delete method' do
813
840
  subject.send(:delete, '/example') {}
814
841
  send(:delete, '/example/and/some/more')
815
- expect(last_response.status).to eql 404
842
+ expect(last_response.status).to be 404
816
843
  end
817
844
 
818
845
  it 'responds to /example/and/some/more for the non-anchored delete method' do
819
846
  subject.send(:delete, '/example', anchor: false) {}
820
847
  send(:delete, '/example/and/some/more')
821
- expect(last_response.status).to eql 204
848
+ expect(last_response.status).to be 204
822
849
  expect(last_response.body).to be_empty
823
850
  end
824
851
  end
@@ -830,7 +857,7 @@ describe Grape::Endpoint do
830
857
  body 'deleted'
831
858
  end
832
859
  send(:delete, '/example/and/some/more')
833
- expect(last_response.status).to eql 200
860
+ expect(last_response.status).to be 200
834
861
  expect(last_response.body).not_to be_empty
835
862
  end
836
863
  end
@@ -839,7 +866,7 @@ describe Grape::Endpoint do
839
866
  it 'responds to /example delete method' do
840
867
  subject.delete(:example) { 'deleted' }
841
868
  delete '/example'
842
- expect(last_response.status).to eql 200
869
+ expect(last_response.status).to be 200
843
870
  expect(last_response.body).not_to be_empty
844
871
  end
845
872
  end
@@ -848,7 +875,7 @@ describe Grape::Endpoint do
848
875
  it 'responds to /example delete method' do
849
876
  subject.delete(:example) { nil }
850
877
  delete '/example'
851
- expect(last_response.status).to eql 204
878
+ expect(last_response.status).to be 204
852
879
  expect(last_response.body).to be_empty
853
880
  end
854
881
  end
@@ -857,7 +884,7 @@ describe Grape::Endpoint do
857
884
  it 'responds to /example delete method' do
858
885
  subject.delete(:example) { '' }
859
886
  delete '/example'
860
- expect(last_response.status).to eql 204
887
+ expect(last_response.status).to be 204
861
888
  expect(last_response.body).to be_empty
862
889
  end
863
890
  end
@@ -869,7 +896,7 @@ describe Grape::Endpoint do
869
896
  verb
870
897
  end
871
898
  send(verb, '/example/and/some/more')
872
- expect(last_response.status).to eql 404
899
+ expect(last_response.status).to be 404
873
900
  end
874
901
 
875
902
  it "anchors paths by default for the #{verb.upcase} method" do
@@ -877,7 +904,7 @@ describe Grape::Endpoint do
877
904
  verb
878
905
  end
879
906
  send(verb, '/example/and/some/more')
880
- expect(last_response.status).to eql 404
907
+ expect(last_response.status).to be 404
881
908
  end
882
909
 
883
910
  it "responds to /example/and/some/more for the non-anchored #{verb.upcase} method" do
@@ -900,8 +927,9 @@ describe Grape::Endpoint do
900
927
  get '/url'
901
928
  expect(last_response.body).to eq('http://example.org/url')
902
929
  end
930
+
903
931
  ['v1', :v1].each do |version|
904
- it "should include version #{version}" do
932
+ it "includes version #{version}" do
905
933
  subject.version version, using: :path
906
934
  subject.get('/url') do
907
935
  request.url
@@ -910,7 +938,7 @@ describe Grape::Endpoint do
910
938
  expect(last_response.body).to eq("http://example.org/#{version}/url")
911
939
  end
912
940
  end
913
- it 'should include prefix' do
941
+ it 'includes prefix' do
914
942
  subject.version 'v1', using: :path
915
943
  subject.prefix 'api'
916
944
  subject.get('/url') do
@@ -1000,26 +1028,26 @@ describe Grape::Endpoint do
1000
1028
 
1001
1029
  # In order that the events finalized (time each block ended)
1002
1030
  expect(@events).to contain_exactly(
1003
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1031
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1004
1032
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
1005
1033
  type: :before }),
1006
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1034
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1007
1035
  filters: [],
1008
1036
  type: :before_validation }),
1009
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1037
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
1010
1038
  validators: [],
1011
1039
  request: a_kind_of(Grape::Request) }),
1012
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1040
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1013
1041
  filters: [],
1014
1042
  type: :after_validation }),
1015
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1016
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1043
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1044
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1017
1045
  filters: [],
1018
1046
  type: :after }),
1019
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1047
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1020
1048
  filters: [],
1021
1049
  type: :finally }),
1022
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1050
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1023
1051
  env: an_instance_of(Hash) }),
1024
1052
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
1025
1053
  formatter: a_kind_of(Module) })
@@ -1027,25 +1055,25 @@ describe Grape::Endpoint do
1027
1055
 
1028
1056
  # In order that events were initialized
1029
1057
  expect(@events.sort_by(&:time)).to contain_exactly(
1030
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1058
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1031
1059
  env: an_instance_of(Hash) }),
1032
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1060
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1033
1061
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
1034
1062
  type: :before }),
1035
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1063
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1036
1064
  filters: [],
1037
1065
  type: :before_validation }),
1038
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1066
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
1039
1067
  validators: [],
1040
1068
  request: a_kind_of(Grape::Request) }),
1041
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1069
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1042
1070
  filters: [],
1043
1071
  type: :after_validation }),
1044
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1045
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1072
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1073
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1046
1074
  filters: [],
1047
1075
  type: :after }),
1048
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1076
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1049
1077
  filters: [],
1050
1078
  type: :finally }),
1051
1079
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  require 'grape_entity'
5
4
 
6
5
  describe Grape::Entity do
@@ -32,7 +31,7 @@ describe Grape::Entity do
32
31
  end
33
32
 
34
33
  it 'pulls a representation from the class options if it exists' do
35
- entity = Class.new(Grape::Entity)
34
+ entity = Class.new(described_class)
36
35
  allow(entity).to receive(:represent).and_return('Hiya')
37
36
 
38
37
  subject.represent Object, with: entity
@@ -44,7 +43,7 @@ describe Grape::Entity do
44
43
  end
45
44
 
46
45
  it 'pulls a representation from the class options if the presented object is a collection of objects' do
47
- entity = Class.new(Grape::Entity)
46
+ entity = Class.new(described_class)
48
47
  allow(entity).to receive(:represent).and_return('Hiya')
49
48
 
50
49
  module EntitySpec
@@ -75,7 +74,7 @@ describe Grape::Entity do
75
74
  end
76
75
 
77
76
  it 'pulls a representation from the class ancestor if it exists' do
78
- entity = Class.new(Grape::Entity)
77
+ entity = Class.new(described_class)
79
78
  allow(entity).to receive(:represent).and_return('Hiya')
80
79
 
81
80
  subclass = Class.new(Object)
@@ -90,7 +89,7 @@ describe Grape::Entity do
90
89
 
91
90
  it 'automatically uses Klass::Entity if that exists' do
92
91
  some_model = Class.new
93
- entity = Class.new(Grape::Entity)
92
+ entity = Class.new(described_class)
94
93
  allow(entity).to receive(:represent).and_return('Auto-detect!')
95
94
 
96
95
  some_model.const_set :Entity, entity
@@ -104,7 +103,7 @@ describe Grape::Entity do
104
103
 
105
104
  it 'automatically uses Klass::Entity based on the first object in the collection being presented' do
106
105
  some_model = Class.new
107
- entity = Class.new(Grape::Entity)
106
+ entity = Class.new(described_class)
108
107
  allow(entity).to receive(:represent).and_return('Auto-detect!')
109
108
 
110
109
  some_model.const_set :Entity, entity
@@ -117,7 +116,7 @@ describe Grape::Entity do
117
116
  end
118
117
 
119
118
  it 'does not run autodetection for Entity when explicitly provided' do
120
- entity = Class.new(Grape::Entity)
119
+ entity = Class.new(described_class)
121
120
  some_array = []
122
121
 
123
122
  subject.get '/example' do
@@ -129,7 +128,7 @@ describe Grape::Entity do
129
128
  end
130
129
 
131
130
  it 'does not use #first method on ActiveRecord::Relation to prevent needless sql query' do
132
- entity = Class.new(Grape::Entity)
131
+ entity = Class.new(described_class)
133
132
  some_relation = Class.new
134
133
  some_model = Class.new
135
134
 
@@ -173,7 +172,7 @@ describe Grape::Entity do
173
172
 
174
173
  %i[json serializable_hash].each do |format|
175
174
  it "presents with #{format}" do
176
- entity = Class.new(Grape::Entity)
175
+ entity = Class.new(described_class)
177
176
  entity.root 'examples', 'example'
178
177
  entity.expose :id
179
178
 
@@ -195,7 +194,7 @@ describe Grape::Entity do
195
194
  end
196
195
 
197
196
  it "presents with #{format} collection" do
198
- entity = Class.new(Grape::Entity)
197
+ entity = Class.new(described_class)
199
198
  entity.root 'examples', 'example'
200
199
  entity.expose :id
201
200
 
@@ -219,7 +218,7 @@ describe Grape::Entity do
219
218
  end
220
219
 
221
220
  it 'presents with xml' do
222
- entity = Class.new(Grape::Entity)
221
+ entity = Class.new(described_class)
223
222
  entity.root 'examples', 'example'
224
223
  entity.expose :name
225
224
 
@@ -238,18 +237,18 @@ describe Grape::Entity do
238
237
  get '/example'
239
238
  expect(last_response.status).to eq(200)
240
239
  expect(last_response.headers['Content-type']).to eq('application/xml')
241
- expect(last_response.body).to eq <<-XML
242
- <?xml version="1.0" encoding="UTF-8"?>
243
- <hash>
244
- <example>
245
- <name>johnnyiller</name>
246
- </example>
247
- </hash>
248
- XML
240
+ expect(last_response.body).to eq <<~XML
241
+ <?xml version="1.0" encoding="UTF-8"?>
242
+ <hash>
243
+ <example>
244
+ <name>johnnyiller</name>
245
+ </example>
246
+ </hash>
247
+ XML
249
248
  end
250
249
 
251
250
  it 'presents with json' do
252
- entity = Class.new(Grape::Entity)
251
+ entity = Class.new(described_class)
253
252
  entity.root 'examples', 'example'
254
253
  entity.expose :name
255
254
 
@@ -275,7 +274,7 @@ XML
275
274
  # Include JSONP middleware
276
275
  subject.use Rack::JSONP
277
276
 
278
- entity = Class.new(Grape::Entity)
277
+ entity = Class.new(described_class)
279
278
  entity.root 'examples', 'example'
280
279
  entity.expose :name
281
280
 
@@ -315,7 +314,7 @@ XML
315
314
  user1 = user.new(name: 'user1')
316
315
  user2 = user.new(name: 'user2')
317
316
 
318
- entity = Class.new(Grape::Entity)
317
+ entity = Class.new(described_class)
319
318
  entity.expose :name
320
319
 
321
320
  subject.format :json
@@ -326,7 +325,7 @@ XML
326
325
  end
327
326
  get '/example'
328
327
  expect_response_json = {
329
- 'page' => 1,
328
+ 'page' => 1,
330
329
  'user1' => { 'name' => 'user1' },
331
330
  'user2' => { 'name' => 'user2' }
332
331
  }
@@ -1,8 +1,22 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::Base do
4
+ describe '#to_s' do
5
+ subject { described_class.new(message: message).to_s }
6
+
7
+ let(:message) { 'a_message' }
8
+
9
+ it { is_expected.to eq(message) }
10
+ end
11
+
12
+ describe '#message' do
13
+ subject { described_class.new(message: message).message }
14
+
15
+ let(:message) { 'a_message' }
16
+
17
+ it { is_expected.to eq(message) }
18
+ end
19
+
6
20
  describe '#compose_message' do
7
21
  subject { described_class.new.send(:compose_message, key, **attributes) }
8
22
 
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Exceptions::ValidationErrors do
6
4
  context 'api with rescue_from :all handler' do
7
5
  subject { Class.new(Grape::API) }
6
+
8
7
  before do
9
8
  subject.rescue_from :all do |_e|
10
9
  rack_response 'message was processed', 400
@@ -56,6 +55,7 @@ describe Grape::Exceptions::ValidationErrors do
56
55
 
57
56
  context 'api with rescue_from :grape_exceptions handler' do
58
57
  subject { Class.new(Grape::API) }
58
+
59
59
  before do
60
60
  subject.rescue_from :all do |_e|
61
61
  rack_response 'message was processed', 400
@@ -93,6 +93,7 @@ describe Grape::Exceptions::ValidationErrors do
93
93
 
94
94
  context 'api without a rescue handler' do
95
95
  subject { Class.new(Grape::API) }
96
+
96
97
  before do
97
98
  subject.params do
98
99
  requires :beer