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.

Files changed (101) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +8 -0
  3. data/.rubocop.yml +70 -0
  4. data/.travis.yml +7 -6
  5. data/CHANGELOG.md +134 -4
  6. data/CONTRIBUTING.md +118 -0
  7. data/Gemfile +5 -2
  8. data/README.md +551 -116
  9. data/RELEASING.md +105 -0
  10. data/Rakefile +29 -8
  11. data/UPGRADING.md +124 -0
  12. data/grape.gemspec +3 -3
  13. data/lib/grape/api.rb +207 -88
  14. data/lib/grape/cookies.rb +4 -8
  15. data/lib/grape/endpoint.rb +198 -144
  16. data/lib/grape/error_formatter/base.rb +5 -7
  17. data/lib/grape/error_formatter/json.rb +3 -5
  18. data/lib/grape/error_formatter/txt.rb +1 -3
  19. data/lib/grape/error_formatter/xml.rb +4 -6
  20. data/lib/grape/exceptions/base.rb +9 -9
  21. data/lib/grape/exceptions/incompatible_option_values.rb +10 -0
  22. data/lib/grape/exceptions/invalid_formatter.rb +1 -4
  23. data/lib/grape/exceptions/invalid_versioner_option.rb +1 -5
  24. data/lib/grape/exceptions/invalid_with_option_for_represent.rb +1 -6
  25. data/lib/grape/exceptions/missing_mime_type.rb +1 -5
  26. data/lib/grape/exceptions/missing_option.rb +1 -4
  27. data/lib/grape/exceptions/missing_vendor_option.rb +1 -4
  28. data/lib/grape/exceptions/unknown_options.rb +1 -5
  29. data/lib/grape/exceptions/unknown_validator.rb +1 -3
  30. data/lib/grape/exceptions/validation.rb +13 -3
  31. data/lib/grape/exceptions/validation_errors.rb +43 -0
  32. data/lib/grape/formatter/base.rb +5 -7
  33. data/lib/grape/formatter/json.rb +0 -3
  34. data/lib/grape/formatter/serializable_hash.rb +15 -15
  35. data/lib/grape/formatter/txt.rb +0 -2
  36. data/lib/grape/formatter/xml.rb +0 -2
  37. data/lib/grape/http/request.rb +26 -0
  38. data/lib/grape/locale/en.yml +8 -5
  39. data/lib/grape/middleware/auth/base.rb +30 -0
  40. data/lib/grape/middleware/auth/basic.rb +3 -20
  41. data/lib/grape/middleware/auth/digest.rb +2 -19
  42. data/lib/grape/middleware/auth/oauth2.rb +31 -24
  43. data/lib/grape/middleware/base.rb +7 -7
  44. data/lib/grape/middleware/error.rb +36 -22
  45. data/lib/grape/middleware/filter.rb +3 -3
  46. data/lib/grape/middleware/formatter.rb +99 -61
  47. data/lib/grape/middleware/globals.rb +13 -0
  48. data/lib/grape/middleware/versioner/accept_version_header.rb +67 -0
  49. data/lib/grape/middleware/versioner/header.rb +22 -16
  50. data/lib/grape/middleware/versioner/param.rb +9 -11
  51. data/lib/grape/middleware/versioner/path.rb +10 -13
  52. data/lib/grape/middleware/versioner.rb +3 -1
  53. data/lib/grape/namespace.rb +23 -0
  54. data/lib/grape/parser/base.rb +3 -5
  55. data/lib/grape/parser/json.rb +0 -2
  56. data/lib/grape/parser/xml.rb +0 -2
  57. data/lib/grape/path.rb +70 -0
  58. data/lib/grape/route.rb +10 -6
  59. data/lib/grape/util/content_types.rb +2 -1
  60. data/lib/grape/util/deep_merge.rb +5 -5
  61. data/lib/grape/util/hash_stack.rb +13 -2
  62. data/lib/grape/validations/coerce.rb +11 -10
  63. data/lib/grape/validations/default.rb +25 -0
  64. data/lib/grape/validations/presence.rb +7 -3
  65. data/lib/grape/validations/regexp.rb +2 -5
  66. data/lib/grape/validations/values.rb +17 -0
  67. data/lib/grape/validations.rb +161 -54
  68. data/lib/grape/version.rb +1 -1
  69. data/lib/grape.rb +19 -4
  70. data/spec/grape/api_spec.rb +897 -268
  71. data/spec/grape/endpoint_spec.rb +283 -66
  72. data/spec/grape/entity_spec.rb +132 -29
  73. data/spec/grape/exceptions/missing_mime_type_spec.rb +3 -9
  74. data/spec/grape/exceptions/validation_errors_spec.rb +19 -0
  75. data/spec/grape/middleware/auth/basic_spec.rb +8 -8
  76. data/spec/grape/middleware/auth/digest_spec.rb +5 -5
  77. data/spec/grape/middleware/auth/oauth2_spec.rb +81 -36
  78. data/spec/grape/middleware/base_spec.rb +8 -13
  79. data/spec/grape/middleware/error_spec.rb +13 -17
  80. data/spec/grape/middleware/exception_spec.rb +47 -27
  81. data/spec/grape/middleware/formatter_spec.rb +103 -41
  82. data/spec/grape/middleware/versioner/accept_version_header_spec.rb +121 -0
  83. data/spec/grape/middleware/versioner/header_spec.rb +76 -51
  84. data/spec/grape/middleware/versioner/param_spec.rb +18 -18
  85. data/spec/grape/middleware/versioner/path_spec.rb +6 -6
  86. data/spec/grape/middleware/versioner_spec.rb +5 -2
  87. data/spec/grape/path_spec.rb +229 -0
  88. data/spec/grape/util/hash_stack_spec.rb +31 -32
  89. data/spec/grape/validations/coerce_spec.rb +116 -51
  90. data/spec/grape/validations/default_spec.rb +123 -0
  91. data/spec/grape/validations/presence_spec.rb +42 -44
  92. data/spec/grape/validations/regexp_spec.rb +9 -9
  93. data/spec/grape/validations/values_spec.rb +138 -0
  94. data/spec/grape/validations/zh-CN.yml +4 -3
  95. data/spec/grape/validations_spec.rb +681 -48
  96. data/spec/shared/versioning_examples.rb +22 -6
  97. data/spec/spec_helper.rb +3 -2
  98. data/spec/support/basic_auth_encode_helpers.rb +0 -1
  99. data/spec/support/content_type_helpers.rb +11 -0
  100. data/spec/support/versioned_helpers.rb +13 -5
  101. 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
