grape 0.3.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of grape might be problematic. Click here for more details.
- checksums.yaml +15 -0
- data/.gitignore +8 -0
- data/.rubocop.yml +70 -0
- data/.travis.yml +7 -6
- data/CHANGELOG.md +134 -4
- data/CONTRIBUTING.md +118 -0
- data/Gemfile +5 -2
- data/README.md +551 -116
- data/RELEASING.md +105 -0
- data/Rakefile +29 -8
- data/UPGRADING.md +124 -0
- data/grape.gemspec +3 -3
- data/lib/grape/api.rb +207 -88
- data/lib/grape/cookies.rb +4 -8
- data/lib/grape/endpoint.rb +198 -144
- data/lib/grape/error_formatter/base.rb +5 -7
- data/lib/grape/error_formatter/json.rb +3 -5
- data/lib/grape/error_formatter/txt.rb +1 -3
- data/lib/grape/error_formatter/xml.rb +4 -6
- data/lib/grape/exceptions/base.rb +9 -9
- data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
- data/lib/grape/exceptions/invalid_formatter.rb +1 -4
- data/lib/grape/exceptions/invalid_versioner_option.rb +1 -5
- data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -6
- data/lib/grape/exceptions/missing_mime_type.rb +1 -5
- data/lib/grape/exceptions/missing_option.rb +1 -4
- data/lib/grape/exceptions/missing_vendor_option.rb +1 -4
- data/lib/grape/exceptions/unknown_options.rb +1 -5
- data/lib/grape/exceptions/unknown_validator.rb +1 -3
- data/lib/grape/exceptions/validation.rb +13 -3
- data/lib/grape/exceptions/validation_errors.rb +43 -0
- data/lib/grape/formatter/base.rb +5 -7
- data/lib/grape/formatter/json.rb +0 -3
- data/lib/grape/formatter/serializable_hash.rb +15 -15
- data/lib/grape/formatter/txt.rb +0 -2
- data/lib/grape/formatter/xml.rb +0 -2
- data/lib/grape/http/request.rb +26 -0
- data/lib/grape/locale/en.yml +8 -5
- data/lib/grape/middleware/auth/base.rb +30 -0
- data/lib/grape/middleware/auth/basic.rb +3 -20
- data/lib/grape/middleware/auth/digest.rb +2 -19
- data/lib/grape/middleware/auth/oauth2.rb +31 -24
- data/lib/grape/middleware/base.rb +7 -7
- data/lib/grape/middleware/error.rb +36 -22
- data/lib/grape/middleware/filter.rb +3 -3
- data/lib/grape/middleware/formatter.rb +99 -61
- data/lib/grape/middleware/globals.rb +13 -0
- data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
- data/lib/grape/middleware/versioner/header.rb +22 -16
- data/lib/grape/middleware/versioner/param.rb +9 -11
- data/lib/grape/middleware/versioner/path.rb +10 -13
- data/lib/grape/middleware/versioner.rb +3 -1
- data/lib/grape/namespace.rb +23 -0
- data/lib/grape/parser/base.rb +3 -5
- data/lib/grape/parser/json.rb +0 -2
- data/lib/grape/parser/xml.rb +0 -2
- data/lib/grape/path.rb +70 -0
- data/lib/grape/route.rb +10 -6
- data/lib/grape/util/content_types.rb +2 -1
- data/lib/grape/util/deep_merge.rb +5 -5
- data/lib/grape/util/hash_stack.rb +13 -2
- data/lib/grape/validations/coerce.rb +11 -10
- data/lib/grape/validations/default.rb +25 -0
- data/lib/grape/validations/presence.rb +7 -3
- data/lib/grape/validations/regexp.rb +2 -5
- data/lib/grape/validations/values.rb +17 -0
- data/lib/grape/validations.rb +161 -54
- data/lib/grape/version.rb +1 -1
- data/lib/grape.rb +19 -4
- data/spec/grape/api_spec.rb +897 -268
- data/spec/grape/endpoint_spec.rb +283 -66
- data/spec/grape/entity_spec.rb +132 -29
- data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
- data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
- data/spec/grape/middleware/auth/basic_spec.rb +8 -8
- data/spec/grape/middleware/auth/digest_spec.rb +5 -5
- data/spec/grape/middleware/auth/oauth2_spec.rb +81 -36
- data/spec/grape/middleware/base_spec.rb +8 -13
- data/spec/grape/middleware/error_spec.rb +13 -17
- data/spec/grape/middleware/exception_spec.rb +47 -27
- data/spec/grape/middleware/formatter_spec.rb +103 -41
- data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
- data/spec/grape/middleware/versioner/header_spec.rb +76 -51
- data/spec/grape/middleware/versioner/param_spec.rb +18 -18
- data/spec/grape/middleware/versioner/path_spec.rb +6 -6
- data/spec/grape/middleware/versioner_spec.rb +5 -2
- data/spec/grape/path_spec.rb +229 -0
- data/spec/grape/util/hash_stack_spec.rb +31 -32
- data/spec/grape/validations/coerce_spec.rb +116 -51
- data/spec/grape/validations/default_spec.rb +123 -0
- data/spec/grape/validations/presence_spec.rb +42 -44
- data/spec/grape/validations/regexp_spec.rb +9 -9
- data/spec/grape/validations/values_spec.rb +138 -0
- data/spec/grape/validations/zh-CN.yml +4 -3
- data/spec/grape/validations_spec.rb +681 -48
- data/spec/shared/versioning_examples.rb +22 -6
- data/spec/spec_helper.rb +3 -2
- data/spec/support/basic_auth_encode_helpers.rb +0 -1
- data/spec/support/content_type_helpers.rb +11 -0
- data/spec/support/versioned_helpers.rb +13 -5
- metadata +34 -84
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Grape::Middleware::Versioner::Header do
|
4
|
-
let(:app) { lambda{|env| [200, env, env]} }
|
4
|
+
let(:app) { lambda { |env| [200, env, env] } }
|
5
5
|
subject { Grape::Middleware::Versioner::Header.new(app, @options || {}) }
|
6
6
|
|
7
7
|
before do
|
8
8
|
@options = {
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
9
|
+
version_options: {
|
10
|
+
using: :header,
|
11
|
+
vendor: 'vendor',
|
12
12
|
},
|
13
13
|
}
|
14
14
|
end
|
@@ -49,10 +49,10 @@ describe Grape::Middleware::Versioner::Header do
|
|
49
49
|
status.should == 200
|
50
50
|
end
|
51
51
|
|
52
|
-
[
|
53
|
-
context 'when version is set to #{version{' do
|
52
|
+
['v1', :v1].each do |version|
|
53
|
+
context 'when version is set to #{version{ ' do
|
54
54
|
before do
|
55
|
-
@options[:versions] = [
|
55
|
+
@options[:versions] = [version]
|
56
56
|
end
|
57
57
|
|
58
58
|
it 'is set' do
|
@@ -85,12 +85,12 @@ describe Grape::Middleware::Versioner::Header do
|
|
85
85
|
|
86
86
|
it 'fails with 406 Not Acceptable if vendor is invalid' do
|
87
87
|
expect {
|
88
|
-
|
88
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last
|
89
89
|
}.to throw_symbol(
|
90
90
|
:error,
|
91
|
-
:
|
92
|
-
:
|
93
|
-
:
|
91
|
+
status: 406,
|
92
|
+
headers: { 'X-Cascade' => 'pass' },
|
93
|
+
message: 'API vendor or version not found.'
|
94
94
|
)
|
95
95
|
end
|
96
96
|
|
@@ -113,12 +113,12 @@ describe Grape::Middleware::Versioner::Header do
|
|
113
113
|
|
114
114
|
it 'fails with 406 Not Acceptable if vendor is invalid' do
|
115
115
|
expect {
|
116
|
-
|
116
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last
|
117
117
|
}.to throw_symbol(
|
118
118
|
:error,
|
119
|
-
:
|
120
|
-
:
|
121
|
-
:
|
119
|
+
status: 406,
|
120
|
+
headers: { 'X-Cascade' => 'pass' },
|
121
|
+
message: 'API vendor or version not found.'
|
122
122
|
)
|
123
123
|
end
|
124
124
|
end
|
@@ -143,12 +143,12 @@ describe Grape::Middleware::Versioner::Header do
|
|
143
143
|
|
144
144
|
it 'fails with 406 Not Acceptable if version is invalid' do
|
145
145
|
expect {
|
146
|
-
|
146
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last
|
147
147
|
}.to throw_symbol(
|
148
148
|
:error,
|
149
|
-
:
|
150
|
-
:
|
151
|
-
:
|
149
|
+
status: 406,
|
150
|
+
headers: { 'X-Cascade' => 'pass' },
|
151
|
+
message: 'API vendor or version not found.'
|
152
152
|
)
|
153
153
|
end
|
154
154
|
end
|
@@ -172,45 +172,45 @@ describe Grape::Middleware::Versioner::Header do
|
|
172
172
|
|
173
173
|
it 'fails with 406 Not Acceptable if header is not set' do
|
174
174
|
expect {
|
175
|
-
|
175
|
+
subject.call({}).last
|
176
176
|
}.to throw_symbol(
|
177
177
|
:error,
|
178
|
-
:
|
179
|
-
:
|
180
|
-
:
|
178
|
+
status: 406,
|
179
|
+
headers: { 'X-Cascade' => 'pass' },
|
180
|
+
message: 'Accept header must be set.'
|
181
181
|
)
|
182
182
|
end
|
183
183
|
|
184
184
|
it 'fails with 406 Not Acceptable if header is empty' do
|
185
185
|
expect {
|
186
|
-
|
186
|
+
subject.call('HTTP_ACCEPT' => '').last
|
187
187
|
}.to throw_symbol(
|
188
188
|
:error,
|
189
|
-
:
|
190
|
-
:
|
191
|
-
:
|
189
|
+
status: 406,
|
190
|
+
headers: { 'X-Cascade' => 'pass' },
|
191
|
+
message: 'Accept header must be set.'
|
192
192
|
)
|
193
193
|
end
|
194
194
|
|
195
195
|
it 'fails with 406 Not Acceptable if type is a range' do
|
196
196
|
expect {
|
197
|
-
|
197
|
+
subject.call('HTTP_ACCEPT' => '*/*').last
|
198
198
|
}.to throw_symbol(
|
199
199
|
:error,
|
200
|
-
:
|
201
|
-
:
|
202
|
-
:
|
200
|
+
status: 406,
|
201
|
+
headers: { 'X-Cascade' => 'pass' },
|
202
|
+
message: 'Accept header must not contain ranges ("*").'
|
203
203
|
)
|
204
204
|
end
|
205
205
|
|
206
206
|
it 'fails with 406 Not Acceptable if subtype is a range' do
|
207
207
|
expect {
|
208
|
-
|
208
|
+
subject.call('HTTP_ACCEPT' => 'application/*').last
|
209
209
|
}.to throw_symbol(
|
210
210
|
:error,
|
211
|
-
:
|
212
|
-
:
|
213
|
-
:
|
211
|
+
status: 406,
|
212
|
+
headers: { 'X-Cascade' => 'pass' },
|
213
|
+
message: 'Accept header must not contain ranges ("*").'
|
214
214
|
)
|
215
215
|
end
|
216
216
|
|
@@ -228,45 +228,45 @@ describe Grape::Middleware::Versioner::Header do
|
|
228
228
|
|
229
229
|
it 'fails with 406 Not Acceptable if header is not set' do
|
230
230
|
expect {
|
231
|
-
|
231
|
+
subject.call({}).last
|
232
232
|
}.to throw_symbol(
|
233
233
|
:error,
|
234
|
-
:
|
235
|
-
:
|
236
|
-
:
|
234
|
+
status: 406,
|
235
|
+
headers: {},
|
236
|
+
message: 'Accept header must be set.'
|
237
237
|
)
|
238
238
|
end
|
239
239
|
|
240
240
|
it 'fails with 406 Not Acceptable if header is empty' do
|
241
241
|
expect {
|
242
|
-
|
242
|
+
subject.call('HTTP_ACCEPT' => '').last
|
243
243
|
}.to throw_symbol(
|
244
244
|
:error,
|
245
|
-
:
|
246
|
-
:
|
247
|
-
:
|
245
|
+
status: 406,
|
246
|
+
headers: {},
|
247
|
+
message: 'Accept header must be set.'
|
248
248
|
)
|
249
249
|
end
|
250
250
|
|
251
251
|
it 'fails with 406 Not Acceptable if type is a range' do
|
252
252
|
expect {
|
253
|
-
|
253
|
+
subject.call('HTTP_ACCEPT' => '*/*').last
|
254
254
|
}.to throw_symbol(
|
255
255
|
:error,
|
256
|
-
:
|
257
|
-
:
|
258
|
-
:
|
256
|
+
status: 406,
|
257
|
+
headers: {},
|
258
|
+
message: 'Accept header must not contain ranges ("*").'
|
259
259
|
)
|
260
260
|
end
|
261
261
|
|
262
262
|
it 'fails with 406 Not Acceptable if subtype is a range' do
|
263
263
|
expect {
|
264
|
-
|
264
|
+
subject.call('HTTP_ACCEPT' => 'application/*').last
|
265
265
|
}.to throw_symbol(
|
266
266
|
:error,
|
267
|
-
:
|
268
|
-
:
|
269
|
-
:
|
267
|
+
status: 406,
|
268
|
+
headers: {},
|
269
|
+
message: 'Accept header must not contain ranges ("*").'
|
270
270
|
)
|
271
271
|
end
|
272
272
|
|
@@ -274,4 +274,29 @@ describe Grape::Middleware::Versioner::Header do
|
|
274
274
|
subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json').first.should == 200
|
275
275
|
end
|
276
276
|
end
|
277
|
+
|
278
|
+
context 'when multiple versions are specified' do
|
279
|
+
before do
|
280
|
+
@options[:versions] = ['v1', 'v2']
|
281
|
+
end
|
282
|
+
|
283
|
+
it 'succeeds with v1' do
|
284
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v1+json').first.should == 200
|
285
|
+
end
|
286
|
+
|
287
|
+
it 'succeeds with v2' do
|
288
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').first.should == 200
|
289
|
+
end
|
290
|
+
|
291
|
+
it 'fails with another version' do
|
292
|
+
expect {
|
293
|
+
subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v3+json')
|
294
|
+
}.to throw_symbol(
|
295
|
+
:error,
|
296
|
+
status: 406,
|
297
|
+
headers: { 'X-Cascade' => 'pass' },
|
298
|
+
message: 'API vendor or version not found.'
|
299
|
+
)
|
300
|
+
end
|
301
|
+
end
|
277
302
|
end
|
@@ -2,16 +2,17 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Grape::Middleware::Versioner::Param do
|
4
4
|
|
5
|
-
let(:app) { lambda{|env| [200, env, env['api.version']]} }
|
5
|
+
let(:app) { lambda { |env| [200, env, env['api.version']] } }
|
6
6
|
subject { Grape::Middleware::Versioner::Param.new(app, @options || {}) }
|
7
7
|
|
8
8
|
it 'sets the API version based on the default param (apiver)' do
|
9
|
-
env = Rack::MockRequest.env_for("/awesome",
|
9
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "apiver" => "v1" })
|
10
10
|
subject.call(env)[1]["api.version"].should == 'v1'
|
11
11
|
end
|
12
12
|
|
13
|
-
it 'cuts (only) the version out of the params', :
|
14
|
-
env = Rack::MockRequest.env_for("/awesome",
|
13
|
+
it 'cuts (only) the version out of the params', focus: true do
|
14
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "apiver" => "v1", "other_param" => "5" })
|
15
|
+
env['rack.request.query_hash'] = Rack::Utils.parse_nested_query(env['QUERY_STRING'])
|
15
16
|
subject.call(env)[1]['rack.request.query_hash']["apiver"].should be_nil
|
16
17
|
subject.call(env)[1]['rack.request.query_hash']["other_param"].should == "5"
|
17
18
|
end
|
@@ -22,37 +23,36 @@ describe Grape::Middleware::Versioner::Param do
|
|
22
23
|
end
|
23
24
|
|
24
25
|
context 'with specified parameter name' do
|
25
|
-
before{ @options = {:
|
26
|
+
before { @options = { parameter: 'v' } }
|
26
27
|
it 'sets the API version based on the custom parameter name' do
|
27
|
-
env = Rack::MockRequest.env_for("/awesome",
|
28
|
-
|
28
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "v" => "v1" })
|
29
|
+
subject.call(env)[1]["api.version"].should == "v1"
|
29
30
|
end
|
30
31
|
it 'does not set the API version based on the default param' do
|
31
|
-
env = Rack::MockRequest.env_for("/awesome",
|
32
|
-
|
32
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "apiver" => "v1" })
|
33
|
+
subject.call(env)[1]["api.version"].should be_nil
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
context 'with specified versions' do
|
37
|
-
before{ @options = {:
|
38
|
+
before { @options = { versions: ['v1', 'v2'] } }
|
38
39
|
it 'throws an error if a non-allowed version is specified' do
|
39
|
-
env = Rack::MockRequest.env_for("/awesome",
|
40
|
-
catch(:error){subject.call(env)}[:status].should == 404
|
40
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "apiver" => "v3" })
|
41
|
+
catch(:error) { subject.call(env) }[:status].should == 404
|
41
42
|
end
|
42
|
-
|
43
43
|
it 'allows versions that have been specified' do
|
44
|
-
env = Rack::MockRequest.env_for("/awesome",
|
44
|
+
env = Rack::MockRequest.env_for("/awesome", params: { "apiver" => "v1" })
|
45
45
|
subject.call(env)[1]["api.version"].should == 'v1'
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
it 'returns a 200 when no version is set (matches the first version found)' do
|
50
50
|
@options = {
|
51
|
-
:
|
52
|
-
:
|
51
|
+
versions: ['v1'],
|
52
|
+
version_options: { using: :header }
|
53
53
|
}
|
54
|
-
env = Rack::MockRequest.env_for("/awesome",
|
54
|
+
env = Rack::MockRequest.env_for("/awesome", params: {})
|
55
55
|
subject.call(env).first.should == 200
|
56
56
|
end
|
57
57
|
|
58
|
-
end
|
58
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Grape::Middleware::Versioner::Path do
|
4
|
-
let(:app) { lambda{|env| [200, env, env['api.version']]} }
|
4
|
+
let(:app) { lambda { |env| [200, env, env['api.version']] } }
|
5
5
|
subject { Grape::Middleware::Versioner::Path.new(app, @options || {}) }
|
6
6
|
|
7
7
|
it 'sets the API version based on the first path' do
|
@@ -17,7 +17,7 @@ describe Grape::Middleware::Versioner::Path do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
context 'with a pattern' do
|
20
|
-
before { @options = {:
|
20
|
+
before { @options = { pattern: /v./i } }
|
21
21
|
it 'sets the version if it matches' do
|
22
22
|
subject.call('PATH_INFO' => '/v1/awesome').last.should == 'v1'
|
23
23
|
end
|
@@ -27,12 +27,12 @@ describe Grape::Middleware::Versioner::Path do
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
30
|
-
[
|
30
|
+
[['v1', 'v2'], [:v1, :v2], [:v1, 'v2'], ['v1', :v2]].each do |versions|
|
31
31
|
context 'with specified versions as #{versions}' do
|
32
|
-
before { @options = { :
|
32
|
+
before { @options = { versions: versions } }
|
33
33
|
|
34
34
|
it 'throws an error if a non-allowed version is specified' do
|
35
|
-
catch(:error){subject.call('PATH_INFO' => '/v3/awesome')}[:status].should == 404
|
35
|
+
catch(:error) { subject.call('PATH_INFO' => '/v3/awesome') }[:status].should == 404
|
36
36
|
end
|
37
37
|
|
38
38
|
it 'allows versions that have been specified' do
|
@@ -41,4 +41,4 @@ describe Grape::Middleware::Versioner::Path do
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
end
|
44
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Grape::Middleware::Versioner do
|
4
|
-
|
4
|
+
|
5
5
|
let(:klass) { Grape::Middleware::Versioner }
|
6
6
|
|
7
7
|
it 'recognizes :path' do
|
@@ -16,4 +16,7 @@ describe Grape::Middleware::Versioner do
|
|
16
16
|
klass.using(:param).should == Grape::Middleware::Versioner::Param
|
17
17
|
end
|
18
18
|
|
19
|
-
|
19
|
+
it 'recognizes :accept_version_header' do
|
20
|
+
klass.using(:accept_version_header).should == Grape::Middleware::Versioner::AcceptVersionHeader
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Grape
|
4
|
+
describe Path do
|
5
|
+
|
6
|
+
describe "#initialize" do
|
7
|
+
it "remembers the path" do
|
8
|
+
path = Path.new('/:id', anything, anything)
|
9
|
+
expect(path.raw_path).to eql('/:id')
|
10
|
+
end
|
11
|
+
|
12
|
+
it "remembers the namespace" do
|
13
|
+
path = Path.new(anything, '/users', anything)
|
14
|
+
expect(path.namespace).to eql('/users')
|
15
|
+
end
|
16
|
+
|
17
|
+
it "remebers the settings" do
|
18
|
+
path = Path.new(anything, anything, foo: 'bar')
|
19
|
+
expect(path.settings).to eql(foo: 'bar')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "#mount_path" do
|
24
|
+
it "is nil when no mount path setting exists" do
|
25
|
+
path = Path.new(anything, anything, {})
|
26
|
+
expect(path.mount_path).to be_nil
|
27
|
+
end
|
28
|
+
|
29
|
+
it "is nil when the mount path is nil" do
|
30
|
+
path = Path.new(anything, anything, mount_path: nil)
|
31
|
+
expect(path.mount_path).to be_nil
|
32
|
+
end
|
33
|
+
|
34
|
+
it "splits the mount path" do
|
35
|
+
path = Path.new(anything, anything, mount_path: 'foo/bar')
|
36
|
+
expect(path.mount_path).to eql(['foo', 'bar'])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#root_prefix" do
|
41
|
+
it "is nil when no root prefix setting exists" do
|
42
|
+
path = Path.new(anything, anything, {})
|
43
|
+
expect(path.root_prefix).to be_nil
|
44
|
+
end
|
45
|
+
|
46
|
+
it "is nil when the mount path is nil" do
|
47
|
+
path = Path.new(anything, anything, root_prefix: nil)
|
48
|
+
expect(path.root_prefix).to be_nil
|
49
|
+
end
|
50
|
+
|
51
|
+
it "splits the mount path" do
|
52
|
+
path = Path.new(anything, anything, root_prefix: 'hello/world')
|
53
|
+
expect(path.root_prefix).to eql(['hello', 'world'])
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "#uses_path_versioning?" do
|
58
|
+
it "is false when the version setting is nil" do
|
59
|
+
path = Path.new(anything, anything, version: nil)
|
60
|
+
expect(path.uses_path_versioning?).to be false
|
61
|
+
end
|
62
|
+
|
63
|
+
it "is false when the version option is header" do
|
64
|
+
path = Path.new(
|
65
|
+
anything,
|
66
|
+
anything,
|
67
|
+
version: 'v1',
|
68
|
+
version_options: { using: :header }
|
69
|
+
)
|
70
|
+
|
71
|
+
expect(path.uses_path_versioning?).to be false
|
72
|
+
end
|
73
|
+
|
74
|
+
it "is true when the version option is path" do
|
75
|
+
path = Path.new(
|
76
|
+
anything,
|
77
|
+
anything,
|
78
|
+
version: 'v1',
|
79
|
+
version_options: { using: :path }
|
80
|
+
)
|
81
|
+
|
82
|
+
expect(path.uses_path_versioning?).to be true
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "#has_namespace?" do
|
87
|
+
it "is false when the namespace is nil" do
|
88
|
+
path = Path.new(anything, nil, anything)
|
89
|
+
expect(path).not_to have_namespace
|
90
|
+
end
|
91
|
+
|
92
|
+
it "is false when the namespace starts with whitespace" do
|
93
|
+
path = Path.new(anything, ' /foo', anything)
|
94
|
+
expect(path).not_to have_namespace
|
95
|
+
end
|
96
|
+
|
97
|
+
it "is false when the namespace is the root path" do
|
98
|
+
path = Path.new(anything, '/', anything)
|
99
|
+
expect(path).not_to have_namespace
|
100
|
+
end
|
101
|
+
|
102
|
+
it "is true otherwise" do
|
103
|
+
path = Path.new(anything, '/world', anything)
|
104
|
+
expect(path).to have_namespace
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
describe "#has_path?" do
|
109
|
+
it "is false when the path is nil" do
|
110
|
+
path = Path.new(nil, anything, anything)
|
111
|
+
expect(path).not_to have_path
|
112
|
+
end
|
113
|
+
|
114
|
+
it "is false when the path starts with whitespace" do
|
115
|
+
path = Path.new(' /foo', anything, anything)
|
116
|
+
expect(path).not_to have_path
|
117
|
+
end
|
118
|
+
|
119
|
+
it "is false when the path is the root path" do
|
120
|
+
path = Path.new('/', anything, anything)
|
121
|
+
expect(path).not_to have_path
|
122
|
+
end
|
123
|
+
|
124
|
+
it "is true otherwise" do
|
125
|
+
path = Path.new('/hello', anything, anything)
|
126
|
+
expect(path).to have_path
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
describe "#path" do
|
131
|
+
context "mount_path" do
|
132
|
+
it "is not included when it is nil" do
|
133
|
+
path = Path.new(nil, nil, mount_path: '/foo/bar')
|
134
|
+
expect(path.path).to eql '/foo/bar'
|
135
|
+
end
|
136
|
+
|
137
|
+
it "is included when it is not nil" do
|
138
|
+
path = Path.new(nil, nil, {})
|
139
|
+
expect(path.path).to eql('/')
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context "root_prefix" do
|
144
|
+
it "is not included when it is nil" do
|
145
|
+
path = Path.new(nil, nil, {})
|
146
|
+
expect(path.path).to eql('/')
|
147
|
+
end
|
148
|
+
|
149
|
+
it "is included after the mount path" do
|
150
|
+
path = Path.new(
|
151
|
+
nil,
|
152
|
+
nil,
|
153
|
+
mount_path: '/foo',
|
154
|
+
root_prefix: '/hello'
|
155
|
+
)
|
156
|
+
|
157
|
+
expect(path.path).to eql('/foo/hello')
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
it "uses the namespace after the mount path and root prefix" do
|
162
|
+
path = Path.new(
|
163
|
+
nil,
|
164
|
+
'namespace',
|
165
|
+
mount_path: '/foo',
|
166
|
+
root_prefix: '/hello'
|
167
|
+
)
|
168
|
+
|
169
|
+
expect(path.path).to eql('/foo/hello/namespace')
|
170
|
+
end
|
171
|
+
|
172
|
+
it "uses the raw path after the namespace" do
|
173
|
+
path = Path.new(
|
174
|
+
'raw_path',
|
175
|
+
'namespace',
|
176
|
+
mount_path: '/foo',
|
177
|
+
root_prefix: '/hello'
|
178
|
+
)
|
179
|
+
|
180
|
+
expect(path.path).to eql('/foo/hello/namespace/raw_path')
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "#suffix" do
|
185
|
+
context "when path versioning is used" do
|
186
|
+
it "includes a '/'" do
|
187
|
+
path = Path.new(nil, nil, {})
|
188
|
+
path.stub(:uses_path_versioning?) { true }
|
189
|
+
|
190
|
+
expect(path.suffix).to eql('(/.:format)')
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
context "when path versioning is not used" do
|
195
|
+
it "does not include a '/' when the path has a namespace" do
|
196
|
+
path = Path.new(nil, 'namespace', {})
|
197
|
+
path.stub(:uses_path_versioning?) { true }
|
198
|
+
|
199
|
+
expect(path.suffix).to eql('(.:format)')
|
200
|
+
end
|
201
|
+
|
202
|
+
it "does not include a '/' when the path has a path" do
|
203
|
+
path = Path.new('/path', nil, {})
|
204
|
+
path.stub(:uses_path_versioning?) { true }
|
205
|
+
|
206
|
+
expect(path.suffix).to eql('(.:format)')
|
207
|
+
end
|
208
|
+
|
209
|
+
it "includes a '/' otherwise" do
|
210
|
+
path = Path.new(nil, nil, {})
|
211
|
+
path.stub(:uses_path_versioning?) { true }
|
212
|
+
|
213
|
+
expect(path.suffix).to eql('(/.:format)')
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
describe "#path_with_suffix" do
|
219
|
+
it "combines the path and suffix" do
|
220
|
+
path = Path.new(nil, nil, {})
|
221
|
+
path.stub(:path) { '/the/path' }
|
222
|
+
path.stub(:suffix) { 'suffix' }
|
223
|
+
|
224
|
+
expect(path.path_with_suffix).to eql('/the/pathsuffix')
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
end
|