grape 1.6.2 → 1.7.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 (171) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +54 -1
  3. data/CONTRIBUTING.md +30 -0
  4. data/README.md +146 -23
  5. data/UPGRADING.md +15 -0
  6. data/grape.gemspec +2 -2
  7. data/lib/grape/api/instance.rb +1 -1
  8. data/lib/grape/dry_types.rb +12 -0
  9. data/lib/grape/dsl/api.rb +0 -2
  10. data/lib/grape/dsl/callbacks.rb +0 -2
  11. data/lib/grape/dsl/configuration.rb +0 -2
  12. data/lib/grape/dsl/desc.rb +2 -16
  13. data/lib/grape/dsl/helpers.rb +0 -2
  14. data/lib/grape/dsl/inside_route.rb +34 -30
  15. data/lib/grape/dsl/middleware.rb +0 -2
  16. data/lib/grape/dsl/parameters.rb +10 -7
  17. data/lib/grape/dsl/request_response.rb +1 -3
  18. data/lib/grape/dsl/routing.rb +4 -2
  19. data/lib/grape/dsl/settings.rb +0 -2
  20. data/lib/grape/dsl/validations.rb +0 -15
  21. data/lib/grape/endpoint.rb +2 -2
  22. data/lib/grape/error_formatter/json.rb +7 -1
  23. data/lib/grape/exceptions/base.rb +3 -2
  24. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  25. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  26. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  27. data/lib/grape/exceptions/validation.rb +0 -4
  28. data/lib/grape/locale/en.yml +9 -8
  29. data/lib/grape/middleware/auth/dsl.rb +0 -1
  30. data/lib/grape/middleware/error.rb +2 -2
  31. data/lib/grape/middleware/stack.rb +1 -1
  32. data/lib/grape/request.rb +3 -1
  33. data/lib/grape/router/attribute_translator.rb +1 -1
  34. data/lib/grape/types/invalid_value.rb +8 -0
  35. data/lib/grape/util/cache.rb +1 -1
  36. data/lib/grape/util/json.rb +2 -0
  37. data/lib/grape/validations/attributes_doc.rb +58 -0
  38. data/lib/grape/validations/params_scope.rb +67 -41
  39. data/lib/grape/validations/types/array_coercer.rb +0 -2
  40. data/lib/grape/validations/types/dry_type_coercer.rb +3 -7
  41. data/lib/grape/validations/types/invalid_value.rb +0 -7
  42. data/lib/grape/validations/types/primitive_coercer.rb +14 -6
  43. data/lib/grape/validations/types/set_coercer.rb +0 -2
  44. data/lib/grape/validations/types.rb +98 -30
  45. data/lib/grape/validations/validators/{all_or_none.rb → all_or_none_of_validator.rb} +0 -2
  46. data/lib/grape/validations/validators/{at_least_one_of.rb → at_least_one_of_validator.rb} +0 -2
  47. data/lib/grape/validations/validators/base.rb +7 -0
  48. data/lib/grape/validations/validators/{exactly_one_of.rb → exactly_one_of_validator.rb} +0 -2
  49. data/lib/grape/validations/validators/{mutual_exclusion.rb → mutual_exclusion_validator.rb} +0 -2
  50. data/lib/grape/validations.rb +16 -12
  51. data/lib/grape/version.rb +1 -1
  52. data/lib/grape.rb +74 -28
  53. data/spec/grape/api/custom_validations_spec.rb +41 -2
  54. data/spec/grape/api/deeply_included_options_spec.rb +0 -2
  55. data/spec/grape/api/defines_boolean_in_params_spec.rb +0 -2
  56. data/spec/grape/api/documentation_spec.rb +59 -0
  57. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  58. data/spec/grape/api/instance_spec.rb +0 -1
  59. data/spec/grape/api/invalid_format_spec.rb +0 -2
  60. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  61. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  62. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  63. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  64. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  65. data/spec/grape/api/recognize_path_spec.rb +0 -2
  66. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  67. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  68. data/spec/grape/api/routes_with_requirements_spec.rb +0 -2
  69. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +0 -2
  70. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  71. data/spec/grape/api_remount_spec.rb +0 -1
  72. data/spec/grape/api_spec.rb +23 -25
  73. data/spec/grape/config_spec.rb +0 -2
  74. data/spec/grape/dsl/callbacks_spec.rb +0 -2
  75. data/spec/grape/dsl/desc_spec.rb +2 -2
  76. data/spec/grape/dsl/headers_spec.rb +2 -4
  77. data/spec/grape/dsl/helpers_spec.rb +0 -2
  78. data/spec/grape/dsl/inside_route_spec.rb +10 -12
  79. data/spec/grape/dsl/logger_spec.rb +0 -2
  80. data/spec/grape/dsl/middleware_spec.rb +0 -2
  81. data/spec/grape/dsl/parameters_spec.rb +0 -2
  82. data/spec/grape/dsl/request_response_spec.rb +6 -8
  83. data/spec/grape/dsl/routing_spec.rb +1 -3
  84. data/spec/grape/dsl/settings_spec.rb +0 -2
  85. data/spec/grape/dsl/validations_spec.rb +0 -17
  86. data/spec/grape/endpoint/declared_spec.rb +2 -4
  87. data/spec/grape/endpoint_spec.rb +29 -9
  88. data/spec/grape/entity_spec.rb +0 -1
  89. data/spec/grape/exceptions/base_spec.rb +16 -2
  90. data/spec/grape/exceptions/body_parse_errors_spec.rb +0 -2
  91. data/spec/grape/exceptions/invalid_accept_header_spec.rb +3 -2
  92. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  93. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  94. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  95. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  96. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  97. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  98. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  99. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  100. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  101. data/spec/grape/exceptions/validation_errors_spec.rb +0 -1
  102. data/spec/grape/exceptions/validation_spec.rb +1 -3
  103. data/spec/grape/extensions/param_builders/hash_spec.rb +0 -2
  104. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +0 -2
  105. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +0 -2
  106. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  107. data/spec/grape/integration/rack_sendfile_spec.rb +0 -2
  108. data/spec/grape/integration/rack_spec.rb +6 -7
  109. data/spec/grape/loading_spec.rb +0 -2
  110. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  111. data/spec/grape/middleware/auth/dsl_spec.rb +0 -2
  112. data/spec/grape/middleware/auth/strategies_spec.rb +0 -2
  113. data/spec/grape/middleware/base_spec.rb +7 -7
  114. data/spec/grape/middleware/error_spec.rb +6 -1
  115. data/spec/grape/middleware/exception_spec.rb +0 -2
  116. data/spec/grape/middleware/formatter_spec.rb +6 -8
  117. data/spec/grape/middleware/globals_spec.rb +0 -2
  118. data/spec/grape/middleware/stack_spec.rb +0 -2
  119. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +0 -2
  120. data/spec/grape/middleware/versioner/header_spec.rb +18 -4
  121. data/spec/grape/middleware/versioner/param_spec.rb +0 -2
  122. data/spec/grape/middleware/versioner/path_spec.rb +0 -2
  123. data/spec/grape/middleware/versioner_spec.rb +0 -2
  124. data/spec/grape/named_api_spec.rb +0 -2
  125. data/spec/grape/parser_spec.rb +0 -2
  126. data/spec/grape/path_spec.rb +0 -2
  127. data/spec/grape/presenters/presenter_spec.rb +0 -2
  128. data/spec/grape/request_spec.rb +0 -2
  129. data/spec/grape/util/inheritable_setting_spec.rb +0 -1
  130. data/spec/grape/util/inheritable_values_spec.rb +0 -1
  131. data/spec/grape/util/reverse_stackable_values_spec.rb +0 -1
  132. data/spec/grape/util/stackable_values_spec.rb +0 -1
  133. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  134. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  135. data/spec/grape/validations/instance_behaivour_spec.rb +0 -2
  136. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +0 -2
  137. data/spec/grape/validations/params_scope_spec.rb +315 -86
  138. data/spec/grape/validations/single_attribute_iterator_spec.rb +0 -2
  139. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  140. data/spec/grape/validations/types/primitive_coercer_spec.rb +20 -5
  141. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  142. data/spec/grape/validations/types_spec.rb +28 -2
  143. data/spec/grape/validations/validators/all_or_none_spec.rb +0 -2
  144. data/spec/grape/validations/validators/allow_blank_spec.rb +0 -2
  145. data/spec/grape/validations/validators/at_least_one_of_spec.rb +0 -2
  146. data/spec/grape/validations/validators/coerce_spec.rb +0 -2
  147. data/spec/grape/validations/validators/default_spec.rb +0 -2
  148. data/spec/grape/validations/validators/exactly_one_of_spec.rb +0 -2
  149. data/spec/grape/validations/validators/except_values_spec.rb +0 -2
  150. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +0 -2
  151. data/spec/grape/validations/validators/presence_spec.rb +0 -2
  152. data/spec/grape/validations/validators/regexp_spec.rb +0 -2
  153. data/spec/grape/validations/validators/same_as_spec.rb +0 -2
  154. data/spec/grape/validations/validators/values_spec.rb +19 -2
  155. data/spec/grape/validations_spec.rb +78 -27
  156. data/spec/integration/multi_json/json_spec.rb +0 -2
  157. data/spec/integration/multi_xml/xml_spec.rb +0 -2
  158. data/spec/spec_helper.rb +9 -4
  159. metadata +134 -122
  160. data/spec/grape/dsl/configuration_spec.rb +0 -16
  161. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  162. data/spec/support/eager_load.rb +0 -19
  163. /data/lib/grape/validations/validators/{allow_blank.rb → allow_blank_validator.rb} +0 -0
  164. /data/lib/grape/validations/validators/{as.rb → as_validator.rb} +0 -0
  165. /data/lib/grape/validations/validators/{coerce.rb → coerce_validator.rb} +0 -0
  166. /data/lib/grape/validations/validators/{default.rb → default_validator.rb} +0 -0
  167. /data/lib/grape/validations/validators/{except_values.rb → except_values_validator.rb} +0 -0
  168. /data/lib/grape/validations/validators/{presence.rb → presence_validator.rb} +0 -0
  169. /data/lib/grape/validations/validators/{regexp.rb → regexp_validator.rb} +0 -0
  170. /data/lib/grape/validations/validators/{same_as.rb → same_as_validator.rb} +0 -0
  171. /data/lib/grape/validations/validators/{values.rb → values_validator.rb} +0 -0
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Types::PrimitiveCoercer do
6
4
  subject { described_class.new(type, strict) }
