grape 1.5.3 → 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 (211) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +92 -0
  3. data/CONTRIBUTING.md +32 -1
  4. data/README.md +176 -25
  5. data/UPGRADING.md +61 -4
  6. data/grape.gemspec +6 -6
  7. data/lib/grape/api/instance.rb +14 -18
  8. data/lib/grape/api.rb +17 -12
  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 +4 -20
  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 +13 -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 +22 -37
  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 +3 -2
  28. data/lib/grape/exceptions/missing_group_type.rb +8 -1
  29. data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
  30. data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
  31. data/lib/grape/exceptions/validation.rb +1 -6
  32. data/lib/grape/formatter/json.rb +1 -0
  33. data/lib/grape/formatter/serializable_hash.rb +2 -1
  34. data/lib/grape/formatter/xml.rb +1 -0
  35. data/lib/grape/locale/en.yml +9 -8
  36. data/lib/grape/middleware/auth/dsl.rb +7 -2
  37. data/lib/grape/middleware/base.rb +3 -1
  38. data/lib/grape/middleware/error.rb +2 -2
  39. data/lib/grape/middleware/formatter.rb +4 -4
  40. data/lib/grape/middleware/stack.rb +3 -3
  41. data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
  42. data/lib/grape/middleware/versioner/header.rb +6 -4
  43. data/lib/grape/middleware/versioner/param.rb +1 -0
  44. data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
  45. data/lib/grape/middleware/versioner/path.rb +2 -0
  46. data/lib/grape/path.rb +1 -0
  47. data/lib/grape/request.rb +4 -1
  48. data/lib/grape/router/attribute_translator.rb +1 -1
  49. data/lib/grape/router/pattern.rb +1 -1
  50. data/lib/grape/router/route.rb +2 -2
  51. data/lib/grape/router.rb +6 -0
  52. data/lib/grape/types/invalid_value.rb +8 -0
  53. data/lib/grape/util/cache.rb +1 -1
  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 +138 -79
  60. data/lib/grape/validations/types/array_coercer.rb +0 -2
  61. data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
  62. data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
  63. data/lib/grape/validations/types/invalid_value.rb +0 -7
  64. data/lib/grape/validations/types/json.rb +2 -1
  65. data/lib/grape/validations/types/primitive_coercer.rb +16 -8
  66. data/lib/grape/validations/types/set_coercer.rb +0 -2
  67. data/lib/grape/validations/types.rb +98 -30
  68. data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
  69. data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
  70. data/lib/grape/validations/validators/as_validator.rb +14 -0
  71. data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
  72. data/lib/grape/validations/validators/base.rb +82 -70
  73. data/lib/grape/validations/validators/coerce_validator.rb +75 -0
  74. data/lib/grape/validations/validators/default_validator.rb +51 -0
  75. data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
  76. data/lib/grape/validations/validators/except_values_validator.rb +24 -0
  77. data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
  78. data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
  79. data/lib/grape/validations/validators/presence_validator.rb +15 -0
  80. data/lib/grape/validations/validators/regexp_validator.rb +16 -0
  81. data/lib/grape/validations/validators/same_as_validator.rb +29 -0
  82. data/lib/grape/validations/validators/values_validator.rb +88 -0
  83. data/lib/grape/validations.rb +16 -6
  84. data/lib/grape/version.rb +1 -1
  85. data/lib/grape.rb +77 -29
  86. data/spec/grape/api/custom_validations_spec.rb +116 -45
  87. data/spec/grape/api/deeply_included_options_spec.rb +3 -5
  88. data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
  89. data/spec/grape/api/documentation_spec.rb +59 -0
  90. data/spec/grape/api/inherited_helpers_spec.rb +0 -2
  91. data/spec/grape/api/instance_spec.rb +0 -1
  92. data/spec/grape/api/invalid_format_spec.rb +2 -2
  93. data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
  94. data/spec/grape/api/nested_helpers_spec.rb +0 -2
  95. data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
  96. data/spec/grape/api/parameters_modification_spec.rb +0 -2
  97. data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
  98. data/spec/grape/api/recognize_path_spec.rb +1 -3
  99. data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
  100. data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
  101. data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
  102. data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
  103. data/spec/grape/api/shared_helpers_spec.rb +0 -2
  104. data/spec/grape/api_remount_spec.rb +16 -16
  105. data/spec/grape/api_spec.rb +462 -251
  106. data/spec/grape/config_spec.rb +0 -2
  107. data/spec/grape/dsl/callbacks_spec.rb +2 -3
  108. data/spec/grape/dsl/desc_spec.rb +2 -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 +88 -59
  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 +64 -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 +6 -7
  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 +28 -19
  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 +33 -14
  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/instance_behaivour_spec.rb +9 -12
  169. data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
  170. data/spec/grape/validations/params_scope_spec.rb +361 -96
  171. data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
  172. data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
  173. data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
  174. data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
  175. data/spec/grape/validations/types_spec.rb +36 -10
  176. data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
  177. data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
  178. data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
  179. data/spec/grape/validations/validators/coerce_spec.rb +23 -24
  180. data/spec/grape/validations/validators/default_spec.rb +72 -80
  181. data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
  182. data/spec/grape/validations/validators/except_values_spec.rb +3 -5
  183. data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
  184. data/spec/grape/validations/validators/presence_spec.rb +16 -3
  185. data/spec/grape/validations/validators/regexp_spec.rb +25 -33
  186. data/spec/grape/validations/validators/same_as_spec.rb +14 -22
  187. data/spec/grape/validations/validators/values_spec.rb +201 -179
  188. data/spec/grape/validations_spec.rb +171 -79
  189. data/spec/integration/eager_load/eager_load_spec.rb +2 -2
  190. data/spec/integration/multi_json/json_spec.rb +1 -3
  191. data/spec/integration/multi_xml/xml_spec.rb +1 -3
  192. data/spec/shared/versioning_examples.rb +12 -9
  193. data/spec/spec_helper.rb +21 -6
  194. data/spec/support/basic_auth_encode_helpers.rb +1 -1
  195. metadata +41 -29
  196. data/lib/grape/validations/validators/all_or_none.rb +0 -15
  197. data/lib/grape/validations/validators/allow_blank.rb +0 -18
  198. data/lib/grape/validations/validators/as.rb +0 -16
  199. data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
  200. data/lib/grape/validations/validators/coerce.rb +0 -91
  201. data/lib/grape/validations/validators/default.rb +0 -48
  202. data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
  203. data/lib/grape/validations/validators/except_values.rb +0 -22
  204. data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
  205. data/lib/grape/validations/validators/presence.rb +0 -12
  206. data/lib/grape/validations/validators/regexp.rb +0 -13
  207. data/lib/grape/validations/validators/same_as.rb +0 -26
  208. data/lib/grape/validations/validators/values.rb +0 -83
  209. data/spec/grape/dsl/configuration_spec.rb +0 -16
  210. data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
  211. data/spec/support/eager_load.rb +0 -19
