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,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  module Presenters
7
5
  module PresenterSpec
@@ -19,18 +17,18 @@ module Grape
19
17
  end
20
18
 
21
19
  describe Presenter do
20
+ subject { PresenterSpec::Dummy.new }
21
+
22
22
  describe 'represent' do
23
23
  let(:object_mock) do
24
24
  Object.new
25
25
  end
26
26
 
27
27
  it 'represent object' do
28
- expect(Presenter.represent(object_mock)).to eq object_mock
28
+ expect(described_class.represent(object_mock)).to eq object_mock
29
29
  end
30
30
  end
31
31
 
32
- subject { PresenterSpec::Dummy.new }
33
-
34
32
  describe 'present' do
35
33
  let(:hash_mock) do
36
34
  { key: :value }
@@ -38,8 +36,9 @@ module Grape
38
36
 
39
37
  describe 'instance' do
40
38
  before do
41
- subject.present hash_mock, with: Grape::Presenters::Presenter
39
+ subject.present hash_mock, with: described_class
42
40
  end
41
+
43
42
  it 'presents dummy hash' do
44
43
  expect(subject.body).to eq hash_mock
45
44
  end
@@ -56,8 +55,8 @@ module Grape
56
55
 
57
56
  describe 'instance' do
58
57
  before do
59
- subject.present hash_mock1, with: Grape::Presenters::Presenter
60
- subject.present hash_mock2, with: Grape::Presenters::Presenter
58
+ subject.present hash_mock1, with: described_class
59
+ subject.present hash_mock2, with: described_class
61
60
  end
62
61
 
63
62
  it 'presents both dummy presenter' do
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  describe Request do
7
5
  let(:default_method) { 'GET' }
@@ -21,7 +19,7 @@ module Grape
21
19
  let(:env) { default_env }
22
20
 
23
21
  let(:request) do
24
- Grape::Request.new(env)
22
+ described_class.new(env)
25
23
  end
26
24
 
27
25
  describe '#params' do
@@ -38,7 +36,7 @@ module Grape
38
36
 
39
37
  context 'when build_params_with: Grape::Extensions::Hash::ParamBuilder is specified' do
40
38
  let(:request) do
41
- Grape::Request.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
39
+ described_class.new(env, build_params_with: Grape::Extensions::Hash::ParamBuilder)
42
40
  end
43
41
 
44
42
  it 'returns symbolized params' do
@@ -65,6 +63,8 @@ module Grape
65
63
  end
66
64
 
67
65
  describe 'when the param_builder is set to Hashie' do
66
+ subject(:request_params) { described_class.new(env, **opts).params }
67
+
68
68
  before do
69
69
  Grape.configure do |config|
70
70
  config.param_builder = Grape::Extensions::Hashie::Mash::ParamBuilder
@@ -75,15 +75,15 @@ module Grape
75
75
  Grape.config.reset
76
76
  end
77
77
 
78
- subject(:request_params) { Grape::Request.new(env, **opts).params }
79
-
80
78
  context 'when the API does not include a specific param builder' do
81
79
  let(:opts) { {} }
80
+
82
81
  it { is_expected.to be_a(Hashie::Mash) }
83
82
  end
84
83
 
85
84
  context 'when the API includes a specific param builder' do
86
85
  let(:opts) { { build_params_with: Grape::Extensions::Hash::ParamBuilder } }
86
+
87
87
  it { is_expected.to be_a(Hash) }
88
88
  end
89
89
  end
@@ -1,15 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  module Grape
5
4
  module Util
6
5
  describe InheritableSetting do
7
- before :each do
8
- InheritableSetting.reset_global!
6
+ before do
7
+ described_class.reset_global!
9
8
  end
10
9
 
11
10
  let(:parent) do
12
- Grape::Util::InheritableSetting.new.tap do |settings|
11
+ described_class.new.tap do |settings|
13
12
  settings.global[:global_thing] = :global_foo_bar
14
13
  settings.namespace[:namespace_thing] = :namespace_foo_bar
15
14
  settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar
@@ -20,7 +19,7 @@ module Grape
20
19
  end
21
20
 
22
21
  let(:other_parent) do
23
- Grape::Util::InheritableSetting.new.tap do |settings|
22
+ described_class.new.tap do |settings|
24
23
  settings.namespace[:namespace_thing] = :namespace_foo_bar_other
25
24
  settings.namespace_inheritable[:namespace_inheritable_thing] = :namespace_inheritable_foo_bar_other
26
25
  settings.namespace_stackable[:namespace_stackable_thing] = :namespace_stackable_foo_bar_other
@@ -29,7 +28,7 @@ module Grape
29
28
  end
30
29
  end
31
30
 
