grape 1.5.2 → 1.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +47 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +33 -3
  5. data/UPGRADING.md +71 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +13 -17
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dsl/desc.rb +3 -5
  11. data/lib/grape/dsl/headers.rb +5 -2
  12. data/lib/grape/dsl/helpers.rb +7 -5
  13. data/lib/grape/dsl/inside_route.rb +17 -8
  14. data/lib/grape/dsl/middleware.rb +4 -4
  15. data/lib/grape/dsl/parameters.rb +3 -3
  16. data/lib/grape/dsl/request_response.rb +9 -6
  17. data/lib/grape/dsl/routing.rb +2 -2
  18. data/lib/grape/dsl/settings.rb +5 -5
  19. data/lib/grape/endpoint.rb +21 -36
  20. data/lib/grape/error_formatter/json.rb +2 -6
  21. data/lib/grape/error_formatter/xml.rb +2 -6
  22. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  23. data/lib/grape/exceptions/validation.rb +1 -2
  24. data/lib/grape/formatter/json.rb +1 -0
  25. data/lib/grape/formatter/serializable_hash.rb +2 -1
  26. data/lib/grape/formatter/xml.rb +1 -0
  27. data/lib/grape/locale/en.yml +1 -1
  28. data/lib/grape/middleware/auth/dsl.rb +7 -1
  29. data/lib/grape/middleware/base.rb +3 -1
  30. data/lib/grape/middleware/formatter.rb +4 -4
  31. data/lib/grape/middleware/stack.rb +2 -2
  32. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  33. data/lib/grape/middleware/versioner/header.rb +6 -4
  34. data/lib/grape/middleware/versioner/param.rb +1 -0
  35. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  36. data/lib/grape/middleware/versioner/path.rb +2 -0
  37. data/lib/grape/parser/json.rb +1 -1
  38. data/lib/grape/parser/xml.rb +1 -1
  39. data/lib/grape/path.rb +1 -0
  40. data/lib/grape/request.rb +3 -0
  41. data/lib/grape/router/pattern.rb +1 -1
  42. data/lib/grape/router/route.rb +2 -2
  43. data/lib/grape/router.rb +6 -0
  44. data/lib/grape/util/inheritable_setting.rb +1 -3
  45. data/lib/grape/util/lazy_value.rb +3 -2
  46. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  47. data/lib/grape/validations/params_scope.rb +88 -55
  48. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  49. data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
  50. data/lib/grape/validations/types/json.rb +2 -1
  51. data/lib/grape/validations/types/primitive_coercer.rb +3 -3
  52. data/lib/grape/validations/validators/all_or_none.rb +8 -5
  53. data/lib/grape/validations/validators/allow_blank.rb +9 -7
  54. data/lib/grape/validations/validators/as.rb +6 -8
  55. data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
  56. data/lib/grape/validations/validators/base.rb +75 -70
  57. data/lib/grape/validations/validators/coerce.rb +63 -79
  58. data/lib/grape/validations/validators/default.rb +37 -34
  59. data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
  60. data/lib/grape/validations/validators/except_values.rb +13 -11
  61. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  62. data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
  63. data/lib/grape/validations/validators/presence.rb +7 -4
  64. data/lib/grape/validations/validators/regexp.rb +8 -5
  65. data/lib/grape/validations/validators/same_as.rb +18 -15
  66. data/lib/grape/validations/validators/values.rb +61 -56
  67. data/lib/grape/validations.rb +6 -0
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +4 -1
  70. data/spec/grape/api/custom_validations_spec.rb +77 -45
  71. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  72. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  73. data/spec/grape/api/invalid_format_spec.rb +2 -0
  74. data/spec/grape/api/recognize_path_spec.rb +1 -1
  75. data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
  76. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  77. data/spec/grape/api_remount_spec.rb +16 -15
  78. data/spec/grape/api_spec.rb +510 -220
  79. data/spec/grape/dsl/callbacks_spec.rb +2 -1
  80. data/spec/grape/dsl/headers_spec.rb +39 -9
  81. data/spec/grape/dsl/helpers_spec.rb +3 -2
  82. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  83. data/spec/grape/dsl/logger_spec.rb +16 -18
  84. data/spec/grape/dsl/middleware_spec.rb +2 -1
  85. data/spec/grape/dsl/parameters_spec.rb +2 -0
  86. data/spec/grape/dsl/request_response_spec.rb +1 -0
  87. data/spec/grape/dsl/routing_spec.rb +10 -7
  88. data/spec/grape/endpoint/declared_spec.rb +259 -12
  89. data/spec/grape/endpoint_spec.rb +77 -55
  90. data/spec/grape/entity_spec.rb +22 -22
  91. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  92. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  93. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  94. data/spec/grape/exceptions/validation_spec.rb +5 -3
  95. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  96. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  97. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  98. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  99. data/spec/grape/loading_spec.rb +8 -8
  100. data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
  101. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  102. data/spec/grape/middleware/base_spec.rb +24 -15
  103. data/spec/grape/middleware/error_spec.rb +2 -2
  104. data/spec/grape/middleware/exception_spec.rb +111 -161
  105. data/spec/grape/middleware/formatter_spec.rb +27 -6
  106. data/spec/grape/middleware/globals_spec.rb +7 -4
  107. data/spec/grape/middleware/stack_spec.rb +14 -12
  108. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  109. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  110. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  111. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  112. data/spec/grape/middleware/versioner_spec.rb +1 -1
  113. data/spec/grape/parser_spec.rb +4 -0
  114. data/spec/grape/path_spec.rb +52 -52
  115. data/spec/grape/presenters/presenter_spec.rb +7 -6
  116. data/spec/grape/request_spec.rb +6 -4
  117. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  118. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  119. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  120. data/spec/grape/util/stackable_values_spec.rb +7 -5
  121. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  122. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  123. data/spec/grape/validations/params_scope_spec.rb +46 -10
  124. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -1
  125. data/spec/grape/validations/types/primitive_coercer_spec.rb +4 -4
  126. data/spec/grape/validations/types_spec.rb +8 -8
  127. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  128. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  129. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  130. data/spec/grape/validations/validators/coerce_spec.rb +99 -22
  131. data/spec/grape/validations/validators/default_spec.rb +72 -78
  132. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  133. data/spec/grape/validations/validators/except_values_spec.rb +3 -3
  134. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  135. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  136. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  137. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  138. data/spec/grape/validations/validators/values_spec.rb +183 -178
  139. data/spec/grape/validations_spec.rb +99 -58
  140. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  141. data/spec/integration/multi_json/json_spec.rb +1 -1
  142. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  143. data/spec/shared/versioning_examples.rb +12 -9
  144. data/spec/spec_helper.rb +12 -2
  145. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  146. metadata +102 -101
