grape 1.5.2 → 1.7.0

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 (210) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/CONTRIBUTING.md +2 -1
  4. data/README.md +152 -21
  5. data/UPGRADING.md +86 -2
  6. data/grape.gemspec +5 -5
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +18 -13
  9. data/lib/grape/cookies.rb +2 -0
  10. data/lib/grape/dry_types.rb +12 -0
  11. data/lib/grape/dsl/api.rb +0 -2
  12. data/lib/grape/dsl/callbacks.rb +0 -2
  13. data/lib/grape/dsl/configuration.rb +0 -2
  14. data/lib/grape/dsl/desc.rb +2 -19
  15. data/lib/grape/dsl/headers.rb +5 -2
  16. data/lib/grape/dsl/helpers.rb +7 -7
  17. data/lib/grape/dsl/inside_route.rb +43 -30
  18. data/lib/grape/dsl/middleware.rb +4 -6
  19. data/lib/grape/dsl/parameters.rb +8 -10
  20. data/lib/grape/dsl/request_response.rb +9 -8
  21. data/lib/grape/dsl/routing.rb +6 -4
  22. data/lib/grape/dsl/settings.rb +5 -7
  23. data/lib/grape/dsl/validations.rb +0 -15
  24. data/lib/grape/endpoint.rb +21 -36
  25. data/lib/grape/error_formatter/json.rb +9 -7
  26. data/lib/grape/error_formatter/xml.rb +2 -6
  27. data/lib/grape/exceptions/base.rb +2 -2
  28. data/lib/grape/exceptions/empty_message_body.rb +11 -0
  29. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  30. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  31. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  32. data/lib/grape/exceptions/validation.rb +1 -6
  33. data/lib/grape/formatter/json.rb +1 -0
  34. data/lib/grape/formatter/serializable_hash.rb +2 -1
  35. data/lib/grape/formatter/xml.rb +1 -0
  36. data/lib/grape/locale/en.yml +9 -8
  37. data/lib/grape/middleware/auth/dsl.rb +7 -2
  38. data/lib/grape/middleware/base.rb +3 -1
  39. data/lib/grape/middleware/error.rb +2 -2
  40. data/lib/grape/middleware/formatter.rb +4 -4
  41. data/lib/grape/middleware/stack.rb +2 -2
  42. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  43. data/lib/grape/middleware/versioner/header.rb +6 -4
  44. data/lib/grape/middleware/versioner/param.rb +1 -0
  45. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  46. data/lib/grape/middleware/versioner/path.rb +2 -0
  47. data/lib/grape/parser/json.rb +1 -1
  48. data/lib/grape/parser/xml.rb +1 -1
  49. data/lib/grape/path.rb +1 -0
  50. data/lib/grape/request.rb +5 -0
  51. data/lib/grape/router/pattern.rb +1 -1
  52. data/lib/grape/router/route.rb +2 -2
  53. data/lib/grape/router.rb +6 -0
  54. data/lib/grape/util/inheritable_setting.rb +1 -3
  55. data/lib/grape/util/json.rb +2 -0
  56. data/lib/grape/util/lazy_value.rb +3 -2
  57. data/lib/grape/util/strict_hash_configuration.rb +1 -1
  58. data/lib/grape/validations/attributes_doc.rb +58 -0
  59. data/lib/grape/validations/params_scope.rb +137 -78
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -2
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/json.rb +2 -1
  64. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  65. data/lib/grape/validations/types/set_coercer.rb +0 -2
  66. data/lib/grape/validations/types.rb +98 -30
  67. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  68. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  69. data/lib/grape/validations/validators/as_validator.rb +14 -0
  70. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  71. data/lib/grape/validations/validators/base.rb +82 -70
  72. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  73. data/lib/grape/validations/validators/default_validator.rb +51 -0
  74. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  75. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  76. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  77. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  78. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  79. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  80. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  81. data/lib/grape/validations/validators/values_validator.rb +88 -0
  82. data/lib/grape/validations.rb +16 -6
  83. data/lib/grape/version.rb +1 -1
  84. data/lib/grape.rb +70 -29
  85. data/spec/grape/api/custom_validations_spec.rb +116 -45
  86. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  87. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  88. data/spec/grape/api/documentation_spec.rb +59 -0
  89. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  90. data/spec/grape/api/instance_spec.rb +0 -1
  91. data/spec/grape/api/invalid_format_spec.rb +2 -2
  92. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  93. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  94. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  95. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  96. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  97. data/spec/grape/api/recognize_path_spec.rb +1 -3
  98. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  99. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  100. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  101. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  102. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  103. data/spec/grape/api_remount_spec.rb +16 -16
  104. data/spec/grape/api_spec.rb +527 -224
  105. data/spec/grape/config_spec.rb +0 -2
  106. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  107. data/spec/grape/dsl/configuration_spec.rb +0 -2
  108. data/spec/grape/dsl/desc_spec.rb +0 -2
  109. data/spec/grape/dsl/headers_spec.rb +39 -11
  110. data/spec/grape/dsl/helpers_spec.rb +3 -4
  111. data/spec/grape/dsl/inside_route_spec.rb +16 -16
  112. data/spec/grape/dsl/logger_spec.rb +15 -19
  113. data/spec/grape/dsl/middleware_spec.rb +2 -3
  114. data/spec/grape/dsl/parameters_spec.rb +2 -2
  115. data/spec/grape/dsl/request_response_spec.rb +7 -8
  116. data/spec/grape/dsl/routing_spec.rb +11 -10
  117. data/spec/grape/dsl/settings_spec.rb +0 -2
  118. data/spec/grape/dsl/validations_spec.rb +0 -17
  119. data/spec/grape/endpoint/declared_spec.rb +261 -16
  120. data/spec/grape/endpoint_spec.rb +98 -57
  121. data/spec/grape/entity_spec.rb +22 -23
  122. data/spec/grape/exceptions/base_spec.rb +16 -2
  123. data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
  124. data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -24
  125. data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
  126. data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
  127. data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
  128. data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
  129. data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
  130. data/spec/grape/exceptions/missing_option_spec.rb +1 -3
  131. data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
  132. data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
  133. data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
  134. data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
  135. data/spec/grape/exceptions/validation_spec.rb +5 -5
  136. data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
  137. data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
  138. data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
  139. data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
  140. data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
  141. data/spec/grape/integration/rack_spec.rb +0 -2
  142. data/spec/grape/loading_spec.rb +8 -10
  143. data/spec/grape/middleware/auth/base_spec.rb +0 -1
  144. data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
  145. data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
  146. data/spec/grape/middleware/base_spec.rb +24 -17
  147. data/spec/grape/middleware/error_spec.rb +8 -3
  148. data/spec/grape/middleware/exception_spec.rb +111 -163
  149. data/spec/grape/middleware/formatter_spec.rb +27 -8
  150. data/spec/grape/middleware/globals_spec.rb +7 -6
  151. data/spec/grape/middleware/stack_spec.rb +14 -14
  152. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
  153. data/spec/grape/middleware/versioner/header_spec.rb +30 -15
  154. data/spec/grape/middleware/versioner/param_spec.rb +7 -3
  155. data/spec/grape/middleware/versioner/path_spec.rb +5 -3
  156. data/spec/grape/middleware/versioner_spec.rb +1 -3
  157. data/spec/grape/named_api_spec.rb +0 -2
  158. data/spec/grape/parser_spec.rb +4 -2
  159. data/spec/grape/path_spec.rb +52 -54
  160. data/spec/grape/presenters/presenter_spec.rb +7 -8
  161. data/spec/grape/request_spec.rb +6 -6
  162. data/spec/grape/util/inheritable_setting_spec.rb +7 -8
  163. data/spec/grape/util/inheritable_values_spec.rb +3 -3
  164. data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
  165. data/spec/grape/util/stackable_values_spec.rb +7 -6
  166. data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
  167. data/spec/grape/validations/attributes_doc_spec.rb +153 -0
  168. data/spec/grape/validations/attributes_iterator_spec.rb +0 -2
  169. data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
  170. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  171. data/spec/grape/validations/params_scope_spec.rb +361 -96
  172. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  173. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  174. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  175. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  176. data/spec/grape/validations/types_spec.rb +36 -10
  177. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  178. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  179. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  180. data/spec/grape/validations/validators/coerce_spec.rb +99 -24
  181. data/spec/grape/validations/validators/default_spec.rb +72 -80
  182. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  183. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  184. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  185. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  186. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  187. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  188. data/spec/grape/validations/validators/values_spec.rb +182 -179
  189. data/spec/grape/validations_spec.rb +149 -80
  190. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  191. data/spec/integration/multi_json/json_spec.rb +1 -3
  192. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  193. data/spec/shared/versioning_examples.rb +12 -9
  194. data/spec/spec_helper.rb +21 -6
  195. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  196. metadata +125 -115
  197. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  198. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  199. data/lib/grape/validations/validators/as.rb +0 -16
  200. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  201. data/lib/grape/validations/validators/coerce.rb +0 -91
  202. data/lib/grape/validations/validators/default.rb +0 -48
  203. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  204. data/lib/grape/validations/validators/except_values.rb +0 -22
  205. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  206. data/lib/grape/validations/validators/presence.rb +0 -12
  207. data/lib/grape/validations/validators/regexp.rb +0 -13
  208. data/lib/grape/validations/validators/same_as.rb +0 -26
  209. data/lib/grape/validations/validators/values.rb +0 -83
  210. data/spec/support/eager_load.rb +0 -19