7
5
 
@@ -25,13 +23,13 @@ describe Grape::Validations::Types::PrimitiveCoercer do
25
23
 
26
24
  [true, 'true', 1].each do |val|
27
25
  it "coerces '#{val}' to true" do
28
- expect(subject.call(val)).to eq(true)
26
+ expect(subject.call(val)).to be(true)
29
27
  end
30
28
  end
31
29
 
32
30
  [false, 'false', 0].each do |val|
33
31
  it "coerces '#{val}' to false" do
34
- expect(subject.call(val)).to eq(false)
32
+ expect(subject.call(val)).to be(false)
35
33
  end
36
34
  end
37
35
 
@@ -66,6 +64,10 @@ describe Grape::Validations::Types::PrimitiveCoercer do
66
64
  it 'coerces an empty string to nil' do
67
65
  expect(subject.call('')).to be_nil
68
66
  end
67
+
68
+ it 'accepts non-nil value' do
69
+ expect(subject.call(42)).to be_a(Integer)
70
+ end
69
71
  end
70
72
 
71
73
  context 'Numeric' do
@@ -74,6 +76,10 @@ describe Grape::Validations::Types::PrimitiveCoercer do
74
76
  it 'coerces an empty string to nil' do
75
77
  expect(subject.call('')).to be_nil
