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
@@ -1,8 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Webmachine::Decision::Falsey do
4
- specify { (described_class.=== false).should be_true }
5
- specify { (described_class.=== nil).should be_true }
6
- specify { (described_class.=== true).should be_false }
7
- specify { (described_class.=== []).should be_false }
4
+ specify { expect(described_class.=== false).to be(true) }
5
+ specify { expect(described_class.=== nil).to be(true) }
6
+ specify { expect(described_class.=== true).to be(false) }
7
+ specify { expect(described_class.=== []).to be(false) }
8
8
  end
@@ -16,7 +16,7 @@ describe Webmachine::Decision::Flow do
16
16
  # ... [except 1xx or 5xx]
17
17
  after(:each) do
18
18
  unless response.code < 200 || response.code >= 500
19
- response.headers.should have_key('Date')
19
+ expect(response.headers).to have_key('Date')
20
20
  end
21
21
  end
22
22
 
@@ -46,7 +46,7 @@ describe Webmachine::Decision::Flow do
46
46
  it "should respond with 503 when the service is unavailable" do
47
47
  resource.available = false
48
48
  subject.run
49
- response.code.should == 503
49
+ expect(response.code).to eq 503
50
50
  end
51
51
  end
52
52
 
@@ -59,7 +59,7 @@ describe Webmachine::Decision::Flow do
59
59
 
60
60
  it "should respond with 501 when the method is unknown" do
61
61
  subject.run
62
- response.code.should == 501
62
+ expect(response.code).to eq 501
63
63
  end
64
64
  end
65
65
 
@@ -72,7 +72,7 @@ describe Webmachine::Decision::Flow do
72
72
 
73
73
  it "should respond with 414 when the URI is too long" do
74
74
  subject.run
75
- response.code.should == 414
75
+ expect(response.code).to eq 414
76
76
  end
77
77
  end
78
78
 
@@ -85,8 +85,8 @@ describe Webmachine::Decision::Flow do
85
85
 
86
86
  it "should respond with 405 when the method is not allowed" do
87
87
  subject.run
88
- response.code.should == 405
89
- response.headers['Allow'].should == "POST"
88
+ expect(response.code).to eq 405
89
+ expect(response.headers['Allow']).to eq "POST"
90
90
  end
91
91
  end
92
92
 
@@ -95,7 +95,7 @@ describe Webmachine::Decision::Flow do
95
95
 
96
96
  it "should respond with 400 when the request is malformed" do
97
97
  subject.run
98
- response.code.should == 400
98
+ expect(response.code).to eq 400
99
99
  end
100
100
 
101
101
  context "when the Content-MD5 header is present" do
@@ -112,31 +112,61 @@ describe Webmachine::Decision::Flow do
112
112
  let(:body) { "This is the body." }
113
113
  let(:headers) { Webmachine::Headers["Content-Type" => "text/plain"] }
114
114
 
115
+ it "should respond with 204 when the request body does match the header" do
116
+ headers['Content-MD5'] = Base64.encode64 Digest::MD5.hexdigest(body)
117
+ subject.run
118
+ expect(response.code).to eq 204
119
+ end
120
+
121
+ it "should bypass validation when the header has a nil value" do
122
+ headers['Content-MD5'] = nil
123
+ subject.run
124
+ expect(response.code).to eq 204
125
+ end
126
+
127
+ it "should respond with 400 when the header has a empty string value" do
128
+ headers['Content-MD5'] = ""
129
+ subject.run
130
+ expect(response.code).to eq 400
131
+ end
132
+
133
+ it "should respond with 400 when the header has a non-hashed, non-encoded value" do
134
+ headers["Content-MD5"] = body
135
+ subject.run
136
+ expect(response.code).to eq 400
137
+ end
138
+
139
+ it "should respond with 400 when the header is not encoded as Base64 but digest matches the body" do
140
+ headers['Content-MD5'] = Digest::MD5.hexdigest(body)
141
+ subject.run
142
+ expect(response.code).to eq 400
143
+ end
144
+
115
145
  it "should respond with 400 when the request body does not match the header" do
116
- headers['Content-MD5'] = "thiswillnotmatchthehash"
146
+ headers['Content-MD5'] = Base64.encode64 Digest::MD5.hexdigest("thiswillnotmatchthehash")
117
147
  subject.run
118
- response.code.should == 400
148
+ expect(response.code).to eq 400
119
149
  end
120
150
 
121
151
  it "should respond with 400 when the resource invalidates the checksum" do
122
152
  resource.validation = false
123
- headers['Content-MD5'] = "thiswillnotmatchthehash"
153
+ headers['Content-MD5'] = Base64.encode64 Digest::MD5.hexdigest("thiswillnotmatchthehash")
124
154
  subject.run