32
- before :each do
31
+ before do
33
32
  subject.inherit_from parent
34
33
  end
35
34
 
@@ -50,7 +49,7 @@ module Grape
50
49
  expect(parent.global[:global_thing]).to eq :global_new_foo_bar
51
50
  end
52
51
 
53
- it 'should handle different parents' do
52
+ it 'handles different parents' do
54
53
  subject.global[:global_thing] = :global_new_foo_bar
55
54
 
56
55
  subject.inherit_from other_parent
@@ -89,7 +88,7 @@ module Grape
89
88
  expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
90
89
  end
91
90
 
92
- it 'should handle different parents' do
91
+ it 'handles different parents' do
93
92
  expect(subject.namespace_inheritable[:namespace_inheritable_thing]).to eq :namespace_inheritable_foo_bar
94
93
 
95
94
  subject.inherit_from other_parent
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  module Grape
5
4
  module Util
6
5
  describe InheritableValues do
7
- let(:parent) { InheritableValues.new }
8
- subject { InheritableValues.new(parent) }
6
+ subject { described_class.new(parent) }
7
+
8
+ let(:parent) { described_class.new }
9
9
 
10
10
  describe '#delete' do
11
11
  it 'deletes a key' do
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  module Grape
5
4
  module Util
6
5
  describe ReverseStackableValues do
7
- let(:parent) { described_class.new }
8
6
  subject { described_class.new(parent) }
9
7
 
8
+ let(:parent) { described_class.new }
9
+
10
10
  describe '#keys' do
11
11
  it 'returns all keys' do
12
12
  subject[:some_thing] = :foo_bar
@@ -102,6 +102,7 @@ module Grape
102
102
 
103
103
  describe '#clone' do
104
104
  let(:obj_cloned) { subject.clone }
105
+
105
106
  it 'copies all values' do
106
107
  parent = described_class.new
107
108
  child = described_class.new parent
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  module Grape
5
4
  module Util
6
5
  describe StackableValues do
7
- let(:parent) { StackableValues.new }
8
- subject { StackableValues.new(parent) }
6
+ subject { described_class.new(parent) }
7
+
8
+ let(:parent) { described_class.new }
9
9
 
10
10
  describe '#keys' do
11
11
  it 'returns all keys' do
@@ -99,10 +99,11 @@ module Grape
99
99
 
100
100
  describe '#clone' do
101
101
  let(:obj_cloned) { subject.clone }
102
+
102
103
  it 'copies all values' do
103
- parent = StackableValues.new
104
- child = StackableValues.new parent
105
- grandchild = StackableValues.new child
104
+ parent = described_class.new
105
+ child = described_class.new parent
106
+ grandchild = described_class.new child
106
107
 
107
108
  parent[:some_thing] = :foo
108
109
  child[:some_thing] = %i[bar more]
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
3
  module Grape
5
4
  module Util
6
5
  describe 'StrictHashConfiguration' do