@@ -10,32 +10,32 @@ describe Grape::Endpoint do
10
10
  end
11
11
 
12
12
  describe '.before_each' do
13
- after { Grape::Endpoint.before_each.clear }
13
+ after { described_class.before_each.clear }
14
14
 
15
15
  it 'is settable via block' do
16
16
  block = ->(_endpoint) { 'noop' }
17
- Grape::Endpoint.before_each(&block)
18
- expect(Grape::Endpoint.before_each.first).to eq(block)
17
+ described_class.before_each(&block)
18
+ expect(described_class.before_each.first).to eq(block)
19
19
  end
20
20
 
21
21
  it 'is settable via reference' do
22
22
  block = ->(_endpoint) { 'noop' }
23
- Grape::Endpoint.before_each block
24
- expect(Grape::Endpoint.before_each.first).to eq(block)
23
+ described_class.before_each block
24
+ expect(described_class.before_each.first).to eq(block)
25
25
  end
26
26
 
27
27
  it 'is able to override a helper' do
28
28
  subject.get('/') { current_user }
29
29
  expect { get '/' }.to raise_error(NameError)
30
30
 
31
- Grape::Endpoint.before_each do |endpoint|
31
+ described_class.before_each do |endpoint|
32
32
  allow(endpoint).to receive(:current_user).and_return('Bob')
33
33
  end
34
34
 
35
35
  get '/'
36
36
  expect(last_response.body).to eq('Bob')
37
37
 
38
- Grape::Endpoint.before_each(nil)
38
+ described_class.before_each(nil)
39
39
  expect { get '/' }.to raise_error(NameError)
40
40
  end
41
41
 
@@ -46,18 +46,18 @@ describe Grape::Endpoint do
46
46
  end
47
47
  expect { get '/' }.to raise_error(NameError)
48
48
 
49
- Grape::Endpoint.before_each do |endpoint|
49
+ described_class.before_each do |endpoint|
50
50
  allow(endpoint).to receive(:current_user).and_return('Bob')
