rocketio 0.0.0 → 0.0.1

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 (75) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -5
  3. data/.pryrc +2 -0
  4. data/.travis.yml +3 -0
  5. data/README.md +22 -5
  6. data/Rakefile +7 -1
  7. data/bin/console +14 -0
  8. data/bin/setup +7 -0
  9. data/lib/rocketio.rb +131 -3
  10. data/lib/rocketio/application.rb +31 -0
  11. data/lib/rocketio/controller.rb +288 -0
  12. data/lib/rocketio/controller/authentication.rb +141 -0
  13. data/lib/rocketio/controller/authorization.rb +53 -0
  14. data/lib/rocketio/controller/cookies.rb +59 -0
  15. data/lib/rocketio/controller/error_handlers.rb +89 -0
  16. data/lib/rocketio/controller/filters.rb +119 -0
  17. data/lib/rocketio/controller/flash.rb +21 -0
  18. data/lib/rocketio/controller/helpers.rb +438 -0
  19. data/lib/rocketio/controller/middleware.rb +32 -0
  20. data/lib/rocketio/controller/render.rb +148 -0
  21. data/lib/rocketio/controller/render/engine.rb +76 -0
  22. data/lib/rocketio/controller/render/layout.rb +27 -0
  23. data/lib/rocketio/controller/render/layouts.rb +85 -0
  24. data/lib/rocketio/controller/render/templates.rb +83 -0
  25. data/lib/rocketio/controller/request.rb +115 -0
  26. data/lib/rocketio/controller/response.rb +84 -0
  27. data/lib/rocketio/controller/sessions.rb +64 -0
  28. data/lib/rocketio/controller/token_auth.rb +118 -0
  29. data/lib/rocketio/controller/websocket.rb +21 -0
  30. data/lib/rocketio/error_templates/404.html +3 -0
  31. data/lib/rocketio/error_templates/409.html +7 -0
  32. data/lib/rocketio/error_templates/500.html +3 -0
  33. data/lib/rocketio/error_templates/501.html +6 -0
  34. data/lib/rocketio/error_templates/layout.html +1 -0
  35. data/lib/rocketio/exceptions.rb +4 -0
  36. data/lib/rocketio/router.rb +65 -0
  37. data/lib/rocketio/util.rb +122 -0
  38. data/lib/rocketio/version.rb +2 -2
  39. data/rocketio.gemspec +21 -17
  40. data/test/aliases_test.rb +54 -0
  41. data/test/authentication_test.rb +307 -0
  42. data/test/authorization_test.rb +91 -0
  43. data/test/cache_control_test.rb +268 -0
  44. data/test/content_type_test.rb +124 -0
  45. data/test/cookies_test.rb +49 -0
  46. data/test/error_handlers_test.rb +125 -0
  47. data/test/etag_test.rb +445 -0
  48. data/test/filters_test.rb +177 -0
  49. data/test/halt_test.rb +73 -0
  50. data/test/helpers_test.rb +171 -0
  51. data/test/middleware_test.rb +57 -0
  52. data/test/redirect_test.rb +135 -0
  53. data/test/render/engine_test.rb +71 -0
  54. data/test/render/get.erb +1 -0
  55. data/test/render/items.erb +1 -0
  56. data/test/render/layout.erb +1 -0
  57. data/test/render/layout_test.rb +104 -0
  58. data/test/render/layouts/master.erb +1 -0
  59. data/test/render/layouts_test.rb +145 -0
  60. data/test/render/master.erb +1 -0
  61. data/test/render/post.erb +1 -0
  62. data/test/render/put.erb +1 -0
  63. data/test/render/render_test.rb +101 -0
  64. data/test/render/setup.rb +14 -0
  65. data/test/render/templates/a/get.erb +1 -0
  66. data/test/render/templates/master.erb +1 -0
  67. data/test/render/templates_test.rb +146 -0
  68. data/test/request_test.rb +105 -0
  69. data/test/response_test.rb +119 -0
  70. data/test/routes_test.rb +70 -0
  71. data/test/sendfile_test.rb +209 -0
  72. data/test/sessions_test.rb +176 -0
  73. data/test/setup.rb +59 -0
  74. metadata +144 -9
  75. data/LICENSE.txt +0 -22