76
78
  end
79
+
80
+ it 'accepts a non-nil value' do
81
+ expect(subject.call(42)).to be_a(Numeric) # in fact Integer
82
+ end
77
83
  end
78
84
 
79
85
  context 'Time' do
@@ -104,6 +110,15 @@ describe Grape::Validations::Types::PrimitiveCoercer do
104
110
  end
105
111
  end
106
112
 
113
+ context 'a type unknown in Dry-types' do
114
+ let(:type) { Complex }
115
+
116
+ it 'raises error on init' do
117
+ expect(DryTypes::Params.constants).not_to include(type.name.to_sym)
118
+ expect { subject }.to raise_error(/type Complex should support coercion/)
119
+ end
120
+ end
121
+
107
122
  context 'the strict mode' do
108
123
  let(:strict) { true }
109
124
 
@@ -115,7 +130,7 @@ describe Grape::Validations::Types::PrimitiveCoercer do
115
130
  end
116
131
 
117
132
  it 'returns a value as it is when the given value is Boolean' do
118
- expect(subject.call(true)).to eq(true)
133
+ expect(subject.call(true)).to be(true)
119
134
  end
120
135
  end
121
136
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Types::SetCoercer do
6
4
  subject { described_class.new(type) }
7
5
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Types do
6
4
  module TypesSpec