125
- response.code.should == 400
155
+ expect(response.code).to eq 400
126
156
  end
127
157
 
128
158
  it "should not respond with 400 when the resource validates the checksum" do
129
159
  resource.validation = true
130
- headers['Content-MD5'] = "thiswillnotmatchthehash"
160
+ headers['Content-MD5'] = Base64.encode64 Digest::MD5.hexdigest("thiswillnotmatchthehash")
131
161
  subject.run
132
- response.code.should_not == 400
162
+ expect(response.code).to_not eq 400
133
163
  end
134
164
 
135
165
  it "should respond with the given code when the resource returns a code while validating" do
136
166
  resource.validation = 500
137
- headers['Content-MD5'] = "thiswillnotmatchthehash"
167
+ headers['Content-MD5'] = Base64.encode64 Digest::MD5.hexdigest("thiswillnotmatchthehash")
138
168
  subject.run
139
- response.code.should == 500
169
+ expect(response.code).to eq 500
140
170
  end
141
171
  end
142
172
  end
@@ -147,26 +177,26 @@ describe Webmachine::Decision::Flow do
147
177
  it "should reply with 401 when the client is unauthorized" do
148
178
  resource.auth = false
149
179
  subject.run
150
- response.code.should == 401
180
+ expect(response.code).to eq 401
151
181
  end
152
182
 
153
183
  it "should reply with 401 when the resource gives a challenge" do
154
184
  resource.auth = "Basic realm=Webmachine"
155
185
  subject.run
156
- response.code.should == 401
157
- response.headers['WWW-Authenticate'].should == "Basic realm=Webmachine"
186
+ expect(response.code).to eq 401
187
+ expect(response.headers['WWW-Authenticate']).to eq "Basic realm=Webmachine"
158
188
  end
159
189
 
160
190
  it "should halt with the given code when the resource returns a status code" do
161
191
  resource.auth = 400
162
192
  subject.run
163
- response.code.should == 400
193
+ expect(response.code).to eq 400
164
194
  end
165
195
 
166
196
  it "should not reply with 401 when the client is authorized" do
167
197
  resource.auth = true
168
198
  subject.run
169
- response.code.should_not == 401
199
+ expect(response.code).to_not eq 401
170
200
  end
171
201
  end
172
202
 
@@ -176,19 +206,19 @@ describe Webmachine::Decision::Flow do
176
206
  it "should reply with 403 when the request is forbidden" do
177
207
  resource.forbid = true
178
208
  subject.run
179
- response.code.should == 403
209
+ expect(response.code).to eq 403
180
210
  end
181
211
 
182
212
  it "should not reply with 403 when the request is permitted" do
183
213
  resource.forbid = false
184
214
  subject.run
185
- response.code.should_not == 403
215
+ expect(response.code).to_not eq 403
186
216
  end
187
217
 
188
218
  it "should halt with the given code when the resource returns a status code" do
189
219
  resource.forbid = 400
190
220
  subject.run
191
- response.code.should == 400
221
+ expect(response.code).to eq 400
192
222
  end
193
223
  end
194
224
 
@@ -204,12 +234,12 @@ describe Webmachine::Decision::Flow do
204
234
  it "should reply with 501 when an invalid Content-* header is present" do
205
235
  headers['Content-Fail'] = "yup"
206
236
  subject.run
207
- response.code.should == 501
237
+ expect(response.code).to eq 501
208
238
  end
209
239
 
210
240
  it "should not reply with 501 when all Content-* headers are valid" do
211
241
  subject.run
212
- response.code.should_not == 501
242
+ expect(response.code).to_not eq 501
213
243
  end
214
244
  end
215
245
 
@@ -229,13 +259,13 @@ describe Webmachine::Decision::Flow do
229
259
  it "should reply with 415 when the Content-Type is unknown" do
230
260
  headers['Content-Type'] = "application/x-unknown-type"
231
261
  subject.run
232
- response.code.should == 415
262
+ expect(response.code).to eq 415
233
263
  end
234
264
 
235
265
  it "should not reply with 415 when the Content-Type is known" do
236
266
  headers['Content-Type'] = "text/plain"
237
267
  subject.run
238
- response.code.should_not == 415
268
+ expect(response.code).to_not eq 415
239
269
  end
240
270
  end
241
271
 
@@ -254,7 +284,7 @@ describe Webmachine::Decision::Flow do
254
284
  let(:body) { "Big" * 100 }
255
285
  it "should reply with 413" do
256
286
  subject.run
257
- response.code.should == 413
287
+ expect(response.code).to eq 413
258
288
  end
259
289
  end
260
290
 
@@ -263,7 +293,7 @@ describe Webmachine::Decision::Flow do
263
293
 
