grape 1.3.3 → 1.6.2
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 +111 -2
- data/CONTRIBUTING.md +2 -1
- data/README.md +135 -23
- data/UPGRADING.md +237 -46
- data/grape.gemspec +5 -5
- data/lib/grape/api/instance.rb +34 -42
- data/lib/grape/api.rb +21 -16
- data/lib/grape/cookies.rb +2 -0
- data/lib/grape/dsl/callbacks.rb +1 -1
- data/lib/grape/dsl/desc.rb +3 -5
- data/lib/grape/dsl/headers.rb +5 -2
- data/lib/grape/dsl/helpers.rb +8 -5
- data/lib/grape/dsl/inside_route.rb +72 -53
- data/lib/grape/dsl/middleware.rb +4 -4
- data/lib/grape/dsl/parameters.rb +11 -7
- data/lib/grape/dsl/request_response.rb +9 -6
- data/lib/grape/dsl/routing.rb +8 -9
- data/lib/grape/dsl/settings.rb +5 -5
- data/lib/grape/dsl/validations.rb +18 -1
- data/lib/grape/eager_load.rb +1 -1
- data/lib/grape/endpoint.rb +29 -42
- data/lib/grape/error_formatter/json.rb +2 -6
- data/lib/grape/error_formatter/xml.rb +2 -6
- data/lib/grape/exceptions/empty_message_body.rb +11 -0
- data/lib/grape/exceptions/validation.rb +2 -3
- data/lib/grape/exceptions/validation_errors.rb +1 -1
- 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 +1 -1
- data/lib/grape/middleware/auth/base.rb +3 -3
- data/lib/grape/middleware/auth/dsl.rb +7 -1
- data/lib/grape/middleware/base.rb +6 -3
- data/lib/grape/middleware/error.rb +11 -13
- data/lib/grape/middleware/formatter.rb +7 -7
- data/lib/grape/middleware/stack.rb +10 -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/parser/json.rb +1 -1
- data/lib/grape/parser/xml.rb +1 -1
- data/lib/grape/path.rb +1 -0
- data/lib/grape/request.rb +4 -1
- data/lib/grape/router/attribute_translator.rb +3 -3
- data/lib/grape/router/pattern.rb +1 -1
- data/lib/grape/router/route.rb +2 -2
- data/lib/grape/router.rb +31 -30
- data/lib/grape/{serve_file → serve_stream}/file_body.rb +1 -1
- data/lib/grape/{serve_file → serve_stream}/sendfile_response.rb +1 -1
- data/lib/grape/{serve_file/file_response.rb → serve_stream/stream_response.rb} +8 -8
- data/lib/grape/util/base_inheritable.rb +2 -2
- data/lib/grape/util/inheritable_setting.rb +1 -3
- data/lib/grape/util/lazy_value.rb +4 -2
- data/lib/grape/util/strict_hash_configuration.rb +1 -1
- data/lib/grape/validations/attributes_iterator.rb +8 -0
- data/lib/grape/validations/multiple_attributes_iterator.rb +1 -1
- data/lib/grape/validations/params_scope.rb +97 -62
- data/lib/grape/validations/single_attribute_iterator.rb +1 -1
- data/lib/grape/validations/types/custom_type_coercer.rb +16 -3
- data/lib/grape/validations/types/dry_type_coercer.rb +1 -1
- data/lib/grape/validations/types/invalid_value.rb +24 -0
- data/lib/grape/validations/types/json.rb +2 -1
- data/lib/grape/validations/types/primitive_coercer.rb +4 -5
- data/lib/grape/validations/types.rb +1 -4
- data/lib/grape/validations/validator_factory.rb +1 -1
- data/lib/grape/validations/validators/all_or_none.rb +8 -5
- data/lib/grape/validations/validators/allow_blank.rb +9 -7
- data/lib/grape/validations/validators/as.rb +6 -8
- data/lib/grape/validations/validators/at_least_one_of.rb +7 -4
- data/lib/grape/validations/validators/base.rb +74 -69
- data/lib/grape/validations/validators/coerce.rb +63 -76
- data/lib/grape/validations/validators/default.rb +36 -34
- data/lib/grape/validations/validators/exactly_one_of.rb +9 -6
- data/lib/grape/validations/validators/except_values.rb +13 -11
- data/lib/grape/validations/validators/multiple_params_base.rb +24 -19
- data/lib/grape/validations/validators/mutual_exclusion.rb +8 -5
- data/lib/grape/validations/validators/presence.rb +7 -4
- data/lib/grape/validations/validators/regexp.rb +8 -5
- data/lib/grape/validations/validators/same_as.rb +18 -15
- data/lib/grape/validations/validators/values.rb +61 -56
- data/lib/grape/validations.rb +6 -0
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +7 -3
- data/spec/grape/api/custom_validations_spec.rb +77 -45
- data/spec/grape/api/deeply_included_options_spec.rb +3 -3
- data/spec/grape/api/defines_boolean_in_params_spec.rb +2 -1
- data/spec/grape/api/invalid_format_spec.rb +2 -0
- data/spec/grape/api/recognize_path_spec.rb +1 -1
- data/spec/grape/api/routes_with_requirements_spec.rb +8 -8
- data/spec/grape/api/shared_helpers_exactly_one_of_spec.rb +9 -15
- data/spec/grape/api_remount_spec.rb +25 -19
- data/spec/grape/api_spec.rb +576 -211
- data/spec/grape/dsl/callbacks_spec.rb +2 -1
- data/spec/grape/dsl/headers_spec.rb +39 -9
- data/spec/grape/dsl/helpers_spec.rb +3 -2
- data/spec/grape/dsl/inside_route_spec.rb +185 -34
- data/spec/grape/dsl/logger_spec.rb +16 -18
- data/spec/grape/dsl/middleware_spec.rb +2 -1
- data/spec/grape/dsl/parameters_spec.rb +2 -0
- data/spec/grape/dsl/request_response_spec.rb +1 -0
- data/spec/grape/dsl/routing_spec.rb +10 -7
- data/spec/grape/endpoint/declared_spec.rb +848 -0
- data/spec/grape/endpoint_spec.rb +77 -589
- data/spec/grape/entity_spec.rb +29 -23
- data/spec/grape/exceptions/body_parse_errors_spec.rb +3 -0
- data/spec/grape/exceptions/invalid_accept_header_spec.rb +61 -22
- data/spec/grape/exceptions/validation_errors_spec.rb +13 -10
- data/spec/grape/exceptions/validation_spec.rb +5 -3
- data/spec/grape/extensions/param_builders/hash_spec.rb +7 -7
- data/spec/grape/extensions/param_builders/hash_with_indifferent_access_spec.rb +8 -8
- data/spec/grape/extensions/param_builders/hashie/mash_spec.rb +8 -8
- data/spec/grape/integration/rack_sendfile_spec.rb +13 -9
- data/spec/grape/loading_spec.rb +8 -8
- data/spec/grape/middleware/auth/dsl_spec.rb +15 -6
- data/spec/grape/middleware/auth/strategies_spec.rb +61 -21
- data/spec/grape/middleware/base_spec.rb +24 -15
- data/spec/grape/middleware/error_spec.rb +3 -3
- data/spec/grape/middleware/exception_spec.rb +111 -161
- data/spec/grape/middleware/formatter_spec.rb +28 -7
- data/spec/grape/middleware/globals_spec.rb +7 -4
- data/spec/grape/middleware/stack_spec.rb +15 -12
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +2 -1
- data/spec/grape/middleware/versioner/header_spec.rb +14 -13
- data/spec/grape/middleware/versioner/param_spec.rb +7 -1
- data/spec/grape/middleware/versioner/path_spec.rb +5 -1
- data/spec/grape/middleware/versioner_spec.rb +1 -1
- data/spec/grape/parser_spec.rb +4 -0
- data/spec/grape/path_spec.rb +52 -52
- data/spec/grape/presenters/presenter_spec.rb +7 -6
- data/spec/grape/request_spec.rb +6 -4
- data/spec/grape/util/inheritable_setting_spec.rb +7 -7
- data/spec/grape/util/inheritable_values_spec.rb +3 -2
- data/spec/grape/util/reverse_stackable_values_spec.rb +3 -1
- data/spec/grape/util/stackable_values_spec.rb +7 -5
- data/spec/grape/validations/instance_behaivour_spec.rb +9 -10
- data/spec/grape/validations/multiple_attributes_iterator_spec.rb +14 -3
- data/spec/grape/validations/params_scope_spec.rb +72 -10
- data/spec/grape/validations/single_attribute_iterator_spec.rb +18 -6
- data/spec/grape/validations/types/primitive_coercer_spec.rb +63 -7
- data/spec/grape/validations/types_spec.rb +8 -8
- data/spec/grape/validations/validators/all_or_none_spec.rb +50 -56
- data/spec/grape/validations/validators/allow_blank_spec.rb +136 -140
- data/spec/grape/validations/validators/at_least_one_of_spec.rb +50 -56
- data/spec/grape/validations/validators/coerce_spec.rb +248 -33
- data/spec/grape/validations/validators/default_spec.rb +121 -78
- data/spec/grape/validations/validators/exactly_one_of_spec.rb +71 -77
- data/spec/grape/validations/validators/except_values_spec.rb +4 -3
- data/spec/grape/validations/validators/mutual_exclusion_spec.rb +71 -77
- data/spec/grape/validations/validators/presence_spec.rb +16 -1
- data/spec/grape/validations/validators/regexp_spec.rb +25 -31
- data/spec/grape/validations/validators/same_as_spec.rb +14 -20
- data/spec/grape/validations/validators/values_spec.rb +183 -178
- data/spec/grape/validations_spec.rb +342 -29
- data/spec/integration/eager_load/eager_load_spec.rb +15 -0
- data/spec/integration/multi_json/json_spec.rb +1 -1
- data/spec/integration/multi_xml/xml_spec.rb +1 -1
- data/spec/shared/versioning_examples.rb +32 -29
- data/spec/spec_helper.rb +12 -12
- data/spec/support/basic_auth_encode_helpers.rb +1 -1
- data/spec/support/chunks.rb +14 -0
- data/spec/support/versioned_helpers.rb +4 -6
- metadata +110 -102
@@ -5,19 +5,22 @@ require 'spec_helper'
|
|
5
5
|
describe Grape::Middleware::Stack do
|
6
6
|
module StackSpec
|
7
7
|
class FooMiddleware; end
|
8
|
+
|
8
9
|
class BarMiddleware; end
|
10
|
+
|
9
11
|
class BlockMiddleware
|
10
12
|
attr_reader :block
|
13
|
+
|
11
14
|
def initialize(&block)
|
12
15
|
@block = block
|
13
16
|
end
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
17
|
-
|
18
|
-
let(:others) { [[:use, StackSpec::BarMiddleware], [:insert_before, StackSpec::BarMiddleware, StackSpec::BlockMiddleware, proc]] }
|
20
|
+
subject { described_class.new }
|
19
21
|
|
20
|
-
|
22
|
+
let(:proc) { -> {} }
|
23
|
+
let(:others) { [[:use, StackSpec::BarMiddleware], [:insert_before, StackSpec::BarMiddleware, StackSpec::BlockMiddleware, proc]] }
|
21
24
|
|
22
25
|
before do
|
23
26
|
subject.use StackSpec::FooMiddleware
|
@@ -26,20 +29,20 @@ describe Grape::Middleware::Stack do
|
|
26
29
|
describe '#use' do
|
27
30
|
it 'pushes a middleware class onto the stack' do
|
28
31
|
expect { subject.use StackSpec::BarMiddleware }
|
29
|
-
.to change
|
32
|
+
.to change(subject, :size).by(1)
|
30
33
|
expect(subject.last).to eq(StackSpec::BarMiddleware)
|
31
34
|
end
|
32
35
|
|
33
36
|
it 'pushes a middleware class with arguments onto the stack' do
|
34
37
|
expect { subject.use StackSpec::BarMiddleware, false, my_arg: 42 }
|
35
|
-
.to change
|
38
|
+
.to change(subject, :size).by(1)
|
36
39
|
expect(subject.last).to eq(StackSpec::BarMiddleware)
|
37
40
|
expect(subject.last.args).to eq([false, { my_arg: 42 }])
|
38
41
|
end
|
39
42
|
|
40
43
|
it 'pushes a middleware class with block arguments onto the stack' do
|
41
44
|
expect { subject.use StackSpec::BlockMiddleware, &proc }
|
42
|
-
.to change
|
45
|
+
.to change(subject, :size).by(1)
|
43
46
|
expect(subject.last).to eq(StackSpec::BlockMiddleware)
|
44
47
|
expect(subject.last.args).to eq([])
|
45
48
|
expect(subject.last.block).to eq(proc)
|
@@ -49,7 +52,7 @@ describe Grape::Middleware::Stack do
|
|
49
52
|
describe '#insert' do
|
50
53
|
it 'inserts a middleware class at the integer index' do
|
51
54
|
expect { subject.insert 0, StackSpec::BarMiddleware }
|
52
|
-
.to change
|
55
|
+
.to change(subject, :size).by(1)
|
53
56
|
expect(subject[0]).to eq(StackSpec::BarMiddleware)
|
54
57
|
expect(subject[1]).to eq(StackSpec::FooMiddleware)
|
55
58
|
end
|
@@ -58,7 +61,7 @@ describe Grape::Middleware::Stack do
|
|
58
61
|
describe '#insert_before' do
|
59
62
|
it 'inserts a middleware before another middleware class' do
|
60
63
|
expect { subject.insert_before StackSpec::FooMiddleware, StackSpec::BarMiddleware }
|
61
|
-
.to change
|
64
|
+
.to change(subject, :size).by(1)
|
62
65
|
expect(subject[0]).to eq(StackSpec::BarMiddleware)
|
63
66
|
expect(subject[1]).to eq(StackSpec::FooMiddleware)
|
64
67
|
end
|
@@ -67,7 +70,7 @@ describe Grape::Middleware::Stack do
|
|
67
70
|
subject.use Class.new(StackSpec::BlockMiddleware)
|
68
71
|
|
69
72
|
expect { subject.insert_before StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
|
70
|
-
.to change
|
73
|
+
.to change(subject, :size).by(1)
|
71
74
|
|
72
75
|
expect(subject[1]).to eq(StackSpec::BarMiddleware)
|
73
76
|
expect(subject[2]).to eq(StackSpec::BlockMiddleware)
|
@@ -82,7 +85,7 @@ describe Grape::Middleware::Stack do
|
|
82
85
|
describe '#insert_after' do
|
83
86
|
it 'inserts a middleware after another middleware class' do
|
84
87
|
expect { subject.insert_after StackSpec::FooMiddleware, StackSpec::BarMiddleware }
|
85
|
-
.to change
|
88
|
+
.to change(subject, :size).by(1)
|
86
89
|
expect(subject[1]).to eq(StackSpec::BarMiddleware)
|
87
90
|
expect(subject[0]).to eq(StackSpec::FooMiddleware)
|
88
91
|
end
|
@@ -91,7 +94,7 @@ describe Grape::Middleware::Stack do
|
|
91
94
|
subject.use Class.new(StackSpec::BlockMiddleware)
|
92
95
|
|
93
96
|
expect { subject.insert_after StackSpec::BlockMiddleware, StackSpec::BarMiddleware }
|
94
|
-
.to change
|
97
|
+
.to change(subject, :size).by(1)
|
95
98
|
|
96
99
|
expect(subject[1]).to eq(StackSpec::BlockMiddleware)
|
97
100
|
expect(subject[2]).to eq(StackSpec::BarMiddleware)
|
@@ -106,7 +109,7 @@ describe Grape::Middleware::Stack do
|
|
106
109
|
describe '#merge_with' do
|
107
110
|
it 'applies a collection of operations and middlewares' do
|
108
111
|
expect { subject.merge_with(others) }
|
109
|
-
.to change
|
112
|
+
.to change(subject, :size).by(2)
|
110
113
|
expect(subject[0]).to eq(StackSpec::FooMiddleware)
|
111
114
|
expect(subject[1]).to eq(StackSpec::BlockMiddleware)
|
112
115
|
expect(subject[2]).to eq(StackSpec::BarMiddleware)
|
@@ -3,8 +3,9 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Versioner::AcceptVersionHeader do
|
6
|
+
subject { described_class.new(app, **(@options || {})) }
|
7
|
+
|
6
8
|
let(:app) { ->(env) { [200, env, env] } }
|
7
|
-
subject { Grape::Middleware::Versioner::AcceptVersionHeader.new(app, **(@options || {})) }
|
8
9
|
|
9
10
|
before do
|
10
11
|
@options = {
|
@@ -3,8 +3,9 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Versioner::Header do
|
6
|
+
subject { described_class.new(app, **(@options || {})) }
|
7
|
+
|
6
8
|
let(:app) { ->(env) { [200, env, env] } }
|
7
|
-
subject { Grape::Middleware::Versioner::Header.new(app, **(@options || {})) }
|
8
9
|
|
9
10
|
before do
|
10
11
|
@options = {
|
@@ -47,7 +48,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
47
48
|
|
48
49
|
it 'is nil if not provided' do
|
49
50
|
status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor')
|
50
|
-
expect(env['api.format']).to
|
51
|
+
expect(env['api.format']).to be nil
|
51
52
|
expect(status).to eq(200)
|
52
53
|
end
|
53
54
|
|
@@ -65,7 +66,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
65
66
|
|
66
67
|
it 'is nil if not provided' do
|
67
68
|
status, _, env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1')
|
68
|
-
expect(env['api.format']).to
|
69
|
+
expect(env['api.format']).to be nil
|
69
70
|
expect(status).to eq(200)
|
70
71
|
end
|
71
72
|
end
|
@@ -90,7 +91,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
90
91
|
.to raise_exception do |exception|
|
91
92
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
92
93
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
93
|
-
expect(exception.status).to
|
94
|
+
expect(exception.status).to be 406
|
94
95
|
expect(exception.message).to include 'API vendor not found'
|
95
96
|
end
|
96
97
|
end
|
@@ -117,7 +118,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
117
118
|
.to raise_exception do |exception|
|
118
119
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
119
120
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
120
|
-
expect(exception.status).to
|
121
|
+
expect(exception.status).to be 406
|
121
122
|
expect(exception.message).to include('API vendor not found')
|
122
123
|
end
|
123
124
|
end
|
@@ -145,7 +146,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
145
146
|
expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last }.to raise_exception do |exception|
|
146
147
|
expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader)
|
147
148
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
148
|
-
expect(exception.status).to
|
149
|
+
expect(exception.status).to be 406
|
149
150
|
expect(exception.message).to include('API version not found')
|
150
151
|
end
|
151
152
|
end
|
@@ -178,7 +179,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
178
179
|
expect { subject.call({}).last }.to raise_exception do |exception|
|
179
180
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
180
181
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
181
|
-
expect(exception.status).to
|
182
|
+
expect(exception.status).to be 406
|
182
183
|
expect(exception.message).to include('Accept header must be set.')
|
183
184
|
end
|
184
185
|
end
|
@@ -187,7 +188,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
187
188
|
expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
|
188
189
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
189
190
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
190
|
-
expect(exception.status).to
|
191
|
+
expect(exception.status).to be 406
|
191
192
|
expect(exception.message).to include('Accept header must be set.')
|
192
193
|
end
|
193
194
|
end
|
@@ -208,7 +209,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
208
209
|
expect { subject.call({}).last }.to raise_exception do |exception|
|
209
210
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
210
211
|
expect(exception.headers).to eql({})
|
211
|
-
expect(exception.status).to
|
212
|
+
expect(exception.status).to be 406
|
212
213
|
expect(exception.message).to include('Accept header must be set.')
|
213
214
|
end
|
214
215
|
end
|
@@ -218,7 +219,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
218
219
|
.to raise_exception do |exception|
|
219
220
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
220
221
|
expect(exception.headers).to eql({})
|
221
|
-
expect(exception.status).to
|
222
|
+
expect(exception.status).to be 406
|
222
223
|
expect(exception.message).to include('API vendor or version not found.')
|
223
224
|
end
|
224
225
|
end
|
@@ -227,7 +228,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
227
228
|
expect { subject.call('HTTP_ACCEPT' => '').last }.to raise_exception do |exception|
|
228
229
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
229
230
|
expect(exception.headers).to eql({})
|
230
|
-
expect(exception.status).to
|
231
|
+
expect(exception.status).to be 406
|
231
232
|
expect(exception.message).to include('Accept header must be set.')
|
232
233
|
end
|
233
234
|
end
|
@@ -237,7 +238,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
237
238
|
.to raise_exception do |exception|
|
238
239
|
expect(exception).to be_a(Grape::Exceptions::InvalidAcceptHeader)
|
239
240
|
expect(exception.headers).to eql({})
|
240
|
-
expect(exception.status).to
|
241
|
+
expect(exception.status).to be 406
|
241
242
|
expect(exception.message).to include('API vendor or version not found.')
|
242
243
|
end
|
243
244
|
end
|
@@ -264,7 +265,7 @@ describe Grape::Middleware::Versioner::Header do
|
|
264
265
|
expect { subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json') }.to raise_exception do |exception|
|
265
266
|
expect(exception).to be_a(Grape::Exceptions::InvalidVersionHeader)
|
266
267
|
expect(exception.headers).to eql('X-Cascade' => 'pass')
|
267
|
-
expect(exception.status).to
|
268
|
+
expect(exception.status).to be 406
|
268
269
|
expect(exception.message).to include('API version not found')
|
269
270
|
end
|
270
271
|
end
|
@@ -3,9 +3,10 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Versioner::Param do
|
6
|
+
subject { described_class.new(app, **options) }
|
7
|
+
|
6
8
|
let(:app) { ->(env) { [200, env, env['api.version']] } }
|
7
9
|
let(:options) { {} }
|
8
|
-
subject { Grape::Middleware::Versioner::Param.new(app, **options) }
|
9
10
|
|
10
11
|
it 'sets the API version based on the default param (apiver)' do
|
11
12
|
env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
|
@@ -26,10 +27,12 @@ describe Grape::Middleware::Versioner::Param do
|
|
26
27
|
|
27
28
|
context 'with specified parameter name' do
|
28
29
|
let(:options) { { version_options: { parameter: 'v' } } }
|
30
|
+
|
29
31
|
it 'sets the API version based on the custom parameter name' do
|
30
32
|
env = Rack::MockRequest.env_for('/awesome', params: { 'v' => 'v1' })
|
31
33
|
expect(subject.call(env)[1]['api.version']).to eq('v1')
|
32
34
|
end
|
35
|
+
|
33
36
|
it 'does not set the API version based on the default param' do
|
34
37
|
env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
|
35
38
|
expect(subject.call(env)[1]['api.version']).to be_nil
|
@@ -38,10 +41,12 @@ describe Grape::Middleware::Versioner::Param do
|
|
38
41
|
|
39
42
|
context 'with specified versions' do
|
40
43
|
let(:options) { { versions: %w[v1 v2] } }
|
44
|
+
|
41
45
|
it 'throws an error if a non-allowed version is specified' do
|
42
46
|
env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v3' })
|
43
47
|
expect(catch(:error) { subject.call(env) }[:status]).to eq(404)
|
44
48
|
end
|
49
|
+
|
45
50
|
it 'allows versions that have been specified' do
|
46
51
|
env = Rack::MockRequest.env_for('/awesome', params: { 'apiver' => 'v1' })
|
47
52
|
expect(subject.call(env)[1]['api.version']).to eq('v1')
|
@@ -55,6 +60,7 @@ describe Grape::Middleware::Versioner::Param do
|
|
55
60
|
version_options: { using: :header }
|
56
61
|
}
|
57
62
|
end
|
63
|
+
|
58
64
|
it 'returns a 200 (matches the first version found)' do
|
59
65
|
env = Rack::MockRequest.env_for('/awesome', params: {})
|
60
66
|
expect(subject.call(env).first).to eq(200)
|
@@ -3,9 +3,10 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe Grape::Middleware::Versioner::Path do
|
6
|
+
subject { described_class.new(app, **options) }
|
7
|
+
|
6
8
|
let(:app) { ->(env) { [200, env, env['api.version']] } }
|
7
9
|
let(:options) { {} }
|
8
|
-
subject { Grape::Middleware::Versioner::Path.new(app, **options) }
|
9
10
|
|
10
11
|
it 'sets the API version based on the first path' do
|
11
12
|
expect(subject.call('PATH_INFO' => '/v1/awesome').last).to eq('v1')
|
@@ -21,6 +22,7 @@ describe Grape::Middleware::Versioner::Path do
|
|
21
22
|
|
22
23
|
context 'with a pattern' do
|
23
24
|
let(:options) { { pattern: /v./i } }
|
25
|
+
|
24
26
|
it 'sets the version if it matches' do
|
25
27
|
expect(subject.call('PATH_INFO' => '/v1/awesome').last).to eq('v1')
|
26
28
|
end
|
@@ -46,6 +48,7 @@ describe Grape::Middleware::Versioner::Path do
|
|
46
48
|
|
47
49
|
context 'with prefix, but requested version is not matched' do
|
48
50
|
let(:options) { { prefix: '/v1', pattern: /v./i } }
|
51
|
+
|
49
52
|
it 'recognizes potential version' do
|
50
53
|
expect(subject.call('PATH_INFO' => '/v3/foo').last).to eq('v3')
|
51
54
|
end
|
@@ -53,6 +56,7 @@ describe Grape::Middleware::Versioner::Path do
|
|
53
56
|
|
54
57
|
context 'with mount path' do
|
55
58
|
let(:options) { { mount_path: '/mounted', versions: [:v1] } }
|
59
|
+
|
56
60
|
it 'recognizes potential version' do
|
57
61
|
expect(subject.call('PATH_INFO' => '/mounted/v1/foo').last).to eq('v1')
|
58
62
|
end
|
data/spec/grape/parser_spec.rb
CHANGED
@@ -26,6 +26,7 @@ describe Grape::Parser do
|
|
26
26
|
|
27
27
|
context 'with :parsers option' do
|
28
28
|
let(:parsers) { { customized: Class.new } }
|
29
|
+
|
29
30
|
it 'includes passed :parsers values' do
|
30
31
|
expect(subject.parsers(parsers: parsers)).to include(parsers)
|
31
32
|
end
|
@@ -33,7 +34,9 @@ describe Grape::Parser do
|
|
33
34
|
|
34
35
|
context 'with added parser by using `register` keyword' do
|
35
36
|
let(:added_parser) { Class.new }
|
37
|
+
|
36
38
|
before { subject.register :added, added_parser }
|
39
|
+
|
37
40
|
it 'includes added parser' do
|
38
41
|
expect(subject.parsers(**{})).to include(added: added_parser)
|
39
42
|
end
|
@@ -54,6 +57,7 @@ describe Grape::Parser do
|
|
54
57
|
|
55
58
|
context 'when parser is available' do
|
56
59
|
before { subject.register :customized_json, Grape::Parser::Json }
|
60
|
+
|
57
61
|
it 'returns registered parser if available' do
|
58
62
|
expect(subject.parser_for(:customized_json)).to eq(Grape::Parser::Json)
|
59
63
|
end
|
data/spec/grape/path_spec.rb
CHANGED
@@ -6,63 +6,63 @@ module Grape
|
|
6
6
|
describe Path do
|
7
7
|
describe '#initialize' do
|
8
8
|
it 'remembers the path' do
|
9
|
-
path =
|
9
|
+
path = described_class.new('/:id', anything, anything)
|
10
10
|
expect(path.raw_path).to eql('/:id')
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'remembers the namespace' do
|
14
|
-
path =
|
14
|
+
path = described_class.new(anything, '/users', anything)
|
15
15
|
expect(path.namespace).to eql('/users')
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'remebers the settings' do
|
19
|
-
path =
|
19
|
+
path = described_class.new(anything, anything, foo: 'bar')
|
20
20
|
expect(path.settings).to eql(foo: 'bar')
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
describe '#mount_path' do
|
25
25
|
it 'is nil when no mount path setting exists' do
|
26
|
-
path =
|
26
|
+
path = described_class.new(anything, anything, {})
|
27
27
|
expect(path.mount_path).to be_nil
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'is nil when the mount path is nil' do
|
31
|
-
path =
|
31
|
+
path = described_class.new(anything, anything, mount_path: nil)
|
32
32
|
expect(path.mount_path).to be_nil
|
33
33
|
end
|
34
34
|
|
35
35
|
it 'splits the mount path' do
|
36
|
-
path =
|
36
|
+
path = described_class.new(anything, anything, mount_path: %w[foo bar])
|
37
37
|
expect(path.mount_path).to eql(%w[foo bar])
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
describe '#root_prefix' do
|
42
42
|
it 'is nil when no root prefix setting exists' do
|
43
|
-
path =
|
43
|
+
path = described_class.new(anything, anything, {})
|
44
44
|
expect(path.root_prefix).to be_nil
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'is nil when the mount path is nil' do
|
48
|
-
path =
|
48
|
+
path = described_class.new(anything, anything, root_prefix: nil)
|
49
49
|
expect(path.root_prefix).to be_nil
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'splits the mount path' do
|
53
|
-
path =
|
53
|
+
path = described_class.new(anything, anything, root_prefix: 'hello/world')
|
54
54
|
expect(path.root_prefix).to eql(%w[hello world])
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
describe '#uses_path_versioning?' do
|
59
59
|
it 'is false when the version setting is nil' do
|
60
|
-
path =
|
60
|
+
path = described_class.new(anything, anything, version: nil)
|
61
61
|
expect(path.uses_path_versioning?).to be false
|
62
62
|
end
|
63
63
|
|
64
64
|
it 'is false when the version option is header' do
|
65
|
-
path =
|
65
|
+
path = described_class.new(
|
66
66
|
anything,
|
67
67
|
anything,
|
68
68
|
version: 'v1',
|
@@ -73,7 +73,7 @@ module Grape
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it 'is true when the version option is path' do
|
76
|
-
path =
|
76
|
+
path = described_class.new(
|
77
77
|
anything,
|
78
78
|
anything,
|
79
79
|
version: 'v1',
|
@@ -86,44 +86,44 @@ module Grape
|
|
86
86
|
|
87
87
|
describe '#namespace?' do
|
88
88
|
it 'is false when the namespace is nil' do
|
89
|
-
path =
|
90
|
-
expect(path
|
89
|
+
path = described_class.new(anything, nil, anything)
|
90
|
+
expect(path).not_to be_namespace
|
91
91
|
end
|
92
92
|
|
93
93
|
it 'is false when the namespace starts with whitespace' do
|
94
|
-
path =
|
95
|
-
expect(path
|
94
|
+
path = described_class.new(anything, ' /foo', anything)
|
95
|
+
expect(path).not_to be_namespace
|
96
96
|
end
|
97
97
|
|
98
98
|
it 'is false when the namespace is the root path' do
|
99
|
-
path =
|
99
|
+
path = described_class.new(anything, '/', anything)
|
100
100
|
expect(path.namespace?).to be false
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'is true otherwise' do
|
104
|
-
path =
|
104
|
+
path = described_class.new(anything, '/world', anything)
|
105
105
|
expect(path.namespace?).to be true
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
describe '#path?' do
|
110
110
|
it 'is false when the path is nil' do
|
111
|
-
path =
|
112
|
-
expect(path
|
111
|
+
path = described_class.new(nil, anything, anything)
|
112
|
+
expect(path).not_to be_path
|
113
113
|
end
|
114
114
|
|
115
115
|
it 'is false when the path starts with whitespace' do
|
116
|
-
path =
|
117
|
-
expect(path
|
116
|
+
path = described_class.new(' /foo', anything, anything)
|
117
|
+
expect(path).not_to be_path
|
118
118
|
end
|
119
119
|
|
120
120
|
it 'is false when the path is the root path' do
|
121
|
-
path =
|
121
|
+
path = described_class.new('/', anything, anything)
|
122
122
|
expect(path.path?).to be false
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'is true otherwise' do
|
126
|
-
path =
|
126
|
+
path = described_class.new('/hello', anything, anything)
|
127
127
|
expect(path.path?).to be true
|
128
128
|
end
|
129
129
|
end
|
@@ -131,24 +131,24 @@ module Grape
|
|
131
131
|
describe '#path' do
|
132
132
|
context 'mount_path' do
|
133
133
|
it 'is not included when it is nil' do
|
134
|
-
path =
|
134
|
+
path = described_class.new(nil, nil, mount_path: '/foo/bar')
|
135
135
|
expect(path.path).to eql '/foo/bar'
|
136
136
|
end
|
137
137
|
|
138
138
|
it 'is included when it is not nil' do
|
139
|
-
path =
|
139
|
+
path = described_class.new(nil, nil, {})
|
140
140
|
expect(path.path).to eql('/')
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
144
|
context 'root_prefix' do
|
145
145
|
it 'is not included when it is nil' do
|
146
|
-
path =
|
146
|
+
path = described_class.new(nil, nil, {})
|
147
147
|
expect(path.path).to eql('/')
|
148
148
|
end
|
149
149
|
|
150
150
|
it 'is included after the mount path' do
|
151
|
-
path =
|
151
|
+
path = described_class.new(
|
152
152
|
nil,
|
153
153
|
nil,
|
154
154
|
mount_path: '/foo',
|
@@ -160,7 +160,7 @@ module Grape
|
|
160
160
|
end
|
161
161
|
|
162
162
|
it 'uses the namespace after the mount path and root prefix' do
|
163
|
-
path =
|
163
|
+
path = described_class.new(
|
164
164
|
nil,
|
165
165
|
'namespace',
|
166
166
|
mount_path: '/foo',
|
@@ -171,7 +171,7 @@ module Grape
|
|
171
171
|
end
|
172
172
|
|
173
173
|
it 'uses the raw path after the namespace' do
|
174
|
-
path =
|
174
|
+
path = described_class.new(
|
175
175
|
'raw_path',
|
176
176
|
'namespace',
|
177
177
|
mount_path: '/foo',
|
@@ -185,9 +185,9 @@ module Grape
|
|
185
185
|
describe '#suffix' do
|
186
186
|
context 'when using a specific format' do
|
187
187
|
it 'accepts specified format' do
|
188
|
-
path =
|
189
|
-
allow(path).to receive(:uses_specific_format?)
|
190
|
-
allow(path).to receive(:settings)
|
188
|
+
path = described_class.new(nil, nil, {})
|
189
|
+
allow(path).to receive(:uses_specific_format?).and_return(true)
|
190
|
+
allow(path).to receive(:settings).and_return({ format: :json })
|
191
191
|
|
192
192
|
expect(path.suffix).to eql('(.json)')
|
193
193
|
end
|
@@ -195,9 +195,9 @@ module Grape
|
|
195
195
|
|
196
196
|
context 'when path versioning is used' do
|
197
197
|
it "includes a '/'" do
|
198
|
-
path =
|
199
|
-
allow(path).to receive(:uses_specific_format?)
|
200
|
-
allow(path).to receive(:uses_path_versioning?)
|
198
|
+
path = described_class.new(nil, nil, {})
|
199
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
200
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
201
201
|
|
202
202
|
expect(path.suffix).to eql('(/.:format)')
|
203
203
|
end
|
@@ -205,25 +205,25 @@ module Grape
|
|
205
205
|
|
206
206
|
context 'when path versioning is not used' do
|
207
207
|
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?)
|
208
|
+
path = described_class.new(nil, 'namespace', {})
|
209
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
210
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
211
211
|
|
212
212
|
expect(path.suffix).to eql('(.:format)')
|
213
213
|
end
|
214
214
|
|
215
215
|
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?)
|
216
|
+
path = described_class.new('/path', nil, {})
|
217
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
218
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
219
219
|
|
220
220
|
expect(path.suffix).to eql('(.:format)')
|
221
221
|
end
|
222
222
|
|
223
223
|
it "includes a '/' otherwise" do
|
224
|
-
path =
|
225
|
-
allow(path).to receive(:uses_specific_format?)
|
226
|
-
allow(path).to receive(:uses_path_versioning?)
|
224
|
+
path = described_class.new(nil, nil, {})
|
225
|
+
allow(path).to receive(:uses_specific_format?).and_return(false)
|
226
|
+
allow(path).to receive(:uses_path_versioning?).and_return(true)
|
227
227
|
|
228
228
|
expect(path.suffix).to eql('(/.:format)')
|
229
229
|
end
|
@@ -232,19 +232,19 @@ module Grape
|
|
232
232
|
|
233
233
|
describe '#path_with_suffix' do
|
234
234
|
it 'combines the path and suffix' do
|
235
|
-
path =
|
236
|
-
allow(path).to receive(:path)
|
237
|
-
allow(path).to receive(:suffix)
|
235
|
+
path = described_class.new(nil, nil, {})
|
236
|
+
allow(path).to receive(:path).and_return('/the/path')
|
237
|
+
allow(path).to receive(:suffix).and_return('suffix')
|
238
238
|
|
239
239
|
expect(path.path_with_suffix).to eql('/the/pathsuffix')
|
240
240
|
end
|
241
241
|
|
242
242
|
context 'when using a specific format' do
|
243
243
|
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)
|
244
|
+
path = described_class.new(nil, nil, {})
|
245
|
+
allow(path).to receive(:path).and_return('/the/path')
|
246
|
+
allow(path).to receive(:uses_specific_format?).and_return(true)
|
247
|
+
allow(path).to receive(:settings).and_return({ format: :json })
|
248
248
|
|
249
249
|
expect(path.path_with_suffix).to eql('/the/path(.json)')
|
250
250
|
end
|
@@ -19,18 +19,18 @@ module Grape
|
|
19
19
|
end
|
20
20
|
|
21
21
|
describe Presenter do
|
22
|
+
subject { PresenterSpec::Dummy.new }
|
23
|
+
|
22
24
|
describe 'represent' do
|
23
25
|
let(:object_mock) do
|
24
26
|
Object.new
|
25
27
|
end
|
26
28
|
|
27
29
|
it 'represent object' do
|
28
|
-
expect(
|
30
|
+
expect(described_class.represent(object_mock)).to eq object_mock
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
subject { PresenterSpec::Dummy.new }
|
33
|
-
|
34
34
|
describe 'present' do
|
35
35
|
let(:hash_mock) do
|
36
36
|
{ key: :value }
|
@@ -38,8 +38,9 @@ module Grape
|
|
38
38
|
|
39
39
|
describe 'instance' do
|
40
40
|
before do
|
41
|
-
subject.present hash_mock, with:
|
41
|
+
subject.present hash_mock, with: described_class
|
42
42
|
end
|
43
|
+
|
43
44
|
it 'presents dummy hash' do
|
44
45
|
expect(subject.body).to eq hash_mock
|
45
46
|
end
|
@@ -56,8 +57,8 @@ module Grape
|
|
56
57
|
|
57
58
|
describe 'instance' do
|
58
59
|
before do
|
59
|
-
subject.present hash_mock1, with:
|
60
|
-
subject.present hash_mock2, with:
|
60
|
+
subject.present hash_mock1, with: described_class
|
61
|
+
subject.present hash_mock2, with: described_class
|
61
62
|
end
|
62
63
|
|
63
64
|
it 'presents both dummy presenter' do
|