7
5
  class FooType
@@ -50,6 +48,34 @@ describe Grape::Validations::Types do
50
48
  end
51
49
  end
52
50
 
51
+ describe 'special types' do
52
+ subject { described_class::SPECIAL[type] }
53
+
54
+ context 'when JSON' do
55
+ let(:type) { JSON }
56
+
57
+ it { is_expected.to eq(Grape::Validations::Types::Json) }
58
+ end
59
+
60
+ context 'when Array[JSON]' do
61
+ let(:type) { Array[JSON] }
62
+
63
+ it { is_expected.to eq(Grape::Validations::Types::JsonArray) }
64
+ end
65
+
66
+ context 'when File' do
67
+ let(:type) { File }
68
+
69
+ it { is_expected.to eq(Grape::Validations::Types::File) }
70
+ end
71
+
72
+ context 'when Rack::Multipart::UploadedFile' do
73
+ let(:type) { Rack::Multipart::UploadedFile }
74
+
75
+ it { is_expected.to eq(Grape::Validations::Types::File) }
76
+ end
77
+ end
78
+
53
79
  describe '::custom?' do
54
80
  it 'returns false if the type does not respond to :parse' do
55
81
  expect(described_class).not_to be_custom(Object)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::AllOrNoneOfValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::AllowBlankValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::AtLeastOneOfValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::CoerceValidator do
6
4
  subject do
7
5
  Class.new(Grape::API)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::DefaultValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::ExactlyOneOfValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::ExceptValuesValidator do
6
4
  module ValidationsSpec
7
5
  class ExceptValuesModel
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::MutualExclusionValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::PresenceValidator do
6
4
  subject do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::RegexpValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::SameAsValidator do
6
4
  let_it_be(:app) do
7
5
  Class.new(Grape::API) do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Validators::ValuesValidator do
6
4
  let_it_be(:values_model) do
7
5
  Class.new do
@@ -116,6 +114,13 @@ describe Grape::Validations::Validators::ValuesValidator do
116
114
  { type: params[:type] }
117
115
  end
118
116
 
117
+ params do
118
+ optional :type, type: Integer, values: 1..
119
+ end
120
+ get '/endless' do
121
+ { type: params[:type] }
122
+ end
123
+
119
124
  params do
120
125
  requires :type, values: ->(v) { ValuesModel.include? v }
121
126
  end
@@ -376,6 +381,18 @@ describe Grape::Validations::Validators::ValuesValidator do
376
381
  expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
377
382
  end
378
383
 
384
+ it 'validates against values in an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
385
+ get('/endless', type: 10)
386
+ expect(last_response.status).to eq 200
387
+ expect(last_response.body).to eq({ type: 10 }.to_json)
388
+ end
389
+
390
+ it 'does not allow an invalid value for a parameter using an endless range', if: ActiveSupport::VERSION::MAJOR >= 6 do
391
+ get('/endless', type: 0)
392
+ expect(last_response.status).to eq 400
393
+ expect(last_response.body).to eq({ error: 'type does not have a valid value' }.to_json)
394
+ end
395
+
379
396
  it 'does not allow non-numeric string value for int value using lambda' do
380
397
  get('/lambda_int_val', number: 'foo')
381
398
  expect(last_response.status).to eq 400
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations do
6
4
  subject { Class.new(Grape::API) }
7
5
 
@@ -45,7 +43,7 @@ describe Grape::Validations do
45
43
  subject.params do
46
44
  optional :some_param
47
45
  end
48
- expect(declared_params).to eq([:some_param])
46
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([:some_param])
49
47
  end
50
48
  end
51
49
 
@@ -65,7 +63,7 @@ describe Grape::Validations do
65
63
 
66
64
  it 'adds entity documentation to declared params' do
67
65
  define_optional_using
68
- expect(declared_params).to eq(%i[field_a field_b])
66
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[field_a field_b])
69
67
  end
