webmachine 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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