264
294
  it "should not reply with 413" do
265
295
  subject.run
266
- response.code.should_not == 413
296
+ expect(response.code).to_not eq 413
267
297
  end
268
298
  end
269
299
  end
@@ -273,7 +303,7 @@ describe Webmachine::Decision::Flow do
273
303
  let(:resource){ resource_with { def allowed_methods; %w[GET HEAD OPTIONS]; end } }
274
304
  it "should reply with 200 when the request method is OPTIONS" do
275
305
  subject.run
276
- response.code.should == 200
306
+ expect(response.code).to eq 200
277
307
  end
278
308
  end
279
309
 
@@ -283,23 +313,23 @@ describe Webmachine::Decision::Flow do
283
313
  it "should reply with 406 when the type is unacceptable" do
284
314
  headers['Accept'] = "text/plain"
285
315
  subject.run
286
- response.code.should == 406
316
+ expect(response.code).to eq 406
287
317
  end
288
318
 
289
319
  it "should not reply with 406 when the type is acceptable" do
290
320
  headers['Accept'] = "text/*"
291
321
  subject.run
292
- response.code.should_not == 406
293
- response.headers['Content-Type'].should == "text/html"
322
+ expect(response.code).to_not eq 406
323
+ expect(response.headers['Content-Type']).to eq "text/html"
294
324
  end
295
325
  end
296
326
 
297
327
  context "when the Accept header does not exist" do
298
328
  it "should not negotiate a media type" do
299
- headers['Accept'].should be_nil
300
- subject.should_not_receive(:c4)
329
+ expect(headers['Accept']).to be_nil
330
+ expect(subject).to_not receive(:c4)
301
331
  subject.run
302
- response.headers['Content-Type'].should == 'text/html'
332
+ expect(response.headers['Content-Type']).to eq 'text/html'
303
333
  end
304
334
  end
305
335
  end
@@ -310,25 +340,25 @@ describe Webmachine::Decision::Flow do
310
340
  it "should reply with 406 when the language is unacceptable" do
311
341
  headers['Accept-Language'] = "es, de"
312
342
  subject.run
313
- response.code.should == 406
343
+ expect(response.code).to eq 406
314
344
  end
315
345
 
316
346
  it "should not reply with 406 when the language is acceptable" do
317
347
  headers['Accept-Language'] = "en-GB, en;q=0.7"
318
348
  subject.run
319
- response.code.should_not == 406
320
- response.headers['Content-Language'].should == "en-US"
321
- resource.instance_variable_get(:@language).should == 'en-US'
349
+ expect(response.code).to_not eq 406
350
+ expect(response.headers['Content-Language']).to eq "en-US"
351
+ expect(resource.instance_variable_get(:@language)).to eq 'en-US'
322
352
  end
323
353
  end
324
354
 
325
355
  context "when the Accept-Language header is absent" do
326
356
  it "should not negotiate the language" do
327
- headers['Accept-Language'].should be_nil
328
- subject.should_not_receive(:d5)
357
+ expect(headers['Accept-Language']).to be_nil
358
+ expect(subject).to_not receive(:d5)
329
359
  subject.run
330
- response.headers['Content-Language'].should == 'en-US'
331
- resource.instance_variable_get(:@language).should == 'en-US'
360
+ expect(response.headers['Content-Language']).to eq 'en-US'
361
+ expect(resource.instance_variable_get(:@language)).to eq 'en-US'
332
362
  end
333
363
  end
334
364
  end
@@ -348,23 +378,23 @@ describe Webmachine::Decision::Flow do
348
378
  it "should reply with 406 when the charset is unacceptable" do
349
379
  headers['Accept-Charset'] = "utf-16"
350
380
  subject.run
351
- response.code.should == 406
381
+ expect(response.code).to eq 406
352
382
  end
353
383
 
354
384
  it "should not reply with 406 when the charset is acceptable" do
355
385
  headers['Accept-Charset'] = "iso8859-1"
356
386
  subject.run
357
- response.code.should_not == 406
358
- response.headers['Content-Type'].should == "text/html;charset=iso8859-1"
387
+ expect(response.code).to_not eq 406
388
+ expect(response.headers['Content-Type']).to eq "text/html;charset=iso8859-1"
359
389
  end
360
390
  end
361
391
 
362
392
  context "when the Accept-Charset header is absent" do
363
393
  it "should not negotiate the language" do
364
- headers['Accept-Charset'].should be_nil
365
- subject.should_not_receive(:e6)
394
+ expect(headers['Accept-Charset']).to be_nil
395
+ expect(subject).to_not receive(:e6)
366
396
  subject.run
367
- response.headers['Content-Type'].should == 'text/html;charset=iso8859-1'
397
+ expect(response.headers['Content-Type']).to eq 'text/html;charset=iso8859-1'
368
398
  end
