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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +92 -0
- data/CONTRIBUTING.md +32 -1
- data/README.md +176 -25
- data/UPGRADING.md +61 -4
- data/grape.gemspec +6 -6
- data/lib/grape/api/instance.rb +14 -18
- data/lib/grape/api.rb +17 -12
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dry_types.rb +12 -0
- data/lib/grape/dsl/api.rb +0 -2
- data/lib/grape/dsl/callbacks.rb +0 -2
- data/lib/grape/dsl/configuration.rb +0 -2
- data/lib/grape/dsl/desc.rb +4 -20
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +7 -7
- data/lib/grape/dsl/inside_route.rb +43 -30
- data/lib/grape/dsl/middleware.rb +4 -6
- data/lib/grape/dsl/parameters.rb +13 -10
- data/lib/grape/dsl/request_response.rb +9 -8
- data/lib/grape/dsl/routing.rb +6 -4
- data/lib/grape/dsl/settings.rb +5 -7
- data/lib/grape/dsl/validations.rb +0 -15
- data/lib/grape/endpoint.rb +22 -37
- data/lib/grape/error_formatter/json.rb +9 -7
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/base.rb +3 -2
- data/lib/grape/exceptions/missing_group_type.rb +8 -1
- data/lib/grape/exceptions/too_many_multipart_files.rb +11 -0
- data/lib/grape/exceptions/unsupported_group_type.rb +8 -1
- data/lib/grape/exceptions/validation.rb +1 -6
- data/lib/grape/formatter/json.rb +1 -0
- data/lib/grape/formatter/serializable_hash.rb +2 -1
- data/lib/grape/formatter/xml.rb +1 -0
- data/lib/grape/locale/en.yml +9 -8
- data/lib/grape/middleware/auth/dsl.rb +7 -2
- data/lib/grape/middleware/base.rb +3 -1
- data/lib/grape/middleware/error.rb +2 -2
- data/lib/grape/middleware/formatter.rb +4 -4
- data/lib/grape/middleware/stack.rb +3 -3
- data/lib/grape/middleware/versioner/accept_version_header.rb +3 -5
- data/lib/grape/middleware/versioner/header.rb +6 -4
- data/lib/grape/middleware/versioner/param.rb +1 -0
- data/lib/grape/middleware/versioner/parse_media_type_patch.rb +2 -1
- data/lib/grape/middleware/versioner/path.rb +2 -0
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +4 -1
- data/lib/grape/router/attribute_translator.rb +1 -1
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +6 -0
- data/lib/grape/types/invalid_value.rb +8 -0
- data/lib/grape/util/cache.rb +1 -1
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/json.rb +2 -0
- data/lib/grape/util/lazy_value.rb +3 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_doc.rb +58 -0
- data/lib/grape/validations/params_scope.rb +138 -79
- data/lib/grape/validations/types/array_coercer.rb +0 -2
- data/lib/grape/validations/types/custom_type_coercer.rb +1 -0
- data/lib/grape/validations/types/dry_type_coercer.rb +4 -8
- data/lib/grape/validations/types/invalid_value.rb +0 -7
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +16 -8
- data/lib/grape/validations/types/set_coercer.rb +0 -2
- data/lib/grape/validations/types.rb +98 -30
- data/lib/grape/validations/validators/all_or_none_of_validator.rb +16 -0
- data/lib/grape/validations/validators/allow_blank_validator.rb +20 -0
- data/lib/grape/validations/validators/as_validator.rb +14 -0
- data/lib/grape/validations/validators/at_least_one_of_validator.rb +15 -0
- data/lib/grape/validations/validators/base.rb +82 -70
- data/lib/grape/validations/validators/coerce_validator.rb +75 -0
- data/lib/grape/validations/validators/default_validator.rb +51 -0
- data/lib/grape/validations/validators/exactly_one_of_validator.rb +17 -0
- data/lib/grape/validations/validators/except_values_validator.rb +24 -0
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -20
- data/lib/grape/validations/validators/mutual_exclusion_validator.rb +16 -0
- data/lib/grape/validations/validators/presence_validator.rb +15 -0
- data/lib/grape/validations/validators/regexp_validator.rb +16 -0
- data/lib/grape/validations/validators/same_as_validator.rb +29 -0
- data/lib/grape/validations/validators/values_validator.rb +88 -0
- data/lib/grape/validations.rb +16 -6
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +77 -29
- data/spec/grape/api/custom_validations_spec.rb +116 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -5
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -3
- data/spec/grape/api/documentation_spec.rb +59 -0
- data/spec/grape/api/inherited_helpers_spec.rb +0 -2
- data/spec/grape/api/instance_spec.rb +0 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -2
- data/spec/grape/api/namespace_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/nested_helpers_spec.rb +0 -2
- data/spec/grape/api/optional_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/parameters_modification_spec.rb +0 -2
- data/spec/grape/api/patch_method_helpers_spec.rb +0 -2
- data/spec/grape/api/recognize_path_spec.rb +1 -3
- data/spec/grape/api/required_parameters_in_route_spec.rb +0 -2
- data/spec/grape/api/required_parameters_with_invalid_method_spec.rb +0 -2
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -10
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -17
- data/spec/grape/api/shared_helpers_spec.rb +0 -2
- data/spec/grape/api_remount_spec.rb +16 -16
- data/spec/grape/api_spec.rb +462 -251
- data/spec/grape/config_spec.rb +0 -2
- data/spec/grape/dsl/callbacks_spec.rb +2 -3
- data/spec/grape/dsl/desc_spec.rb +2 -2
- data/spec/grape/dsl/headers_spec.rb +39 -11
- data/spec/grape/dsl/helpers_spec.rb +3 -4
- data/spec/grape/dsl/inside_route_spec.rb +16 -16
- data/spec/grape/dsl/logger_spec.rb +15 -19
- data/spec/grape/dsl/middleware_spec.rb +2 -3
- data/spec/grape/dsl/parameters_spec.rb +2 -2
- data/spec/grape/dsl/request_response_spec.rb +7 -8
- data/spec/grape/dsl/routing_spec.rb +11 -10
- data/spec/grape/dsl/settings_spec.rb +0 -2
- data/spec/grape/dsl/validations_spec.rb +0 -17
- data/spec/grape/endpoint/declared_spec.rb +261 -16
- data/spec/grape/endpoint_spec.rb +88 -59
- data/spec/grape/entity_spec.rb +22 -23
- data/spec/grape/exceptions/base_spec.rb +16 -2
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -2
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +64 -24
- data/spec/grape/exceptions/invalid_formatter_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_response_spec.rb +0 -2
- data/spec/grape/exceptions/invalid_versioner_option_spec.rb +1 -3
- data/spec/grape/exceptions/missing_group_type_spec.rb +21 -0
- data/spec/grape/exceptions/missing_mime_type_spec.rb +0 -2
- data/spec/grape/exceptions/missing_option_spec.rb +1 -3
- data/spec/grape/exceptions/unknown_options_spec.rb +0 -2
- data/spec/grape/exceptions/unknown_validator_spec.rb +0 -2
- data/spec/grape/exceptions/unsupported_group_type_spec.rb +23 -0
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -11
- data/spec/grape/exceptions/validation_spec.rb +5 -5
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -9
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -10
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -10
- data/spec/grape/integration/global_namespace_function_spec.rb +0 -2
- data/spec/grape/integration/rack_sendfile_spec.rb +1 -3
- data/spec/grape/integration/rack_spec.rb +6 -7
- data/spec/grape/loading_spec.rb +8 -10
- data/spec/grape/middleware/auth/base_spec.rb +0 -1
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -8
- data/spec/grape/middleware/auth/strategies_spec.rb +60 -22
- data/spec/grape/middleware/base_spec.rb +28 -19
- data/spec/grape/middleware/error_spec.rb +8 -3
- data/spec/grape/middleware/exception_spec.rb +111 -163
- data/spec/grape/middleware/formatter_spec.rb +33 -14
- data/spec/grape/middleware/globals_spec.rb +7 -6
- data/spec/grape/middleware/stack_spec.rb +14 -14
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -3
- data/spec/grape/middleware/versioner/header_spec.rb +30 -15
- data/spec/grape/middleware/versioner/param_spec.rb +7 -3
- data/spec/grape/middleware/versioner/path_spec.rb +5 -3
- data/spec/grape/middleware/versioner_spec.rb +1 -3
- data/spec/grape/named_api_spec.rb +0 -2
- data/spec/grape/parser_spec.rb +4 -2
- data/spec/grape/path_spec.rb +52 -54
- data/spec/grape/presenters/presenter_spec.rb +7 -8
- data/spec/grape/request_spec.rb +6 -6
- data/spec/grape/util/inheritable_setting_spec.rb +7 -8
- data/spec/grape/util/inheritable_values_spec.rb +3 -3
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -2
- data/spec/grape/util/stackable_values_spec.rb +7 -6
- data/spec/grape/util/strict_hash_configuration_spec.rb +0 -1
- data/spec/grape/validations/attributes_doc_spec.rb +153 -0
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -12
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +1 -2
- data/spec/grape/validations/params_scope_spec.rb +361 -96
- data/spec/grape/validations/single_attribute_iterator_spec.rb +2 -3
- data/spec/grape/validations/types/array_coercer_spec.rb +0 -2
- data/spec/grape/validations/types/primitive_coercer_spec.rb +24 -9
- data/spec/grape/validations/types/set_coercer_spec.rb +0 -2
- data/spec/grape/validations/types_spec.rb +36 -10
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -58
- data/spec/grape/validations/validators/allow_blank_spec.rb +135 -141
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -58
- data/spec/grape/validations/validators/coerce_spec.rb +23 -24
- data/spec/grape/validations/validators/default_spec.rb +72 -80
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -79
- data/spec/grape/validations/validators/except_values_spec.rb +3 -5
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -79
- data/spec/grape/validations/validators/presence_spec.rb +16 -3
- data/spec/grape/validations/validators/regexp_spec.rb +25 -33
- data/spec/grape/validations/validators/same_as_spec.rb +14 -22
- data/spec/grape/validations/validators/values_spec.rb +201 -179
- data/spec/grape/validations_spec.rb +171 -79
- data/spec/integration/eager_load/eager_load_spec.rb +2 -2
- data/spec/integration/multi_json/json_spec.rb +1 -3
- data/spec/integration/multi_xml/xml_spec.rb +1 -3
- data/spec/shared/versioning_examples.rb +12 -9
- data/spec/spec_helper.rb +21 -6
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- metadata +41 -29
- data/lib/grape/validations/validators/all_or_none.rb +0 -15
- data/lib/grape/validations/validators/allow_blank.rb +0 -18
- data/lib/grape/validations/validators/as.rb +0 -16
- data/lib/grape/validations/validators/at_least_one_of.rb +0 -14
- data/lib/grape/validations/validators/coerce.rb +0 -91
- data/lib/grape/validations/validators/default.rb +0 -48
- data/lib/grape/validations/validators/exactly_one_of.rb +0 -16
- data/lib/grape/validations/validators/except_values.rb +0 -22
- data/lib/grape/validations/validators/mutual_exclusion.rb +0 -15
- data/lib/grape/validations/validators/presence.rb +0 -12
- data/lib/grape/validations/validators/regexp.rb +0 -13
- data/lib/grape/validations/validators/same_as.rb +0 -26
- data/lib/grape/validations/validators/values.rb +0 -83
- data/spec/grape/dsl/configuration_spec.rb +0 -16
- data/spec/grape/validations/attributes_iterator_spec.rb +0 -6
- data/spec/support/eager_load.rb +0 -19
data/spec/grape/path_spec.rb
CHANGED
@@ -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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
90
|
-
expect(path
|
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 =
|
95
|
-
expect(path
|
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 =
|
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 =
|
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 =
|
112
|
-
expect(path
|
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 =
|
117
|
-
expect(path
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
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 =
|
189
|
-
allow(path).to receive(:uses_specific_format?)
|
190
|
-
allow(path).to receive(:settings)
|
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 =
|
199
|
-
allow(path).to receive(:uses_specific_format?)
|
200
|
-
allow(path).to receive(:uses_path_versioning?)
|
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 =
|
209
|
-
allow(path).to receive(:uses_specific_format?)
|
210
|
-
allow(path).to receive(:uses_path_versioning?)
|
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 =
|
217
|
-
allow(path).to receive(:uses_specific_format?)
|
218
|
-
allow(path).to receive(:uses_path_versioning?)
|
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 =
|
225
|
-
allow(path).to receive(:uses_specific_format?)
|
226
|
-
allow(path).to receive(:uses_path_versioning?)
|
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 =
|
236
|
-
allow(path).to receive(:path)
|
237
|
-
allow(path).to receive(: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 =
|
245
|
-
allow(path).to receive(:path)
|
246
|
-
allow(path).to receive(:uses_specific_format?)
|
247
|
-
allow(path).to receive(:settings)
|
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(
|
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:
|
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:
|
60
|
-
subject.present hash_mock2, with:
|
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
|
data/spec/grape/request_spec.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
8
|
-
|
6
|
+
before do
|
7
|
+
described_class.reset_global!
|
9
8
|
end
|
10
9
|
|
11
10
|
let(:parent) do
|
12
|
-
|
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
|
-
|
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
|
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 '
|
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 '
|
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
|
-
|
8
|
-
|
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
|
-
|
8
|
-
|
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 =
|
104
|
-
child =
|
105
|
-
grandchild =
|
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]
|
@@ -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
|