@@ -1,68 +1,66 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper'
4
-
5
3
  module Grape
6
4
  describe Path do
7
5
  describe '#initialize' do
8
6
  it 'remembers the path' do
9
- path = Path.new('/:id', anything, anything)
7
+ path = described_class.new('/:id', anything, anything)
10
8
  expect(path.raw_path).to eql('/:id')
11
9
  end
12
10
 
13
11
  it 'remembers the namespace' do
14
- path = Path.new(anything, '/users', anything)
12
+ path = described_class.new(anything, '/users', anything)
15
13
  expect(path.namespace).to eql('/users')
16
14
  end
17
15
 
18
16
  it 'remebers the settings' do
19
- path = Path.new(anything, anything, foo: 'bar')
17
+ path = described_class.new(anything, anything, foo: 'bar')
20
18
  expect(path.settings).to eql(foo: 'bar')
21
19
  end
22
20
  end
23
21
 
24
22
  describe '#mount_path' do
25
23
  it 'is nil when no mount path setting exists' do
26
- path = Path.new(anything, anything, {})
24
+ path = described_class.new(anything, anything, {})
27
25
  expect(path.mount_path).to be_nil
28
26
  end
29
27
 
30
28
  it 'is nil when the mount path is nil' do
31
- path = Path.new(anything, anything, mount_path: nil)
29
+ path = described_class.new(anything, anything, mount_path: nil)
32
30
  expect(path.mount_path).to be_nil
33
31
  end
34
32
 
35
33
  it 'splits the mount path' do
36
- path = Path.new(anything, anything, mount_path: %w[foo bar])
34
+ path = described_class.new(anything, anything, mount_path: %w[foo bar])
37
35
  expect(path.mount_path).to eql(%w[foo bar])
38
36
  end
39
37
  end
40
38
 
41
39
  describe '#root_prefix' do
42
40
  it 'is nil when no root prefix setting exists' do
43
- path = Path.new(anything, anything, {})
41
+ path = described_class.new(anything, anything, {})
44
42
  expect(path.root_prefix).to be_nil
45
43
  end
46
44
 
47
45
  it 'is nil when the mount path is nil' do
48
- path = Path.new(anything, anything, root_prefix: nil)
46
+ path = described_class.new(anything, anything, root_prefix: nil)
49
47
  expect(path.root_prefix).to be_nil