369
399
  end
370
400
  end
@@ -382,27 +412,27 @@ describe Webmachine::Decision::Flow do
382
412
  it "should reply with 406 if the encoding is unacceptable" do
383
413
  headers['Accept-Encoding'] = 'deflate, identity;q=0.0'
384
414
  subject.run
385
- response.code.should == 406
415
+ expect(response.code).to eq 406
386
416
  end
387
417
 
388
418
  it "should not reply with 406 if the encoding is acceptable" do
389
419
  headers['Accept-Encoding'] = 'gzip, deflate'
390
420
  subject.run
391
- response.code.should_not == 406
392
- response.headers['Content-Encoding'].should == 'gzip'
421
+ expect(response.code).to_not eq 406
422
+ expect(response.headers['Content-Encoding']).to eq 'gzip'
393
423
  # It should be compressed
394
- response.body.should_not == 'test resource'
424
+ expect(response.body).to_not eq 'test resource'
395
425
  end
396
426
  end
397
427
 
398
428
  context "when the Accept-Encoding header is not present" do
399
429
  it "should not negotiate an encoding" do
400
- headers['Accept-Encoding'].should be_nil
401
- subject.should_not_receive(:f7)
430
+ expect(headers['Accept-Encoding']).to be_nil
431
+ expect(subject).to_not receive(:f7)
402
432
  subject.run
403
- response.code.should_not == 406
433
+ expect(response.code).to_not eq 406
404
434
  # It should not be compressed
405
- response.body.should == 'test resource'
435
+ expect(response.body).to eq 'test resource'
406
436
  end
407
437
  end
408
438
  end
@@ -412,28 +442,28 @@ describe Webmachine::Decision::Flow do
412
442
 
413
443
  it "should not enter conditional requests if missing (and eventually reply with 404)" do
414
444
  resource.exist = false
415
- subject.should_not_receive(:g8)
445
+ expect(subject).to_not receive(:g8)
416
446
  subject.run
417
- response.code.should == 404
447
+ expect(response.code).to eq 404
418
448
  end
419
449
 
420
450
  it "should not reply with 404 if it does exist" do
421
451
  resource.exist = true
422
- subject.should_not_receive(:h7)
452
+ expect(subject).to_not receive(:h7)
423
453
  subject.run
424
- response.code.should_not == 404
454
+ expect(response.code).to_not eq 404
425
455
  end
426
456
 
427
457
  it "should not reply with 404 for truthy non-booleans" do
428
458
  resource.exist = []
429
459
  subject.run
430
- response.code.should_not == 404
460
+ expect(response.code).to_not eq 404
431
461
  end
432
462
 
433
463
  it "should reply with 404 for nil" do
434
464
  resource.exist = nil
435
465
  subject.run
436
- response.code.should == 404
466
+ expect(response.code).to eq 404
437
467
  end
438
468
  end
439
469
 
@@ -441,26 +471,26 @@ describe Webmachine::Decision::Flow do
441
471
  describe "#g8, #g9, #g10 (ETag match)" do
442
472
  let(:resource) { resource_with { def generate_etag; "etag"; end } }
443
473
  it "should skip ETag matching when If-Match is missing" do
444
- headers['If-Match'].should be_nil
445
- subject.should_not_receive(:g9)
446
- subject.should_not_receive(:g11)
474
+ expect(headers['If-Match']).to be_nil
475
+ expect(subject).to_not receive(:g9)
476
+ expect(subject).to_not receive(:g11)
447
477
  subject.run
448
- response.code.should_not == 412
478
+ expect(response.code).to_not eq 412
449
479
  end
450
480
  it "should not reply with 304 when If-Match is *" do
451
481
  headers['If-Match'] = "*"
452
482
  subject.run
453
- response.code.should_not == 412
483
+ expect(response.code).to_not eq 412
454
484
  end
455
485
  it "should reply with 412 if the ETag is not in If-Match" do
456
486
  headers['If-Match'] = '"notetag"'
457
487
  subject.run
458
- response.code.should == 412
488
+ expect(response.code).to eq 412
459
489
  end
460
490
  it "should not reply with 412 if the ETag is in If-Match" do
461
491
  headers['If-Match'] = '"etag"'
462
492
  subject.run
463
- response.code.should_not == 412
493
+ expect(response.code).to_not eq 412
464
494
  end
465
495
  end
466
496
 
@@ -469,30 +499,30 @@ describe Webmachine::Decision::Flow do
469
499
  before { @now = resource.now = Time.now }
470
500
 
471
501
  it "should skip LM matching if IUMS is missing" do
