webmachine 1.2.2 → 1.3.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.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/CHANGELOG.md +4 -0
  4. data/Gemfile +13 -11
  5. data/README.md +85 -89
  6. data/Rakefile +0 -1
  7. data/documentation/adapters.md +39 -0
  8. data/documentation/authentication-and-authorization.md +37 -0
  9. data/documentation/configurator.md +19 -0
  10. data/documentation/error-handling.md +86 -0
  11. data/documentation/examples.md +215 -0
  12. data/documentation/how-it-works.md +76 -0
  13. data/documentation/routes.md +97 -0
  14. data/documentation/validation.md +159 -0
  15. data/documentation/versioning-apis.md +74 -0
  16. data/documentation/visual-debugger.md +38 -0
  17. data/examples/application.rb +2 -2
  18. data/examples/debugger.rb +1 -1
  19. data/lib/webmachine.rb +3 -1
  20. data/lib/webmachine/adapter.rb +7 -13
  21. data/lib/webmachine/adapters.rb +1 -2
  22. data/lib/webmachine/adapters/httpkit.rb +74 -0
  23. data/lib/webmachine/adapters/lazy_request_body.rb +1 -2
  24. data/lib/webmachine/adapters/rack.rb +37 -21
  25. data/lib/webmachine/adapters/reel.rb +21 -23
  26. data/lib/webmachine/adapters/webrick.rb +16 -16
  27. data/lib/webmachine/application.rb +2 -2
  28. data/lib/webmachine/chunked_body.rb +3 -4
  29. data/lib/webmachine/constants.rb +75 -0
  30. data/lib/webmachine/decision/conneg.rb +12 -10
  31. data/lib/webmachine/decision/flow.rb +31 -21
  32. data/lib/webmachine/decision/fsm.rb +10 -18
  33. data/lib/webmachine/decision/helpers.rb +9 -37
  34. data/lib/webmachine/dispatcher.rb +13 -10
  35. data/lib/webmachine/dispatcher/route.rb +18 -8
  36. data/lib/webmachine/errors.rb +7 -1
  37. data/lib/webmachine/header_negotiation.rb +25 -0
  38. data/lib/webmachine/headers.rb +7 -2
  39. data/lib/webmachine/locale/en.yml +7 -5
  40. data/lib/webmachine/media_type.rb +10 -8
  41. data/lib/webmachine/request.rb +44 -15
  42. data/lib/webmachine/resource.rb +1 -1
  43. data/lib/webmachine/resource/callbacks.rb +6 -4
  44. data/lib/webmachine/spec/IO_response.body +1 -0
  45. data/lib/webmachine/spec/adapter_lint.rb +70 -36
  46. data/lib/webmachine/spec/test_resource.rb +10 -4
  47. data/lib/webmachine/streaming/fiber_encoder.rb +1 -5
  48. data/lib/webmachine/streaming/io_encoder.rb +6 -0
  49. data/lib/webmachine/trace.rb +1 -0
  50. data/lib/webmachine/trace/fsm.rb +20 -10
  51. data/lib/webmachine/trace/resource_proxy.rb +2 -0
  52. data/lib/webmachine/translation.rb +2 -1
  53. data/lib/webmachine/version.rb +3 -3
  54. data/memory_test.rb +37 -0
  55. data/spec/spec_helper.rb +9 -9
  56. data/spec/webmachine/adapter_spec.rb +14 -15
  57. data/spec/webmachine/adapters/httpkit_spec.rb +10 -0
  58. data/spec/webmachine/adapters/rack_spec.rb +6 -6
  59. data/spec/webmachine/adapters/reel_spec.rb +15 -11
  60. data/spec/webmachine/adapters/webrick_spec.rb +2 -2
  61. data/spec/webmachine/application_spec.rb +18 -17
  62. data/spec/webmachine/chunked_body_spec.rb +3 -3
  63. data/spec/webmachine/configuration_spec.rb +5 -5
  64. data/spec/webmachine/cookie_spec.rb +13 -13
  65. data/spec/webmachine/decision/conneg_spec.rb +48 -42
  66. data/spec/webmachine/decision/falsey_spec.rb +4 -4
  67. data/spec/webmachine/decision/flow_spec.rb +194 -144
  68. data/spec/webmachine/decision/fsm_spec.rb +17 -17
  69. data/spec/webmachine/decision/helpers_spec.rb +20 -20
  70. data/spec/webmachine/dispatcher/route_spec.rb +73 -27
  71. data/spec/webmachine/dispatcher_spec.rb +34 -24
  72. data/spec/webmachine/errors_spec.rb +1 -1
  73. data/spec/webmachine/etags_spec.rb +19 -19
  74. data/spec/webmachine/events_spec.rb +6 -6
  75. data/spec/webmachine/headers_spec.rb +14 -14
  76. data/spec/webmachine/media_type_spec.rb +36 -36
  77. data/spec/webmachine/request_spec.rb +33 -33
  78. data/spec/webmachine/resource/authentication_spec.rb +6 -6
  79. data/spec/webmachine/response_spec.rb +12 -12
  80. data/spec/webmachine/trace/fsm_spec.rb +8 -8
  81. data/spec/webmachine/trace/resource_proxy_spec.rb +9 -9
  82. data/spec/webmachine/trace/trace_store_spec.rb +5 -5
  83. data/spec/webmachine/trace_spec.rb +3 -3
  84. data/webmachine.gemspec +2 -6
  85. metadata +48 -206
  86. data/lib/webmachine/adapters/hatetepe.rb +0 -108
  87. data/lib/webmachine/adapters/mongrel.rb +0 -127
  88. data/lib/webmachine/dispatcher/not_found_resource.rb +0 -5
  89. data/lib/webmachine/fiber18.rb +0 -88
  90. data/spec/webmachine/adapters/hatetepe_spec.rb +0 -60
  91. data/spec/webmachine/adapters/mongrel_spec.rb +0 -16
