grape 1.6.0 → 1.6.1

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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/CONTRIBUTING.md +1 -0
  4. data/README.md +9 -1
  5. data/lib/grape/api.rb +12 -0
  6. data/lib/grape/dry_types.rb +12 -0
  7. data/lib/grape/dsl/headers.rb +5 -2
  8. data/lib/grape/dsl/helpers.rb +1 -1
  9. data/lib/grape/middleware/auth/dsl.rb +7 -1
  10. data/lib/grape/middleware/base.rb +1 -1
  11. data/lib/grape/util/json.rb +2 -0
  12. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  13. data/lib/grape/validations/types/array_coercer.rb +0 -2
  14. data/lib/grape/validations/types/dry_type_coercer.rb +1 -10
  15. data/lib/grape/validations/types/json.rb +0 -2
  16. data/lib/grape/validations/types/primitive_coercer.rb +5 -7
  17. data/lib/grape/validations/types/set_coercer.rb +0 -3
  18. data/lib/grape/validations/types.rb +83 -9
  19. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  20. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  21. data/lib/grape/validations/validators/as_validator.rb +14 -0
  22. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  23. data/lib/grape/validations/validators/base.rb +73 -71
  24. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  25. data/lib/grape/validations/validators/default_validator.rb +51 -0
  26. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  27. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  28. data/lib/grape/validations/validators/multiple_params_base.rb +24 -22
  29. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  30. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  31. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  32. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  33. data/lib/grape/validations/validators/values_validator.rb +88 -0
  34. data/lib/grape/version.rb +1 -1
  35. data/lib/grape.rb +59 -24
  36. data/spec/grape/api/custom_validations_spec.rb +77 -46
  37. data/spec/grape/api/deeply_included_options_spec.rb +3 -3
  38. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
  39. data/spec/grape/api/invalid_format_spec.rb +2 -0
  40. data/spec/grape/api/recognize_path_spec.rb +1 -1
  41. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
  42. data/spec/grape/api_remount_spec.rb +16 -15
  43. data/spec/grape/api_spec.rb +317 -193
  44. data/spec/grape/dsl/callbacks_spec.rb +1 -0
  45. data/spec/grape/dsl/headers_spec.rb +39 -9
  46. data/spec/grape/dsl/helpers_spec.rb +3 -2
  47. data/spec/grape/dsl/inside_route_spec.rb +6 -4
  48. data/spec/grape/dsl/logger_spec.rb +16 -18
  49. data/spec/grape/dsl/middleware_spec.rb +1 -0
  50. data/spec/grape/dsl/parameters_spec.rb +1 -0
  51. data/spec/grape/dsl/request_response_spec.rb +1 -0
  52. data/spec/grape/dsl/routing_spec.rb +9 -6
  53. data/spec/grape/endpoint/declared_spec.rb +12 -12
  54. data/spec/grape/endpoint_spec.rb +59 -50
  55. data/spec/grape/entity_spec.rb +13 -13
  56. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
  57. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
  58. data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
  59. data/spec/grape/exceptions/validation_spec.rb +5 -3
  60. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
  61. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
  62. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
  63. data/spec/grape/integration/rack_sendfile_spec.rb +1 -1
  64. data/spec/grape/loading_spec.rb +8 -8
  65. data/spec/grape/middleware/auth/dsl_spec.rb +14 -5
  66. data/spec/grape/middleware/auth/strategies_spec.rb +60 -20
  67. data/spec/grape/middleware/base_spec.rb +24 -15
  68. data/spec/grape/middleware/error_spec.rb +1 -0
  69. data/spec/grape/middleware/exception_spec.rb +111 -161
  70. data/spec/grape/middleware/formatter_spec.rb +25 -4
  71. data/spec/grape/middleware/globals_spec.rb +7 -4
  72. data/spec/grape/middleware/stack_spec.rb +11 -11
  73. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
  74. data/spec/grape/middleware/versioner/header_spec.rb +14 -13
  75. data/spec/grape/middleware/versioner/param_spec.rb +7 -1
  76. data/spec/grape/middleware/versioner/path_spec.rb +5 -1
  77. data/spec/grape/middleware/versioner_spec.rb +1 -1
  78. data/spec/grape/parser_spec.rb +4 -0
  79. data/spec/grape/path_spec.rb +52 -52
  80. data/spec/grape/presenters/presenter_spec.rb +7 -6
  81. data/spec/grape/request_spec.rb +6 -4
  82. data/spec/grape/util/inheritable_setting_spec.rb +7 -7
  83. data/spec/grape/util/inheritable_values_spec.rb +3 -2
  84. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
  85. data/spec/grape/util/stackable_values_spec.rb +7 -5
  86. data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
  87. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -0
  88. data/spec/grape/validations/params_scope_spec.rb +9 -7
  89. data/spec/grape/validations/single_attribute_iterator_spec.rb +1 -0
  90. data/spec/grape/validations/types/primitive_coercer_spec.rb +2 -2
  91. data/spec/grape/validations/types_spec.rb +8 -8
  92. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
  93. data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
  94. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
  95. data/spec/grape/validations/validators/coerce_spec.rb +10 -12
  96. data/spec/grape/validations/validators/default_spec.rb +72 -78
  97. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
  98. data/spec/grape/validations/validators/except_values_spec.rb +1 -1
  99. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
  100. data/spec/grape/validations/validators/presence_spec.rb +16 -1
  101. data/spec/grape/validations/validators/regexp_spec.rb +25 -31
  102. data/spec/grape/validations/validators/same_as_spec.rb +14 -20
  103. data/spec/grape/validations/validators/values_spec.rb +172 -171
  104. data/spec/grape/validations_spec.rb +45 -16
  105. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  106. data/spec/integration/multi_json/json_spec.rb +1 -1
  107. data/spec/integration/multi_xml/xml_spec.rb +1 -1
  108. data/spec/shared/versioning_examples.rb +10 -7
  109. data/spec/spec_helper.rb +11 -1
  110. metadata +116 -116
  111. data/lib/grape/validations/types/build_coercer.rb +0 -94
  112. data/lib/grape/validations/validators/all_or_none.rb +0 -16
  113. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  114. data/lib/grape/validations/validators/as.rb +0 -12
  115. data/lib/grape/validations/validators/at_least_one_of.rb +0 -15
  116. data/lib/grape/validations/validators/coerce.rb +0 -87
  117. data/lib/grape/validations/validators/default.rb +0 -49
  118. data/lib/grape/validations/validators/exactly_one_of.rb +0 -17
  119. data/lib/grape/validations/validators/except_values.rb +0 -22
  120. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -16
  121. data/lib/grape/validations/validators/presence.rb +0 -13
  122. data/lib/grape/validations/validators/regexp.rb +0 -14
  123. data/lib/grape/validations/validators/same_as.rb +0 -27
  124. data/lib/grape/validations/validators/values.rb +0 -86