50
48
  end
51
49
 
52
50
  it 'splits the mount path' do
53
- path = Path.new(anything, anything, root_prefix: 'hello/world')
51
+ path = described_class.new(anything, anything, root_prefix: 'hello/world')
54
52
  expect(path.root_prefix).to eql(%w[hello world])
55
53
  end
56
54
  end
57
55
 
58
56
  describe '#uses_path_versioning?' do
59
57
  it 'is false when the version setting is nil' do
60
- path = Path.new(anything, anything, version: nil)
58
+ path = described_class.new(anything, anything, version: nil)
61
59
  expect(path.uses_path_versioning?).to be false
62
60
  end
63
61
 
64
62
  it 'is false when the version option is header' do
65
- path = Path.new(
63
+ path = described_class.new(
66
64
  anything,
67
65
  anything,
68
66
  version: 'v1',
@@ -73,7 +71,7 @@ module Grape
73
71
  end
74
72
 
75
73
  it 'is true when the version option is path' do
76
- path = Path.new(
74
+ path = described_class.new(
77
75
  anything,
78
76
  anything,
79
77
  version: 'v1',
@@ -86,44 +84,44 @@ module Grape
86
84
 
87
85
  describe '#namespace?' do
88
86
  it 'is false when the namespace is nil' do
89
- path = Path.new(anything, nil, anything)
90
- expect(path.namespace?).to be_falsey
87
+ path = described_class.new(anything, nil, anything)
88
+ expect(path).not_to be_namespace
91
89
  end
92
90
 
93
91
  it 'is false when the namespace starts with whitespace' do
94
- path = Path.new(anything, ' /foo', anything)
95
- expect(path.namespace?).to be_falsey
92
+ path = described_class.new(anything, ' /foo', anything)
93
+ expect(path).not_to be_namespace
96
94
  end
97
95
 
98
96
  it 'is false when the namespace is the root path' do
99
- path = Path.new(anything, '/', anything)
97
+ path = described_class.new(anything, '/', anything)
100
98
  expect(path.namespace?).to be false
101
99
  end
102
100
 
103
101
  it 'is true otherwise' do
104
- path = Path.new(anything, '/world', anything)
102
+ path = described_class.new(anything, '/world', anything)
105
103
  expect(path.namespace?).to be true
106
104
  end
107
105
  end
108
106
 
109
107
  describe '#path?' do
110
108
  it 'is false when the path is nil' do
111
- path = Path.new(nil, anything, anything)
112
- expect(path.path?).to be_falsey
109
+ path = described_class.new(nil, anything, anything)
110
+ expect(path).not_to be_path
113
111
  end
114
112
 
115
113
  it 'is false when the path starts with whitespace' do
116
- path = Path.new(' /foo', anything, anything)
117
- expect(path.path?).to be_falsey
114
+ path = described_class.new(' /foo', anything, anything)
115
+ expect(path).not_to be_path
118
116
  end
119
117
 
120
118
  it 'is false when the path is the root path' do
121
- path = Path.new('/', anything, anything)
119
+ path = described_class.new('/', anything, anything)
122
120
  expect(path.path?).to be false
123
121
  end
124
122
 
125
123
  it 'is true otherwise' do
126
- path = Path.new('/hello', anything, anything)
124
+ path = described_class.new('/hello', anything, anything)
127
125
  expect(path.path?).to be true
128
126
  end
129
127
  end
@@ -131,24 +129,24 @@ module Grape
131
129
  describe '#path' do
132
130
  context 'mount_path' do
133
131
  it 'is not included when it is nil' do
134
- path = Path.new(nil, nil, mount_path: '/foo/bar')
132
+ path = described_class.new(nil, nil, mount_path: '/foo/bar')
135
133
  expect(path.path).to eql '/foo/bar'
136
134
  end
137
135
 
138
136
  it 'is included when it is not nil' do
139
- path = Path.new(nil, nil, {})
137
+ path = described_class.new(nil, nil, {})
140
138
  expect(path.path).to eql('/')
141
139
  end
142
140
  end
143
141
 
144
142
  context 'root_prefix' do
145
143
  it 'is not included when it is nil' do
146
- path = Path.new(nil, nil, {})
144
+ path = described_class.new(nil, nil, {})
147
145
  expect(path.path).to eql('/')
148
146
  end
149
147
 
150
148
  it 'is included after the mount path' do
151
- path = Path.new(
149
+ path = described_class.new(
152
150
  nil,
153
151
  nil,
154
152
  mount_path: '/foo',
@@ -160,7 +158,7 @@ module Grape
160
158
  end
161
159
 
162
160
  it 'uses the namespace after the mount path and root prefix' do
163
- path = Path.new(
161
+ path = described_class.new(
164
162
  nil,
165
163
  'namespace',
166
164
  mount_path: '/foo',
@@ -171,7 +169,7 @@ module Grape
171
169
  end
172
170
 
173
171
  it 'uses the raw path after the namespace' do
174
- path = Path.new(
172
+ path = described_class.new(
175
173
  'raw_path',
176
174
  'namespace',
177
175
  mount_path: '/foo',
@@ -185,9 +183,9 @@ module Grape
185
183
  describe '#suffix' do
186
184
  context 'when using a specific format' do
187
185
  it 'accepts specified format' do
188
- path = Path.new(nil, nil, {})
189
- allow(path).to receive(:uses_specific_format?) { true }
190
- allow(path).to receive(:settings) { { format: :json } }
186
+ path = described_class.new(nil, nil, {})
187
+ allow(path).to receive(:uses_specific_format?).and_return(true)
188
+ allow(path).to receive(:settings).and_return({ format: :json })
191
189
 
192
190
  expect(path.suffix).to eql('(.json)')
193
191
  end
@@ -195,9 +193,9 @@ module Grape
195
193
 
196
194
  context 'when path versioning is used' do
197
195
  it "includes a '/'" do
198
- path = Path.new(nil, nil, {})
199
- allow(path).to receive(:uses_specific_format?) { false }
200
- allow(path).to receive(:uses_path_versioning?) { true }
196
+ path = described_class.new(nil, nil, {})
197
+ allow(path).to receive(:uses_specific_format?).and_return(false)
198
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
201
199
 
202
200
  expect(path.suffix).to eql('(/.:format)')
203
201
  end
@@ -205,25 +203,25 @@ module Grape
205
203
 
206
204
  context 'when path versioning is not used' do
207
205
  it "does not include a '/' when the path has a namespace" do
208
- path = Path.new(nil, 'namespace', {})
209
- allow(path).to receive(:uses_specific_format?) { false }
210
- allow(path).to receive(:uses_path_versioning?) { true }
206
+ path = described_class.new(nil, 'namespace', {})
207
+ allow(path).to receive(:uses_specific_format?).and_return(false)
208
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
211
209
 
212
210
  expect(path.suffix).to eql('(.:format)')
213
211
  end
214
212
 
215
213
  it "does not include a '/' when the path has a path" do
216
- path = Path.new('/path', nil, {})
217
- allow(path).to receive(:uses_specific_format?) { false }
218
- allow(path).to receive(:uses_path_versioning?) { true }
214
+ path = described_class.new('/path', nil, {})
215
+ allow(path).to receive(:uses_specific_format?).and_return(false)
216
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
219
217
 
220
218
  expect(path.suffix).to eql('(.:format)')
221
219
  end
222
220
 
223
221
  it "includes a '/' otherwise" do
224
- path = Path.new(nil, nil, {})
225
- allow(path).to receive(:uses_specific_format?) { false }
226
- allow(path).to receive(:uses_path_versioning?) { true }
222
+ path = described_class.new(nil, nil, {})
223
+ allow(path).to receive(:uses_specific_format?).and_return(false)
224
+ allow(path).to receive(:uses_path_versioning?).and_return(true)
227
225
 
228
226
  expect(path.suffix).to eql('(/.:format)')
229
227
  end
@@ -232,19 +230,19 @@ module Grape
232
230
 
233
231
  describe '#path_with_suffix' do
234
232
  it 'combines the path and suffix' do
235
- path = Path.new(nil, nil, {})
236
- allow(path).to receive(:path) { '/the/path' }
237
- allow(path).to receive(:suffix) { 'suffix' }
233
+ path = described_class.new(nil, nil, {})
234
+ allow(path).to receive(:path).and_return('/the/path')
235
+ allow(path).to receive(:suffix).and_return('suffix')
238
236
 
239
237
  expect(path.path_with_suffix).to eql('/the/pathsuffix')
240
238
  end
241
239
 
242
240
  context 'when using a specific format' do
243
241
  it 'might have a suffix with specified format' do
244
- path = Path.new(nil, nil, {})
245
- allow(path).to receive(:path) { '/the/path' }
246
- allow(path).to receive(:uses_specific_format?) { true }
247
- allow(path).to receive(:settings) { { format: :json } }
242
+ path = described_class.new(nil, nil, {})
243
+ allow(path).to receive(:path).and_return('/the/path')
244
+ allow(path).to receive(:uses_specific_format?).and_return(true)
245
+ allow(path).to receive(:settings).and_return({ format: :json })
248
246
 
249
247
  expect(path.path_with_suffix).to eql('/the/path(.json)')
250
248
  end
@@ -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