@@ -6,63 +6,63 @@ describe Webmachine::Decision::FSM do
6
6
  subject { described_class.new(resource, request, response) }
7
7
 
8
8
  describe 'handling of exceptions from decision methods' do
9
- let(:exception) { Exception.new }
9
+ let(:exception) { RuntimeError.new }
10
10
 
11
11
  before do
12
- subject.stub(Webmachine::Decision::Flow::START) { raise exception }
12
+ allow(subject).to receive(Webmachine::Decision::Flow::START) { raise exception }
13
13
  end
14
14
 
15
15
  it 'calls resource.handle_exception' do
16
- resource.should_receive(:handle_exception).with(exception)
16
+ expect(resource).to receive(:handle_exception).with(exception)
17
17
  subject.run
18
18
  end
19
19
 
20
20
  it 'calls resource.finish_request' do
21
- resource.should_receive(:finish_request)
21
+ expect(resource).to receive(:finish_request)
22
22
  subject.run
23
23
  end
24
24
  end
25
25
 
26
26
  describe 'handling of exceptions from resource.handle_exception' do
27
- let(:exception) { Exception.new('an error message') }
27
+ let(:exception) { RuntimeError.new('an error message') }
28
28
 
29
29
  before do
30
- subject.stub(Webmachine::Decision::Flow::START) { raise }
31
- resource.stub(:handle_exception) { raise exception }
30
+ allow(subject).to receive(Webmachine::Decision::Flow::START) { raise }
31
+ allow(resource).to receive(:handle_exception) { raise exception }
32
32
  end
33
33
 
34
34
  it 'does not call resource.handle_exception again' do
35
- resource.should_receive(:handle_exception).once { raise }
35
+ expect(resource).to receive(:handle_exception).once { raise }
36
36
  subject.run
37
37
  end
38
38
 
39
39
  it 'does not call resource.finish_request' do
40
- resource.should_not_receive(:finish_request)
40
+ expect(resource).not_to receive(:finish_request)
41
41
  subject.run
42
42
  end
43
43
 
44
44
  it 'renders an error' do
45
- Webmachine.
46
- should_receive(:render_error).
45
+ expect(Webmachine).
46
+ to receive(:render_error).
47
47
  with(500, request, response, { :message => exception.message })
48
48
  subject.run
49
49
  end
50
50
  end
51
51
 
52
52
  describe 'handling of exceptions from resource.finish_request' do