472
- headers['If-Unmodified-Since'].should be_nil
473
- subject.should_not_receive(:h11)
474
- subject.should_not_receive(:h12)
502
+ expect(headers['If-Unmodified-Since']).to be_nil
503
+ expect(subject).to_not receive(:h11)
504
+ expect(subject).to_not receive(:h12)
475
505
  subject.run
476
- response.code.should_not == 412
506
+ expect(response.code).to_not eq 412
477
507
  end
478
508
 
479
509
  it "should skip LM matching if IUMS is an invalid date" do
480
510
  headers['If-Unmodified-Since'] = "garbage"
481
- subject.should_not_receive(:h12)
511
+ expect(subject).to_not receive(:h12)
482
512
  subject.run
483
- response.code.should_not == 412
513
+ expect(response.code).to_not eq 412
484
514
  end
485
515
 
486
516
  it "should not reply with 412 if LM is <= IUMS" do
487
517
  headers['If-Unmodified-Since'] = (@now + 100).httpdate
488
518
  subject.run
489
- response.code.should_not == 412
519
+ expect(response.code).to_not eq 412
490
520
  end
491
521
 
492
522
  it "should reply with 412 if LM is > IUMS" do
493
523
  headers['If-Unmodified-Since'] = (@now - 100).httpdate
494
524
  subject.run
495
- response.code.should == 412
525
+ expect(response.code).to eq 412
496
526
  end
497
527
  end
498
528
 
@@ -506,18 +536,18 @@ describe Webmachine::Decision::Flow do
506
536
  end
507
537
 
508
538
  it "should skip ETag matching if If-None-Match is missing" do
509
- headers['If-None-Match'].should be_nil
539
+ expect(headers['If-None-Match']).to be_nil
510
540
  %w{i13 k13 j18}.each do |m|
511
- subject.should_not_receive(m.to_sym)
541
+ expect(subject).to_not receive(m.to_sym)
512
542
  end
513
543
  subject.run
514
- [304, 412].should_not include(response.code)
544
+ expect([304, 412]).to_not include(response.code)
515
545
  end
516
546
 
517
547
  it "should not reply with 412 or 304 if the ETag is not in If-None-Match" do
518
548
  headers['If-None-Match'] = '"notetag"'
519
549
  subject.run
520
- [304, 412].should_not include(response.code)
550
+ expect([304, 412]).to_not include(response.code)
521
551
  end
522
552
 
523
553
  context "when the method is GET or HEAD" do
@@ -528,7 +558,7 @@ describe Webmachine::Decision::Flow do
528
558
  it "should reply with 304 when the ETag is in If-None-Match" do
529
559
  headers['If-None-Match'] = '"etag", "foobar"'
530
560
  end
531
- after { subject.run; response.code.should == 304 }
561
+ after { subject.run; expect(response.code).to eq 304 }
532
562
  end
533
563
 
534
564
  context "when the method is not GET or HEAD" do
@@ -543,7 +573,27 @@ describe Webmachine::Decision::Flow do
543
573
  it "should reply with 412 when the ETag is in If-None-Match" do
544
574
  headers['If-None-Match'] = '"etag"'
545
575
  end
546
- after { subject.run; response.code.should == 412 }
576
+ after { subject.run; expect(response.code).to eq 412 }
577
+ end
578
+
579
+ context "when the resource does not define an ETag" do
580
+ let(:resource) do
581
+ resource_with do
582
+ def generate_etag; nil; end
583
+ end
584
+ end
585
+
586
+ it "should reply with 200 when If-None-Match is missing" do
587
+ headers.delete 'If-None-Match'
588
+ subject.run
589
+ expect(response.code).to eq 200
590
+ end
591
+
592
+ it "should reply with 200 when If-None-Match is present" do
593
+ headers['If-None-Match'] = '"etag"'
594
+ subject.run
595
+ expect(response.code).to eq 200
596
+ end
547
597
  end
548
598
  end
549
599
 
@@ -551,41 +601,41 @@ describe Webmachine::Decision::Flow do
551
601
  let(:resource) { resource_with { attr_accessor :now; def last_modified; @now; end } }
552
602
  before { @now = resource.now = Time.now }
553
603
  it "should skip LM matching if IMS is missing" do
554
- headers['If-Modified-Since'].should be_nil
604
+ expect(headers['If-Modified-Since']).to be_nil
555
605
  %w{l14 l15 l17}.each do |m|
556
- subject.should_not_receive(m.to_sym)
606
+ expect(subject).to_not receive(m.to_sym)
557
607
  end
558
608
  subject.run
559
- response.code.should_not == 304
609
+ expect(response.code).to_not eq 304
560
610
  end
561
611
 
562
612
  it "should skip LM matching if IMS is an invalid date" do
563
613
  headers['If-Modified-Since'] = "garbage"