@@ -1,18 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::Types::PrimitiveCoercer do
6
- let(:strict) { false }
7
-
8
4
  subject { described_class.new(type, strict) }
9
5
 
6
+ let(:strict) { false }
7
+
10
8
  describe '#call' do
11
9
  context 'BigDecimal' do
12
10
  let(:type) { BigDecimal }
13
11
 
14
12
  it 'coerces to BigDecimal' do
15
- expect(subject.call(5)).to eq(BigDecimal(5))
13
+ expect(subject.call(5)).to eq(BigDecimal('5'))
16
14
  end
17
15
 
18
16
  it 'coerces an empty string to nil' do
@@ -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
 
@@ -127,7 +142,7 @@ describe Grape::Validations::Types::PrimitiveCoercer do
127
142
  end
128
143
 
129
144
  it 'returns a value as it is when the given value is BigDecimal' do
130
- expect(subject.call(BigDecimal(0))).to eq(BigDecimal(0))
145
+ expect(subject.call(BigDecimal('0'))).to eq(BigDecimal('0'))
131
146
  end
132
147
  end
133
148
  end
@@ -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
@@ -20,13 +18,13 @@ describe Grape::Validations::Types do
20
18
  Date, DateTime, Time
21
19
  ].each do |type|
22
20
  it "recognizes #{type} as a primitive" do