53
- let(:exception) { Exception.new }
53
+ let(:exception) { RuntimeError.new }
54
54
 
55
55
  before do
56
- resource.stub(:finish_request) { raise exception }
56
+ allow(resource).to receive(:finish_request) { raise exception }
57
57
  end
58
58
 
59
59
  it 'calls resource.handle_exception' do
60
- resource.should_receive(:handle_exception).with(exception)
60
+ expect(resource).to receive(:handle_exception).with(exception)
61
61
  subject.run
62
62
  end
63
63
 
64
64
  it 'does not call resource.finish_request again' do
65
- resource.should_receive(:finish_request).once { raise }
65
+ expect(resource).to receive(:finish_request).once { raise }
66
66
  subject.run
67
67
  end
68
68
  end
@@ -84,7 +84,7 @@ describe Webmachine::Decision::FSM do
84
84
 
85
85
  subject.run
86
86
 
87
- resource_class.current_response_code.should be(201)
87
+ expect(resource_class.current_response_code).to be(201)
88
88
  end
89
89
 
90
90
  it 'respects a response code set by resource.finish_request' do
@@ -96,6 +96,6 @@ describe Webmachine::Decision::FSM do
96
96
 
97
97
  subject.run
98
98
 
99
- response.code.should be(451)
99
+ expect(response.code).to be(451)
100
100
  end
101
101
  end
@@ -29,20 +29,20 @@ describe Webmachine::Decision::Helpers do
29
29
  end
30
30
 
31
31
  it "should return 415 when no types are accepted" do
32
- subject.accept_helper.should == 415
32
+ expect(subject.accept_helper).to eq 415
33
33
  end
34
34
 
35
35
  it "should return 415 when the posted type is not acceptable" do
36
36
  resource.accepted = %W{application/json}
37
37
  headers['Content-Type'] = "text/xml"
38
- subject.accept_helper.should == 415
38
+ expect(subject.accept_helper).to eq 415
39
39
  end
40
40
 
41
41
  it "should call the method for the first acceptable type, taking into account params" do
42
42
  resource.accepted = ["application/json;v=3", ["application/json", :other]]
43
- resource.should_receive(:other).and_return(true)
43
+ expect(resource).to receive(:other).and_return(true)
44
44
  headers['Content-Type'] = 'application/json;v=2'
45
- subject.accept_helper.should be_true
45
+ expect(subject.accept_helper).to be(true)
46
46
  end
47
47
  end
48
48
 
@@ -52,7 +52,7 @@ describe Webmachine::Decision::Helpers do
52
52
  response.headers['Content-Length'] = '0'
53
53
  response.body = nil
54
54
  subject.send :respond, code
55
- response.headers.should_not include 'Content-Length'
55
+ expect(response.headers).to_not include 'Content-Length'
56
56
  end
57
57
  end
58
58
 
@@ -65,7 +65,7 @@ describe Webmachine::Decision::Helpers do
65
65
  response.code = code
66
66
  response.body = nil
67
67
  subject.send :respond, code
68
- response.headers['Content-Length'].should == '0'
68
+ expect(response.headers['Content-Length']).to eq '0'
69
69
  end
70
70
  end
71
71
 
@@ -76,7 +76,7 @@ describe Webmachine::Decision::Helpers do
76
76
  response.headers['Transfer-Encoding'] = 'chunked'
77
77
  response.body = []
78
78
  subject.send :respond, code
79
- response.headers.should_not include 'Content-Length'
79
+ expect(response.headers).to_not include 'Content-Length'
80
80
  end
81
81
  end
82
82
  end
@@ -89,24 +89,24 @@ describe Webmachine::Decision::Helpers do
89
89
 
90
90
  it "does not modify the response body" do
91
91
  subject.encode_body
92
- String.should === response.body
92
+ expect(response.body).to be_instance_of(String)
93
93
  end
94
94
 
95
95
  it "sets the Content-Length header in the response" do
96
96
  subject.encode_body
97
- response.headers['Content-Length'].should == response.body.bytesize.to_s
97
+ expect(response.headers['Content-Length']).to eq response.body.bytesize.to_s
98
98
  end
99
99
  end
100
100
 
101
101
  shared_examples_for "a non-String body" do
