rocketio 0.0.0 → 0.0.1

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