webmachine 1.6.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/README.md +2 -5
  4. data/documentation/adapters.md +2 -11
  5. data/examples/debugger.rb +5 -3
  6. data/examples/logging.rb +2 -2
  7. data/examples/webrick.rb +2 -2
  8. data/lib/webmachine/adapter.rb +0 -3
  9. data/lib/webmachine/adapters/lazy_request_body.rb +1 -1
  10. data/lib/webmachine/adapters/rack.rb +38 -34
  11. data/lib/webmachine/adapters/rack_mapped.rb +1 -2
  12. data/lib/webmachine/adapters/webrick.rb +11 -12
  13. data/lib/webmachine/adapters.rb +0 -2
  14. data/lib/webmachine/application.rb +2 -2
  15. data/lib/webmachine/chunked_body.rb +1 -1
  16. data/lib/webmachine/configuration.rb +1 -1
  17. data/lib/webmachine/constants.rb +12 -12
  18. data/lib/webmachine/cookie.rb +20 -18
  19. data/lib/webmachine/decision/conneg.rb +24 -24
  20. data/lib/webmachine/decision/falsey.rb +0 -1
  21. data/lib/webmachine/decision/flow.rb +19 -20
  22. data/lib/webmachine/decision/fsm.rb +4 -4
  23. data/lib/webmachine/decision/helpers.rb +21 -21
  24. data/lib/webmachine/dispatcher/route.rb +28 -28
  25. data/lib/webmachine/dispatcher.rb +3 -2
  26. data/lib/webmachine/errors.rb +7 -8
  27. data/lib/webmachine/etags.rb +2 -1
  28. data/lib/webmachine/header_negotiation.rb +5 -6
  29. data/lib/webmachine/headers.rb +5 -5
  30. data/lib/webmachine/media_type.rb +5 -5
  31. data/lib/webmachine/quoted_string.rb +3 -3
  32. data/lib/webmachine/request.rb +7 -10
  33. data/lib/webmachine/rescueable_exception.rb +3 -3
  34. data/lib/webmachine/resource/authentication.rb +3 -4
  35. data/lib/webmachine/resource/callbacks.rb +3 -3
  36. data/lib/webmachine/resource/encodings.rb +3 -9
  37. data/lib/webmachine/resource.rb +1 -1
  38. data/lib/webmachine/response.rb +7 -9
  39. data/lib/webmachine/spec/adapter_lint.rb +67 -69
  40. data/lib/webmachine/spec/test_resource.rb +22 -22
  41. data/lib/webmachine/streaming/encoder.rb +3 -2
  42. data/lib/webmachine/streaming/io_encoder.rb +4 -3
  43. data/lib/webmachine/trace/fsm.rb +25 -18
  44. data/lib/webmachine/trace/resource_proxy.rb +10 -9
  45. data/lib/webmachine/trace/static/http-headers-status-v3.png +0 -0
  46. data/lib/webmachine/trace/trace_resource.rb +22 -24
  47. data/lib/webmachine/trace.rb +7 -6
  48. data/lib/webmachine/translation.rb +3 -3
  49. data/lib/webmachine/version.rb +1 -1
  50. data/pkg/webmachine-2.0.0.beta.gem +0 -0
  51. metadata +51 -84
  52. data/.gitignore +0 -31
  53. data/Gemfile +0 -46
  54. data/Guardfile +0 -11
  55. data/RELEASING.md +0 -21
  56. data/Rakefile +0 -44
  57. data/lib/webmachine/adapters/httpkit.rb +0 -74
  58. data/lib/webmachine/adapters/reel.rb +0 -113
  59. data/memory_test.rb +0 -37
  60. data/spec/spec_helper.rb +0 -56
  61. data/spec/webmachine/adapter_spec.rb +0 -39
  62. data/spec/webmachine/adapters/httpkit_spec.rb +0 -10
  63. data/spec/webmachine/adapters/rack_mapped_spec.rb +0 -71
  64. data/spec/webmachine/adapters/rack_spec.rb +0 -62
  65. data/spec/webmachine/adapters/reel_spec.rb +0 -76
  66. data/spec/webmachine/adapters/webrick_spec.rb +0 -12
  67. data/spec/webmachine/application_spec.rb +0 -74
  68. data/spec/webmachine/chunked_body_spec.rb +0 -30
  69. data/spec/webmachine/configuration_spec.rb +0 -27
  70. data/spec/webmachine/cookie_spec.rb +0 -99
  71. data/spec/webmachine/decision/conneg_spec.rb +0 -166
  72. data/spec/webmachine/decision/falsey_spec.rb +0 -8
  73. data/spec/webmachine/decision/flow_spec.rb +0 -1148
  74. data/spec/webmachine/decision/fsm_spec.rb +0 -163
  75. data/spec/webmachine/decision/helpers_spec.rb +0 -216
  76. data/spec/webmachine/dispatcher/rfc3986_percent_decode_spec.rb +0 -22
  77. data/spec/webmachine/dispatcher/route_spec.rb +0 -248
  78. data/spec/webmachine/dispatcher_spec.rb +0 -104
  79. data/spec/webmachine/errors_spec.rb +0 -13
  80. data/spec/webmachine/etags_spec.rb +0 -75
  81. data/spec/webmachine/events_spec.rb +0 -58
  82. data/spec/webmachine/headers_spec.rb +0 -99
  83. data/spec/webmachine/media_type_spec.rb +0 -85
  84. data/spec/webmachine/request_spec.rb +0 -273
  85. data/spec/webmachine/rescueable_exception_spec.rb +0 -15
  86. data/spec/webmachine/resource/authentication_spec.rb +0 -68
  87. data/spec/webmachine/response_spec.rb +0 -51
  88. data/spec/webmachine/trace/fsm_spec.rb +0 -37
  89. data/spec/webmachine/trace/resource_proxy_spec.rb +0 -34
  90. data/spec/webmachine/trace/trace_store_spec.rb +0 -29
  91. data/spec/webmachine/trace_spec.rb +0 -17
  92. data/webmachine.gemspec +0 -25