@@ -0,0 +1,153 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe Grape::Validations::ParamsScope::AttributesDoc do
4
+ shared_examples 'an optional doc attribute' do |attr|
5
+ it 'does not mention it' do
6
+ expected_opts.delete(attr)
7
+ validations.delete(attr)
8
+
9
+ expect(subject.first['nested[engine_age]']).not_to have_key(attr)
10
+ end
11
+ end
12
+
13
+ let(:api) { Class.new(Grape::API::Instance) }
14
+ let(:scope) do
15
+ params = nil
16
+ api_instance = api
17
+
18
+ # just to get nested params
19
+ Grape::Validations::ParamsScope.new(type: Hash, api: api) do
20
+ params = Grape::Validations::ParamsScope.new(element: 'nested',
21
+ type: Hash,
22
+ api: api_instance,
23
+ parent: self)
24
+ end
25
+
26
+ params
27
+ end
28
+
29
+ let(:validations) do
30
+ {
31
+ presence: true,
32
+ desc: 'Age of...',
33
+ documentation: 'Age is...',
34
+ default: 1
35
+ }
36
+ end
37
+
38
+ let(:doc) { described_class.new(api, scope) }
39
+
40
+ describe '#extract_details' do
41
+ subject { doc.extract_details(validations) }
42
+
43
+ it 'cleans up doc attrs needed for documentation only' do
44
+ subject
45
+
46
+ expect(validations[:desc]).to be_nil
47
+ expect(validations[:documentation]).to be_nil
48
+ end
49
+
50
+ it 'does not clean up doc attrs mandatory for validators' do
51
+ subject
52
+
53
+ expect(validations[:presence]).not_to be_nil
54
+ expect(validations[:default]).not_to be_nil
55
+ end
56
+
57
+ it 'tells when attributes are required' do
58
+ subject
59
+
60
+ expect(doc.required).to be_truthy
61
+ end
62
+ end
63
+
64
+ describe '#document' do
65
+ subject do
66
+ doc.extract_details validations
67
+ doc.document attrs
68
+ end
69
+
70
+ let(:attrs) { %w[engine_age car_age] }
71
+ let(:valid_values) { [1, 3, 5, 8] }
72
+
73
+ let!(:expected_opts) do
74
+ {
75
+ required: true,
76
+ desc: validations[:desc],
77
+ documentation: validations[:documentation],
78
+ default: validations[:default],
79
+ type: 'Integer',
80
+ values: valid_values
81
+ }
82
+ end
83
+
84
+ before do
85
+ doc.type = Integer
86
+ doc.values = valid_values
87
+ end
88
+
89
+ context 'documentation is enabled' do
90
+ subject do
91
+ super()
92
+ api.namespace_stackable(:params)
93
+ end
94
+
95
+ it 'documents attributes' do
96
+ expect(subject.first).to eq('nested[engine_age]' => expected_opts,
97
+ 'nested[car_age]' => expected_opts)
98
+ end
99
+
100
+ it_behaves_like 'an optional doc attribute', :default
101
+ it_behaves_like 'an optional doc attribute', :documentation
102
+ it_behaves_like 'an optional doc attribute', :desc
103
+ it_behaves_like 'an optional doc attribute', :type do
104
+ before { doc.type = nil }
105
+ end
106
+ it_behaves_like 'an optional doc attribute', :values do
107
+ before { doc.values = nil }
108
+ end
109
+
110
+ context 'false as a default value' do
111
+ before { validations[:default] = false }
112
+
113
+ it 'is still documented' do
114
+ doc = subject.first['nested[engine_age]']
115
+
116
+ expect(doc).to have_key(:default)
117
+ expect(doc[:default]).to be(false)
118
+ end
119
+ end
120
+
121
+ context 'nil as a default value' do
122
+ before { validations[:default] = nil }
123
+
124
+ it 'is still documented' do
125
+ doc = subject.first['nested[engine_age]']
126
+
127
+ expect(doc).to have_key(:default)
128
+ expect(doc[:default]).to be_nil
129
+ end
130
+ end
131
+
132
+ context 'the description key instead of desc' do
133
+ let!(:desc) { validations.delete(:desc) }
134
+
135
+ before { validations[:description] = desc }
136
+
137
+ it 'adds the given description' do
138
+ expect(subject.first['nested[engine_age]'][:desc]).to eq(desc)
139
+ end
140
+ end
141
+ end
142
+
143
+ context 'documentation is disabled' do
144
+ before { api.namespace_inheritable :do_not_document, true }
145
+
146
+ it 'does not document attributes' do
147
+ subject
148
+
149
+ expect(api.namespace_stackable(:params)).to eq([])
150
+ end
151
+ end
152
+ end
153
+ end
@@ -1,6 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::AttributesIterator do
6
4
  end
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe 'Validator with instance variables' do
6
4
  let(:validator_type) do
7
- Class.new(Grape::Validations::Base) do
5
+ Class.new(Grape::Validations::Validators::Base) do
8
6
  def validate_param!(_attr_name, _params)
9
7
  if instance_variable_defined?(:@instance_variable) && @instance_variable
10
8
  raise Grape::Exceptions::Validation.new(params: ['params'],
@@ -14,15 +12,6 @@ describe 'Validator with instance variables' do
14
12
  end
15
13
  end
16
14
  end
17
-
18
- before do
19
- Grape::Validations.register_validator('instance_validator', validator_type)
20
- end
21
-
22
- after do
23
- Grape::Validations.deregister_validator('instance_validator')
24
- end
25
-
26
15
  let(:app) do
27
16
  Class.new(Grape::API) do
28
17
  params do
@@ -35,6 +24,14 @@ describe 'Validator with instance variables' do
35
24
  end
36
25
  end
37
26
 
27
+ before do
28
+ Grape::Validations.register_validator('instance_validator', validator_type)
29
+ end
30
+
31
+ after do
32
+ Grape::Validations.deregister_validator('instance_validator')
33
+ end
34
+
38
35
  it 'passes validation every time' do
39
36
  expect(validator_type).to receive(:new).exactly(4).times.and_call_original
40
37
 
@@ -1,10 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  describe Grape::Validations::MultipleAttributesIterator do
6
4
  describe '#each' do
7
5
  subject(:iterator) { described_class.new(validator, scope, params) }
6
+
8
7
  let(:scope) { Grape::Validations::ParamsScope.new(api: Class.new(Grape::API)) }
9
8
  let(:validator) { double(attrs: %i[first second third]) }
10
9