564
614
  %w{l15 l17}.each do |m|
565
- subject.should_not_receive(m.to_sym)
615
+ expect(subject).to_not receive(m.to_sym)
566
616
  end
567
617
  subject.run
568
- response.code.should_not == 304
618
+ expect(response.code).to_not eq 304
569
619
  end
570
620
 
571
621
  it "should skip LM matching if IMS is later than current time" do
572
622
  headers['If-Modified-Since'] = (@now + 1000).httpdate
573
- subject.should_not_receive(:l17)
623
+ expect(subject).to_not receive(:l17)
574
624
  subject.run
575
- response.code.should_not == 304
625
+ expect(response.code).to_not eq 304
576
626
  end
577
627
 
578
628
  it "should reply with 304 if LM is <= IMS" do
579
629
  headers['If-Modified-Since'] = (@now - 1).httpdate
580
630
  resource.now = @now - 1000
581
631
  subject.run
582
- response.code.should == 304
632
+ expect(response.code).to eq 304
583
633
  end
584
634
 
585
635
  it "should not reply with 304 if LM is > IMS" do
586
636
  headers['If-Modified-Since'] = (@now - 1000).httpdate
587
637
  subject.run
588
- response.code.should_not == 304
638
+ expect(response.code).to_not eq 304
589
639
  end
590
640
  end
591
641
 
@@ -595,13 +645,13 @@ describe Webmachine::Decision::Flow do
595
645
  it "should reply with 412 when the If-Match header is *" do
596
646
  headers['If-Match'] = '"*"'
597
647
  subject.run
598
- response.code.should == 412
648
+ expect(response.code).to eq 412
599
649
  end
600
650
 
601
651
  it "should not reply with 412 when the If-Match header is missing or not *" do
602
652
  headers['If-Match'] = ['"etag"', nil][rand(1)]
603
653
  subject.run
604
- response.code.should_not == 412
654
+ expect(response.code).to_not eq 412
605
655
  end
606
656
  end
607
657
 
@@ -619,22 +669,22 @@ describe Webmachine::Decision::Flow do
619
669
  let(:method){ "PUT" }
620
670
 
621
671
  it "should not reach state k7" do
622
- subject.should_not_receive(:k7)
672
+ expect(subject).to_not receive(:k7)
623
673
  subject.run
624
674
  end
625
675
 
626
- after { [404, 410, 303].should_not include(response.code) }
676
+ after { expect([404, 410, 303]).to_not include(response.code) }
627
677
  end
628
678
 
629
679
  context "when the method is not PUT" do
630
680
  let(:method){ %W{GET HEAD POST DELETE}[rand(4)] }
631
681
 
632
682
  it "should not reach state i4" do
633
- subject.should_not_receive(:i4)
683
+ expect(subject).to_not receive(:i4)
634
684
  subject.run
635
685
  end
636
686
 
637
- after { response.code.should_not == 409 }
687
+ after { expect(response.code).to_not eq 409 }
638
688
  end
639
689
  end
640
690
 
@@ -653,14 +703,14 @@ describe Webmachine::Decision::Flow do
653
703
  it "should reply with 301 when the resource has moved" do
654
704
  resource.location = URI.parse("http://localhost:8098/newuri")
655
705
  subject.run
656
- response.code.should == 301
657
- response.headers['Location'].should == resource.location.to_s
706
+ expect(response.code).to eq 301
707
+ expect(response.headers['Location']).to eq resource.location.to_s
658
708
  end
659
709
 
660
710
  it "should not reply with 301 when resource has not moved" do
661
711
  resource.location = false
662
712
  subject.run
663
- response.code.should_not == 301
713
+ expect(response.code).to_not eq 301
664
714
  end
665
715
  end
666
716
 
@@ -682,13 +732,13 @@ describe Webmachine::Decision::Flow do
682
732
  it "should reply with 301 when the resource has moved permanently" do
683
733
  uri = resource.moved_perm = URI.parse("http://www.google.com/")
684
734
  subject.run
685
- response.code.should == 301
686
- response.headers['Location'].should == uri.to_s
735
+ expect(response.code).to eq 301
736
+ expect(response.headers['Location']).to eq uri.to_s
687
737
  end
688
738
  it "should not reply with 301 when the resource has not moved permanently" do
689
739
  resource.moved_perm = false
690
740
  subject.run
691
- response.code.should_not == 301
741
+ expect(response.code).to_not eq 301
692
742
  end
693
743
  end
694
744
 
@@ -697,34 +747,34 @@ describe Webmachine::Decision::Flow do
697
747
  it "should reply with 307 when the resource has moved temporarily" do
698
748
  uri = resource.moved_temp = URI.parse("http://www.basho.com/")
699
749
  subject.run