23
- expect(described_class.primitive?(type)).to be_truthy
21
+ expect(described_class).to be_primitive(type)
24
22
  end
25
23
  end
26
24
 
27
25
  it 'identifies unknown types' do
28
- expect(described_class.primitive?(Object)).to be_falsy
29
- expect(described_class.primitive?(TypesSpec::FooType)).to be_falsy
26
+ expect(described_class).not_to be_primitive(Object)
27
+ expect(described_class).not_to be_primitive(TypesSpec::FooType)
30
28
  end
31
29
  end
32
30
 
@@ -35,7 +33,7 @@ describe Grape::Validations::Types do
35
33
  Hash, Array, Set
36
34
  ].each do |type|
37
35
  it "recognizes #{type} as a structure" do
38
- expect(described_class.structure?(type)).to be_truthy
36
+ expect(described_class).to be_structure(type)
39
37
  end
40
38
  end
41
39
  end
@@ -45,22 +43,50 @@ describe Grape::Validations::Types do
45
43
  JSON, Array[JSON], File, Rack::Multipart::UploadedFile
46
44
  ].each do |type|
47
45
  it "provides special handling for #{type.inspect}" do
48
- expect(described_class.special?(type)).to be_truthy
46
+ expect(described_class).to be_special(type)
49
47
  end
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
- expect(described_class.custom?(Object)).to be_falsy
81
+ expect(described_class).not_to be_custom(Object)
56
82
  end