@@ -1,163 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Webmachine::Decision::FSM do
4
- include_context 'default resource'
5
-
6
- subject { described_class.new(resource, request, response) }
7
-
8
- let(:run_with_exception) do
9
- begin
10
- subject.run
11
- rescue Exception
12
- end
13
- end
14
-
15
- describe 'handling of exceptions from decision methods' do
16
- let(:UNRESCUABLE_exceptions) do
17
- Webmachine::RescuableException::UNRESCUABLE
18
- end
19
-
20
- describe "rescueable exceptions" do
21
- it 'does rescue Exception' do
22
- allow(subject).to receive(Webmachine::Decision::Flow::START) { raise(Exception) }
23
- expect(resource).to receive(:handle_exception).with instance_of(Exception)
24
- expect { subject.run }.to_not raise_error
25
- end
26
-
27
- it 'does rescue a failed require' do
28
- allow(subject).to receive(Webmachine::Decision::Flow::START) { require 'laterequire' }
29
- expect(resource).to receive(:handle_exception).with instance_of(LoadError)
30
- expect { subject.run }.to_not raise_error
31
- end
32
- end
33
-
34
- describe "UNRESCUABLE exceptions" do
35
- shared_examples "UNRESCUABLE" do |e|
36
- specify "#{e} is not rescued" do
37
- allow(subject).to receive(Webmachine::Decision::Flow::START) {raise(e)}
38
- expect(resource).to_not receive(:handle_exception).with instance_of(e)
39
- expect { subject.run }.to raise_error(e)
40
- end
41
- end
42
- eary = Webmachine::RescuableException::UNRESCUABLE_DEFAULTS - [
43
- Webmachine::MalformedRequest, # Webmachine rescues by default, so it won't re-raise.
44
- SignalException # Requires raise in form 'raise SignalException, "SIGSOMESIGNAL"'.
45
- # Haven't found a good no-op signal to use here.
46
- ]
47
- eary.each{|e| include_examples "UNRESCUABLE", e}
48
- end
49
- end
50
-
51
- describe 'handling of errors from decision methods' do
52
- let(:error) { RuntimeError.new }
53
-
54
- before do
55
- allow(subject).to receive(Webmachine::Decision::Flow::START) { raise error }
56
- end
57
-
58
- it 'calls resource.handle_exception' do
59
- expect(resource).to receive(:handle_exception).with(error)
60
- subject.run
61
- end
62
-
63
- it 'calls resource.finish_request' do
64
- expect(resource).to receive(:finish_request)
65
- subject.run
66
- end
67
- end
68
-
69
- describe 'handling of errors from resource.handle_exception' do
70
- let(:error) { RuntimeError.new('an error message') }
71
-
72
- before do
73
- allow(subject).to receive(Webmachine::Decision::Flow::START) { raise }
74
- allow(resource).to receive(:handle_exception) { raise error }
75
- end
76
-
77
- it 'does not call resource.handle_exception again' do
78
- expect(resource).to receive(:handle_exception).once { raise }
79
- subject.run
80
- end
81
-
82
- it 'does not call resource.finish_request' do
83
- expect(resource).not_to receive(:finish_request)
84
- subject.run
85
- end
86
-
87
- it 'renders an error' do
88
- expect(Webmachine).
89
- to receive(:render_error).
90
- with(500, request, response, { :message => error.message })
91
- subject.run
92
- end
93
- end
94
-
95
- describe 'handling of exceptions from resource.finish_request' do
96
- let(:exception) { Class.new(Exception).new }
97
-
98
- before do
99
- Webmachine::RescuableException.remove(exception)
100
- allow(resource).to receive(:finish_request) { raise exception }
101
- end
102
-
103
- it 'does not call resource.handle_exception' do
104
- expect(resource).to_not receive(:handle_exception)
105
- run_with_exception
106
- end
107
-
108
- it 'does not call resource.finish_request again' do
109
- expect(resource).to receive(:finish_request).once
110
- run_with_exception
111
- end
112
- end
113
-
114
- describe 'handling of errors from resource.finish_request' do
115
- let(:error) { RuntimeError.new }
116
-
117
- before do
118
- allow(resource).to receive(:finish_request) { raise error }
119
- end
120
-
121
- it 'calls resource.handle_exception' do
122
- expect(resource).to receive(:handle_exception).with(error)
123
- subject.run
124
- end
125
-
126
- it 'does not call resource.finish_request again' do
127
- expect(resource).to receive(:finish_request).once { raise }
128
- subject.run
129
- end
130
- end
131
-
132
- it "sets the response code before calling finish_request" do
133
- resource_class.class_eval do
134
- class << self
135
- attr_accessor :current_response_code
136
- end
137
-
138
- def to_html
139
- 201
140
- end
141
-
142
- def finish_request
143
- self.class.current_response_code = response.code
144
- end
145
- end
146
-
147
- subject.run
148
-
149
- expect(resource_class.current_response_code).to be(201)
150
- end
151
-
152
- it 'respects a response code set by resource.finish_request' do
153
- resource_class.class_eval do
154
- def finish_request
155
- response.code = 451
156
- end
157
- end
158
-
159
- subject.run
160
-
161
- expect(response.code).to be(451)
162
- end
163
- end
@@ -1,216 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Webmachine::Decision::Helpers do
4
- include_context "default resource"
5
- subject { Webmachine::Decision::FSM.new(resource, request, response) }
6
-
7
- def resource_with(&block)
8
- klass = Class.new(Webmachine::Resource) do
9
- def to_html; "test resource"; end
10
- end
11
- klass.module_eval(&block) if block_given?
12
- klass.new(request, response)
13
- end
14
-
15
- let(:resource) { resource_with }
16
-
17
- describe "accepting request bodies" do
18
- let(:resource) do
19
- resource_with do
20
- def initialize
21
- @accepted, @result = [], true
22
- end
23
- attr_accessor :accepted, :result
24
- def content_types_accepted
25
- (accepted || []).map {|t| Array === t ? t : [t, :accept_doc] }
26
- end
27
- def accept_doc; result; end
28
- end
29
- end
30
-
31
- it "should return 415 when no types are accepted" do
32
- expect(subject.accept_helper).to eq 415
33
- end
34
-
35
- it "should return 415 when the posted type is not acceptable" do
36
- resource.accepted = %W{application/json}
37
- headers['Content-Type'] = "text/xml"
38
- expect(subject.accept_helper).to eq 415
39
- end
40
-
41
- it "should call the method for the first acceptable type, taking into account params" do
42
- resource.accepted = ["application/json;v=3", ["application/json", :other]]
43
- expect(resource).to receive(:other).and_return(true)
44
- headers['Content-Type'] = 'application/json;v=2'
45
- expect(subject.accept_helper).to be(true)
46
- end
47
- end
48
-
49
- context "setting the Content-Length header when responding" do
50
- [204, 205, 304].each do |code|
51
- it "removes the header for entity-less response code #{code}" do
52
- response.headers['Content-Length'] = '0'
53
- response.body = nil
54
- subject.send :respond, code
55
- expect(response.headers).to_not include 'Content-Length'
56
- end
57
- end
58
-
59
- (200..599).each do |code|
60
- # 204, 205 and 304 have no bodies, 404 is set to a default
61
- # non-zero response by Webmachine
62
- next if [204, 205, 304, 404].include? code
63
-
64
- it "adds the header for response code #{code} that should include an entity but has an empty body" do
65
- response.code = code
66
- response.body = nil
67
- subject.send :respond, code
68
- expect(response.headers['Content-Length']).to eq '0'
69
- end
70
- end
71
-
72
- (200..599).each do |code|
73
- next if [204, 205, 304].include? code
74
-
75
- it "does not add the header when Transfer-Encoding is set on code #{code}" do
76
- response.headers['Transfer-Encoding'] = 'chunked'
77
- response.body = []
78
- subject.send :respond, code
79
- expect(response.headers).to_not include 'Content-Length'
80
- end
81
- end
82
- end
83
-
84
- describe "#encode_body" do
85
- before { subject.run }
86
-
87
- context "with a String body" do
88
- before { response.body = '<body></body>' }
89
-
90
- it "does not modify the response body" do
91
- subject.encode_body
92
- expect(response.body).to be_instance_of(String)
93
- end
94
-
95
- it "sets the Content-Length header in the response" do
96
- subject.encode_body
97
- expect(response.headers['Content-Length']).to eq response.body.bytesize.to_s
98
- end
99
- end
100
-
101
- shared_examples_for "a non-String body" do
102
- it "does not set the Content-Length header in the response" do
103
- subject.encode_body
104
- expect(response.headers).to_not have_key('Content-Length')
105
- end
106
-
107
- it "sets the Transfer-Encoding response header to chunked" do
108
- subject.encode_body
109
- expect(response.headers['Transfer-Encoding']).to eq 'chunked'
110
- end
111
- end
112
-
113
- context "with an Enumerable body" do
114
- before { response.body = ['one', 'two'] }
115
-
116
- it "wraps the response body in an EnumerableEncoder" do
117
- subject.encode_body
118
- expect(response.body).to be_instance_of(Webmachine::Streaming::EnumerableEncoder)
119
- end
120
-
121
- it_should_behave_like "a non-String body"
122
- end
123
-
124
- context "with a callable body" do
125
- before { response.body = Proc.new { 'proc' } }
126
-
127
- it "wraps the response body in a CallableEncoder" do
128
- subject.encode_body
129
- expect(response.body).to be_instance_of(Webmachine::Streaming::CallableEncoder)
130
- end
131
-
132
- it_should_behave_like "a non-String body"
133
- end
134
-
135
- context "with a Fiber body" do
136
- before { response.body = Fiber.new { Fiber.yield "foo" } }
137
-
138
- it "wraps the response body in a FiberEncoder" do
139
- subject.encode_body
140
- expect(response.body).to be_instance_of(Webmachine::Streaming::FiberEncoder)
141
- end
142
-
143
- it_should_behave_like "a non-String body"
144
- end
145
-
146
- context "with a File body" do
147
- before { response.body = File.open("spec/spec_helper.rb", "r") }
148
-
149
- it "wraps the response body in an IOEncoder" do
150
- subject.encode_body
151
- expect(response.body).to be_instance_of(Webmachine::Streaming::IOEncoder)
152
- end
153
-
154
- it "sets the Content-Length header to the size of the file" do
155
- subject.encode_body
156
- expect(response.headers['Content-Length']).to eq File.stat('spec/spec_helper.rb').size.to_s
157
- end
158
-
159
- it "progressively yields file contents for each enumeration" do
160
- subject.encode_body
161
- body_size = 0
162
- response.body.each do |chunk|
163
- expect(chunk).to be_instance_of(String)
164
- body_size += chunk.length
165
- end
166
- expect(body_size).to eq File.stat('spec/spec_helper.rb').size
167
- end
168
-
169
- context "when the resource provides a non-identity encoding that the client accepts" do
170
- let(:resource) do
171
- resource_with do
172
- def encodings_provided
173
- { "deflate" => :encode_deflate, "identity" => :encode_identity }
174
- end
175
- end
176
- end
177
-
178
- let(:headers) do
179
- Webmachine::Headers.new({"Accept-Encoding" => "deflate, identity"})
180
- end
181
-
182
- it_should_behave_like "a non-String body"
183
- end
184
- end
185
-
186
- context "with a StringIO body" do
187
- before { response.body = StringIO.new("A VERY LONG STRING, NOT") }
188
-
189
- it "wraps the response body in an IOEncoder" do
190
- subject.encode_body
191
- expect(response.body).to be_instance_of(Webmachine::Streaming::IOEncoder)
192
- end
193
-
194
- it "sets the Content-Length header to the size of the string" do
195
- subject.encode_body
196
- expect(response.headers['Content-Length']).to eq response.body.size.to_s
197
- end
198
-
199
- context "when the resource provides a non-identity encoding that the client accepts" do
200
- let(:resource) do
201
- resource_with do
202
- def encodings_provided
203
- { "deflate" => :encode_deflate, "identity" => :encode_identity }
204
- end
205
- end
206
- end
207
-
208
- let(:headers) do
209
- Webmachine::Headers.new({"Accept-Encoding" => "deflate, identity"})
210
- end
211
-
212
- it_should_behave_like "a non-String body"
213
- end
214
- end
215
- end
216
- end
@@ -1,22 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Webmachine::Dispatcher::Route do
4
- describe '#rfc3986_percent_decode' do
5
- def call_subject(value)
6
- Webmachine::Dispatcher::Route.rfc3986_percent_decode(value)
7
- end
8
-
9
- it 'does not change un-encoded strings' do
10
- expect(call_subject('this is a normal string, I think')).to eq 'this is a normal string, I think'
11
- expect(call_subject('')).to eq ''
12
- end
13
-
14
- it 'decodes percent encoded sequences' do
15
- expect(call_subject('/tenants/esckimo+test%20%65')).to eq '/tenants/esckimo+test e'
16
- end
17
-
18
- it 'leaves incorrectly encoded sequences as is' do
19
- expect(call_subject('/tenants/esckimo+test%2%65')).to eq '/tenants/esckimo+test%2e'
20
- end
21
- end
22
- end
@@ -1,248 +0,0 @@
1
- require 'spec_helper'
2
-
3
- Webmachine::Dispatcher::Route.class_eval do
4
- def warn(*msgs); end # silence warnings for tests
5
- end
6
-
7
- describe Webmachine::Dispatcher::Route do
8
- let(:method) { "GET" }
9
- let(:uri) { URI.parse("http://localhost:8080/") }
10
- let(:routing_tokens) { nil }
11
- let(:request){ Webmachine::Request.new(method, uri, Webmachine::Headers.new, "", routing_tokens) }
12
- let(:resource){ Class.new(Webmachine::Resource) }
13
-
14
- describe '#apply' do
15
- let(:route) {
16
- Webmachine::Dispatcher::Route.new ['hello', :string], resource, {}
17
- }
18
-
19
- describe 'a path_info fragment' do
20
- let(:uri) { URI.parse("http://localhost:8080/hello/planet%20earth%20++") }
21
-
22
- it 'should decode the value' do
23
- route.apply(request)
24
- expect(request.path_info).to eq({:string => 'planet earth ++'})
25
- end
26
- end
27
- end
28
-
29
- matcher :match_route do |*expected|
30
- route = Webmachine::Dispatcher::Route.new(expected[0], Class.new(Webmachine::Resource), expected[1] || {})
31
- match do |actual|
32
- uri = URI.parse("http://localhost:8080")
33
- uri.path = actual
34
- req = Webmachine::Request.new("GET", uri, Webmachine::Headers.new, "", routing_tokens)
35
- route.match?(req)
36
- end
37
-
38
- failure_message do |_|
39
- "expected route #{expected[0].inspect} to match path #{request.uri.path}"
40
- end
41
- failure_message_when_negated do |_|
42
- "expected route #{expected[0].inspect} not to match path #{request.uri.path}"
43
- end
44
- end
45
-
46
- it "warns about the deprecated string splat when initializing" do
47
- [["*"],["foo", "*"],["foo", :bar, "*"]].each do |path|
48
- route = described_class.allocate
49
- expect(route).to receive(:warn)
50
- route.send :initialize, path, resource, {}
51
- end
52
- end
53
-
54
- context "matching a request" do
55
- context "on the root path" do
56
- subject { "/" }
57
- it { is_expected.to match_route([]) }
58
- it { is_expected.to match_route ['*'] }
59
- it { is_expected.to match_route [:*] }
60
- it { is_expected.not_to match_route %w{foo} }
61
- it { is_expected.not_to match_route [:id] }
62
- end
63
-
64
- context "on a deep path" do
65
- subject { "/foo/bar/baz" }
66
- it { is_expected.to match_route %w{foo bar baz} }
67
- it { is_expected.to match_route ['foo', :id, "baz"] }
68
- it { is_expected.to match_route ['foo', :*] }
69
- it { is_expected.to match_route [:id, :*] }
70
- it { is_expected.not_to match_route [] }
71
- it { is_expected.not_to match_route ['bar', :*] }
72
- end
73
-
74
- context "with a guard on the request method" do
75
- let(:uri){ URI.parse("http://localhost:8080/notes") }
76
- let(:route) do
77
- described_class.new(
78
- ["notes"],
79
- lambda { |request| request.method == "POST" },
80
- resource
81
- )
82
- end
83
- subject { route }
84
-
85
- context "when guard passes" do
86
- let(:method){ "POST" }
87
- it { is_expected.to be_match(request) }
88
-
89
- context "but the path match fails" do
90
- let(:uri){ URI.parse("http://localhost:8080/other") }
91
- it { is_expected.not_to be_match(request) }
92
- end
93
- end
94
-
95
- context "when guard fails" do
96
- let(:method) { "GET" }
97
- it { is_expected.not_to be_match(request) }
98
- end
99
-
100
- context "when the guard responds to #call" do
101
- let(:guard_class) do
102
- Class.new do
103
- def initialize(method)
104
- @method = method
105
- end
106
-
107
- def call(request)
108
- request.method == @method
109
- end
110
- end
111
- end
112
-
113
- let(:route) do
114
- described_class.new(["notes"], guard_class.new("POST"), resource)
115
- end
116
-
117
- context "when the guard passes" do
118
- let(:method){ "POST" }
119
- it { is_expected.to be_match(request) }
120
- end
121
-
122
- context "when the guard fails" do
123
- # let(:method){ "GET" }
124
- it { is_expected.not_to be_match(request) }
125
- end
126
- end
127
- end
128
-
129
- context "with a request with explicitly specified routing tokens" do
130
- subject { "/some/route/foo/bar" }
131
- let(:routing_tokens) { ["foo", "bar"] }
132
- it { is_expected.to match_route(["foo", "bar"]) }
133
- it { is_expected.to match_route(["foo", :id]) }
134
- it { is_expected.to match_route ['*'] }
135
- it { is_expected.to match_route [:*] }
136
- it { is_expected.not_to match_route(["some", "route", "foo", "bar"]) }
137
- it { is_expected.not_to match_route %w{foo} }
138
- it { is_expected.not_to match_route [:id] }
139
- end
140
- end
141
-
142
- context "applying bindings" do
143
- context "on the root path" do
144
- subject { described_class.new([], resource) }
145
- before { subject.apply(request) }
146
-
147
- it "should assign the dispatched path to the empty string" do
148
- expect(request.disp_path).to eq("")
149
- end
150
-
151
- it "should assign empty bindings" do
152
- expect(request.path_info).to eq({})
153
- end
154
-
155
- it "should assign empty path tokens" do
156
- expect(request.path_tokens).to eq([])
157
- end
158
-
159
- context "with extra user-defined bindings" do
160
- subject { described_class.new([], resource, "bar" => "baz") }
161
-
162
- it "should assign the user-defined bindings" do
163
- expect(request.path_info).to eq({"bar" => "baz"})
164
- end
165
- end
166
-
167
- context "with a splat" do
168
- subject { described_class.new([:*], resource) }
169
-
170
- it "should assign empty path tokens" do
171
- expect(request.path_tokens).to eq([])
172
- end
173
- end
174
-
175
- context "with a deprecated splat string" do
176
- subject { described_class.new(['*'], resource) }
177
-
178
- it "should assign empty path tokens" do
179
- expect(request.path_tokens).to eq([])
180
- end
181
- end
182
- end
183
- context "on a deep path" do
184
- subject { described_class.new(%w{foo bar baz}, resource) }
185
- let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz") }
186
- before { subject.apply(request) }
187
-
188
- it "should assign the dispatched path as the path past the initial slash" do
189
- expect(request.disp_path).to eq("foo/bar/baz")
190
- end
191
-
192
- it "should assign empty bindings" do
193
- expect(request.path_info).to eq({})
194
- end
195
-
196
- it "should assign empty path tokens" do
197
- expect(request.path_tokens).to eq([])
198
- end
199
-
200
- context "with path variables" do
201
- subject { described_class.new(['foo', :id, 'baz'], resource) }
202
-
203
- it "should assign the path variables in the bindings" do
204
- expect(request.path_info).to eq({:id => "bar"})
205
- end
206
- end
207
- context "with regex" do
208
- subject { described_class.new([/foo/, /(.*)/, 'baz'], resource) }
209
-
210
- it "should assign the captures path variables" do
211
- expect(request.path_info).to eq({:captures => ["bar"]})
212
- end
213
- end
214
- context "with multi-capture regex" do
215
- subject { described_class.new([/foo/, /(.*)/, /baz\.(.*)/], resource) }
216
- let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz.json") }
217
-
218
- it "should assign the captures path variables" do
219
- expect(request.path_info).to eq({:captures => ["bar", "json"]})
220
- end
221
- end
222
- context "with named capture regex" do
223
- subject { described_class.new(['foo', :bar, /(?<baz>[^.]+)\.(?<format>.*)/], resource) }
224
- let(:uri) { URI.parse("http://localhost:8080/foo/bar/baz.json") }
225
-
226
- it "should assign the captures path variables" do
227
- expect(request.path_info).to eq({bar: 'bar', baz: 'baz', format: "json"})
228
- end
229
- end
230
-
231
- context "with a splat" do
232
- subject { described_class.new(['foo', :*], resource) }
233
-
234
- it "should capture the path tokens matched by the splat" do
235
- expect(request.path_tokens).to eq(%w{ bar baz })
236
- end
237
- end
238
-
239
- context "with a deprecated splat string" do
240
- subject { described_class.new(%w{foo *}, resource) }
241
-
242
- it "should capture the path tokens matched by the splat" do
243
- expect(request.path_tokens).to eq(%w{ bar baz })
244
- end
245
- end
246
- end
247
- end
248
- end