@@ -12,6 +12,7 @@ module Grape
12
12
 
13
13
  describe Callbacks do
14
14
  subject { Class.new(CallbacksSpec::Dummy) }
15
+
15
16
  let(:proc) { -> {} }
16
17
 
17
18
  describe '.before' do
@@ -12,21 +12,51 @@ module Grape
12
12
  describe Headers do
13
13
  subject { HeadersSpec::Dummy.new }
14
14
 
15
- describe '#header' do
16
- describe 'set' do
15
+ let(:header_data) do
16
+ { 'First Key' => 'First Value',
17
+ 'Second Key' => 'Second Value' }
18
+ end
19
+
20
+ context 'when headers are set' do
21
+ describe '#header' do
17
22
  before do
18
- subject.header 'Name', 'Value'
23
+ header_data.each { |k, v| subject.header(k, v) }
24
+ end
25
+
26
+ describe 'get' do
27
+ it 'returns a specifc value' do
28
+ expect(subject.header['First Key']).to eq 'First Value'
29
+ expect(subject.header['Second Key']).to eq 'Second Value'
30
+ end
31
+
32
+ it 'returns all set headers' do
33
+ expect(subject.header).to eq header_data
34
+ expect(subject.headers).to eq header_data
35
+ end
19
36
  end
20
37
 