700
- response.code.should == 307
701
- response.headers['Location'].should == uri.to_s
750
+ expect(response.code).to eq 307
751
+ expect(response.headers['Location']).to eq uri.to_s
702
752
  end
703
753
  it "should not reply with 307 when the resource has not moved temporarily" do
704
754
  resource.moved_temp = false
705
755
  subject.run
706
- response.code.should_not == 307
756
+ expect(response.code).to_not eq 307
707
757
  end
708
758
  end
709
759
 
710
760
  describe "#m5 (POST?), #n5 (POST to missing resource?)" do
711
761
  before { resource.moved_perm = resource.moved_temp = false }
712
762
  it "should reply with 410 when the method is not POST" do
713
- method.should_not == "POST"
763
+ expect(method).to_not eq "POST"
714
764
  subject.run
715
- response.code.should == 410
765
+ expect(response.code).to eq 410
716
766
  end
717
767
  it "should reply with 410 when the resource disallows missing POSTs" do
718
768
  @method = "POST"
719
769
  resource.allow_missing = false
720
770
  subject.run
721
- response.code.should == 410
771
+ expect(response.code).to eq 410
722
772
  end
723
773
  it "should not reply with 410 when the resource allows missing POSTs" do
724
774
  @method = "POST"
725
775
  resource.allow_missing = true
726
776
  subject.run
727
- response.code.should == 410
777
+ expect(response.code).to eq 410
728
778
  end
729
779
  end
730
780
  end
@@ -741,21 +791,21 @@ describe Webmachine::Decision::Flow do
741
791
  end
742
792
  let(:method){ @method || "GET" }
743
793
  it "should reply with 404 when the method is not POST" do
744
- method.should_not == "POST"
794
+ expect(method).to_not eq "POST"
745
795
  subject.run
746
- response.code.should == 404
796
+ expect(response.code).to eq 404
747
797
  end
748
798
  it "should reply with 404 when the resource disallows missing POSTs" do
749
799
  @method = "POST"
750
800
  resource.allow_missing = false
751
801
  subject.run
752
- response.code.should == 404
802
+ expect(response.code).to eq 404
753
803
  end
754
804
  it "should not reply with 404 when the resource allows missing POSTs" do
755
805
  @method = "POST"
756
806
  resource.allow_missing = true
757
807
  subject.run
758
- response.code.should_not == 404
808
+ expect(response.code).to_not eq 404
759
809
  end
760
810
  end
761
811
 
@@ -771,12 +821,12 @@ describe Webmachine::Decision::Flow do
771
821
  it "should reply with 409 if the resource is in conflict" do
772
822
  resource.conflict = true
773
823
  subject.run
774
- response.code.should == 409
824
+ expect(response.code).to eq 409
775
825
  end
776
826
  it "should not reply with 409 if the resource is in conflict" do
777
827
  resource.conflict = false
778
828
  subject.run
779
- response.code.should_not == 409
829
+ expect(response.code).to_not eq 409
780
830
  end
781
831
  end
782
832
 
@@ -801,14 +851,14 @@ describe Webmachine::Decision::Flow do
801
851
  it "should reply with 303 if the resource redirected" do
802
852
  resource.new_loc = URI.parse("/foo/bar")
803
853
  subject.run
804
- response.code.should == 303
805
- response.headers['Location'].should == "/foo/bar"
854
+ expect(response.code).to eq 303
855
+ expect(response.headers['Location']).to eq "/foo/bar"
806
856
  end
807
857
 
808
858
  it "should not reply with 303 if the resource did not redirect" do
809
859
  resource.new_loc = nil
810
860
  subject.run
811
- response.code.should_not == 303
861
+ expect(response.code).to_not eq 303
812
862
  end
813
863
  end
814
864
  end
@@ -845,13 +895,13 @@ describe Webmachine::Decision::Flow do
845
895
  resource.exist = e
846
896
  resource.new_loc = "http://ruby-doc.org/"
847
897
  subject.run
848
- response.code.should == 201
898
+ expect(response.code).to eq 201
849
899
  end
850
900
  it "should not reply with 201 when the Location header has been set" do
851
901
  resource.exist = e
852
902
  subject.run
853
- response.headers['Location'].should be_nil
854
- response.code.should_not == 201
903
+ expect(response.headers['Location']).to be_nil
904
+ expect(response.code).to_not eq 201
855
905
  end
856
906
  end
857
907
  end
@@ -866,19 +916,19 @@ describe Webmachine::Decision::Flow do
866
916
  resource.new_loc = created = "/foo/bar/baz"
867
917
  resource.create = true
868
918
  subject.run
869
- response.code.should == 201
870
- response.headers['Location'].should == created
919
+ expect(response.code).to eq 201
920
+ expect(response.headers['Location']).to eq created
871
921
  end
