webmachine 1.2.2 → 1.6.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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/CHANGELOG.md +57 -0
- data/Gemfile +20 -15
- data/README.md +89 -91
- data/RELEASING.md +21 -0
- data/Rakefile +5 -21
- data/documentation/adapters.md +41 -0
- data/documentation/authentication-and-authorization.md +37 -0
- data/documentation/configurator.md +19 -0
- data/documentation/error-handling.md +86 -0
- data/documentation/examples.md +224 -0
- data/documentation/how-it-works.md +76 -0
- data/documentation/routes.md +112 -0
- data/documentation/validation.md +159 -0
- data/documentation/versioning-apis.md +74 -0
- data/documentation/visual-debugger.md +38 -0
- data/examples/application.rb +2 -2
- data/examples/debugger.rb +1 -1
- data/lib/webmachine.rb +3 -1
- data/lib/webmachine/adapter.rb +7 -13
- data/lib/webmachine/adapters.rb +1 -2
- data/lib/webmachine/adapters/httpkit.rb +74 -0
- data/lib/webmachine/adapters/lazy_request_body.rb +1 -2
- data/lib/webmachine/adapters/rack.rb +70 -25
- data/lib/webmachine/adapters/rack_mapped.rb +42 -0
- data/lib/webmachine/adapters/reel.rb +22 -23
- data/lib/webmachine/adapters/webrick.rb +16 -16
- data/lib/webmachine/application.rb +2 -2
- data/lib/webmachine/chunked_body.rb +3 -4
- data/lib/webmachine/configuration.rb +1 -1
- data/lib/webmachine/constants.rb +75 -0
- data/lib/webmachine/decision/conneg.rb +12 -10
- data/lib/webmachine/decision/flow.rb +42 -32
- data/lib/webmachine/decision/fsm.rb +14 -21
- data/lib/webmachine/decision/helpers.rb +10 -38
- data/lib/webmachine/dispatcher.rb +13 -10
- data/lib/webmachine/dispatcher/route.rb +45 -9
- data/lib/webmachine/errors.rb +9 -3
- data/lib/webmachine/events.rb +2 -2
- data/lib/webmachine/header_negotiation.rb +25 -0
- data/lib/webmachine/headers.rb +8 -3
- data/lib/webmachine/locale/en.yml +7 -5
- data/lib/webmachine/media_type.rb +10 -8
- data/lib/webmachine/request.rb +67 -26
- data/lib/webmachine/rescueable_exception.rb +62 -0
- data/lib/webmachine/resource.rb +1 -1
- data/lib/webmachine/resource/callbacks.rb +11 -9
- data/lib/webmachine/response.rb +3 -5
- data/lib/webmachine/spec/IO_response.body +1 -0
- data/lib/webmachine/spec/adapter_lint.rb +83 -37
- data/lib/webmachine/spec/test_resource.rb +15 -4
- data/lib/webmachine/streaming/fiber_encoder.rb +1 -5
- data/lib/webmachine/streaming/io_encoder.rb +7 -1
- data/lib/webmachine/trace.rb +1 -0
- data/lib/webmachine/trace/fsm.rb +20 -10
- data/lib/webmachine/trace/resource_proxy.rb +2 -0
- data/lib/webmachine/translation.rb +2 -1
- data/lib/webmachine/version.rb +3 -3
- data/memory_test.rb +37 -0
- data/spec/spec_helper.rb +17 -9
- data/spec/webmachine/adapter_spec.rb +14 -15
- data/spec/webmachine/adapters/httpkit_spec.rb +10 -0
- data/spec/webmachine/adapters/rack_mapped_spec.rb +71 -0
- data/spec/webmachine/adapters/rack_spec.rb +32 -6
- data/spec/webmachine/adapters/reel_spec.rb +16 -12
- data/spec/webmachine/adapters/webrick_spec.rb +2 -2
- data/spec/webmachine/application_spec.rb +18 -17
- data/spec/webmachine/chunked_body_spec.rb +3 -3
- data/spec/webmachine/configuration_spec.rb +5 -5
- data/spec/webmachine/cookie_spec.rb +13 -13
- data/spec/webmachine/decision/conneg_spec.rb +49 -43
- data/spec/webmachine/decision/falsey_spec.rb +4 -4
- data/spec/webmachine/decision/flow_spec.rb +195 -145
- data/spec/webmachine/decision/fsm_spec.rb +81 -19
- data/spec/webmachine/decision/helpers_spec.rb +20 -20
- data/spec/webmachine/dispatcher/rfc3986_percent_decode_spec.rb +22 -0
- data/spec/webmachine/dispatcher/route_spec.rb +114 -32
- data/spec/webmachine/dispatcher_spec.rb +49 -24
- data/spec/webmachine/errors_spec.rb +1 -1
- data/spec/webmachine/etags_spec.rb +19 -19
- data/spec/webmachine/events_spec.rb +6 -6
- data/spec/webmachine/headers_spec.rb +14 -14
- data/spec/webmachine/media_type_spec.rb +36 -36
- data/spec/webmachine/request_spec.rb +70 -39
- data/spec/webmachine/rescueable_exception_spec.rb +15 -0
- data/spec/webmachine/resource/authentication_spec.rb +6 -6
- data/spec/webmachine/response_spec.rb +18 -12
- data/spec/webmachine/trace/fsm_spec.rb +8 -8
- data/spec/webmachine/trace/resource_proxy_spec.rb +9 -9
- data/spec/webmachine/trace/trace_store_spec.rb +5 -5
- data/spec/webmachine/trace_spec.rb +3 -3
- data/webmachine.gemspec +2 -6
- metadata +78 -228
- data/lib/webmachine/adapters/hatetepe.rb +0 -108
- data/lib/webmachine/adapters/mongrel.rb +0 -127
- data/lib/webmachine/dispatcher/not_found_resource.rb +0 -5
- data/lib/webmachine/fiber18.rb +0 -88
- data/spec/webmachine/adapters/hatetepe_spec.rb +0 -60
- data/spec/webmachine/adapters/mongrel_spec.rb +0 -16
|
@@ -3,55 +3,66 @@ require 'spec_helper'
|
|
|
3
3
|
describe Webmachine::Request do
|
|
4
4
|
subject { request }
|
|
5
5
|
|
|
6
|
-
let(:uri)
|
|
7
|
-
let(:http_method)
|
|
8
|
-
let(:headers)
|
|
9
|
-
let(:body)
|
|
10
|
-
let(:
|
|
6
|
+
let(:uri) { URI.parse("http://localhost:8080/some/resource") }
|
|
7
|
+
let(:http_method) { "GET" }
|
|
8
|
+
let(:headers) { Webmachine::Headers.new }
|
|
9
|
+
let(:body) { "" }
|
|
10
|
+
let(:routing_tokens) { nil }
|
|
11
|
+
let(:base_uri) { nil }
|
|
12
|
+
let(:request) { Webmachine::Request.new(http_method, uri, headers, body, routing_tokens, base_uri) }
|
|
11
13
|
|
|
12
14
|
it "should provide access to the headers via brackets" do
|
|
13
15
|
subject.headers['Accept'] = "*/*"
|
|
14
|
-
subject["accept"].
|
|
16
|
+
expect(subject["accept"]).to eq("*/*")
|
|
15
17
|
end
|
|
16
18
|
|
|
17
19
|
it "should provide access to the cookies" do
|
|
18
20
|
subject.headers['Cookie'] = 'name=value;name2=value2';
|
|
19
|
-
subject.cookies.
|
|
21
|
+
expect(subject.cookies).to eq({ 'name' => 'value', 'name2' => 'value2' })
|
|
20
22
|
end
|
|
21
23
|
|
|
22
24
|
it "should handle cookies with extra whitespace" do
|
|
23
25
|
subject.headers['Cookie'] = 'name = value; name2 = value2';
|
|
24
|
-
subject.cookies.
|
|
26
|
+
expect(subject.cookies).to eq({ 'name' => 'value', 'name2' => 'value2' })
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
it "should provide access to the headers via underscored methods" do
|
|
28
30
|
subject.headers["Accept-Encoding"] = "identity"
|
|
29
|
-
subject.accept_encoding.
|
|
30
|
-
subject.content_md5.
|
|
31
|
+
expect(subject.accept_encoding).to eq("identity")
|
|
32
|
+
expect(subject.content_md5).to be_nil
|
|
31
33
|
end
|
|
32
34
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
+
context "base_uri" do
|
|
36
|
+
it "should calculate a base URI" do
|
|
37
|
+
expect(subject.base_uri).to eq(URI.parse("http://localhost:8080/"))
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "when base_uri has been explicitly set" do
|
|
41
|
+
let(:base_uri) { URI.parse("http://localhost:8080/some_base_uri/here") }
|
|
42
|
+
it "should use the provided base_uri" do
|
|
43
|
+
expect(subject.base_uri).to eq(URI.parse("http://localhost:8080/some_base_uri/here"))
|
|
44
|
+
end
|
|
45
|
+
end
|
|
35
46
|
end
|
|
36
47
|
|
|
37
48
|
it "should provide a hash of query parameters" do
|
|
38
49
|
subject.uri.query = "foo=bar&baz=bam"
|
|
39
|
-
subject.query.
|
|
50
|
+
expect(subject.query).to eq({"foo" => "bar", "baz" => "bam"})
|
|
40
51
|
end
|
|
41
52
|
|
|
42
53
|
it "should handle = being encoded as a query value." do
|
|
43
54
|
subject.uri.query = "foo=bar%3D%3D"
|
|
44
|
-
subject.query.
|
|
55
|
+
expect(subject.query).to eq({ "foo" => "bar=="})
|
|
45
56
|
end
|
|
46
57
|
|
|
47
58
|
it "should treat '+' characters in query parameters as spaces" do
|
|
48
59
|
subject.uri.query = "a%20b=foo+bar&c+d=baz%20quux"
|
|
49
|
-
subject.query.
|
|
60
|
+
expect(subject.query).to eq({"a b" => "foo bar", "c d" => "baz quux"})
|
|
50
61
|
end
|
|
51
62
|
|
|
52
63
|
it "should handle a query parameter value of nil" do
|
|
53
64
|
subject.uri.query = nil
|
|
54
|
-
subject.query.
|
|
65
|
+
expect(subject.query).to eq({})
|
|
55
66
|
end
|
|
56
67
|
|
|
57
68
|
describe '#has_body?' do
|
|
@@ -67,31 +78,31 @@ describe Webmachine::Request do
|
|
|
67
78
|
context "when body is nil" do
|
|
68
79
|
let(:body) { nil }
|
|
69
80
|
|
|
70
|
-
it {
|
|
81
|
+
it { is_expected.to be(false) }
|
|
71
82
|
end
|
|
72
83
|
|
|
73
84
|
context "when body is an empty string" do
|
|
74
85
|
let(:body) { '' }
|
|
75
86
|
|
|
76
|
-
it {
|
|
87
|
+
it { is_expected.to be(false) }
|
|
77
88
|
end
|
|
78
89
|
|
|
79
90
|
context "when body is not empty" do
|
|
80
91
|
let(:body) { 'foo' }
|
|
81
92
|
|
|
82
|
-
it {
|
|
93
|
+
it { is_expected.to be(true) }
|
|
83
94
|
end
|
|
84
95
|
|
|
85
96
|
context "when body is an empty LazyRequestBody" do
|
|
86
97
|
let(:body) { Webmachine::Adapters::LazyRequestBody.new(wreq.new('')) }
|
|
87
98
|
|
|
88
|
-
it {
|
|
99
|
+
it { is_expected.to be(false) }
|
|
89
100
|
end
|
|
90
101
|
|
|
91
102
|
context "when body is a LazyRequestBody" do
|
|
92
103
|
let(:body) { Webmachine::Adapters::LazyRequestBody.new(wreq.new('foo')) }
|
|
93
104
|
|
|
94
|
-
it {
|
|
105
|
+
it { is_expected.to be(true) }
|
|
95
106
|
end
|
|
96
107
|
end
|
|
97
108
|
|
|
@@ -101,13 +112,13 @@ describe Webmachine::Request do
|
|
|
101
112
|
context "when the request was issued via HTTPS" do
|
|
102
113
|
let(:uri) { URI.parse("https://localhost.com:8080/some/resource") }
|
|
103
114
|
|
|
104
|
-
it {
|
|
115
|
+
it { is_expected.to be(true) }
|
|
105
116
|
end
|
|
106
117
|
|
|
107
118
|
context "when the request was not issued via HTTPS" do
|
|
108
119
|
let(:uri) { URI.parse("http://localhost.com:8080/some/resource") }
|
|
109
120
|
|
|
110
|
-
it {
|
|
121
|
+
it { is_expected.to be(false) }
|
|
111
122
|
end
|
|
112
123
|
end
|
|
113
124
|
|
|
@@ -117,13 +128,13 @@ describe Webmachine::Request do
|
|
|
117
128
|
context "when the request method is GET" do
|
|
118
129
|
let(:http_method) { "GET" }
|
|
119
130
|
|
|
120
|
-
it {
|
|
131
|
+
it { is_expected.to be(true) }
|
|
121
132
|
end
|
|
122
133
|
|
|
123
134
|
context "when the request method is not GET" do
|
|
124
135
|
let(:http_method) { "POST" }
|
|
125
136
|
|
|
126
|
-
it {
|
|
137
|
+
it { is_expected.to be(false) }
|
|
127
138
|
end
|
|
128
139
|
end
|
|
129
140
|
|
|
@@ -133,13 +144,13 @@ describe Webmachine::Request do
|
|
|
133
144
|
context "when the request method is HEAD" do
|
|
134
145
|
let(:http_method) { "HEAD" }
|
|
135
146
|
|
|
136
|
-
it {
|
|
147
|
+
it { is_expected.to be(true) }
|
|
137
148
|
end
|
|
138
149
|
|
|
139
150
|
context "when the request method is not HEAD" do
|
|
140
151
|
let(:http_method) { "GET" }
|
|
141
152
|
|
|
142
|
-
it {
|
|
153
|
+
it { is_expected.to be(false) }
|
|
143
154
|
end
|
|
144
155
|
end
|
|
145
156
|
|
|
@@ -149,13 +160,13 @@ describe Webmachine::Request do
|
|
|
149
160
|
context "when the request method is POST" do
|
|
150
161
|
let(:http_method) { "POST" }
|
|
151
162
|
|
|
152
|
-
it {
|
|
163
|
+
it { is_expected.to be(true) }
|
|
153
164
|
end
|
|
154
165
|
|
|
155
166
|
context "when the request method is not POST" do
|
|
156
167
|
let(:http_method) { "GET" }
|
|
157
168
|
|
|
158
|
-
it {
|
|
169
|
+
it { is_expected.to be(false) }
|
|
159
170
|
end
|
|
160
171
|
end
|
|
161
172
|
|
|
@@ -165,13 +176,13 @@ describe Webmachine::Request do
|
|
|
165
176
|
context "when the request method is PUT" do
|
|
166
177
|
let(:http_method) { "PUT" }
|
|
167
178
|
|
|
168
|
-
it {
|
|
179
|
+
it { is_expected.to be(true) }
|
|
169
180
|
end
|
|
170
181
|
|
|
171
182
|
context "when the request method is not PUT" do
|
|
172
183
|
let(:http_method) { "GET" }
|
|
173
184
|
|
|
174
|
-
it {
|
|
185
|
+
it { is_expected.to be(false) }
|
|
175
186
|
end
|
|
176
187
|
end
|
|
177
188
|
|
|
@@ -181,13 +192,13 @@ describe Webmachine::Request do
|
|
|
181
192
|
context "when the request method is DELETE" do
|
|
182
193
|
let(:http_method) { "DELETE" }
|
|
183
194
|
|
|
184
|
-
it {
|
|
195
|
+
it { is_expected.to be(true) }
|
|
185
196
|
end
|
|
186
197
|
|
|
187
198
|
context "when the request method is not DELETE" do
|
|
188
199
|
let(:http_method) { "GET" }
|
|
189
200
|
|
|
190
|
-
it {
|
|
201
|
+
it { is_expected.to be(false) }
|
|
191
202
|
end
|
|
192
203
|
end
|
|
193
204
|
|
|
@@ -197,13 +208,13 @@ describe Webmachine::Request do
|
|
|
197
208
|
context "when the request method is TRACE" do
|
|
198
209
|
let(:http_method) { "TRACE" }
|
|
199
210
|
|
|
200
|
-
it {
|
|
211
|
+
it { is_expected.to be(true) }
|
|
201
212
|
end
|
|
202
213
|
|
|
203
214
|
context "when the request method is not TRACE" do
|
|
204
215
|
let(:http_method) { "GET" }
|
|
205
216
|
|
|
206
|
-
it {
|
|
217
|
+
it { is_expected.to be(false) }
|
|
207
218
|
end
|
|
208
219
|
end
|
|
209
220
|
|
|
@@ -213,13 +224,13 @@ describe Webmachine::Request do
|
|
|
213
224
|
context "when the request method is CONNECT" do
|
|
214
225
|
let(:http_method) { "CONNECT" }
|
|
215
226
|
|
|
216
|
-
it {
|
|
227
|
+
it { is_expected.to be(true) }
|
|
217
228
|
end
|
|
218
229
|
|
|
219
230
|
context "when the request method is not CONNECT" do
|
|
220
231
|
let(:http_method) { "GET" }
|
|
221
232
|
|
|
222
|
-
it {
|
|
233
|
+
it { is_expected.to be(false) }
|
|
223
234
|
end
|
|
224
235
|
end
|
|
225
236
|
|
|
@@ -229,14 +240,34 @@ describe Webmachine::Request do
|
|
|
229
240
|
context "when the request method is OPTIONS" do
|
|
230
241
|
let(:http_method) { "OPTIONS" }
|
|
231
242
|
|
|
232
|
-
it {
|
|
243
|
+
it { is_expected.to be(true) }
|
|
233
244
|
end
|
|
234
245
|
|
|
235
246
|
context "when the request method is not OPTIONS" do
|
|
236
247
|
let(:http_method) { "GET" }
|
|
237
248
|
|
|
238
|
-
it {
|
|
249
|
+
it { is_expected.to be(false) }
|
|
239
250
|
end
|
|
240
251
|
end
|
|
241
252
|
|
|
253
|
+
describe '#routing_tokens' do
|
|
254
|
+
subject { request.routing_tokens }
|
|
255
|
+
|
|
256
|
+
context "haven't been explicitly set" do
|
|
257
|
+
let(:routing_tokens) { nil }
|
|
258
|
+
it "extracts the routing tokens from the path portion of the uri" do
|
|
259
|
+
expect(subject).to eq(["some", "resource"])
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context "have been explicitly set" do
|
|
264
|
+
let(:routing_tokens) { ["foo", "bar"] }
|
|
265
|
+
|
|
266
|
+
it "uses the specified routing_tokens" do
|
|
267
|
+
expect(subject).to eq(["foo", "bar"])
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
end
|
|
272
|
+
|
|
242
273
|
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
RSpec.describe Webmachine::RescuableException do
|
|
3
|
+
before { described_class.default! }
|
|
4
|
+
|
|
5
|
+
describe ".UNRESCUABLEs" do
|
|
6
|
+
specify "returns an array of UNRESCUABLE exceptions" do
|
|
7
|
+
expect(described_class.UNRESCUABLEs).to eq(described_class::UNRESCUABLE_DEFAULTS)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
specify "returns an array of UNRESCUABLE exceptions, with custom exceptions added" do
|
|
11
|
+
described_class.remove(Exception)
|
|
12
|
+
expect(described_class.UNRESCUABLEs).to eq(described_class::UNRESCUABLE_DEFAULTS.dup.concat([Exception]))
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -31,14 +31,14 @@ describe Webmachine::Resource::Authentication do
|
|
|
31
31
|
context "when no authorization is sent by the client" do
|
|
32
32
|
it "should reply with a 401 Unauthorized and a WWW-Authenticate header using Basic" do
|
|
33
33
|
subject.run
|
|
34
|
-
response.code.
|
|
35
|
-
response.headers['WWW-Authenticate'].
|
|
34
|
+
expect(response.code).to eq(401)
|
|
35
|
+
expect(response.headers['WWW-Authenticate']).to eq('Basic realm="Webmachine"')
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
it "should use the specified realm in the WWW-Authenticate header" do
|
|
39
39
|
resource.realm = "My App"
|
|
40
40
|
subject.run
|
|
41
|
-
response.headers['WWW-Authenticate'].
|
|
41
|
+
expect(response.headers['WWW-Authenticate']).to eq('Basic realm="My App"')
|
|
42
42
|
end
|
|
43
43
|
end
|
|
44
44
|
|
|
@@ -49,8 +49,8 @@ describe Webmachine::Resource::Authentication do
|
|
|
49
49
|
|
|
50
50
|
it "should reply with a 401 Unauthorized and a WWW-Authenticate header using Basic" do
|
|
51
51
|
subject.run
|
|
52
|
-
response.code.
|
|
53
|
-
response.headers['WWW-Authenticate'].
|
|
52
|
+
expect(response.code).to eq(401)
|
|
53
|
+
expect(response.headers['WWW-Authenticate']).to eq('Basic realm="Webmachine"')
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
|
|
@@ -61,7 +61,7 @@ describe Webmachine::Resource::Authentication do
|
|
|
61
61
|
|
|
62
62
|
it "should not reply with 401 Unauthorized" do
|
|
63
63
|
subject.run
|
|
64
|
-
response.code.
|
|
64
|
+
expect(response.code).not_to eq(401)
|
|
65
65
|
end
|
|
66
66
|
end
|
|
67
67
|
end
|
|
@@ -3,20 +3,20 @@ require 'spec_helper'
|
|
|
3
3
|
describe Webmachine::Response do
|
|
4
4
|
|
|
5
5
|
it "should have sane default values" do
|
|
6
|
-
subject.code.
|
|
7
|
-
subject.is_redirect
|
|
8
|
-
subject.headers.
|
|
6
|
+
expect(subject.code).to eq(200)
|
|
7
|
+
expect(subject.is_redirect?).to be(false)
|
|
8
|
+
expect(subject.headers).to be_empty
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
describe "a redirected response" do
|
|
12
12
|
let(:redirect_url) { "/" }
|
|
13
13
|
|
|
14
|
-
before(:
|
|
14
|
+
before(:each) { subject.redirect_to redirect_url }
|
|
15
15
|
|
|
16
|
-
its(:is_redirect?) { should
|
|
16
|
+
its(:is_redirect?) { should be(true) }
|
|
17
17
|
|
|
18
18
|
it "should have a proper Location header" do
|
|
19
|
-
subject.headers["Location"].
|
|
19
|
+
expect(subject.headers["Location"]).to eq(redirect_url)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
@@ -24,21 +24,27 @@ describe Webmachine::Response do
|
|
|
24
24
|
let(:cookie) { "monster" }
|
|
25
25
|
let(:cookie_value) { "mash" }
|
|
26
26
|
|
|
27
|
-
before(:
|
|
27
|
+
before(:each) { subject.set_cookie(cookie, cookie_value) }
|
|
28
28
|
|
|
29
29
|
it "should have a proper Set-Cookie header" do
|
|
30
|
-
subject.headers["Set-Cookie"].
|
|
30
|
+
expect(subject.headers["Set-Cookie"]).to include "monster=mash"
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
describe "setting multiple cookies" do
|
|
34
34
|
let(:cookie2) { "rodeo" }
|
|
35
35
|
let(:cookie2_value) { "clown" }
|
|
36
|
-
|
|
36
|
+
let(:cookie3) {"color"}
|
|
37
|
+
let(:cookie3_value) {"blue"}
|
|
38
|
+
before(:each) do
|
|
39
|
+
subject.set_cookie(cookie2, cookie2_value)
|
|
40
|
+
subject.set_cookie(cookie3, cookie3_value)
|
|
41
|
+
end
|
|
37
42
|
|
|
38
43
|
it "should have a proper Set-Cookie header" do
|
|
39
|
-
subject.headers["Set-Cookie"].
|
|
40
|
-
subject.headers["Set-Cookie"].
|
|
41
|
-
subject.headers["Set-Cookie"].
|
|
44
|
+
expect(subject.headers["Set-Cookie"]).to be_a Array
|
|
45
|
+
expect(subject.headers["Set-Cookie"]).to include "rodeo=clown"
|
|
46
|
+
expect(subject.headers["Set-Cookie"]).to include "monster=mash"
|
|
47
|
+
expect(subject.headers["Set-Cookie"]).to include "color=blue"
|
|
42
48
|
end
|
|
43
49
|
end
|
|
44
50
|
end
|
|
@@ -7,31 +7,31 @@ describe Webmachine::Trace::FSM do
|
|
|
7
7
|
before { Webmachine::Trace.trace_store = :memory }
|
|
8
8
|
|
|
9
9
|
context "when tracing is enabled" do
|
|
10
|
-
before { Webmachine::Trace.
|
|
10
|
+
before { allow(Webmachine::Trace).to receive(:trace?).and_return(true) }
|
|
11
11
|
|
|
12
12
|
it "proxies the resource" do
|
|
13
|
-
subject.resource.
|
|
13
|
+
expect(subject.resource).to be_kind_of(Webmachine::Trace::ResourceProxy)
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
it "records a trace" do
|
|
17
17
|
subject.run
|
|
18
|
-
response.trace.
|
|
19
|
-
Webmachine::Trace.traces.
|
|
18
|
+
expect(response.trace).to_not be_empty
|
|
19
|
+
expect(Webmachine::Trace.traces.size).to eq(1)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it "commits the trace to separate storage when the request has finished processing" do
|
|
23
|
-
Webmachine::Trace.
|
|
23
|
+
expect(Webmachine::Trace).to receive(:record).with(subject.resource.object_id.to_s, response.trace).and_return(true)
|
|
24
24
|
subject.run
|
|
25
25
|
end
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
context "when tracing is disabled" do
|
|
29
|
-
before { Webmachine::Trace.
|
|
29
|
+
before { allow(Webmachine::Trace).to receive(:trace?).and_return(false) }
|
|
30
30
|
|
|
31
31
|
it "leaves no trace" do
|
|
32
32
|
subject.run
|
|
33
|
-
response.trace.
|
|
34
|
-
Webmachine::Trace.traces.
|
|
33
|
+
expect(response.trace).to be_empty
|
|
34
|
+
expect(Webmachine::Trace.traces).to be_empty
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -7,28 +7,28 @@ describe Webmachine::Trace::ResourceProxy do
|
|
|
7
7
|
|
|
8
8
|
it "duck-types all callback methods" do
|
|
9
9
|
Webmachine::Resource::Callbacks.instance_methods(false).each do |m|
|
|
10
|
-
subject.
|
|
10
|
+
expect(subject).to respond_to(m)
|
|
11
11
|
end
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it "logs invocations of callbacks" do
|
|
15
15
|
subject.generate_etag
|
|
16
|
-
response.trace.
|
|
17
|
-
{:type => :result, :value => nil}]
|
|
16
|
+
expect(response.trace).to eq([{:type => :attempt, :name => "(default)#generate_etag"},
|
|
17
|
+
{:type => :result, :value => nil}])
|
|
18
18
|
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
it "logs invocations of body-producing methods" do
|
|
22
|
-
subject.content_types_provided.
|
|
22
|
+
expect(subject.content_types_provided).to eq([["text/html", :to_html]])
|
|
23
23
|
subject.to_html
|
|
24
|
-
response.trace[-2][:type].
|
|
25
|
-
response.trace[-2][:name].
|
|
26
|
-
response.trace[-2][:source].
|
|
27
|
-
response.trace[-1].
|
|
24
|
+
expect(response.trace[-2][:type]).to eq(:attempt)
|
|
25
|
+
expect(response.trace[-2][:name]).to match(/to_html$/)
|
|
26
|
+
expect(response.trace[-2][:source]).to include("spec_helper.rb") if response.trace[-2][:source]
|
|
27
|
+
expect(response.trace[-1]).to eq({:type => :result, :value => "<html><body>Hello, world!</body></html>"})
|
|
28
28
|
end
|
|
29
29
|
|
|
30
30
|
it "sets the trace id header when the request has finished processing" do
|
|
31
31
|
subject.finish_request
|
|
32
|
-
response.headers["X-Webmachine-Trace-Id"].
|
|
32
|
+
expect(response.headers["X-Webmachine-Trace-Id"]).to eq(subject.object_id.to_s)
|
|
33
33
|
end
|
|
34
34
|
end
|