grape 1.5.3 → 1.7.0

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