872
922
  it "should reply with 500 when post_is_create is true and create_path returns nil" do
873
923
  resource.create = true
874
924
  subject.run
875
- response.code.should == 500
876
- response.error.should_not be_nil
925
+ expect(response.code).to eq 500
926
+ expect(response.error).to_not be_nil
877
927
  end
878
928
  it "should not reply with 201 when post_is_create is false" do
879
929
  resource.create = false
880
930
  subject.run
881
- response.code.should_not == 201
931
+ expect(response.code).to_not eq 201
882
932
  end
883
933
  end
884
934
  end
@@ -897,12 +947,12 @@ describe Webmachine::Decision::Flow do
897
947
  it "should reply with 409 if the resource is in conflict" do
898
948
  resource.conflict = true
899
949
  subject.run
900
- response.code.should == 409
950
+ expect(response.code).to eq 409
901
951
  end
902
952
  it "should not reply with 409 if the resource is in conflict" do
903
953
  resource.conflict = false
904
954
  subject.run
905
- response.code.should_not == 409
955
+ expect(response.code).to_not eq 409
906
956
  end
907
957
  end
908
958
 
@@ -919,23 +969,23 @@ describe Webmachine::Decision::Flow do
919
969
  it "should not reply with 202 if the method is not DELETE" do
920
970
  @method = "GET"
921
971
  subject.run
922
- response.code.should_not == 202
972
+ expect(response.code).to_not eq 202
923
973
  end
924
974
  it "should reply with 500 if the DELETE fails" do
925
975
  resource.deleted = false
926
976
  subject.run
927
- response.code.should == 500
977
+ expect(response.code).to eq 500
928
978
  end
929
979
  it "should reply with 202 if the DELETE succeeds but is not complete" do
930
980
  resource.deleted = true
931
981
  resource.completed = false
932
982
  subject.run
933
- response.code.should == 202
983
+ expect(response.code).to eq 202
934
984
  end
935
985
  it "should not reply with 202 if the DELETE succeeds and completes" do
936
986
  resource.completed = resource.deleted = true
937
987
  subject.run
938
- response.code.should_not == 202
988
+ expect(response.code).to_not eq 202
939
989
  end
940
990
  end
941
991
 
@@ -980,13 +1030,13 @@ describe Webmachine::Decision::Flow do
980
1030
  resource.multiple = false
981
1031
  subject.run
982
1032
  puts response.error if response.code == 500
983
- response.code.should == 200
1033
+ expect(response.code).to eq 200
984
1034
  end
985
1035
  it "should reply with 300 if there are multiple representations" do
986
1036
  resource.multiple = true
987
1037
  subject.run
988
1038
  puts response.error if response.code == 500
989
- response.code.should == 300
1039
+ expect(response.code).to eq 300
990
1040
  end
991
1041
  end
992
1042
  end
@@ -1028,7 +1078,7 @@ describe Webmachine::Decision::Flow do
1028
1078
  @method = m
1029
1079
  resource.exist = e
1030
1080
  subject.run
1031
- response.code.should_not == 204
1081
+ expect(response.code).to_not eq 204
1032
1082
  end
1033
1083
  end
1034
1084
  end
@@ -1044,7 +1094,7 @@ describe Webmachine::Decision::Flow do
1044
1094
  @method = m
1045
1095
  resource.exist = e
1046
1096
  subject.run
1047
- response.code.should == 204
1097
+ expect(response.code).to eq 204
1048
1098
  end
1049
1099
  end
1050
1100
  end
@@ -1061,13 +1111,13 @@ describe Webmachine::Decision::Flow do
1061
1111
  end
1062
1112
 
1063
1113
  it "calls handle_exception" do
1064
- resource.should_receive(:handle_exception).with instance_of(RuntimeError)
1114
+ expect(resource).to receive(:handle_exception).with instance_of(RuntimeError)
1065
1115
  subject.run
1066
1116
  end
1067
1117
 
1068
1118
  it "sets the response code to 500" do
1069
1119
  subject.run
1070
- response.code.should == 500
1120
+ expect(response.code).to eq 500
1071
1121
  end
1072
1122
  end
1073
1123
 
@@ -1086,12 +1136,12 @@ describe Webmachine::Decision::Flow do
1086
1136
 
1087
1137
  it "can define a response body" do
1088
1138
  subject.run
1089
- response.body.should == "error"
1139
+ expect(response.body).to eq "error"
1090
1140
  end
1091
1141
 
1092
1142
  it "sets the response code to 500" do
1093
1143
  subject.run
1094
- response.code.should == 500
1144
+ expect(response.code).to eq 500
1095
1145
  end
1096
1146
  end
1097
1147
  end