21
- it 'returns value' do
22
- expect(subject.header['Name']).to eq 'Value'
23
- expect(subject.header('Name')).to eq 'Value'
38
+ describe 'set' do
39
+ it 'returns value' do
40
+ expect(subject.header('Third Key', 'Third Value'))
41
+ expect(subject.header['Third Key']).to eq 'Third Value'
42
+ end
43
+ end
44
+
45
+ describe 'delete' do
46
+ it 'deletes a header key-value pair' do
47
+ expect(subject.header('First Key')).to eq header_data['First Key']
48
+ expect(subject.header).not_to have_key('First Key')
49
+ end
24
50
  end
25
51
  end
52
+ end
26
53
 
27
- it 'returns nil' do
28
- expect(subject.header['Name']).to be nil
29
- expect(subject.header('Name')).to be nil
54
+ context 'when no headers are set' do
55
+ describe '#header' do
56
+ it 'returns nil' do
57
+ expect(subject.header['First Key']).to be nil
58
+ expect(subject.header('First Key')).to be nil
59
+ end
30
60
  end
31
61
  end
32
62
  end
@@ -34,6 +34,7 @@ module Grape
34
34
 
35
35
  describe Helpers do
36
36
  subject { Class.new(HelpersSpec::Dummy) }
37
+
37
38
  let(:proc) do
38
39
  lambda do |*|
39
40
  def test
@@ -54,7 +55,7 @@ module Grape
54
55
  it 'uses provided modules' do
55
56
  mod = Module.new
56
57
 
57
- expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.exactly(2).times
58
+ expect(subject).to receive(:namespace_stackable).with(:helpers, kind_of(Grape::DSL::Helpers::BaseHelper)).and_call_original.twice
58
59
  expect(subject).to receive(:namespace_stackable).with(:helpers).and_call_original
59
60
  subject.helpers(mod, &proc)
60
61
 
@@ -92,7 +93,7 @@ module Grape
92
93
  use :requires_toggle_prm
93
94
  end
94
95
  end
95
- end.to_not raise_exception
96
+ end.not_to raise_exception
96
97
  end
97
98
  end
98
99
  end
@@ -43,6 +43,7 @@ describe Grape::Endpoint do
43
43
  before do
44
44
  catch(:error) { subject.error! 'Not Found', 404 }
45
45
  end
46
+
46
47
  it 'sets status' do
47
48
  expect(subject.status).to eq 404
48
49
  end
@@ -53,6 +54,7 @@ describe Grape::Endpoint do
53
54
  subject.namespace_inheritable(:default_error_status, 500)
54
55
  catch(:error) { subject.error! 'Unknown' }
55
56
  end
57
+
56
58
  it 'sets status to default_error_status' do
57
59
  expect(subject.status).to eq 500
58
60
  end
@@ -136,7 +138,7 @@ describe Grape::Endpoint do
136
138
  end
137
139
 
138
140
  it 'accepts unknown Integer status codes' do
139
- expect { subject.status 210 }.to_not raise_error
141
+ expect { subject.status 210 }.not_to raise_error
140
142
  end
141
143
 
142
144
  it 'raises error if status is not a integer or symbol' do
@@ -273,7 +275,7 @@ describe Grape::Endpoint do
273
275
  end
274
276
 
275
277
  it 'sends no deprecation warnings' do
276
- expect(subject).to_not receive(:warn)
278
+ expect(subject).not_to receive(:warn)
277
279
 
278
280
  subject.sendfile file_path
279
281
  end
@@ -334,7 +336,7 @@ describe Grape::Endpoint do
334
336
  end
335
337
 
336
338
  it 'emits no deprecation warnings' do