70
68
 
71
69
  it 'works when field_a and field_b are not present' do
@@ -112,7 +110,7 @@ describe Grape::Validations do
112
110
  subject.params do
113
111
  requires :some_param
114
112
  end
115
- expect(declared_params).to eq([:some_param])
113
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([:some_param])
116
114
  end
117
115
 
118
116
  it 'works when required field is present but nil' do
@@ -197,7 +195,7 @@ describe Grape::Validations do
197
195
 
198
196
  it 'adds entity documentation to declared params' do
199
197
  define_requires_all
200
- expect(declared_params).to eq(%i[required_field optional_field])
198
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
201
199
  end
202
200
 
203
201
  it 'errors when required_field is not present' do
@@ -232,7 +230,7 @@ describe Grape::Validations do
232
230
 
233
231
  it 'adds entity documentation to declared params' do
234
232
  define_requires_none
235
- expect(declared_params).to eq(%i[required_field optional_field])
233
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
236
234
  end
237
235
 
238
236
  it 'errors when required_field is not present' do
@@ -262,7 +260,7 @@ describe Grape::Validations do
262
260
 
263
261
  it 'adds only the entity documentation to declared params, nothing more' do
264
262
  define_requires_all
265
- expect(declared_params).to eq(%i[required_field optional_field])
263
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq(%i[required_field optional_field])
266
264
  end
267
265
  end
268
266
 
@@ -328,7 +326,7 @@ describe Grape::Validations do
328
326
  requires :key
329
327
  end
330
328
  end
331
- expect(declared_params).to eq([items: [:key]])
329
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
332
330
  end
333
331
  end
334
332
 
@@ -400,7 +398,7 @@ describe Grape::Validations do
400
398
  requires :key
401
399
  end
402
400
  end
403
- expect(declared_params).to eq([items: [:key]])
401
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
404
402
  end
405
403
  end
406
404
 
@@ -463,7 +461,7 @@ describe Grape::Validations do
463
461
  requires :key
464
462
  end
465
463
  end
466
- expect(declared_params).to eq([items: [:key]])
464
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
467
465
  end
468
466
  end
469
467
 
@@ -824,7 +822,7 @@ describe Grape::Validations do
824
822
  requires :key
825
823
  end
826
824
  end
827
- expect(declared_params).to eq([items: [:key]])
825
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key]])
828
826
  end
829
827
  end
830
828
 
@@ -888,7 +886,7 @@ describe Grape::Validations do
888
886
  requires(:required_subitems, type: Array) { requires :value }
889
887
  end
890
888
  end
891
- expect(declared_params).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])
889
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq([items: [:key, { optional_subitems: [:value] }, { required_subitems: [:value] }]])
892
890
  end
893
891
 
894
892
  context <<~DESC do
@@ -1073,12 +1071,12 @@ describe Grape::Validations do
1073
1071
  }
1074
1072
  # debugger
1075
1073
  get '/multi_level', data
1076
- expect(last_response.body.split(', ')).to match_array([
1077
- 'top[3][top_id] is empty',
1078
- 'top[2][middle_1][0][middle_1_id] is empty',
1079
- 'top[1][middle_1][1][middle_2][0][middle_2_id] is empty',
1080
- 'top[0][middle_1][1][middle_2][1][bottom][0][bottom_id] is empty'
1081
- ])
1074
+ expect(last_response.body.split(', ')).to contain_exactly(
1075
+ 'top[3][top_id] is empty',
1076
+ 'top[2][middle_1][0][middle_1_id] is empty',
1077
+ 'top[1][middle_1][1][middle_2][0][middle_2_id] is empty',
1078
+ 'top[0][middle_1][1][middle_2][1][bottom][0][bottom_id] is empty'
1079
+ )
1082
1080
  expect(last_response.status).to eq(400)
1083
1081
  end
1084
1082
  end
@@ -1428,14 +1426,14 @@ describe Grape::Validations do
1428
1426
  subject.params do
1429
1427
  use :pagination
1430
1428
  end
1431
- expect(declared_params).to eq %i[page per_page]
1429
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq %i[page per_page]
1432
1430
  end
1433
1431
 
1434
1432
  it 'by #use with multiple params' do
1435
1433
  subject.params do