102
102
  it "does not set the Content-Length header in the response" do
103
103
  subject.encode_body
104
- response.headers.should_not have_key('Content-Length')
104
+ expect(response.headers).to_not have_key('Content-Length')
105
105
  end
106
106
 
107
107
  it "sets the Transfer-Encoding response header to chunked" do
108
108
  subject.encode_body
109
- response.headers['Transfer-Encoding'].should == 'chunked'
109
+ expect(response.headers['Transfer-Encoding']).to eq 'chunked'
110
110
  end
111
111
  end
112
112
 
@@ -115,7 +115,7 @@ describe Webmachine::Decision::Helpers do
115
115
 
116
116
  it "wraps the response body in an EnumerableEncoder" do
117
117
  subject.encode_body
118
- Webmachine::Streaming::EnumerableEncoder.should === response.body
118
+ expect(response.body).to be_instance_of(Webmachine::Streaming::EnumerableEncoder)
119
119
  end
120
120
 
121
121
  it_should_behave_like "a non-String body"
@@ -126,7 +126,7 @@ describe Webmachine::Decision::Helpers do
126
126
 
127
127
  it "wraps the response body in a CallableEncoder" do
128
128
  subject.encode_body
129
- Webmachine::Streaming::CallableEncoder.should === response.body
129
+ expect(response.body).to be_instance_of(Webmachine::Streaming::CallableEncoder)
130
130
  end
131
131
 
132
132
  it_should_behave_like "a non-String body"
@@ -137,7 +137,7 @@ describe Webmachine::Decision::Helpers do
137
137
 
138
138
  it "wraps the response body in a FiberEncoder" do
139
139
  subject.encode_body
140
- Webmachine::Streaming::FiberEncoder.should === response.body
140
+ expect(response.body).to be_instance_of(Webmachine::Streaming::FiberEncoder)
141
141
  end
142
142
 
143
143
  it_should_behave_like "a non-String body"
@@ -148,22 +148,22 @@ describe Webmachine::Decision::Helpers do
148
148
 
149
149
  it "wraps the response body in an IOEncoder" do
150
150
  subject.encode_body
151
- Webmachine::Streaming::IOEncoder.should === response.body
151
+ expect(response.body).to be_instance_of(Webmachine::Streaming::IOEncoder)
152
152
  end
153
153
 
154
154
  it "sets the Content-Length header to the size of the file" do
155
155
  subject.encode_body
156
- response.headers['Content-Length'].should == File.stat('spec/spec_helper.rb').size.to_s
156
+ expect(response.headers['Content-Length']).to eq File.stat('spec/spec_helper.rb').size.to_s
157
157
  end
158
158
 
159
159
  it "progressively yields file contents for each enumeration" do
160
160
  subject.encode_body
161
161
  body_size = 0
162
162
  response.body.each do |chunk|
163
- chunk.should be_a(String)
163
+ expect(chunk).to be_instance_of(String)
164
164
  body_size += chunk.length
165
165
  end
166
- body_size.should == File.stat('spec/spec_helper.rb').size
166
+ expect(body_size).to eq File.stat('spec/spec_helper.rb').size
167
167
  end
168
168
 
169
169
  context "when the resource provides a non-identity encoding that the client accepts" do
@@ -188,12 +188,12 @@ describe Webmachine::Decision::Helpers do
188
188
 
189
189
  it "wraps the response body in an IOEncoder" do
190
190
  subject.encode_body
191
- Webmachine::Streaming::IOEncoder.should === response.body
191
+ expect(response.body).to be_instance_of(Webmachine::Streaming::IOEncoder)
192
192
  end
193
193
 
194
194
  it "sets the Content-Length header to the size of the string" do
195
195
  subject.encode_body
196
- response.headers['Content-Length'].should == response.body.size.to_s
196
+ expect(response.headers['Content-Length']).to eq response.body.size.to_s
197
197
  end
198
198
 
199
199
  context "when the resource provides a non-identity encoding that the client accepts" do
@@ -1,11 +1,32 @@
1
1
  require 'spec_helper'
2
2
 
3
+ Webmachine::Dispatcher::Route.class_eval do
4
+ def warn(*msgs); end # silence warnings for tests
5
+ end
6
+
3
7
  describe Webmachine::Dispatcher::Route do