337
- expect(subject).to_not receive(:warn)
339
+ expect(subject).not_to receive(:warn)
338
340
 
339
341
  subject.stream file_path
340
342
  end
@@ -384,7 +386,7 @@ describe Grape::Endpoint do
384
386
  end
385
387
 
386
388
  it 'emits no deprecation warnings' do
387
- expect(subject).to_not receive(:warn)
389
+ expect(subject).not_to receive(:warn)
388
390
 
389
391
  subject.stream stream_object
390
392
  end
@@ -2,27 +2,25 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- module Grape
6
- module DSL
7
- module LoggerSpec
8
- class Dummy
9
- extend Grape::DSL::Logger
10
- end
5
+ describe Grape::DSL::Logger do
6
+ subject { Class.new(dummy_logger) }
7
+
8
+ let(:dummy_logger) do
9
+ Class.new do
10
+ extend Grape::DSL::Logger
11
11
  end
12
- describe Logger do
13
- subject { Class.new(LoggerSpec::Dummy) }
14
- let(:logger) { double(:logger) }
12
+ end
15
13
 
16
- describe '.logger' do
17
- it 'sets a logger' do
18
- subject.logger logger
19
- expect(subject.logger).to eq logger
20
- end
14
+ let(:logger) { instance_double(::Logger) }
15
+
16
+ describe '.logger' do
17
+ it 'sets a logger' do
18
+ subject.logger logger
19
+ expect(subject.logger).to eq logger
20
+ end
21
21
 
22
- it 'returns a logger' do
23
- expect(subject.logger(logger)).to eq logger
24
- end
25
- end
22
+ it 'returns a logger' do
23
+ expect(subject.logger(logger)).to eq logger
26
24
  end
27
25
  end
28
26
  end
@@ -12,6 +12,7 @@ module Grape
12
12
 
13
13
  describe Middleware do
14
14
  subject { Class.new(MiddlewareSpec::Dummy) }
15
+
15
16
  let(:proc) { -> {} }
16
17
  let(:foo_middleware) { Class.new }
17
18
  let(:bar_middleware) { Class.new }
@@ -55,6 +55,7 @@ module Grape
55
55
  allow_message_expectations_on_nil
56
56
  allow(subject.api).to receive(:namespace_stackable).with(:named_params)
57
57
  end
58
+
58
59
  let(:options) { { option: 'value' } }
59
60
  let(:named_params) { { params_group: proc {} } }
60
61
 
@@ -20,6 +20,7 @@ module Grape
20
20
 
21
21
  describe RequestResponse do
22
22
  subject { Class.new(RequestResponseSpec::Dummy) }
23
+
23
24
  let(:c_type) { 'application/json' }
24
25
  let(:format) { 'txt' }
25
26
 
@@ -12,6 +12,7 @@ module Grape
12
12
 
13
13
  describe Routing do
14
14
  subject { Class.new(RoutingSpec::Dummy) }
15
+
15
16
  let(:proc) { -> {} }
16
17
  let(:options) { { a: :b } }
17
18
  let(:path) { '/dummy' }
@@ -109,7 +110,7 @@ module Grape
109
110
  it 'does not duplicate identical endpoints' do
110
111
  subject.route(:any)
111
112
  expect { subject.route(:any) }
112
- .to_not change(subject.endpoints, :count)
113
+ .not_to change(subject.endpoints, :count)
113
114
  end
114
115
 
115
116
  it 'generates correct endpoint options' do
@@ -233,21 +234,23 @@ module Grape
233
234
  allow(subject).to receive(:prepare_routes).and_return(routes)
234
235
  subject.routes
235
236
  end
236
- it 'it does not call prepare_routes again' do
237
- expect(subject).to_not receive(:prepare_routes)
237
+
238
+ it 'does not call prepare_routes again' do
239
+ expect(subject).not_to receive(:prepare_routes)
238
240
  expect(subject.routes).to eq routes
239
241
  end
240
242
  end
