webmachine 1.6.0 → 2.0.0.beta

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.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +6 -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. metadata +52 -86
  51. data/.gitignore +0 -31
  52. data/Gemfile +0 -46
  53. data/Guardfile +0 -11
  54. data/RELEASING.md +0 -21
  55. data/Rakefile +0 -44
  56. data/lib/webmachine/adapters/httpkit.rb +0 -74
  57. data/lib/webmachine/adapters/reel.rb +0 -113
  58. data/memory_test.rb +0 -37
  59. data/spec/spec_helper.rb +0 -56
  60. data/spec/webmachine/adapter_spec.rb +0 -39
  61. data/spec/webmachine/adapters/httpkit_spec.rb +0 -10
  62. data/spec/webmachine/adapters/rack_mapped_spec.rb +0 -71
  63. data/spec/webmachine/adapters/rack_spec.rb +0 -62
  64. data/spec/webmachine/adapters/reel_spec.rb +0 -76
  65. data/spec/webmachine/adapters/webrick_spec.rb +0 -12
  66. data/spec/webmachine/application_spec.rb +0 -74
  67. data/spec/webmachine/chunked_body_spec.rb +0 -30
  68. data/spec/webmachine/configuration_spec.rb +0 -27
  69. data/spec/webmachine/cookie_spec.rb +0 -99
  70. data/spec/webmachine/decision/conneg_spec.rb +0 -166
  71. data/spec/webmachine/decision/falsey_spec.rb +0 -8
  72. data/spec/webmachine/decision/flow_spec.rb +0 -1148
  73. data/spec/webmachine/decision/fsm_spec.rb +0 -163
  74. data/spec/webmachine/decision/helpers_spec.rb +0 -216
  75. data/spec/webmachine/dispatcher/rfc3986_percent_decode_spec.rb +0 -22
  76. data/spec/webmachine/dispatcher/route_spec.rb +0 -248
  77. data/spec/webmachine/dispatcher_spec.rb +0 -104
  78. data/spec/webmachine/errors_spec.rb +0 -13
  79. data/spec/webmachine/etags_spec.rb +0 -75
  80. data/spec/webmachine/events_spec.rb +0 -58
  81. data/spec/webmachine/headers_spec.rb +0 -99
  82. data/spec/webmachine/media_type_spec.rb +0 -85
  83. data/spec/webmachine/request_spec.rb +0 -273
  84. data/spec/webmachine/rescueable_exception_spec.rb +0 -15
  85. data/spec/webmachine/resource/authentication_spec.rb +0 -68
  86. data/spec/webmachine/response_spec.rb +0 -51
  87. data/spec/webmachine/trace/fsm_spec.rb +0 -37
  88. data/spec/webmachine/trace/resource_proxy_spec.rb +0 -34
  89. data/spec/webmachine/trace/trace_store_spec.rb +0 -29
  90. data/spec/webmachine/trace_spec.rb +0 -17
  91. 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