4
8
  let(:method) { "GET" }
5
9
  let(:uri) { URI.parse("http://localhost:8080/") }
6
10
  let(:request){ Webmachine::Request.new(method, uri, Webmachine::Headers.new, "") }
7
11
  let(:resource){ Class.new(Webmachine::Resource) }
8
12
 
13
+ describe '#apply' do
14
+ let(:route) {
15
+ Webmachine::Dispatcher::Route.new ['hello', :string], resource, {}
16
+ }
17
+
18
+ describe 'a path_info fragment' do
19
+ before do
20
+ uri.path = '/hello/planet%20earth%20++'
21
+ end
22
+
23
+ it 'should decode the value' do
24
+ route.apply(request)
25
+ expect(request.path_info).to eq({:string => 'planet earth ++'})
26
+ end
27
+ end
28
+ end
29
+
9
30
  matcher :match_route do |*expected|
10
31
  route = Webmachine::Dispatcher::Route.new(expected[0], Class.new(Webmachine::Resource), expected[1] || {})
11
32
  match do |actual|
@@ -13,31 +34,40 @@ describe Webmachine::Dispatcher::Route do
13
34
  route.match?(request)
14
35
  end
15
36
 
16
- failure_message_for_should do |_|
37
+ failure_message do |_|
17
38
  "expected route #{expected[0].inspect} to match path #{request.uri.path}"
18
39
  end
19
- failure_message_for_should_not do |_|
40
+ failure_message_when_negated do |_|
20
41
  "expected route #{expected[0].inspect} not to match path #{request.uri.path}"
21
42
  end
22
43
  end
23
44
 
45
+ it "warns about the deprecated string splat when initializing" do
46
+ [["*"],["foo", "*"],["foo", :bar, "*"]].each do |path|
47
+ route = described_class.allocate
48
+ expect(route).to receive(:warn)
49
+ route.send :initialize, path, resource, {}
50
+ end
51
+ end
52
+
24
53
  context "matching a request" do
25
54
  context "on the root path" do
26
55
  subject { "/" }
27
- it { should match_route([]) }
28
- it { should match_route ['*'] }
29
- it { should_not match_route %w{foo} }
30
- it { should_not match_route [:id] }
56
+ it { is_expected.to match_route([]) }
57
+ it { is_expected.to match_route ['*'] }
58
+ it { is_expected.to match_route [:*] }
59
+ it { is_expected.not_to match_route %w{foo} }
60
+ it { is_expected.not_to match_route [:id] }
31
61
  end
32
62
 
33
63
  context "on a deep path" do
34
64
  subject { "/foo/bar/baz" }
35
- it { should match_route %w{foo bar baz} }
36
- it { should match_route ['foo', :id, "baz"] }
37
- it { should match_route %w{foo *} }
38
- it { should match_route [:id, '*'] }
39
- it { should_not match_route [] }
40
- it { should_not match_route %w{bar *} }
65
+ it { is_expected.to match_route %w{foo bar baz} }
66
+ it { is_expected.to match_route ['foo', :id, "baz"] }
67
+ it { is_expected.to match_route ['foo', :*] }
68
+ it { is_expected.to match_route [:id, :*] }
69
+ it { is_expected.not_to match_route [] }
70
+ it { is_expected.not_to match_route ['bar', :*] }
41
71
  end
42
72
 
43
73
  context "with a guard on the request method" do
@@ -53,17 +83,17 @@ describe Webmachine::Dispatcher::Route do
53
83
 
54
84
  context "when guard passes" do
55
85
  let(:method){ "POST" }
56
- it { should be_match(request) }
86
+ it { is_expected.to be_match(request) }
57
87
 
58
88
  context "but the path match fails" do
59
89
  let(:uri){ URI.parse("http://localhost:8080/other") }
60
- it { should_not be_match(request) }
90
+ it { is_expected.not_to be_match(request) }
61
91
  end
62
92
  end
63
93
 
64
94
  context "when guard fails" do
65
95
  let(:method) { "GET" }
66
- it { should_not be_match(request) }
96
+ it { is_expected.not_to be_match(request) }
67
97
  end
68
98
 