57
83
 
58
84
  it 'returns true if the type responds to :parse with one argument' do
59
- expect(described_class.custom?(TypesSpec::FooType)).to be_truthy
85
+ expect(described_class).to be_custom(TypesSpec::FooType)
60
86
  end
61
87
 
62
88
  it 'returns false if the type\'s #parse method takes other than one argument' do
63
- expect(described_class.custom?(TypesSpec::BarType)).to be_falsy
89
+ expect(described_class).not_to be_custom(TypesSpec::BarType)
64
90
  end
65
91
  end
66
92
 
@@ -1,74 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
- describe Grape::Validations::AllOrNoneOfValidator do
6
- describe '#validate!' do
7
- subject(:validate) { post path, params }
8
-
9
- module ValidationsSpec
10
- module AllOrNoneOfValidatorSpec
11
- class API < Grape::API
12
- rescue_from Grape::Exceptions::ValidationErrors do |e|
13
- error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
14
- end
3
+ describe Grape::Validations::Validators::AllOrNoneOfValidator do
4
+ let_it_be(:app) do
5
+ Class.new(Grape::API) do
6
+ rescue_from Grape::Exceptions::ValidationErrors do |e|
7
+ error!(e.errors.transform_keys! { |key| key.join(',') }, 400)
8
+ end
15
9
 
16
- params do
17
- optional :beer, :wine, type: Boolean
18
- all_or_none_of :beer, :wine
19
- end
20
- post do
21
- end
10
+ params do
11
+ optional :beer, :wine, type: Grape::API::Boolean
12
+ all_or_none_of :beer, :wine
13
+ end
14
+ post do
15
+ end
22
16
 
23
- params do
24
- optional :beer, :wine, :other, type: Boolean
25
- all_or_none_of :beer, :wine
26
- end
27
- post 'mixed-params' do
28
- end
17
+ params do
18
+ optional :beer, :wine, :other, type: Grape::API::Boolean
19
+ all_or_none_of :beer, :wine
20
+ end
21
+ post 'mixed-params' do
22
+ end
29
23
 
30
- params do
31
- optional :beer, :wine, type: Boolean
32
- all_or_none_of :beer, :wine, message: 'choose all or none'
33
- end
34
- post '/custom-message' do
35
- end
24
+ params do
25
+ optional :beer, :wine, type: Grape::API::Boolean
26
+ all_or_none_of :beer, :wine, message: 'choose all or none'
27
+ end
28
+ post '/custom-message' do
29
+ end
36
30
 
37
- params do
38
- requires :item, type: Hash do
39
- optional :beer, :wine, type: Boolean
40
- all_or_none_of :beer, :wine
41
- end
42
- end
43
- post '/nested-hash' do
44
- end
31
+ params do
32
+ requires :item, type: Hash do
33
+ optional :beer, :wine, type: Grape::API::Boolean
34
+ all_or_none_of :beer, :wine
35
+ end
36
+ end
37
+ post '/nested-hash' do
38
+ end
45
39
 
46
- params do
47
- requires :items, type: Array do
48
- optional :beer, :wine, type: Boolean
49
- all_or_none_of :beer, :wine
50
- end
51
- end
52
- post '/nested-array' do
53
- end
40
+ params do
41
+ requires :items, type: Array do
42
+ optional :beer, :wine, type: Grape::API::Boolean
43
+ all_or_none_of :beer, :wine
44
+ end
45
+ end
46
+ post '/nested-array' do
47
+ end
54
48
 
55
- params do
56
- requires :items, type: Array do
57
- requires :nested_items, type: Array do
58
- optional :beer, :wine, type: Boolean
59
- all_or_none_of :beer, :wine
60
- end
61
- end
62
- end
63
- post '/deeply-nested-array' do
49
+ params do
50
+ requires :items, type: Array do
51
+ requires :nested_items, type: Array do
52
+ optional :beer, :wine, type: Grape::API::Boolean
53
+ all_or_none_of :beer, :wine
64
54
  end
65
55
  end
