gin 0.0.0 → 1.0.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.
@@ -0,0 +1,33 @@
1
+ require 'test/test_helper'
2
+ require 'gin/config'
3
+
4
+ class ConfigTest < Test::Unit::TestCase
5
+
6
+ def config_dir
7
+ File.expand_path("../mock_config", __FILE__)
8
+ end
9
+
10
+
11
+ def test_config_dev
12
+ config = Gin::Config.new "development", config_dir
13
+
14
+ assert_equal "localhost", config.memcache['host']
15
+ assert_equal 1, config.memcache['connections']
16
+
17
+ assert_equal "dev.backend.example.com", config.backend['host']
18
+
19
+ assert_raises(NoMethodError){ config.not_a_config }
20
+ end
21
+
22
+
23
+ def test_config_unknown_env
24
+ config = Gin::Config.new "foo", config_dir
25
+
26
+ assert_equal "example.com", config.memcache['host']
27
+ assert_equal 5, config.memcache['connections']
28
+
29
+ assert_equal "backend.example.com", config.backend['host']
30
+
31
+ assert_raises(NoMethodError){ config.not_a_config }
32
+ end
33
+ end
@@ -0,0 +1,808 @@
1
+ require "test/test_helper"
2
+
3
+ unless defined? EventMachine
4
+ class EventMachine; end
5
+ end
6
+
7
+ class AppController < Gin::Controller
8
+ FILTERS_RUN = []
9
+
10
+ before_filter :f1 do
11
+ FILTERS_RUN << :f1
12
+ end
13
+
14
+ after_filter :f2 do
15
+ FILTERS_RUN << :f2
16
+ end
17
+
18
+ error Gin::BadRequest do
19
+ body "Bad Request"
20
+ end
21
+ end
22
+
23
+ class TestController < Gin::Controller
24
+ def show id
25
+ "SHOW #{id}!"
26
+ end
27
+ end
28
+
29
+ class BarController < AppController
30
+ before_filter :stop, :only => :delete do
31
+ FILTERS_RUN << :stop
32
+ halt 404, "Not Found"
33
+ end
34
+
35
+ error 404 do
36
+ content_type "text/plain"
37
+ body "This is not the page you are looking for."
38
+ end
39
+
40
+ def show id
41
+ "SHOW #{id}!"
42
+ end
43
+
44
+ def delete id, email=nil, name=nil
45
+ "DELETE!"
46
+ end
47
+
48
+ def index
49
+ raise "OH NOES"
50
+ end
51
+
52
+ def caught_error
53
+ raise Gin::BadRequest, "Something is wrong"
54
+ end
55
+ end
56
+
57
+
58
+ class ControllerTest < Test::Unit::TestCase
59
+ class MockApp < Gin::App
60
+ mount BarController do
61
+ get :show, "/:id"
62
+ get :delete, :rm_bar
63
+ get :index, "/"
64
+ get :caught_error
65
+ end
66
+ end
67
+
68
+
69
+ def setup
70
+ MockApp.instance_variable_set("@environment", nil)
71
+ MockApp.instance_variable_set("@asset_host", nil)
72
+ @app = MockApp.new
73
+ @ctrl = BarController.new(@app, rack_env)
74
+ end
75
+
76
+
77
+ def teardown
78
+ BarController::FILTERS_RUN.clear
79
+ end
80
+
81
+
82
+ def rack_env
83
+ @rack_env ||= {
84
+ 'HTTP_HOST' => 'example.com',
85
+ 'rack.input' => '',
86
+ 'gin.path_query_hash' => {'id' => 123},
87
+ }
88
+ end
89
+
90
+
91
+ def test_etag
92
+ @ctrl.etag("my-etag")
93
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
94
+
95
+ @ctrl.etag("my-etag", kind: :strong)
96
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
97
+
98
+ @ctrl.etag("my-etag", :strong)
99
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
100
+ end
101
+
102
+
103
+ def test_etag_weak
104
+ @ctrl.etag("my-etag", kind: :weak)
105
+ assert_equal 'W/"my-etag"', @ctrl.response['ETag']
106
+
107
+ @ctrl.etag("my-etag", :weak)
108
+ assert_equal 'W/"my-etag"', @ctrl.response['ETag']
109
+ end
110
+
111
+
112
+ def test_etag_if_match
113
+ rack_env['HTTP_IF_MATCH'] = '"other-etag"'
114
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
115
+ assert_equal 412, resp
116
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
117
+
118
+ rack_env['HTTP_IF_MATCH'] = '*'
119
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
120
+ assert_equal nil, resp
121
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
122
+
123
+ rack_env['HTTP_IF_MATCH'] = '*'
124
+ resp = catch(:halt){ @ctrl.etag "my-etag", new_resource: true }
125
+ assert_equal 412, resp
126
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
127
+
128
+ rack_env['REQUEST_METHOD'] = 'POST'
129
+ rack_env['HTTP_IF_MATCH'] = '*'
130
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
131
+ assert_equal 412, resp
132
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
133
+ end
134
+
135
+
136
+ def test_etag_if_none_match
137
+ rack_env['REQUEST_METHOD'] = 'GET'
138
+
139
+ rack_env['HTTP_IF_NONE_MATCH'] = '"other-etag"'
140
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
141
+ assert_equal nil, resp
142
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
143
+
144
+ rack_env['HTTP_IF_NONE_MATCH'] = '"other-etag", "my-etag"'
145
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
146
+ assert_equal 304, resp
147
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
148
+
149
+ rack_env['HTTP_IF_NONE_MATCH'] = '*'
150
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
151
+ assert_equal 304, resp
152
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
153
+
154
+ rack_env['REQUEST_METHOD'] = 'POST'
155
+ rack_env['HTTP_IF_NONE_MATCH'] = '*'
156
+ resp = catch(:halt){ @ctrl.etag "my-etag", new_resource: false }
157
+ assert_equal 412, resp
158
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
159
+ end
160
+
161
+
162
+ def test_etag_non_error_status
163
+ [200, 201, 202, 304].each do |code|
164
+ @ctrl.status code
165
+ rack_env['HTTP_IF_MATCH'] = '"other-etag"'
166
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
167
+ assert_equal 412, resp
168
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
169
+ end
170
+ end
171
+
172
+
173
+ def test_etag_error_status
174
+ [301, 302, 303, 400, 404, 500, 502, 503].each do |code|
175
+ @ctrl.status code
176
+ rack_env['HTTP_IF_MATCH'] = '"other-etag"'
177
+ resp = catch(:halt){ @ctrl.etag "my-etag" }
178
+ assert_equal nil, resp
179
+ assert_equal "my-etag".inspect, @ctrl.response['ETag']
180
+ end
181
+ end
182
+
183
+
184
+ def test_cache_control
185
+ @ctrl.cache_control :public, :must_revalidate, max_age: 60
186
+ assert_equal "public, must-revalidate, max-age=60",
187
+ @ctrl.response['Cache-Control']
188
+
189
+ @ctrl.cache_control public:true, must_revalidate:false, max_age:'foo'
190
+ assert_equal "public, max-age=0", @ctrl.response['Cache-Control']
191
+ end
192
+
193
+
194
+ def test_expires_int
195
+ time = Time.now
196
+ @ctrl.expires 60, :public, :must_revalidate
197
+
198
+ assert_equal "public, must-revalidate, max-age=60",
199
+ @ctrl.response['Cache-Control']
200
+
201
+ assert_equal (time + 60).httpdate, @ctrl.response['Expires']
202
+ end
203
+
204
+
205
+ def test_expires_time
206
+ time = Time.now + 60
207
+ @ctrl.expires time, :public, must_revalidate:false, max_age:20
208
+
209
+ assert_equal "public, max-age=20",
210
+ @ctrl.response['Cache-Control']
211
+
212
+ assert_equal time.httpdate, @ctrl.response['Expires']
213
+ end
214
+
215
+
216
+ def test_expires_str
217
+ time = Time.now + 60
218
+ @ctrl.expires time.strftime("%Y/%m/%d %H:%M:%S"),
219
+ :public, must_revalidate:false, max_age:20
220
+
221
+ assert_equal "public, max-age=20",
222
+ @ctrl.response['Cache-Control']
223
+
224
+ assert_equal time.httpdate, @ctrl.response['Expires']
225
+ end
226
+
227
+
228
+ def test_expire_cache_control
229
+ @ctrl.expire_cache_control
230
+ assert_equal 'no-cache', @ctrl.response['Pragma']
231
+ assert_equal 'no-cache, no-store, must-revalidate, max-age=0',
232
+ @ctrl.response['Cache-Control']
233
+ assert_equal Time.new("1990","01","01").httpdate,
234
+ @ctrl.response['Expires']
235
+ end
236
+
237
+
238
+ def test_set_cookie
239
+ cookie = {:value => "user@example.com", :expires => Time.now + 360}
240
+ @ctrl.cookies['test'] = cookie
241
+ assert_equal cookie, @ctrl.env["rack.request.cookie_hash"]["test"]
242
+ assert_equal "user@example.com", @ctrl.cookies['test'][:value]
243
+ end
244
+
245
+
246
+ def test_set_session
247
+ @ctrl.session['test'] = 'user@example.com'
248
+ assert_equal({"test"=>"user@example.com"}, @ctrl.env['rack.session'])
249
+ end
250
+
251
+
252
+ def test_call_action
253
+ resp = @ctrl.call_action(:show)
254
+ assert_equal [:f1, :f2], BarController::FILTERS_RUN
255
+ assert_equal [200, {"Content-Type"=>"text/html;charset=UTF-8", "Content-Length"=>"9"},
256
+ ["SHOW 123!"]], resp
257
+ end
258
+
259
+
260
+ def test_call_action_error
261
+ @ctrl.call_action(:index)
262
+ assert_equal [:f1, :f2], BarController::FILTERS_RUN
263
+ end
264
+
265
+
266
+ def test_call_action_caught_error
267
+ resp = @ctrl.call_action(:caught_error)
268
+ assert_equal [:f1, :f2], BarController::FILTERS_RUN
269
+ assert_equal [400, {"Content-Type"=>"text/html;charset=UTF-8", "Content-Length"=>"11"},
270
+ ["Bad Request"]], resp
271
+ end
272
+
273
+
274
+ def test_call_action_halt
275
+ resp = @ctrl.call_action(:delete)
276
+ assert_equal [:f1, :stop, :f2], BarController::FILTERS_RUN
277
+ assert_equal [404, {"Content-Type"=>"text/plain;charset=UTF-8", "Content-Length"=>"41"},
278
+ ["This is not the page you are looking for."]], resp
279
+ end
280
+
281
+
282
+ def test_dispatch
283
+ @ctrl.send(:dispatch, :show)
284
+ assert_equal [:f1, :f2], BarController::FILTERS_RUN
285
+ assert_equal 200, @ctrl.response.status
286
+ assert_equal ["SHOW 123!"], @ctrl.response.body
287
+ end
288
+
289
+
290
+ def test_dispatch_error
291
+ @ctrl.content_type :json
292
+ @ctrl.send(:dispatch, :index)
293
+ assert_equal [:f1, :f2], BarController::FILTERS_RUN
294
+ assert_equal 500, @ctrl.response.status
295
+ assert RuntimeError === @ctrl.env['gin.errors'].first
296
+ assert_equal String, @ctrl.response.body[0].class
297
+ assert_equal "text/html;charset=UTF-8", @ctrl.response['Content-Type']
298
+ assert @ctrl.response.body[0].include?('<h1>RuntimeError</h1>')
299
+ assert @ctrl.response.body[0].include?('<pre>')
300
+ end
301
+
302
+
303
+ def test_dispatch_error_nondev
304
+ MockApp.environment "prod"
305
+ @ctrl.send(:dispatch, :index)
306
+
307
+ assert_equal 500, @ctrl.response.status
308
+ assert RuntimeError === @ctrl.env['gin.errors'].first
309
+
310
+ assert_equal File.read(File.join(Gin::PUBLIC_DIR, "500.html")),
311
+ @ctrl.body.read
312
+ end
313
+
314
+
315
+ def test_dispatch_bad_request_nondev
316
+ MockApp.environment "prod"
317
+ @ctrl = TestController.new @app, rack_env
318
+ @ctrl.params.delete('id')
319
+ @ctrl.send(:dispatch, :show)
320
+
321
+ assert_equal 400, @ctrl.response.status
322
+ assert Gin::BadRequest === @ctrl.env['gin.errors'].first
323
+ assert_equal File.read(File.join(Gin::PUBLIC_DIR, "400.html")),
324
+ @ctrl.body.read
325
+ end
326
+
327
+
328
+ def test_dispatch_not_found_nondev
329
+ MockApp.environment "prod"
330
+ @ctrl = TestController.new @app, rack_env
331
+ @ctrl.params.delete('id')
332
+ @ctrl.send(:dispatch, :not_found)
333
+
334
+ assert_equal 404, @ctrl.response.status
335
+ assert Gin::NotFound === @ctrl.env['gin.errors'].first
336
+ assert_equal File.read(File.join(Gin::PUBLIC_DIR, "404.html")),
337
+ @ctrl.body.read
338
+ end
339
+
340
+
341
+ def test_dispatch_filter_halt
342
+ @ctrl.send(:dispatch, :delete)
343
+ assert_equal [:f1, :stop, :f2], BarController::FILTERS_RUN
344
+ assert_equal 404, @ctrl.response.status
345
+ assert_equal ["Not Found"], @ctrl.response.body
346
+ end
347
+
348
+
349
+ def test_invoke
350
+ @ctrl.send(:invoke){ "test body" }
351
+ assert_equal ["test body"], @ctrl.body
352
+
353
+ @ctrl.send(:invoke){ [401, "test body"] }
354
+ assert_equal 401, @ctrl.status
355
+ assert_equal ["test body"], @ctrl.body
356
+
357
+ @ctrl.send(:invoke){ [302, {'Location' => 'http://foo.com'}, "test body"] }
358
+ assert_equal 302, @ctrl.status
359
+ assert_equal 'http://foo.com', @ctrl.response['Location']
360
+ assert_equal ["test body"], @ctrl.body
361
+
362
+ @ctrl.send(:invoke){ 301 }
363
+ assert_equal 301, @ctrl.status
364
+ end
365
+
366
+
367
+ def test_action_arguments
368
+ assert_raises(Gin::NotFound){ @ctrl.send("action_arguments", "nonaction") }
369
+ assert_equal [], @ctrl.send("action_arguments", "index")
370
+
371
+ assert_equal [123], @ctrl.send("action_arguments", "show")
372
+ assert_equal [123], @ctrl.send("action_arguments", "delete")
373
+
374
+ @ctrl.params.update 'name' => 'bob'
375
+ assert_equal [123,nil,'bob'], @ctrl.send("action_arguments", "delete")
376
+
377
+ @ctrl.params.delete('id')
378
+ assert_raises(Gin::BadRequest){
379
+ @ctrl.send("action_arguments", "show")
380
+ }
381
+ end
382
+
383
+
384
+ if RUBY_VERSION =~ /^2.0/
385
+ eval <<-EVAL
386
+ class SpecialCtrl < Gin::Controller
387
+ def find(q, title_only:false, count: 10); end
388
+ end
389
+ EVAL
390
+
391
+ def test_action_arguments_key_parameters
392
+ @ctrl = SpecialCtrl.new nil, rack_env.merge('QUERY_STRING'=>'q=pizza&count=20')
393
+ assert_equal ["pizza", {count: 20}], @ctrl.send("action_arguments", "find")
394
+ end
395
+ end
396
+
397
+
398
+ def test_asset_url
399
+ old_public_dir = MockApp.public_dir
400
+ MockApp.public_dir File.dirname(__FILE__)
401
+
402
+ file_id = MockApp.md5 __FILE__
403
+ expected = "/test_controller.rb?#{file_id}"
404
+
405
+ assert_equal 8, file_id.length
406
+ assert_equal expected, @ctrl.asset_url(File.basename(__FILE__))
407
+
408
+ ensure
409
+ MockApp.public_dir old_public_dir
410
+ end
411
+
412
+
413
+ def test_asset_url_unknown
414
+ assert_equal "/foo.jpg", @ctrl.asset_url("foo.jpg")
415
+ end
416
+
417
+
418
+ def test_asset_url_w_host
419
+ MockApp.asset_host "http://example.com"
420
+ assert_equal "http://example.com/foo.jpg", @ctrl.asset_url("foo.jpg")
421
+
422
+ MockApp.asset_host do |file|
423
+ file =~ /\.js$/ ? "http://js.example.com" : "http://img.example.com"
424
+ end
425
+ assert_equal "http://js.example.com/foo.js", @ctrl.asset_url("foo.js")
426
+ assert_equal "http://img.example.com/foo.jpg", @ctrl.asset_url("foo.jpg")
427
+ end
428
+
429
+
430
+ def test_redirect_non_get
431
+ rack_env['REQUEST_METHOD'] = 'POST'
432
+ rack_env['HTTP_VERSION'] = 'HTTP/1.0'
433
+ catch(:halt){ @ctrl.redirect "/foo" }
434
+ assert_equal 302, @ctrl.status
435
+ assert_equal "http://example.com/foo", @ctrl.response['Location']
436
+
437
+ rack_env['HTTP_VERSION'] = 'HTTP/1.1'
438
+ catch(:halt){ @ctrl.redirect "/foo" }
439
+ assert_equal 303, @ctrl.status
440
+ assert_equal "http://example.com/foo", @ctrl.response['Location']
441
+ end
442
+
443
+
444
+ def test_redirect
445
+ catch(:halt){ @ctrl.redirect "/foo" }
446
+ assert_equal 302, @ctrl.status
447
+ assert_equal "http://example.com/foo", @ctrl.response['Location']
448
+
449
+ resp = catch(:halt){ @ctrl.redirect "https://google.com/foo", 301, "Move Along" }
450
+ assert_equal 302, @ctrl.status
451
+ assert_equal "https://google.com/foo", @ctrl.response['Location']
452
+ assert_equal [301, "Move Along"], resp
453
+
454
+ resp = catch(:halt){ @ctrl.redirect "https://google.com/foo", 301, {'X-LOC' => "test"}, "Move Along" }
455
+ assert_equal 302, @ctrl.status
456
+ assert_equal "https://google.com/foo", @ctrl.response['Location']
457
+ assert_equal [301, {'X-LOC' => "test"}, "Move Along"], resp
458
+ end
459
+
460
+
461
+ def test_url_to
462
+ assert_equal "http://example.com/bar/123",
463
+ @ctrl.url_to(BarController, :show, :id => 123)
464
+ assert_equal "http://example.com/bar/123", @ctrl.url_to(:show, :id => 123)
465
+ assert_equal "http://example.com/bar/delete?id=123",
466
+ @ctrl.url_to(:rm_bar, :id => 123)
467
+ assert_equal "https://foo.com/path?id=123",
468
+ @ctrl.url_to("https://foo.com/path", :id => 123)
469
+ assert_equal "http://example.com/bar/123",
470
+ @ctrl.to(BarController, :show, :id => 123)
471
+ end
472
+
473
+
474
+ def test_path_to
475
+ assert_equal "/bar/123", @ctrl.path_to(BarController, :show, id: 123)
476
+ assert_equal "/bar/123", @ctrl.path_to(:show, id: 123)
477
+ assert_equal "/bar/delete?id=123", @ctrl.path_to(:rm_bar, id: 123)
478
+ assert_equal "/bar/delete", @ctrl.path_to(:rm_bar)
479
+ assert_equal "/test?id=123", @ctrl.path_to("/test", id: 123)
480
+ assert_equal "/test", @ctrl.path_to("/test")
481
+ end
482
+
483
+
484
+ def test_session
485
+ assert_equal(@ctrl.request.session, @ctrl.session)
486
+ end
487
+
488
+
489
+ def test_params
490
+ assert_equal({'id' => 123}, @ctrl.params)
491
+ assert_equal(@ctrl.request.params, @ctrl.params)
492
+ end
493
+
494
+
495
+ def test_logger
496
+ assert_equal @app.logger, @ctrl.logger
497
+ end
498
+
499
+
500
+ def test_stream
501
+ @ctrl.stream{|out| out << "BODY"}
502
+ assert Gin::Stream === @ctrl.body
503
+ assert_equal Gin::Stream, @ctrl.body.instance_variable_get("@scheduler")
504
+
505
+ @ctrl.env.merge! "async.callback" => lambda{}
506
+
507
+ @ctrl.stream{|out| out << "BODY"}
508
+ assert Gin::Stream === @ctrl.body
509
+ assert_equal EventMachine, @ctrl.body.instance_variable_get("@scheduler")
510
+ end
511
+
512
+
513
+ def test_headers
514
+ @ctrl.headers "Content-Length" => 123
515
+ assert_equal @ctrl.response.headers, @ctrl.headers
516
+ assert_equal({"Content-Length"=>123}, @ctrl.headers)
517
+ end
518
+
519
+
520
+ def test_error_num_and_str
521
+ resp = catch :halt do
522
+ @ctrl.error 404, "Not Found"
523
+ "BAD RESP"
524
+ end
525
+
526
+ assert_equal 404, resp
527
+ assert_equal ["Not Found"], @ctrl.body
528
+ end
529
+
530
+
531
+ def test_error_num
532
+ resp = catch :halt do
533
+ @ctrl.error 404
534
+ "BAD RESP"
535
+ end
536
+
537
+ assert_equal 404, resp
538
+ assert_equal [], @ctrl.body
539
+ end
540
+
541
+
542
+ def test_error_str
543
+ resp = catch :halt do
544
+ @ctrl.error "OH NOES"
545
+ "BAD RESP"
546
+ end
547
+
548
+ assert_equal 500, resp
549
+ assert_equal ["OH NOES"], @ctrl.body
550
+ end
551
+
552
+
553
+ def test_halt_single
554
+ resp = catch :halt do
555
+ @ctrl.halt 400
556
+ "BAD RESP"
557
+ end
558
+
559
+ assert_equal 400, resp
560
+ end
561
+
562
+
563
+ def test_halt_ary
564
+ resp = catch :halt do
565
+ @ctrl.halt 201, "Accepted"
566
+ "BAD RESP"
567
+ end
568
+
569
+ assert_equal [201, "Accepted"], resp
570
+ end
571
+
572
+
573
+ def test_last_modified
574
+ time = Time.now
575
+ @ctrl.last_modified time
576
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
577
+
578
+ date = DateTime.parse time.to_s
579
+ @ctrl.last_modified date
580
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
581
+
582
+ date = Date.parse time.to_s
583
+ expected = Time.new(time.year, time.month, time.day)
584
+ @ctrl.last_modified date
585
+ assert_equal expected.httpdate, @ctrl.response['Last-Modified']
586
+ end
587
+
588
+
589
+ def test_last_modified_str
590
+ time = Time.now
591
+ @ctrl.last_modified time.to_s
592
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
593
+ end
594
+
595
+
596
+ def test_last_modified_int
597
+ time = Time.now
598
+ @ctrl.last_modified time.to_i
599
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
600
+ end
601
+
602
+
603
+ def test_last_modified_false
604
+ @ctrl.last_modified false
605
+ assert_nil @ctrl.response['Last-Modified']
606
+ end
607
+
608
+
609
+ def test_last_modified_if_modified_since
610
+ rack_env['HTTP_IF_MODIFIED_SINCE'] = Time.parse("10 Feb 3012").httpdate
611
+ time = Time.now
612
+ @ctrl.status 200
613
+ res = catch(:halt){ @ctrl.last_modified time }
614
+
615
+ assert_equal 304, res
616
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
617
+
618
+ rack_env['HTTP_IF_MODIFIED_SINCE'] = Time.parse("10 Feb 2012").httpdate
619
+ time = Time.now
620
+ @ctrl.status 200
621
+ @ctrl.last_modified time
622
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
623
+ end
624
+
625
+
626
+ def test_last_modified_if_modified_since_non_200
627
+ rack_env['HTTP_IF_MODIFIED_SINCE'] = Time.parse("10 Feb 3012").httpdate
628
+ time = Time.now
629
+ @ctrl.status 404
630
+ @ctrl.last_modified time
631
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
632
+ end
633
+
634
+
635
+ def test_last_modified_if_unmodified_since
636
+ [200, 299, 412].each do |code|
637
+ rack_env['HTTP_IF_UNMODIFIED_SINCE'] = Time.parse("10 Feb 2012").httpdate
638
+ time = Time.now
639
+ @ctrl.status code
640
+ res = catch(:halt){ @ctrl.last_modified time }
641
+
642
+ assert_equal 412, res
643
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
644
+
645
+ rack_env['HTTP_IF_MODIFIED_SINCE'] = Time.parse("10 Feb 3012").httpdate
646
+ time = Time.now
647
+ @ctrl.status code
648
+ @ctrl.last_modified time
649
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
650
+ end
651
+ end
652
+
653
+
654
+ def test_last_modified_if_unmodified_since_404
655
+ rack_env['HTTP_IF_UNMODIFIED_SINCE'] = Time.parse("10 Feb 2012").httpdate
656
+ time = Time.now
657
+ @ctrl.status 404
658
+ @ctrl.last_modified time
659
+
660
+ assert_equal 404, @ctrl.status
661
+ assert_equal time.httpdate, @ctrl.response['Last-Modified']
662
+ end
663
+
664
+
665
+ def test_send_file
666
+ res = catch(:halt){ @ctrl.send_file "./Manifest.txt" }
667
+ assert_equal 200, res[0]
668
+ assert File === res[1]
669
+
670
+ @ctrl.status 404
671
+ @ctrl.send(:invoke){ @ctrl.send_file "./Manifest.txt" }
672
+ assert_equal 200, @ctrl.status
673
+ assert_equal "text/plain;charset=UTF-8", @ctrl.headers["Content-Type"]
674
+ assert_equal File.size("./Manifest.txt").to_s, @ctrl.headers["Content-Length"]
675
+ assert(Time.parse(@ctrl.headers["Last-Modified"]) >
676
+ Time.parse("Fri, 22 Feb 2012 18:51:31 GMT"))
677
+ assert File === @ctrl.body
678
+
679
+ read_body = ""
680
+ @ctrl.body.each{|data| read_body << data}
681
+ assert_equal File.read("./Manifest.txt"), read_body
682
+ end
683
+
684
+
685
+ def test_send_file_not_found
686
+ res = catch(:halt){ @ctrl.send_file "./no-such-file" }
687
+ assert_equal 404, res
688
+ end
689
+
690
+
691
+ def test_send_file_last_modified
692
+ mod_date = Time.now
693
+ catch(:halt){ @ctrl.send_file "./Manifest.txt", last_modified: mod_date }
694
+ assert_equal mod_date.httpdate, @ctrl.headers["Last-Modified"]
695
+ assert_nil @ctrl.headers['Content-Disposition']
696
+ end
697
+
698
+
699
+ def test_send_file_attachment
700
+ res = catch(:halt){ @ctrl.send_file "./Manifest.txt", :disposition => 'attachment' }
701
+ expected = "attachment; filename=\"Manifest.txt\""
702
+ assert_equal expected, @ctrl.headers['Content-Disposition']
703
+
704
+ res = catch(:halt){
705
+ @ctrl.send_file "./Manifest.txt", :disposition => 'attachment', :filename => "foo.txt"
706
+ }
707
+ expected = "attachment; filename=\"foo.txt\""
708
+ assert_equal expected, @ctrl.headers['Content-Disposition']
709
+ end
710
+
711
+
712
+ def test_mime_type
713
+ assert_equal "text/html", @ctrl.mime_type(:html)
714
+ assert_equal @ctrl.app.mime_type(:html), @ctrl.mime_type(:html)
715
+ end
716
+
717
+
718
+ def test_content_type
719
+ assert_nil @ctrl.content_type
720
+ assert_nil @ctrl.response['Content-Type']
721
+
722
+ @ctrl.content_type 'text/json'
723
+ assert_equal "text/json;charset=UTF-8", @ctrl.content_type
724
+ assert_equal "text/json;charset=UTF-8", @ctrl.response['Content-Type']
725
+
726
+ assert_equal "application/json;charset=UTF-8", @ctrl.content_type(".json")
727
+ end
728
+
729
+
730
+ def test_content_type_params
731
+ assert_equal "application/json;charset=ASCII-8BIT",
732
+ @ctrl.content_type(".json", charset: "ASCII-8BIT")
733
+
734
+ assert_equal "application/json;foo=bar, charset=UTF-8",
735
+ @ctrl.content_type(".json", foo: "bar")
736
+ end
737
+
738
+
739
+ def test_content_type_unknown
740
+ assert_raises RuntimeError do
741
+ @ctrl.content_type 'fhwbghd'
742
+ end
743
+
744
+ assert_equal "text/html;charset=UTF-8",
745
+ @ctrl.content_type('fhwbghd', default: 'text/html')
746
+ end
747
+
748
+
749
+ def test_body
750
+ assert_equal [], @ctrl.body
751
+ assert_equal [], @ctrl.response.body
752
+
753
+ @ctrl.body("<HTML></HTML>")
754
+ assert_equal ["<HTML></HTML>"], @ctrl.body
755
+ assert_equal ["<HTML></HTML>"], @ctrl.response.body
756
+ end
757
+
758
+
759
+ def test_status
760
+ assert_equal 200, @ctrl.status
761
+ assert_equal 200, @ctrl.response.status
762
+
763
+ @ctrl.status(404)
764
+ assert_equal 404, @ctrl.status
765
+ assert_equal 404, @ctrl.response.status
766
+ end
767
+
768
+
769
+ def test_init
770
+ assert Gin::Request === @ctrl.request
771
+ assert Gin::Response === @ctrl.response
772
+ assert_nil @ctrl.response['Content-Type']
773
+ assert_equal @app, @ctrl.app
774
+ assert_equal rack_env, @ctrl.env
775
+ end
776
+
777
+
778
+ def test_supports_features
779
+ assert Gin::Controller.ancestors.include?(Gin::Filterable)
780
+ assert Gin::Controller.ancestors.include?(Gin::Errorable)
781
+ end
782
+
783
+
784
+ def test_class_controller_name
785
+ assert_equal "app", AppController.controller_name
786
+ assert_equal "bar", BarController.controller_name
787
+
788
+ assert_equal "app", AppController.new(nil,rack_env).controller_name
789
+ end
790
+
791
+
792
+ def test_class_content_type
793
+ assert_equal "text/html", AppController.content_type
794
+ assert_equal "text/html", BarController.content_type
795
+
796
+ AppController.content_type "application/json"
797
+ assert_equal "application/json", AppController.content_type
798
+ assert_equal "application/json", BarController.content_type
799
+
800
+ BarController.content_type "text/plain"
801
+ assert_equal "application/json", AppController.content_type
802
+ assert_equal "text/plain", BarController.content_type
803
+
804
+ ensure
805
+ AppController.instance_variable_set("@content_type",nil)
806
+ BarController.instance_variable_set("@content_type",nil)
807
+ end
808
+ end