1436
1434
  use :pagination, :period
1437
1435
  end
1438
- expect(declared_params).to eq %i[page per_page start_date end_date]
1436
+ expect(Grape::Validations::ParamsScope::Attr.attrs_keys(declared_params)).to eq %i[page per_page start_date end_date]
1439
1437
  end
1440
1438
  end
1441
1439
 
@@ -1485,17 +1483,52 @@ describe Grape::Validations do
1485
1483
  end
1486
1484
  end
1487
1485
 
1488
- context 'documentation' do
1489
- it 'can be included with a hash' do
1490
- documentation = { example: 'Joe' }
1486
+ context 'with block and keyword argument' do
1487
+ before do
1488
+ subject.helpers do
1489
+ params :shared_params do |type:|
1490
+ optional :param, default: type
1491
+ end
1492
+ end
1493
+ subject.format :json
1494
+ subject.params do
1495
+ use :shared_params, type: 'value'
1496
+ end
1497
+ subject.get '/shared_params' do
1498
+ {
1499
+ param: params[:param]
1500
+ }
1501
+ end
1502
+ end
1503
+
1504
+ it 'works' do
1505
+ get '/shared_params'
1506
+
1507
+ expect(last_response.status).to eq(200)
1508
+ expect(last_response.body).to eq({ param: 'value' }.to_json)
1509
+ end
1510
+ end
1491
1511
 
1512
+ context 'with block and empty args' do
1513
+ before do
1514
+ subject.helpers do
1515
+ params :shared_params do |empty_args|
1516
+ optional :param, default: empty_args[:some]
1517
+ end
1518
+ end
1519
+ subject.format :json
1492
1520
  subject.params do
1493
- requires 'first_name', documentation: documentation
1521
+ use :shared_params
1494
1522
  end
1495
- subject.get '/' do
1523
+ subject.get '/shared_params' do
1524
+ :ok
1496
1525
  end
1526
+ end
1497
1527
 
1498
- expect(subject.routes.first.params['first_name'][:documentation]).to eq(documentation)
1528
+ it 'works' do
1529
+ get '/shared_params'
1530
+
1531
+ expect(last_response.status).to eq(200)
1499
1532
  end
1500
1533
  end
1501
1534
 
@@ -1975,4 +2008,22 @@ describe Grape::Validations do
1975
2008
  end
1976
2009
  end
1977
2010
  end
2011
+
2012
+ describe 'require_validator' do
2013
+ subject { described_class.require_validator(short_name) }
2014
+
2015
+ context 'when found' do
2016
+ let(:short_name) { :presence }
2017
+
2018
+ it { is_expected.to be(Grape::Validations::Validators::PresenceValidator) }
2019
+ end
2020
+
2021
+ context 'when not found' do
2022
+ let(:short_name) { :test }
2023
+
2024
+ it 'raises an error' do
2025
+ expect { subject }.to raise_error(Grape::Exceptions::UnknownValidator)
2026
+ end
2027
+ end
2028
+ end
1978
2029
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Json do
6
4
  it 'uses multi_json' do
7
5
  expect(described_class).to eq(::MultiJson)
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Xml do
6
4
  it 'uses multi_xml' do
7
5
  expect(described_class).to eq(::MultiXml)
data/spec/spec_helper.rb CHANGED
@@ -23,8 +23,6 @@ Dir["#{File.dirname(__FILE__)}/support/*.rb"].sort.each do |file|
23
23
  require file
24
24
  end
25
25
 
26
- eager_load!
27
-
28
26
  # The default value for this setting is true in a standard Rails app,
29
27
  # so it should be set to true here as well to reflect that.
30
28
  I18n.enforce_available_locales = true
@@ -43,5 +41,12 @@ RSpec.configure do |config|
43
41
  config.example_status_persistence_file_path = '.rspec_status'
44
42
  end
45
43
 
46
- require 'coveralls'
47
- Coveralls.wear!
44
+ require 'simplecov'
45
+ require 'simplecov-lcov'
46
+ SimpleCov::Formatter::LcovFormatter.config do |c|
47
+ c.report_with_single_file = true
48
+ c.single_report_path = 'coverage/lcov.info'
49
+ end
50
+
51
+ SimpleCov.formatter = SimpleCov::Formatter::LcovFormatter
52
+ SimpleCov.start