69
99
  context "when the guard responds to #call" do
@@ -85,12 +115,12 @@ describe Webmachine::Dispatcher::Route do
85
115
 
86
116
  context "when the guard passes" do
87
117
  let(:method){ "POST" }
88
- it { should be_match(request) }
118
+ it { is_expected.to be_match(request) }
89
119
  end
90
120
 
91
121
  context "when the guard fails" do
92
122
  # let(:method){ "GET" }
93
- it { should_not be_match(request) }
123
+ it { is_expected.not_to be_match(request) }
94
124
  end
95
125
  end
96
126
  end
@@ -102,30 +132,38 @@ describe Webmachine::Dispatcher::Route do
102
132
  before { subject.apply(request) }
103
133
 
104
134
  it "should assign the dispatched path to the empty string" do
105
- request.disp_path.should == ""
135
+ expect(request.disp_path).to eq("")
106
136
  end
107
137
 
108
138
  it "should assign empty bindings" do
109
- request.path_info.should == {}
139
+ expect(request.path_info).to eq({})
110
140
  end
111
141
 
112
142
  it "should assign empty path tokens" do
113
- request.path_tokens.should == []
143
+ expect(request.path_tokens).to eq([])
114
144
  end
115
145
 
116
146
  context "with extra user-defined bindings" do
117
147
  subject { described_class.new([], resource, "bar" => "baz") }
118
148
 
119
149
  it "should assign the user-defined bindings" do
120
- request.path_info.should == {"bar" => "baz"}
150
+ expect(request.path_info).to eq({"bar" => "baz"})
121
151
  end
122
152
  end
123
153
 
124
154
  context "with a splat" do
155
+ subject { described_class.new([:*], resource) }
156
+
157
+ it "should assign empty path tokens" do
158
+ expect(request.path_tokens).to eq([])
159
+ end
160
+ end
161
+
162
+ context "with a deprecated splat string" do
125
163
  subject { described_class.new(['*'], resource) }
126
164
 
127
165
  it "should assign empty path tokens" do
128
- request.path_tokens.should == []
166
+ expect(request.path_tokens).to eq([])
129
167
  end
130
168
  end
131
169
  end
@@ -135,30 +173,38 @@ describe Webmachine::Dispatcher::Route do
135
173
  before { request.uri.path = "/foo/bar/baz"; subject.apply(request) }
136
174
 
137
175
  it "should assign the dispatched path as the path past the initial slash" do
138
- request.disp_path.should == "foo/bar/baz"
176
+ expect(request.disp_path).to eq("foo/bar/baz")
139
177
  end
140
178
 
141
179
  it "should assign empty bindings" do
142
- request.path_info.should == {}
180
+ expect(request.path_info).to eq({})
143
181
  end
144
182
 
145
183
  it "should assign empty path tokens" do
146
- request.path_tokens.should == []
184
+ expect(request.path_tokens).to eq([])
147
185
  end
148
186
 
149
187
  context "with path variables" do
150
188
  subject { described_class.new(['foo', :id, 'baz'], resource) }
151
189
 
152
190
  it "should assign the path variables in the bindings" do
153
- request.path_info.should == {:id => "bar"}
191
+ expect(request.path_info).to eq({:id => "bar"})
154
192
  end
155
193
  end
156
194
 
157
195
  context "with a splat" do
196
+ subject { described_class.new(['foo', :*], resource) }
197
+
198
+ it "should capture the path tokens matched by the splat" do
199
+ expect(request.path_tokens).to eq(%w{ bar baz })
200
+ end
201
+ end
202
+
203
+ context "with a deprecated splat string" do
158
204
  subject { described_class.new(%w{foo *}, resource) }
159
205
 
160
206
  it "should capture the path tokens matched by the splat" do
161
- request.path_tokens.should == %w{ bar baz }
207
+ expect(request.path_tokens).to eq(%w{ bar baz })
162
208
  end
163
209
  end
164
210
  end
@@ -14,66 +14,76 @@ describe Webmachine::Dispatcher do
14
14
  def to_html; "goodbye, cruel world"; end
15
15
  end
16
16
  end
17
- let(:fsm){ mock }
17
+ let(:fsm){ double }
18
18
 