- :version_options => {
10
- :using => :header,
11
- :vendor => 'vendor',
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
- [ 'v1', :v1 ].each do |version|
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] = [ version ]
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
- env = subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last
88
+ subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor+json').last
89
89
  }.to throw_symbol(
90
90
  :error,
91
- :status => 406,
92
- :headers => {'X-Cascade' => 'pass'},
93
- :message => 'API vendor or version not found.'
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
- env = subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last
116
+ subject.call('HTTP_ACCEPT' => 'application/vnd.othervendor-v1+json').last
117
117
  }.to throw_symbol(
118
118
  :error,
119
- :status => 406,
120
- :headers => {'X-Cascade' => 'pass'},
121
- :message => 'API vendor or version not found.'
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
- env = subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last
146
+ subject.call('HTTP_ACCEPT' => 'application/vnd.vendor-v2+json').last
147
147
  }.to throw_symbol(
148
148
  :error,
149
- :status => 406,
150
- :headers => {'X-Cascade' => 'pass'},
151
- :message => 'API vendor or version not found.'
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
- env = subject.call({}).last
175
+ subject.call({}).last
176
176
  }.to throw_symbol(
177
177
  :error,
178
- :status => 406,
179
- :headers => {'X-Cascade' => 'pass'},
180
- :message => 'Accept header must be set.'
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
- env = subject.call('HTTP_ACCEPT' => '').last
186
+ subject.call('HTTP_ACCEPT' => '').last
187
187
  }.to throw_symbol(
188
188
  :error,
189
- :status => 406,
190
- :headers => {'X-Cascade' => 'pass'},
191
- :message => 'Accept header must be set.'
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
- env = subject.call('HTTP_ACCEPT' => '*/*').last
197
+ subject.call('HTTP_ACCEPT' => '*/*').last
198
198
  }.to throw_symbol(
199
199
  :error,
200
- :status => 406,
201
- :headers => {'X-Cascade' => 'pass'},
202
- :message => 'Accept header must not contain ranges ("*").'
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
- env = subject.call('HTTP_ACCEPT' => 'application/*').last
208
+ subject.call('HTTP_ACCEPT' => 'application/*').last
209
209
  }.to throw_symbol(
210
210
  :error,
211
- :status => 406,
212
- :headers => {'X-Cascade' => 'pass'},
213
- :message => 'Accept header must not contain ranges ("*").'
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
- env = subject.call({}).last
231
+ subject.call({}).last
232
232
  }.to throw_symbol(
233
233
  :error,
234
- :status => 406,
235
- :headers => {},
236
- :message => 'Accept header must be set.'
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
- env = subject.call('HTTP_ACCEPT' => '').last
242
+ subject.call('HTTP_ACCEPT' => '').last
243
243
  }.to throw_symbol(
244
244
  :error,
245
- :status => 406,
246
- :headers => {},
247
- :message => 'Accept header must be set.'
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
- env = subject.call('HTTP_ACCEPT' => '*/*').last
253
+ subject.call('HTTP_ACCEPT' => '*/*').last
254
254
  }.to throw_symbol(
255
255
  :error,
256
- :status => 406,
257
- :headers => {},
258
- :message => 'Accept header must not contain ranges ("*").'
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
- env = subject.call('HTTP_ACCEPT' => 'application/*').last
264
+ subject.call('HTTP_ACCEPT' => 'application/*').last
265
265
  }.to throw_symbol(
266
266
  :error,
267
- :status => 406,
268
- :headers => {},
269
- :message => 'Accept header must not contain ranges ("*").'
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", {:params => {"apiver" => "v1"}})
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', :focus => true do
14
- env = Rack::MockRequest.env_for("/awesome", {:params => {"apiver" => "v1", "other_param" => "5"}})
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 = {:parameter => ['v']}}
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", {:params => {"v" => "v1"}})
28
- s = subject.call(env)[1]["api.version"] == "v1"
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", {:params => {"apiver" => "v1"}})
32
- s = subject.call(env)[1]["api.version"] == nil
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 = {:versions => ['v1', 'v2']}}
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", {:params => {"apiver" => "v3"}})
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", {:params => {"apiver" => "v1"}})
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
- :versions => ['v1'],
52
- :version_options => {:using => :header}
51
+ versions: ['v1'],
52
+ version_options: { using: :header }
53
53
  }
54
- env = Rack::MockRequest.env_for("/awesome", {:params => {}})
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 = {:pattern => /v./i} }
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
- [ [ 'v1', 'v2'], [ :v1, :v2 ], [ :v1, 'v2' ], [ 'v1', :v2 ] ].each do |versions|
30
+ [['v1', 'v2'], [:v1, :v2], [:v1, 'v2'], ['v1', :v2]].each do |versions|
31
31
  context 'with specified versions as #{versions}' do
32
- before { @options = { :versions => versions } }
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
- end
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