241
243
  end
242
244
 
243
245
  describe '.route_param' do
246
+ let!(:options) { { requirements: regex } }
247
+ let(:regex) { /(.*)/ }
248
+
244
249
  it 'calls #namespace with given params' do
245
250
  expect(subject).to receive(:namespace).with(':foo', {}).and_yield
246
251
  subject.route_param('foo', {}, &proc {})
247
252
  end
248
253
 
249
- let(:regex) { /(.*)/ }
250
- let!(:options) { { requirements: regex } }
251
254
  it 'nests requirements option under param name' do
252
255
  expect(subject).to receive(:namespace) do |_param, options|
253
256
  expect(options[:requirements][:foo]).to eq regex
@@ -258,7 +261,7 @@ module Grape
258
261
  it 'does not modify options parameter' do
259
262
  allow(subject).to receive(:namespace)
260
263
  expect { subject.route_param('foo', options, &proc {}) }
261
- .to_not change { options }
264
+ .not_to change { options }
262
265
  end
263
266
  end
264
267
 
@@ -87,7 +87,7 @@ describe Grape::Endpoint do
87
87
  end
88
88
  end
89
89
 
90
- it 'should show nil for nested params if include_missing is true' do
90
+ it 'shows nil for nested params if include_missing is true' do
91
91
  subject.get '/declared' do
92
92
  declared(params, include_missing: true)
93
93
  end
@@ -97,7 +97,7 @@ describe Grape::Endpoint do
97
97
  expect(JSON.parse(last_response.body)['nested']['fourth']).to be_nil
98
98
  end
99
99
 
100
- it 'should show nil for multiple allowed types if include_missing is true' do
100
+ it 'shows nil for multiple allowed types if include_missing is true' do
101
101
  subject.get '/declared' do
102
102
  declared(params, include_missing: true)
103
103
  end
@@ -568,34 +568,34 @@ describe Grape::Endpoint do
568
568
  get '/artists/1'
569
569
  json = JSON.parse(last_response.body, symbolize_names: true)
570
570
 
571
- expect(json.key?(:id)).to be_truthy
572
- expect(json.key?(:artist_id)).not_to be_truthy
571
+ expect(json).to be_key(:id)
572
+ expect(json).not_to be_key(:artist_id)
573
573
  end
574
574
 
575
575
  it 'return only :artist_id without :id' do
576
576
  get '/artists/1/compositions'
577
577
  json = JSON.parse(last_response.body, symbolize_names: true)
578
578
 
579
- expect(json.key?(:artist_id)).to be_truthy
580
- expect(json.key?(:id)).not_to be_truthy
579
+ expect(json).to be_key(:artist_id)
580
+ expect(json).not_to be_key(:id)
581
581
  end
582
582
 
583
583
  it 'return :filter and :id parameters in declared for second enpoint inside route_param' do
584
584
  get '/artists/1/some_route', filter: 'some_filter'
585
585
  json = JSON.parse(last_response.body, symbolize_names: true)
586
586
 
587
- expect(json.key?(:filter)).to be_truthy
588
- expect(json.key?(:id)).to be_truthy
589
- expect(json.key?(:artist_id)).not_to be_truthy
587
+ expect(json).to be_key(:filter)
588
+ expect(json).to be_key(:id)
589
+ expect(json).not_to be_key(:artist_id)
590
590
  end
591
591
 
592
592
  it 'return :compositor_id for mounter in route_param' do
593
593
  get '/artists/1/albums'
594
594
  json = JSON.parse(last_response.body, symbolize_names: true)
595
595
 
596
- expect(json.key?(:compositor_id)).to be_truthy
597
- expect(json.key?(:id)).not_to be_truthy
598
- expect(json.key?(:artist_id)).not_to be_truthy
596
+ expect(json).to be_key(:compositor_id)
597
+ expect(json).not_to be_key(:id)
598
+ expect(json).not_to be_key(:artist_id)
599
599
  end
600
600
  end
601
601