19
19
  before { dispatcher.reset }
20
20
 
21
21
  it "should add routes from a block" do
22
22
  _resource = resource
23
- Webmachine.routes do
24
- add ['*'], _resource
25
- end.should == Webmachine
26
- dispatcher.routes.should have(1).item
23
+ expect(Webmachine.routes do
24
+ add [:*], _resource
25
+ end).to eq(Webmachine)
26
+ expect(dispatcher.routes.size).to eq(1)
27
27
  end
28
28
 
29
29
  it "should add routes" do
30
30
  expect {
31
- dispatcher.add_route ['*'], resource
31
+ dispatcher.add_route [:*], resource
32
32
  }.to_not raise_error
33
33
  end
34
34
 
35
35
  it "should have add_route return the newly created route" do
36
- route = dispatcher.add_route ['*'], resource
37
- route.should be_instance_of Webmachine::Dispatcher::Route
36
+ route = dispatcher.add_route [:*], resource
37
+ expect(route).to be_instance_of Webmachine::Dispatcher::Route
38
38
  end
39
39
 
40
40
  it "should route to the proper resource" do
41
41
  dispatcher.add_route ["goodbye"], resource2
42
- dispatcher.add_route ['*'], resource
43
- Webmachine::Decision::FSM.should_receive(:new).with(instance_of(resource), request, response).and_return(fsm)
44
- fsm.should_receive(:run)
42
+ dispatcher.add_route [:*], resource
43
+ expect(Webmachine::Decision::FSM).to receive(:new).with(instance_of(resource), request, response).and_return(fsm)
44
+ expect(fsm).to receive(:run)
45
45
  dispatcher.dispatch(request, response)
46
46
  end
47
47
 
48
48
  it "should apply route to request before creating the resource" do
49
- route = dispatcher.add_route ["*"], resource
49
+ route = dispatcher.add_route [:*], resource
50
50
  applied = false
51
51
 
52
- route.should_receive(:apply) { applied = true }
53
- resource.should_receive(:new) do
54
- applied.should be_true
52
+ expect(route).to receive(:apply) { applied = true }
53
+ expect(resource).to(receive(:new) do
54
+ expect(applied).to be(true)
55
55
  resource2.new(request, response)
56
- end
56
+ end)
57
57
 
58
58
  dispatcher.dispatch(request, response)
59
59
  end
60
60
 
61
61
  it "should add routes with guards" do
62
62
  dispatcher.add [], lambda {|req| req.method == "POST" }, resource
63
- dispatcher.add ['*'], resource2 do |req|
63
+ dispatcher.add [:*], resource2 do |req|
64
64
  !req.query.empty?
65
65
  end
66
66
  request.uri.query = "?foo=bar"
67
- dispatcher.routes.should have(2).items
68
- Webmachine::Decision::FSM.should_receive(:new).with(instance_of(resource2), request, response).and_return(fsm)
69
- fsm.should_receive(:run)
67
+ expect(dispatcher.routes.size).to eq(2)
68
+ expect(Webmachine::Decision::FSM).to receive(:new).with(instance_of(resource2), request, response).and_return(fsm)
69
+ expect(fsm).to receive(:run)
70
+ dispatcher.dispatch(request, response)
71
+ end
72
+
73
+ it "should respond with a valid resource for a 404" do
70
74
  dispatcher.dispatch(request, response)
75
+ expect(response.code).to eq(404)
76
+ expect(response.body).to_not be_empty
77
+ expect(response.headers).to have_key('Content-Length')
78
+ expect(response.headers).to have_key('Date')
71
79
  end
72
80
 
73
- it "should respond with valid resource missing response for request to non-existing route" do
81
+ it "should respond with a valid resource for a 404 with a custom Accept header" do
82
+ request.headers['Accept'] = "application/json"
74
83
  dispatcher.dispatch(request, response)
75
- response.code.should eq(404)
76
- response.body.should_not be_empty
77
- response.headers.should have_key('Content-Length')
84
+ expect(response.code).to eq(404)
85
+ expect(response.body).to_not be_empty
86
+ expect(response.headers).to have_key('Content-Length')
87
+ expect(response.headers).to have_key('Date')
78
88
  end
79
89
  end