66
56
  end
57
+ post '/deeply-nested-array' do
58
+ end
67
59
  end
60
+ end
68
61
 
69
- def app
70
- ValidationsSpec::AllOrNoneOfValidatorSpec::API
71
- end
62
+ describe '#validate!' do
63
+ subject(:validate) { post path, params }
72
64
 
73
65
  context 'when all restricted params are present' do
74
66
  let(:path) { '/' }
@@ -1,25 +1,138 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
3
+ describe Grape::Validations::Validators::AllowBlankValidator do
4
+ let_it_be(:app) do
5
+ Class.new(Grape::API) do
6
+ default_format :json
4
7
 
5
- describe Grape::Validations::AllowBlankValidator do
6
- module ValidationsSpec
7
- module AllowBlankValidatorSpec
8
- class API < Grape::API
9
- default_format :json
8
+ params do
9
+ requires :name, allow_blank: false
10
+ end
11
+ get '/disallow_blank'
10
12
 
11
- params do
13
+ params do
14
+ optional :name, type: String, allow_blank: false
15
+ end
16
+ get '/opt_disallow_string_blank'
17
+
18
+ params do
19
+ optional :name, allow_blank: false
20
+ end
21
+ get '/disallow_blank_optional_param'
22
+
23
+ params do
24
+ requires :name, allow_blank: true
25
+ end
26
+ get '/allow_blank'
27
+
28
+ params do
29
+ requires :val, type: DateTime, allow_blank: true
30
+ end
31
+ get '/allow_datetime_blank'
32
+
33
+ params do
34
+ requires :val, type: DateTime, allow_blank: false
35
+ end
36
+ get '/disallow_datetime_blank'
37
+
38
+ params do
39
+ requires :val, type: DateTime
40
+ end
41
+ get '/default_allow_datetime_blank'
42
+
43
+ params do
44
+ requires :val, type: Date, allow_blank: true
45
+ end
46
+ get '/allow_date_blank'
47
+
48
+ params do
49
+ requires :val, type: Integer, allow_blank: true
50
+ end
51
+ get '/allow_integer_blank'
52
+
53
+ params do
54
+ requires :val, type: Float, allow_blank: true
55
+ end
56
+ get '/allow_float_blank'
57
+
58
+ params do
59
+ requires :val, type: Integer, allow_blank: true
60
+ end
61
+ get '/allow_integer_blank'
62
+
63
+ params do
64
+ requires :val, type: Symbol, allow_blank: true
65
+ end
66
+ get '/allow_symbol_blank'
67
+
68
+ params do
69
+ requires :val, type: Grape::API::Boolean, allow_blank: true
70
+ end
71
+ get '/allow_boolean_blank'
72
+
73
+ params do
74
+ requires :val, type: Grape::API::Boolean, allow_blank: false
75
+ end
76
+ get '/disallow_boolean_blank'
77
+
78
+ params do
79
+ optional :user, type: Hash do
80
+ requires :name, allow_blank: false
81
+ end
82
+ end
83
+ get '/disallow_blank_required_param_in_an_optional_group'
84
+
85
+ params do
86
+ optional :user, type: Hash do
87
+ requires :name, type: Date, allow_blank: true
88
+ end
89
+ end
90
+ get '/allow_blank_date_param_in_an_optional_group'
91
+
92
+ params do
93
+ optional :user, type: Hash do
94
+ optional :name, allow_blank: false
95
+ requires :age
96
+ end
97
+ end
98
+ get '/disallow_blank_optional_param_in_an_optional_group'
99
+
100
+ params do
101
+ requires :user, type: Hash do
12
102
  requires :name, allow_blank: false
13
103
  end
14
- get '/disallow_blank'
104
+ end
105
+ get '/disallow_blank_required_param_in_a_required_group'
15
106
 