51
51
  end
52
52
 
53
- Grape::Endpoint.before_each do |endpoint|
53
+ described_class.before_each do |endpoint|
54
54
  allow(endpoint).to receive(:authenticate_user!).and_return(true)
55
55
  end
56
56
 
57
57
  get '/'
58
58
  expect(last_response.body).to eq('Bob')
59
59
 
60
- Grape::Endpoint.before_each(nil)
60
+ described_class.before_each(nil)
61
61
  expect { get '/' }.to raise_error(NameError)
62
62
  end
63
63
  end
@@ -66,7 +66,7 @@ describe Grape::Endpoint do
66
66
  it 'takes a settings stack, options, and a block' do
67
67
  p = proc {}
68
68
  expect do
69
- Grape::Endpoint.new(Grape::Util::InheritableSetting.new, {
69
+ described_class.new(Grape::Util::InheritableSetting.new, {
70
70
  path: '/',
71
71
  method: :get
72
72
  }, &p)
@@ -77,7 +77,7 @@ describe Grape::Endpoint do
77
77
  it 'sets itself in the env upon call' do
78
78
  subject.get('/') { 'Hello world.' }
79
79
  get '/'
80
- expect(last_request.env['api.endpoint']).to be_kind_of(Grape::Endpoint)
80
+ expect(last_request.env['api.endpoint']).to be_kind_of(described_class)
81
81
  end
82
82
 
83
83
  describe '#status' do
@@ -137,6 +137,7 @@ describe Grape::Endpoint do
137
137
  headers.to_json
138
138
  end
139
139
  end
140
+
140
141
  it 'includes request headers' do
141
142
  get '/headers'
142
143
  expect(JSON.parse(last_response.body)).to eq(
@@ -144,13 +145,15 @@ describe Grape::Endpoint do
144
145
  'Cookie' => ''
145
146
  )
146
147
  end
148
+
147
149
  it 'includes additional request headers' do
148
150
  get '/headers', nil, 'HTTP_X_GRAPE_CLIENT' => '1'
149
151
  expect(JSON.parse(last_response.body)['X-Grape-Client']).to eq('1')
150
152
  end
153
+
151
154
  it 'includes headers passed as symbols' do
152
155
  env = Rack::MockRequest.env_for('/headers')
153
- env['HTTP_SYMBOL_HEADER'.to_sym] = 'Goliath passes symbols'
156
+ env[:HTTP_SYMBOL_HEADER] = 'Goliath passes symbols'
154
157
  body = read_chunks(subject.call(env)[2]).join
155
158
  expect(JSON.parse(body)['Symbol-Header']).to eq('Goliath passes symbols')
156
159
  end
@@ -212,10 +215,10 @@ describe Grape::Endpoint do
212
215
  end
213
216
  get '/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2'
214
217
  expect(last_response.body).to eq('3')
215
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
218
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
216
219
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
217
220
  [cookie.name, cookie]
218
- end]
221
+ end.to_h
219
222
  expect(cookies.size).to eq(2)
220
223
  %w[and_this delete_this_cookie].each do |cookie_name|
221
224
  cookie = cookies[cookie_name]
@@ -236,10 +239,10 @@ describe Grape::Endpoint do
236
239
  end
237
240
  get('/test', {}, 'HTTP_COOKIE' => 'delete_this_cookie=1; and_this=2')
238
241
  expect(last_response.body).to eq('3')
239
- cookies = Hash[last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
242
+ cookies = last_response.headers['Set-Cookie'].split("\n").map do |set_cookie|
240
243
  cookie = CookieJar::Cookie.from_set_cookie 'http://localhost/test', set_cookie
241
244
  [cookie.name, cookie]
242
- end]
245
+ end.to_h
243
246
  expect(cookies.size).to eq(2)
244
247
  %w[and_this delete_this_cookie].each do |cookie_name|
245
248
  cookie = cookies[cookie_name]
@@ -253,7 +256,7 @@ describe Grape::Endpoint do
253
256
 
254
257
  describe '#params' do
255
258
  context 'default class' do
256
- it 'should be a ActiveSupport::HashWithIndifferentAccess' do
259
+ it 'is a ActiveSupport::HashWithIndifferentAccess' do
257
260
  subject.get '/foo' do
258
261
  params.class
259
262
  end
@@ -339,7 +342,7 @@ describe Grape::Endpoint do
339
342
  end
340
343
 
341
344
  context 'namespace requirements' do
342
- before :each do
345
+ before do
343
346
  subject.namespace :outer, requirements: { person_email: /abc@(.*).com/ } do
344
347
  get('/:person_email') do
345
348
  params[:person_email]
@@ -358,7 +361,7 @@ describe Grape::Endpoint do
358
361
  expect(last_response.body).to eq('abc@example.com')
359
362
  end
360
363
 
361
- it "should override outer namespace's requirements" do
364
+ it "overrides outer namespace's requirements" do
362
365
  get '/outer/inner/someone@testing.wrong/test/1'
363
366
  expect(last_response.status).to eq(404)
364
367
 
@@ -370,7 +373,7 @@ describe Grape::Endpoint do
370
373
  end
371
374
 
372
375
  context 'from body parameters' do
373
- before(:each) do
376
+ before do
374
377
  subject.post '/request_body' do
375
378
  params[:user]
376
379
  end
@@ -420,6 +423,19 @@ describe Grape::Endpoint do
420
423
  expect(last_response.status).to eq(201)
421
424
  expect(last_response.body).to eq('Bob')
422
425
  end
426
+
427
+ # Rack swallowed this error until v2.2.0
428
+ it 'returns a 400 if given an invalid multipart body', if: Gem::Version.new(Rack.release) >= Gem::Version.new('2.2.0') do
429
+ subject.params do
430
+ requires :file, type: Rack::Multipart::UploadedFile
431
+ end
432
+ subject.post '/upload' do
433
+ params[:file][:filename]
434
+ end
435
+ post '/upload', { file: '' }, 'CONTENT_TYPE' => 'multipart/form-data; boundary=foobar'
436
+ expect(last_response.status).to eq(400)
437
+ expect(last_response.body).to eq('Empty message body supplied with multipart/form-data; boundary=foobar content-type')
438
+ end
423
439
  end
424
440
 
425
441
  it 'responds with a 415 for an unsupported content-type' do
@@ -456,11 +472,11 @@ describe Grape::Endpoint do
456
472
  post '/', ::Grape::Json.dump(data: { some: 'payload' }), 'CONTENT_TYPE' => 'application/json'
457
473
  end
458
474
 
459
- it 'should not response with 406 for same type without params' do
475
+ it 'does not response with 406 for same type without params' do
460
476
  expect(last_response.status).not_to be 406
461
477
  end
462
478
 
463
- it 'should response with given content type in headers' do
479
+ it 'responses with given content type in headers' do
464
480
  expect(last_response.headers['Content-Type']).to eq 'application/json; charset=utf-8'
465
481
  end
466
482
  end
@@ -696,16 +712,18 @@ describe Grape::Endpoint do
696
712
  describe '.generate_api_method' do
697
713
  it 'raises NameError if the method name is already in use' do
698
714
  expect do
699
- Grape::Endpoint.generate_api_method('version', &proc {})
715
+ described_class.generate_api_method('version', &proc {})
700
716
  end.to raise_error(NameError)
701
717
  end
718
+
702
719
  it 'raises ArgumentError if a block is not given' do
703
720
  expect do
704
- Grape::Endpoint.generate_api_method('GET without a block method')
721
+ described_class.generate_api_method('GET without a block method')
705
722
  end.to raise_error(ArgumentError)
706
723
  end
724
+
707
725
  it 'returns a Proc' do
708
- expect(Grape::Endpoint.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
726
+ expect(described_class.generate_api_method('GET test for a proc', &proc {})).to be_a Proc
709
727
  end
710
728
  end
711
729
 
@@ -764,7 +782,7 @@ describe Grape::Endpoint do
764
782
  end
765
783
 
766
784
  get '/error_filters'
767
- expect(last_response.status).to eql 500
785
+ expect(last_response.status).to be 500
768
786
  expect(called).to match_array %w[before before_validation]
769
787
  end
770
788
 
@@ -773,8 +791,11 @@ describe Grape::Endpoint do
773
791
  subject.before { called << 'parent' }
774
792
  subject.namespace :parent do
775
793
  before { called << 'prior' }
794
+
776
795
  before { error! :oops, 500 }
796
+
777
797
  before { called << 'subsequent' }
798
+
778
799
  get :hello do
779
800
  called << :endpoint
780
801
  'Hello!'
@@ -782,7 +803,7 @@ describe Grape::Endpoint do
782
803
  end
783
804
 
784
805
  get '/parent/hello'
785
- expect(last_response.status).to eql 500
806
+ expect(last_response.status).to be 500
786
807
  expect(called).to match_array %w[parent prior]
787
808
  end
788
809
  end
@@ -793,19 +814,19 @@ describe Grape::Endpoint do
793
814
  it 'allows for the anchoring option with a delete method' do
794
815
  subject.send(:delete, '/example', anchor: true) {}
795
816
  send(:delete, '/example/and/some/more')
796
- expect(last_response.status).to eql 404
817
+ expect(last_response.status).to be 404
797
818
  end
798
819
 
799
820
  it 'anchors paths by default for the delete method' do
800
821
  subject.send(:delete, '/example') {}
801
822
  send(:delete, '/example/and/some/more')
802
- expect(last_response.status).to eql 404
823
+ expect(last_response.status).to be 404
803
824
  end
804
825
 
805
826
  it 'responds to /example/and/some/more for the non-anchored delete method' do
806
827
  subject.send(:delete, '/example', anchor: false) {}
807
828
  send(:delete, '/example/and/some/more')
808
- expect(last_response.status).to eql 204
829
+ expect(last_response.status).to be 204
809
830
  expect(last_response.body).to be_empty
810
831
  end
811
832
  end
@@ -817,7 +838,7 @@ describe Grape::Endpoint do
817
838
  body 'deleted'
818
839
  end
819
840
  send(:delete, '/example/and/some/more')
820
- expect(last_response.status).to eql 200
841
+ expect(last_response.status).to be 200
821
842
  expect(last_response.body).not_to be_empty
822
843
  end
823
844
  end
@@ -826,7 +847,7 @@ describe Grape::Endpoint do
826
847
  it 'responds to /example delete method' do
827
848
  subject.delete(:example) { 'deleted' }
828
849
  delete '/example'
829
- expect(last_response.status).to eql 200
850
+ expect(last_response.status).to be 200
830
851
  expect(last_response.body).not_to be_empty
831
852
  end
832
853
  end
@@ -835,7 +856,7 @@ describe Grape::Endpoint do
835
856
  it 'responds to /example delete method' do
836
857
  subject.delete(:example) { nil }
837
858
  delete '/example'
838
- expect(last_response.status).to eql 204
859
+ expect(last_response.status).to be 204
839
860
  expect(last_response.body).to be_empty
840
861
  end
841
862
  end
@@ -844,7 +865,7 @@ describe Grape::Endpoint do
844
865
  it 'responds to /example delete method' do
845
866
  subject.delete(:example) { '' }
846
867
  delete '/example'
847
- expect(last_response.status).to eql 204
868
+ expect(last_response.status).to be 204
848
869
  expect(last_response.body).to be_empty
849
870
  end
850
871
  end
@@ -856,7 +877,7 @@ describe Grape::Endpoint do
856
877
  verb
857
878
  end
858
879
  send(verb, '/example/and/some/more')
859
- expect(last_response.status).to eql 404
880
+ expect(last_response.status).to be 404
860
881
  end
861
882
 
862
883
  it "anchors paths by default for the #{verb.upcase} method" do
@@ -864,7 +885,7 @@ describe Grape::Endpoint do
864
885
  verb
865
886
  end
866
887
  send(verb, '/example/and/some/more')
867
- expect(last_response.status).to eql 404
888
+ expect(last_response.status).to be 404
868
889
  end
869
890
 
870
891
  it "responds to /example/and/some/more for the non-anchored #{verb.upcase} method" do
@@ -887,8 +908,9 @@ describe Grape::Endpoint do
887
908
  get '/url'
888
909
  expect(last_response.body).to eq('http://example.org/url')
889
910
  end
911
+
890
912
  ['v1', :v1].each do |version|
891
- it "should include version #{version}" do
913
+ it "includes version #{version}" do
892
914
  subject.version version, using: :path
893
915
  subject.get('/url') do
894
916
  request.url
@@ -897,7 +919,7 @@ describe Grape::Endpoint do
897
919
  expect(last_response.body).to eq("http://example.org/#{version}/url")
898
920
  end
899
921
  end
900
- it 'should include prefix' do
922
+ it 'includes prefix' do
901
923
  subject.version 'v1', using: :path
902
924
  subject.prefix 'api'
903
925
  subject.get('/url') do
@@ -987,26 +1009,26 @@ describe Grape::Endpoint do
987
1009
 
988
1010
  # In order that the events finalized (time each block ended)
989
1011
  expect(@events).to contain_exactly(
990
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1012
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
991
1013
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
992
1014
  type: :before }),
993
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1015
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
994
1016
  filters: [],
995
1017
  type: :before_validation }),
