grape 1.6.2 → 1.7.1

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