107
+ params do
108
+ requires :user, type: Hash do
109
+ requires :name, allow_blank: false
110
+ end
111
+ end
112
+ get '/disallow_string_value_in_a_required_hash_group'
113
+
114
+ params do
115
+ requires :user, type: Hash do
116
+ optional :name, allow_blank: false
117
+ end
118
+ end
119
+ get '/disallow_blank_optional_param_in_a_required_group'
120
+
121
+ params do
122
+ optional :user, type: Hash do
123
+ optional :name, allow_blank: false
124
+ end
125
+ end
126
+ get '/disallow_string_value_in_an_optional_hash_group'
127
+
128
+ resources :custom_message do
16
129
  params do
17
- optional :name, type: String, allow_blank: false
130
+ requires :name, allow_blank: { value: false, message: 'has no value' }
18
131
  end
19
- get '/opt_disallow_string_blank'
132
+ get
20
133
 
21
134
  params do
22
- optional :name, allow_blank: false
135
+ optional :name, allow_blank: { value: false, message: 'has no value' }
23
136
  end
24
137
  get '/disallow_blank_optional_param'
25
138
 
@@ -34,7 +147,7 @@ describe Grape::Validations::AllowBlankValidator do
34
147
  get '/allow_datetime_blank'
35
148
 
36
149
  params do
37
- requires :val, type: DateTime, allow_blank: false
150
+ requires :val, type: DateTime, allow_blank: { value: false, message: 'has no value' }
38
151
  end
39
152
  get '/disallow_datetime_blank'
40
153
 
@@ -69,18 +182,18 @@ describe Grape::Validations::AllowBlankValidator do
69
182
  get '/allow_symbol_blank'
70
183
 
71
184
  params do
72
- requires :val, type: Boolean, allow_blank: true
185
+ requires :val, type: Grape::API::Boolean, allow_blank: true
73
186
  end
74
187
  get '/allow_boolean_blank'
75
188
 
76
189
  params do
77
- requires :val, type: Boolean, allow_blank: false
190
+ requires :val, type: Grape::API::Boolean, allow_blank: { value: false, message: 'has no value' }
78
191
  end
79
192
  get '/disallow_boolean_blank'
80
193
 
81
194
  params do
82
195
  optional :user, type: Hash do
83
- requires :name, allow_blank: false
196
+ requires :name, allow_blank: { value: false, message: 'has no value' }
84
197
  end
85
198
  end
86
199
  get '/disallow_blank_required_param_in_an_optional_group'
@@ -94,7 +207,7 @@ describe Grape::Validations::AllowBlankValidator do
94
207
 
95
208
  params do
96
209
  optional :user, type: Hash do
97
- optional :name, allow_blank: false
210
+ optional :name, allow_blank: { value: false, message: 'has no value' }
98
211
  requires :age
99
212
  end
100
213
  end
@@ -102,156 +215,35 @@ describe Grape::Validations::AllowBlankValidator do
102
215
 
103
216
  params do
104
217
  requires :user, type: Hash do
105
- requires :name, allow_blank: false
218
+ requires :name, allow_blank: { value: false, message: 'has no value' }
106
219
  end
107
220
  end
108
221
  get '/disallow_blank_required_param_in_a_required_group'
109
222
 
110
223
  params do
111
224
  requires :user, type: Hash do
112
- requires :name, allow_blank: false
225
+ requires :name, allow_blank: { value: false, message: 'has no value' }
113
226
  end
114
227
  end
115
228
  get '/disallow_string_value_in_a_required_hash_group'
116
229
 
117
230
  params do
118
231
  requires :user, type: Hash do
119
- optional :name, allow_blank: false
232
+ optional :name, allow_blank: { value: false, message: 'has no value' }
120
233
  end
121
234
  end
122
235
  get '/disallow_blank_optional_param_in_a_required_group'
123
236
 
124
237
  params do
125
238
  optional :user, type: Hash do
126
- optional :name, allow_blank: false
127
- end
128
- end
129
- get '/disallow_string_value_in_an_optional_hash_group'
130
-
131
- resources :custom_message do
132
- params do
133
- requires :name, allow_blank: { value: false, message: 'has no value' }
134
- end
135
- get
136
-
137
- params do
138
239
  optional :name, allow_blank: { value: false, message: 'has no value' }
139
240
  end