996
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1018
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
997
1019
  validators: [],
998
1020
  request: a_kind_of(Grape::Request) }),
999
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1021
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1000
1022
  filters: [],
1001
1023
  type: :after_validation }),
1002
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1003
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1024
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1025
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1004
1026
  filters: [],
1005
1027
  type: :after }),
1006
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1028
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1007
1029
  filters: [],
1008
1030
  type: :finally }),
1009
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1031
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1010
1032
  env: an_instance_of(Hash) }),
1011
1033
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
1012
1034
  formatter: a_kind_of(Module) })
@@ -1014,25 +1036,25 @@ describe Grape::Endpoint do
1014
1036
 
1015
1037
  # In order that events were initialized
1016
1038
  expect(@events.sort_by(&:time)).to contain_exactly(
1017
- have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1039
+ have_attributes(name: 'endpoint_run.grape', payload: { endpoint: a_kind_of(described_class),
1018
1040
  env: an_instance_of(Hash) }),
1019
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1041
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1020
1042
  filters: a_collection_containing_exactly(an_instance_of(Proc)),
1021
1043
  type: :before }),
1022
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1044
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1023
1045
  filters: [],
1024
1046
  type: :before_validation }),
1025
- have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1047
+ have_attributes(name: 'endpoint_run_validators.grape', payload: { endpoint: a_kind_of(described_class),
1026
1048
  validators: [],
1027
1049
  request: a_kind_of(Grape::Request) }),