@@ -0,0 +1,49 @@
1
+ require 'setup'
2
+
3
+ spec :Cookies do
4
+ it 'reads cookies' do
5
+ app mock_controller {
6
+ def get; cookies[:x] end
7
+ }
8
+ cookies['x'] = 'y'
9
+ get
10
+ assert(last_response).is_ok_with_body 'y'
11
+ end
12
+
13
+ it 'sets cookies' do
14
+ app mock_controller {
15
+ def get; cookies[:x] = 'y' end
16
+ }
17
+ get
18
+ assert(cookies['x']) == 'y'
19
+ end
20
+
21
+ it 'deletes cookies' do
22
+ app mock_controller {
23
+ def get; cookies.delete(:x) end
24
+ }
25
+ cookies['x'] = 'y'
26
+ assert(cookies['x']) == 'y'
27
+ get
28
+ assert(cookies['x']) == ''
29
+ end
30
+
31
+ it 'accepts a Hash with various options' do
32
+ expires = Time.now
33
+ app mock_controller {
34
+ define_method :get do
35
+ cookies[:x] = {
36
+ value: 'y',
37
+ path: '/',
38
+ host: 'blah.com',
39
+ expires: expires
40
+ }
41
+ end
42
+ }
43
+ get
44
+ header = last_response['Set-Cookie'].to_s
45
+ assert(header) =~ /x=y;?/
46
+ assert(header) =~ /path=\/;?/
47
+ assert(header) =~ /expires=#{expires.gmtime.rfc2822};?/
48
+ end
49
+ end
@@ -0,0 +1,125 @@
1
+ require 'setup'
2
+
3
+ spec :ErrorHandlers do
4
+ context '501: Not Implemented' do
5
+ it 'uses default handler' do
6
+ app mock_controller
7
+ get
8
+ assert(last_response.status) == 501
9
+ assert(last_response.body) =~ /501/
10
+ end
11
+
12
+ it 'uses custom handler' do
13
+ app mock_controller {
14
+ error 501 do
15
+ 'goodbye'
16
+ end
17
+ }
18
+ get
19
+ assert(last_response.status) == 501
20
+ assert(last_response.body) == 'goodbye'
21
+ end
22
+
23
+ it 'can be triggered manually' do
24
+ called = false
25
+ app mock_controller {
26
+ define_method(:get) {called = true; error(501)}
27
+ }
28
+ get
29
+ assert(called) == true
30
+ assert(last_response.status) == 501
31
+ end
32
+ end
33
+
34
+ context 'Parameters Error' do
35
+ it 'uses default handler' do
36
+ app mock_app(mock_controller {
37
+ def get; end
38
+ })
39
+ get :x
40
+ assert(last_response.status) == 409
41
+ assert(last_response.body) =~ /wrong number of arguments/i
42
+ end
43
+
44
+ it 'uses custom handler' do
45
+ app mock_app(mock_controller {
46
+ def get; end
47
+ error 409 do
48
+ 'noway'
49
+ end
50
+ })
51
+ get :x
52
+ assert(last_response.status) == 409
53
+ assert(last_response.body) == 'noway'
54
+ end
55
+
56
+ it 'can be triggered manually' do
57
+ called = false
58
+ app mock_app(mock_controller {
59
+ define_method(:get) {called = true; error(409)}
60
+ })
61
+ get
62
+ assert(called) == true
63
+ assert(last_response.status) == 409
64
+ end
65
+ end
66
+
67
+ context '500: Fatal Error' do
68
+ it 'uses default handler' do
69
+ app mock_controller {
70
+ def get; raise end
71
+ }
72
+ get
73
+ assert(last_response.status) == 500
74
+ assert(last_response.body) =~ /500.+fatal/i
75
+ end
76
+
77
+ it 'uses custom handler' do
78
+ app mock_controller {
79
+ def get; raise('badboy') end
80
+ error 500 do |e|
81
+ e.message
82
+ end
83
+ }
84
+ get
85
+ assert(last_response.status) == 500
86
+ assert(last_response.body) == 'badboy'
87
+ end
88
+
89
+ it 'can be triggered manually' do
90
+ called = false
91
+ app mock_controller {
92
+ define_method(:get) {called = true; error(500, 'badgirl')}
93
+ }
94
+ get
95
+ assert(called) == true
96
+ assert(last_response.status) == 500
97
+ assert(last_response.body) =~ /500.+badgirl/im
98
+ end
99
+ end
100
+
101
+ context '404: Not Found' do
102
+ it 'uses default handler' do
103
+ app mock_app(mock_controller(:x) {
104
+ def get; end
105
+ })
106
+ get '/y'
107
+ assert(last_response.status) == 404
108
+ assert(last_response.body) =~ /404/
109
+ end
110
+
111
+ it 'can be triggered manually and use custom handler' do
112
+ called = false
113
+ app mock_controller {
114
+ define_method(:get) {called = true; error(404)}
115
+ error 404 do
116
+ 'trymore'
117
+ end
118
+ }
119
+ get
120
+ assert(called) == true
121
+ assert(last_response.status) == 404
122
+ assert(last_response.body) == 'trymore'
123
+ end
124
+ end
125
+ end
data/test/etag_test.rb ADDED
@@ -0,0 +1,445 @@
1
+ # Copyright (c) 2007, 2008, 2009 Blake Mizerany
2
+ # Copyright (c) 2010, 2011, 2012, 2013, 2014 Konstantin Haase
3
+ # Copyright (c) 2015 Slee Woo
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person
6
+ # obtaining a copy of this software and associated documentation
7
+ # files (the "Software"), to deal in the Software without
8
+ # restriction, including without limitation the rights to use,
9
+ # copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the
11
+ # Software is furnished to do so, subject to the following
12
+ # conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
19
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24
+ # OTHER DEALINGS IN THE SOFTWARE.
25
+
26
+ require 'setup'
27
+
28
+ spec :etag do
29
+
30
+ def run_with *args, &block
31
+ request_method = args.shift || :get
32
+ app mock_controller {
33
+ define_method request_method do
34
+ instance_exec(&block) if block
35
+ args.shift || 'ok'
36
+ end
37
+ }
38
+ end
39
+
40
+ context "safe requests" do
41
+ it 'returns 200 for normal requests' do
42
+ run_with {etag 'foo'}
43
+ get
44
+ assert(last_response).is_ok_with_body('ok')
45
+ end
46
+
47
+ context "If-None-Match" do
48
+ it 'returns 304 when If-None-Match is *' do
49
+ run_with {etag 'foo'}
50
+
51
+ env['HTTP_IF_NONE_MATCH'] = '*'
52
+ get
53
+ assert(last_response).is_not_modified
54
+ end
55
+
56
+ it 'returns 200 when If-None-Match is * for new resources' do
57
+ run_with {etag 'foo', :new_resource => true}
58
+
59
+ env['HTTP_IF_NONE_MATCH'] = '*'
60
+ get
61
+ assert(last_response).is_ok_with_body('ok')
62
+ end
63
+
64
+ it 'returns 304 when If-None-Match is * for existing resources' do
65
+ run_with {etag 'foo', :new_resource => false}
66
+
67
+ env['HTTP_IF_NONE_MATCH'] = '*'
68
+ get
69
+ assert(last_response).is_not_modified
70
+ end
71
+
72
+ it 'returns 304 when If-None-Match is the etag' do
73
+ run_with {etag 'foo'}
74
+
75
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
76
+ get
77
+ assert(last_response).is_not_modified
78
+ end
79
+
80
+ it 'returns 304 when If-None-Match includes the etag' do
81
+ run_with {etag 'foo'}
82
+
83
+ env['HTTP_IF_NONE_MATCH'] = '"bar", "foo"'
84
+ get
85
+ assert(last_response).is_not_modified
86
+ end
87
+
88
+ it 'returns 200 when If-None-Match does not include the etag' do
89
+ run_with {etag 'foo'}
90
+
91
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
92
+ get
93
+ assert(last_response).is_ok_with_body('ok')
94
+ end
95
+
96
+ it 'ignores If-Modified-Since if If-None-Match does not match' do
97
+ run_with do
98
+ etag 'foo'
99
+ last_modified Time.at(0)
100
+ end
101
+
102
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
103
+ get
104
+ assert(last_response).is_ok_with_body('ok')
105
+ end
106
+
107
+ it 'does not change a status code other than 2xx or 304' do
108
+ run_with do
109
+ response.status = 499
110
+ etag 'foo'
111
+ end
112
+
113
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
114
+ get
115
+ assert(last_response).returned 499, 'ok'
116
+ end
117
+
118
+ it 'does change 2xx status codes' do
119
+ run_with do
120
+ response.status = 299
121
+ etag 'foo'
122
+ end
123
+
124
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
125
+ get
126
+ assert(last_response).is_not_modified
127
+ end
128
+
129
+ it 'does not send a body on 304 status codes' do
130
+ run_with do
131
+ response.status = 304
132
+ etag 'foo'
133
+ end
134
+
135
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
136
+ get
137
+ assert(last_response).is_not_modified
138
+ end
139
+ end
140
+
141
+ context "If-Match" do
142
+ it 'returns 200 when If-Match is the etag' do
143
+ run_with {etag 'foo'}
144
+
145
+ env['HTTP_IF_MATCH'] = '"foo"'
146
+ get
147
+ assert(last_response).is_ok_with_body('ok')
148
+ end
149
+
150
+ it 'returns 200 when If-Match includes the etag' do
151
+ run_with {etag 'foo'}
152
+
153
+ env['HTTP_IF_MATCH'] = '"foo", "bar"'
154
+ get
155
+ assert(last_response).is_ok_with_body('ok')
156
+ end
157
+
158
+ it 'returns 200 when If-Match is *' do
159
+ run_with {etag 'foo'}
160
+
161
+ env['HTTP_IF_MATCH'] = '*'
162
+ get
163
+ assert(last_response).is_ok_with_body('ok')
164
+ end
165
+
166
+ it 'returns 412 when If-Match is * for new resources' do
167
+ run_with {etag 'foo', :new_resource => true}
168
+
169
+ env['HTTP_IF_MATCH'] = '*'
170
+ get
171
+ assert(last_response).is_precondition_failed
172
+ end
173
+
174
+ it 'returns 200 when If-Match is * for existing resources' do
175
+ run_with {etag 'foo', :new_resource => false}
176
+
177
+ env['HTTP_IF_MATCH'] = '*'
178
+ get
179
+ assert(last_response).is_ok_with_body('ok')
180
+ end
181
+
182
+ it 'returns 412 when If-Match does not include the etag' do
183
+ run_with {etag 'foo'}
184
+
185
+ env['HTTP_IF_MATCH'] = '"bar"'
186
+ get
187
+ assert(last_response).is_precondition_failed
188
+ end
189
+ end
190
+ end
191
+
192
+ context "idempotent requests" do
193
+ it 'returns 200 for normal requests' do
194
+ run_with(:put) {etag 'foo'}
195
+
196
+ put
197
+ assert(last_response).is_ok_with_body('ok')
198
+ end
199
+
200
+ context "If-None-Match" do
201
+ it 'returns 412 when If-None-Match is *' do
202
+ run_with(:put) {etag 'foo'}
203
+
204
+ env['HTTP_IF_NONE_MATCH'] = '*'
205
+ put
206
+ assert(last_response).is_precondition_failed
207
+ end
208
+
209
+ it 'returns 200 when If-None-Match is * for new resources' do
210
+ run_with(:put) {etag 'foo', :new_resource => true}
211
+
212
+ env['HTTP_IF_NONE_MATCH'] = '*'
213
+ put
214
+ assert(last_response).is_ok_with_body('ok')
215
+ end
216
+
217
+ it 'returns 412 when If-None-Match is * for existing resources' do
218
+ run_with(:put) {etag 'foo', :new_resource => false}
219
+
220
+ env['HTTP_IF_NONE_MATCH'] = '*'
221
+ put
222
+ assert(last_response).is_precondition_failed
223
+ end
224
+
225
+ it 'returns 412 when If-None-Match is the etag' do
226
+ run_with(:put) {etag 'foo'}
227
+
228
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
229
+ put
230
+ assert(last_response).is_precondition_failed
231
+ end
232
+
233
+ it 'returns 412 when If-None-Match includes the etag' do
234
+ run_with(:put) {etag 'foo'}
235
+
236
+ env['HTTP_IF_NONE_MATCH'] = '"bar", "foo"'
237
+ put
238
+ assert(last_response).is_precondition_failed
239
+ end
240
+
241
+ it 'returns 200 when If-None-Match does not include the etag' do
242
+ run_with(:put) {etag 'foo'}
243
+
244
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
245
+ put
246
+ assert(last_response).is_ok_with_body('ok')
247
+ end
248
+
249
+ it 'ignores If-Modified-Since if If-None-Match does not match' do
250
+ run_with(:put) {
251
+ etag 'foo'
252
+ last_modified Time.at(0)
253
+ }
254
+
255
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
256
+ put
257
+ assert(last_response).is_ok_with_body('ok')
258
+ end
259
+ end
260
+
261
+ context "If-Match" do
262
+ it 'returns 200 when If-Match is the etag' do
263
+ run_with(:put) {etag 'foo'}
264
+
265
+ env['HTTP_IF_MATCH'] = '"foo"'
266
+ put
267
+ assert(last_response).is_ok_with_body('ok')
268
+ end
269
+
270
+ it 'returns 200 when If-Match includes the etag' do
271
+ run_with(:put) {etag 'foo'}
272
+
273
+ env['HTTP_IF_MATCH'] = '"foo", "bar"'
274
+ put
275
+ assert(last_response).is_ok_with_body('ok')
276
+ end
277
+
278
+ it 'returns 200 when If-Match is *' do
279
+ run_with(:put) {etag 'foo'}
280
+
281
+ env['HTTP_IF_MATCH'] = '*'
282
+ put
283
+ assert(last_response).is_ok_with_body('ok')
284
+ end
285
+
286
+ it 'returns 412 when If-Match is * for new resources' do
287
+ run_with(:put) {etag 'foo', :new_resource => true}
288
+
289
+ env['HTTP_IF_MATCH'] = '*'
290
+ put
291
+ assert(last_response).is_precondition_failed
292
+ end
293
+
294
+ it 'returns 200 when If-Match is * for existing resources' do
295
+ run_with(:put) {etag 'foo', :new_resource => false}
296
+
297
+ env['HTTP_IF_MATCH'] = '*'
298
+ put
299
+ assert(last_response).is_ok_with_body('ok')
300
+ end
301
+
302
+ it 'returns 412 when If-Match does not include the etag' do
303
+ run_with(:put) {etag 'foo'}
304
+
305
+ env['HTTP_IF_MATCH'] = '"bar"'
306
+ put
307
+ assert(last_response).is_precondition_failed
308
+ end
309
+ end
310
+ end
311
+
312
+ context "post requests" do
313
+ it 'returns 200 for normal requests' do
314
+ run_with(:post) {etag 'foo'}
315
+
316
+ post
317
+ assert(last_response).is_ok_with_body('ok')
318
+ end
319
+
320
+ context "If-None-Match" do
321
+ it 'returns 200 when If-None-Match is *' do
322
+ run_with(:post) {etag 'foo'}
323
+
324
+ env['HTTP_IF_NONE_MATCH'] = '*'
325
+ post
326
+ assert(last_response).is_ok_with_body('ok')
327
+ end
328
+
329
+ it 'returns 200 when If-None-Match is * for new resources' do
330
+ run_with(:post) {etag 'foo', :new_resource => true}
331
+
332
+ env['HTTP_IF_NONE_MATCH'] = '*'
333
+ post
334
+ assert(last_response).is_ok_with_body('ok')
335
+ end
336
+
337
+ it 'returns 412 when If-None-Match is * for existing resources' do
338
+ run_with(:post) {etag 'foo', :new_resource => false}
339
+
340
+ env['HTTP_IF_NONE_MATCH'] = '*'
341
+ post
342
+ assert(last_response).is_precondition_failed
343
+ end
344
+
345
+ it 'returns 412 when If-None-Match is the etag' do
346
+ run_with(:post) {etag 'foo'}
347
+
348
+ env['HTTP_IF_NONE_MATCH'] = '"foo"'
349
+ post
350
+ assert(last_response).is_precondition_failed
351
+ end
352
+
353
+ it 'returns 412 when If-None-Match includes the etag' do
354
+ run_with(:post) {etag 'foo'}
355
+
356
+ env['HTTP_IF_NONE_MATCH'] = '"bar", "foo"'
357
+ post
358
+ assert(last_response).is_precondition_failed
359
+ end
360
+
361
+ it 'returns 200 when If-None-Match does not include the etag' do
362
+ run_with(:post) {etag 'foo'}
363
+
364
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
365
+ post
366
+ assert(last_response).is_ok_with_body('ok')
367
+ end
368
+
369
+ it 'ignores If-Modified-Since if If-None-Match does not match' do
370
+ run_with(:post) {
371
+ etag 'foo'
372
+ last_modified Time.at(0)
373
+ }
374
+
375
+ env['HTTP_IF_NONE_MATCH'] = '"bar"'
376
+ post
377
+ assert(last_response).is_ok_with_body('ok')
378
+ end
379
+ end
380
+
381
+ context "If-Match" do
382
+ it 'returns 200 when If-Match is the etag' do
383
+ run_with(:post) {etag 'foo'}
384
+
385
+ env['HTTP_IF_MATCH'] = '"foo"'
386
+ post
387
+ assert(last_response).is_ok_with_body('ok')
388
+ end
389
+
390
+ it 'returns 200 when If-Match includes the etag' do
391
+ run_with(:post) {etag 'foo'}
392
+
393
+ env['HTTP_IF_MATCH'] = '"foo", "bar"'
394
+ post
395
+ assert(last_response).is_ok_with_body('ok')
396
+ end
397
+
398
+ it 'returns 412 when If-Match is *' do
399
+ run_with(:post) {etag 'foo'}
400
+
401
+ env['HTTP_IF_MATCH'] = '*'
402
+ post
403
+ assert(last_response).is_precondition_failed
404
+ end
405
+
406
+ it 'returns 412 when If-Match is * for new resources' do
407
+ run_with(:post) {etag 'foo', :new_resource => true}
408
+
409
+ env['HTTP_IF_MATCH'] = '*'
410
+ post
411
+ assert(last_response).is_precondition_failed
412
+ end
413
+
414
+ it 'returns 200 when If-Match is * for existing resources' do
415
+ run_with(:post) {etag 'foo', :new_resource => false}
416
+
417
+ env['HTTP_IF_MATCH'] = '*'
418
+ post
419
+ assert(last_response).is_ok_with_body('ok')
420
+ end
421
+
422
+ it 'returns 412 when If-Match does not include the etag' do
423
+ run_with(:post) {etag 'foo'}
424
+
425
+ env['HTTP_IF_MATCH'] = '"bar"'
426
+ post
427
+ assert(last_response).is_precondition_failed
428
+ end
429
+ end
430
+ end
431
+
432
+ it 'uses a weak etag with the :weak option' do
433
+ run_with(:get, "that's weak, dude.") {etag 'FOO', :weak}
434
+
435
+ get
436
+ assert(last_response['ETag']) == 'W/"FOO"'
437
+ end
438
+
439
+ it 'raises an ArgumentError for an invalid strength' do
440
+ run_with(:get, "that's weak, dude.") {etag 'FOO', :w00t}
441
+ get
442
+ assert(last_response.status) == 500
443
+ assert(last_response.body) =~ /:strong or :weak expected/
444
+ end
445
+ end