140
- get '/disallow_blank_optional_param'
141
-
142
- params do
143
- requires :name, allow_blank: true
144
- end
145
- get '/allow_blank'
146
-
147
- params do
148
- requires :val, type: DateTime, allow_blank: true
149
- end
150
- get '/allow_datetime_blank'
151
-
152
- params do
153
- requires :val, type: DateTime, allow_blank: { value: false, message: 'has no value' }
154
- end
155
- get '/disallow_datetime_blank'
156
-
157
- params do
158
- requires :val, type: DateTime
159
- end
160
- get '/default_allow_datetime_blank'
161
-
162
- params do
163
- requires :val, type: Date, allow_blank: true
164
- end
165
- get '/allow_date_blank'
166
-
167
- params do
168
- requires :val, type: Integer, allow_blank: true
169
- end
170
- get '/allow_integer_blank'
171
-
172
- params do
173
- requires :val, type: Float, allow_blank: true
174
- end
175
- get '/allow_float_blank'
176
-
177
- params do
178
- requires :val, type: Integer, allow_blank: true
179
- end
180
- get '/allow_integer_blank'
181
-
182
- params do
183
- requires :val, type: Symbol, allow_blank: true
184
- end
185
- get '/allow_symbol_blank'
186
-
187
- params do
188
- requires :val, type: Boolean, allow_blank: true
189
- end
190
- get '/allow_boolean_blank'
191
-
192
- params do
193
- requires :val, type: Boolean, allow_blank: { value: false, message: 'has no value' }
194
- end
195
- get '/disallow_boolean_blank'
196
-
197
- params do
198
- optional :user, type: Hash do
199
- requires :name, allow_blank: { value: false, message: 'has no value' }
200
- end
201
- end
202
- get '/disallow_blank_required_param_in_an_optional_group'
203
-
204
- params do
205
- optional :user, type: Hash do
206
- requires :name, type: Date, allow_blank: true
207
- end
208
- end
209
- get '/allow_blank_date_param_in_an_optional_group'
210
-
211
- params do
212
- optional :user, type: Hash do
213
- optional :name, allow_blank: { value: false, message: 'has no value' }
214
- requires :age
215
- end
216
- end
217
- get '/disallow_blank_optional_param_in_an_optional_group'
218
-
219
- params do
220
- requires :user, type: Hash do
221
- requires :name, allow_blank: { value: false, message: 'has no value' }
222
- end
223
- end
224
- get '/disallow_blank_required_param_in_a_required_group'
225
-
226
- params do
227
- requires :user, type: Hash do
228
- requires :name, allow_blank: { value: false, message: 'has no value' }
229
- end
230
- end
231
- get '/disallow_string_value_in_a_required_hash_group'
232
-
233
- params do
234
- requires :user, type: Hash do
235
- optional :name, allow_blank: { value: false, message: 'has no value' }
236
- end
237
- end
238
- get '/disallow_blank_optional_param_in_a_required_group'
239
-
240
- params do
241
- optional :user, type: Hash do
242
- optional :name, allow_blank: { value: false, message: 'has no value' }
243
- end
244
- end
245
- get '/disallow_string_value_in_an_optional_hash_group'
246
241
  end
242
+ get '/disallow_string_value_in_an_optional_hash_group'
247
243
  end
248
244
  end
249
245
  end
250
246
 
251
- def app
252
- ValidationsSpec::AllowBlankValidatorSpec::API
253
- end
254
-
255
247
  context 'invalid input' do
256
248
  it 'refuses empty string' do
257
249
  get '/disallow_blank', name: ''
@@ -289,10 +281,12 @@ describe Grape::Validations::AllowBlankValidator do
289
281
  get '/custom_message', name: ''
290
282
  expect(last_response.body).to eq('{"error":"name has no value"}')
291
283
  end
284
+
292
285
  it 'refuses empty string for an optional param' do
293
286
  get '/custom_message/disallow_blank_optional_param', name: ''
294
287
  expect(last_response.body).to eq('{"error":"name has no value"}')
295
288
  end
289
+
296
290
  it 'refuses only whitespaces' do
297
291
  get '/custom_message', name: ' '
298
292
  expect(last_response.body).to eq('{"error":"name has no value"}')