1028
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1050
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1029
1051
  filters: [],
1030
1052
  type: :after_validation }),
1031
- have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(Grape::Endpoint) }),
1032
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1053
+ have_attributes(name: 'endpoint_render.grape', payload: { endpoint: a_kind_of(described_class) }),
1054
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1033
1055
  filters: [],
1034
1056
  type: :after }),
1035
- have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(Grape::Endpoint),
1057
+ have_attributes(name: 'endpoint_run_filters.grape', payload: { endpoint: a_kind_of(described_class),
1036
1058
  filters: [],
1037
1059
  type: :finally }),
1038
1060
  have_attributes(name: 'format_response.grape', payload: { env: an_instance_of(Hash),
@@ -32,7 +32,7 @@ describe Grape::Entity do
32
32
  end
33
33
 
34
34
  it 'pulls a representation from the class options if it exists' do
35
- entity = Class.new(Grape::Entity)
35
+ entity = Class.new(described_class)
36
36
  allow(entity).to receive(:represent).and_return('Hiya')
37
37
 
38
38
  subject.represent Object, with: entity
@@ -44,7 +44,7 @@ describe Grape::Entity do
44
44
  end
45
45
 
46
46
  it 'pulls a representation from the class options if the presented object is a collection of objects' do
47
- entity = Class.new(Grape::Entity)
47
+ entity = Class.new(described_class)
48
48
  allow(entity).to receive(:represent).and_return('Hiya')
49
49
 
50
50
  module EntitySpec
@@ -75,7 +75,7 @@ describe Grape::Entity do
75
75
  end
76
76
 
77
77
  it 'pulls a representation from the class ancestor if it exists' do
78
- entity = Class.new(Grape::Entity)
78
+ entity = Class.new(described_class)
79
79
  allow(entity).to receive(:represent).and_return('Hiya')
80
80
 
81
81
  subclass = Class.new(Object)
@@ -90,7 +90,7 @@ describe Grape::Entity do
90
90
 
91
91
  it 'automatically uses Klass::Entity if that exists' do
92
92
  some_model = Class.new
93
- entity = Class.new(Grape::Entity)
93
+ entity = Class.new(described_class)
94
94
  allow(entity).to receive(:represent).and_return('Auto-detect!')
95
95
 
96
96
  some_model.const_set :Entity, entity
@@ -104,7 +104,7 @@ describe Grape::Entity do
104
104
 
105
105
  it 'automatically uses Klass::Entity based on the first object in the collection being presented' do
106
106
  some_model = Class.new
107
- entity = Class.new(Grape::Entity)
107
+ entity = Class.new(described_class)
108
108
  allow(entity).to receive(:represent).and_return('Auto-detect!')
109
109
 
110
110
  some_model.const_set :Entity, entity
@@ -117,7 +117,7 @@ describe Grape::Entity do
117
117
  end
118
118
 
119
119
  it 'does not run autodetection for Entity when explicitly provided' do
120
- entity = Class.new(Grape::Entity)
120
+ entity = Class.new(described_class)
121
121
  some_array = []
122
122
 
123
123
  subject.get '/example' do
@@ -129,7 +129,7 @@ describe Grape::Entity do
129
129
  end
130
130
 
131
131
  it 'does not use #first method on ActiveRecord::Relation to prevent needless sql query' do
132
- entity = Class.new(Grape::Entity)
132
+ entity = Class.new(described_class)
133
133
  some_relation = Class.new
134
134
  some_model = Class.new
135
135
 
@@ -173,7 +173,7 @@ describe Grape::Entity do
173
173
 
174
174
  %i[json serializable_hash].each do |format|
175
175
  it "presents with #{format}" do
176
- entity = Class.new(Grape::Entity)
176
+ entity = Class.new(described_class)
177
177
  entity.root 'examples', 'example'
178
178
  entity.expose :id
179
179
 
@@ -195,7 +195,7 @@ describe Grape::Entity do
195
195
  end
196
196
 
197
197
  it "presents with #{format} collection" do
198
- entity = Class.new(Grape::Entity)
198
+ entity = Class.new(described_class)
199
199
  entity.root 'examples', 'example'
200
200
  entity.expose :id
201
201
 
@@ -219,7 +219,7 @@ describe Grape::Entity do
219
219
  end
220
220
 
221
221
  it 'presents with xml' do
222
- entity = Class.new(Grape::Entity)
222
+ entity = Class.new(described_class)
223
223
  entity.root 'examples', 'example'
224
224
  entity.expose :name
225
225
 
@@ -238,18 +238,18 @@ describe Grape::Entity do
238
238
  get '/example'
239
239
  expect(last_response.status).to eq(200)
240
240
  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
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
249
249
  end
250
250
 
251
251
  it 'presents with json' do
252
- entity = Class.new(Grape::Entity)
252
+ entity = Class.new(described_class)
253
253
  entity.root 'examples', 'example'
254
254
  entity.expose :name
255
255
 
@@ -275,7 +275,7 @@ XML
275
275
  # Include JSONP middleware
276
276
  subject.use Rack::JSONP
277
277
 
278
- entity = Class.new(Grape::Entity)
278
+ entity = Class.new(described_class)
279
279
  entity.root 'examples', 'example'
280
280
  entity.expose :name
281
281
 
@@ -315,7 +315,7 @@ XML
315
315
  user1 = user.new(name: 'user1')
316
316
  user2 = user.new(name: 'user2')
317
317
 
318
- entity = Class.new(Grape::Entity)
318
+ entity = Class.new(described_class)
319
319
  entity.expose :name
320
320
 
321
321
  subject.format :json
@@ -326,7 +326,7 @@ XML
326
326
  end
327
327
  get '/example'
328
328
  expect_response_json = {
329
- 'page' => 1,
329
+ 'page' => 1,
330
330
  'user1' => { 'name' => 'user1' },
331
331
  'user2' => { 'name' => 'user2' }
332
332
  }
@@ -5,6 +5,7 @@ require 'spec_helper'
5
5
  describe Grape::Exceptions::ValidationErrors do
6
6
  context 'api with rescue_from :all handler' do
7
7
  subject { Class.new(Grape::API) }
8
+
8
9
  before do
9
10
  subject.rescue_from :all do |_e|
10
11
  rack_response 'message was processed', 400
@@ -56,6 +57,7 @@ describe Grape::Exceptions::ValidationErrors do
56
57
 
57
58
  context 'api with rescue_from :grape_exceptions handler' do
58
59
  subject { Class.new(Grape::API) }
60
+
59
61
  before do
60
62
  subject.rescue_from :all do |_e|
61
63
  rack_response 'message was processed', 400
@@ -93,6 +95,7 @@ describe Grape::Exceptions::ValidationErrors do
93
95
 
94
96
  context 'api without a rescue handler' do
95
97
  subject { Class.new(Grape::API) }
98
+
96
99
  before do
97
100
  subject.params do
98
101
  requires :beer