Froze rails gems
[depot.git] / vendor / rails / actionpack / test / controller / caching_test.rb
1 require 'fileutils'
2 require 'abstract_unit'
3
4 CACHE_DIR = 'test_cache'
5 # Don't change '/../temp/' cavalierly or you might hose something you don't want hosed
6 FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR)
7 ActionController::Base.page_cache_directory = FILE_STORE_PATH
8 ActionController::Base.cache_store = :file_store, FILE_STORE_PATH
9
10 class PageCachingTestController < ActionController::Base
11 caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? }
12 caches_page :found, :not_found
13
14 def ok
15 head :ok
16 end
17
18 def no_content
19 head :no_content
20 end
21
22 def found
23 redirect_to :action => 'ok'
24 end
25
26 def not_found
27 head :not_found
28 end
29
30 def custom_path
31 render :text => "Super soaker"
32 cache_page("Super soaker", "/index.html")
33 end
34
35 def expire_custom_path
36 expire_page("/index.html")
37 head :ok
38 end
39
40 def trailing_slash
41 render :text => "Sneak attack"
42 end
43 end
44
45 class PageCachingTest < Test::Unit::TestCase
46 def setup
47 ActionController::Base.perform_caching = true
48
49 ActionController::Routing::Routes.draw do |map|
50 map.main '', :controller => 'posts'
51 map.resources :posts
52 map.connect ':controller/:action/:id'
53 end
54
55 @request = ActionController::TestRequest.new
56 @request.host = 'hostname.com'
57
58 @response = ActionController::TestResponse.new
59 @controller = PageCachingTestController.new
60
61 @params = {:controller => 'posts', :action => 'index', :only_path => true, :skip_relative_url_root => true}
62 @rewriter = ActionController::UrlRewriter.new(@request, @params)
63
64 FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
65 FileUtils.mkdir_p(FILE_STORE_PATH)
66 end
67
68 def teardown
69 FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
70
71 ActionController::Base.perform_caching = false
72 end
73
74 def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
75 @params[:format] = 'rss'
76 assert_equal '/posts.rss', @rewriter.rewrite(@params)
77 @params[:format] = nil
78 assert_equal '/', @rewriter.rewrite(@params)
79 end
80
81 def test_should_cache_get_with_ok_status
82 get :ok
83 assert_response :ok
84 assert_page_cached :ok, "get with ok status should have been cached"
85 end
86
87 def test_should_cache_with_custom_path
88 get :custom_path
89 assert File.exist?("#{FILE_STORE_PATH}/index.html")
90 end
91
92 def test_should_expire_cache_with_custom_path
93 get :custom_path
94 assert File.exist?("#{FILE_STORE_PATH}/index.html")
95
96 get :expire_custom_path
97 assert !File.exist?("#{FILE_STORE_PATH}/index.html")
98 end
99
100 def test_should_cache_without_trailing_slash_on_url
101 @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash'
102 assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
103 end
104
105 def test_should_cache_with_trailing_slash_on_url
106 @controller.class.cache_page 'cached content', '/page_caching_test/trailing_slash/'
107 assert File.exist?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
108 end
109
110 uses_mocha("should_cache_ok_at_custom_path") do
111 def test_should_cache_ok_at_custom_path
112 @request.stubs(:path).returns("/index.html")
113 get :ok
114 assert_response :ok
115 assert File.exist?("#{FILE_STORE_PATH}/index.html")
116 end
117 end
118
119 [:ok, :no_content, :found, :not_found].each do |status|
120 [:get, :post, :put, :delete].each do |method|
121 unless method == :get and status == :ok
122 define_method "test_shouldnt_cache_#{method}_with_#{status}_status" do
123 @request.env['REQUEST_METHOD'] = method.to_s.upcase
124 process status
125 assert_response status
126 assert_page_not_cached status, "#{method} with #{status} status shouldn't have been cached"
127 end
128 end
129 end
130 end
131
132 def test_page_caching_conditional_options
133 get :ok, :format=>'json'
134 assert_page_not_cached :ok
135 end
136
137 private
138 def assert_page_cached(action, message = "#{action} should have been cached")
139 assert page_cached?(action), message
140 end
141
142 def assert_page_not_cached(action, message = "#{action} shouldn't have been cached")
143 assert !page_cached?(action), message
144 end
145
146 def page_cached?(action)
147 File.exist? "#{FILE_STORE_PATH}/page_caching_test/#{action}.html"
148 end
149 end
150
151 class ActionCachingTestController < ActionController::Base
152 caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? }, :expires_in => 1.hour
153 caches_action :show, :cache_path => 'http://test.host/custom/show'
154 caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
155 caches_action :with_layout
156 caches_action :layout_false, :layout => false
157
158 layout 'talk_from_action.erb'
159
160 def index
161 @cache_this = MockTime.now.to_f.to_s
162 render :text => @cache_this
163 end
164
165 def redirected
166 redirect_to :action => 'index'
167 end
168
169 def forbidden
170 render :text => "Forbidden"
171 headers["Status"] = "403 Forbidden"
172 end
173
174 def with_layout
175 @cache_this = MockTime.now.to_f.to_s
176 render :text => @cache_this, :layout => true
177 end
178
179 alias_method :show, :index
180 alias_method :edit, :index
181 alias_method :destroy, :index
182 alias_method :layout_false, :with_layout
183
184 def expire
185 expire_action :controller => 'action_caching_test', :action => 'index'
186 render :nothing => true
187 end
188
189 def expire_xml
190 expire_action :controller => 'action_caching_test', :action => 'index', :format => 'xml'
191 render :nothing => true
192 end
193 end
194
195 class MockTime < Time
196 # Let Time spicy to assure that Time.now != Time.now
197 def to_f
198 super+rand
199 end
200 end
201
202 class ActionCachingMockController
203 attr_accessor :mock_url_for
204 attr_accessor :mock_path
205
206 def initialize
207 yield self if block_given?
208 end
209
210 def url_for(*args)
211 @mock_url_for
212 end
213
214 def request
215 mocked_path = @mock_path
216 Object.new.instance_eval(<<-EVAL)
217 def path; '#{@mock_path}' end
218 def format; 'all' end
219 def cache_format; nil end
220 self
221 EVAL
222 end
223 end
224
225 class ActionCacheTest < Test::Unit::TestCase
226 def setup
227 reset!
228 FileUtils.mkdir_p(FILE_STORE_PATH)
229 @path_class = ActionController::Caching::Actions::ActionCachePath
230 @mock_controller = ActionCachingMockController.new
231 end
232
233 def teardown
234 FileUtils.rm_rf(File.dirname(FILE_STORE_PATH))
235 end
236
237 def test_simple_action_cache
238 get :index
239 cached_time = content_to_cache
240 assert_equal cached_time, @response.body
241 assert fragment_exist?('hostname.com/action_caching_test')
242 reset!
243
244 get :index
245 assert_equal cached_time, @response.body
246 end
247
248 def test_simple_action_not_cached
249 get :destroy
250 cached_time = content_to_cache
251 assert_equal cached_time, @response.body
252 assert !fragment_exist?('hostname.com/action_caching_test/destroy')
253 reset!
254
255 get :destroy
256 assert_not_equal cached_time, @response.body
257 end
258
259 def test_action_cache_with_layout
260 get :with_layout
261 cached_time = content_to_cache
262 assert_not_equal cached_time, @response.body
263 assert fragment_exist?('hostname.com/action_caching_test/with_layout')
264 reset!
265
266 get :with_layout
267 assert_not_equal cached_time, @response.body
268
269 assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout')
270 end
271
272 def test_action_cache_with_layout_and_layout_cache_false
273 get :layout_false
274 cached_time = content_to_cache
275 assert_not_equal cached_time, @response.body
276 assert fragment_exist?('hostname.com/action_caching_test/layout_false')
277 reset!
278
279 get :layout_false
280 assert_not_equal cached_time, @response.body
281
282 assert_equal cached_time, read_fragment('hostname.com/action_caching_test/layout_false')
283 end
284
285 def test_action_cache_conditional_options
286 old_use_accept_header = ActionController::Base.use_accept_header
287 ActionController::Base.use_accept_header = true
288 @request.env['HTTP_ACCEPT'] = 'application/json'
289 get :index
290 assert !fragment_exist?('hostname.com/action_caching_test')
291 ActionController::Base.use_accept_header = old_use_accept_header
292 end
293
294 uses_mocha 'test action cache' do
295 def test_action_cache_with_store_options
296 MockTime.expects(:now).returns(12345).once
297 @controller.expects(:read_fragment).with('hostname.com/action_caching_test', :expires_in => 1.hour).once
298 @controller.expects(:write_fragment).with('hostname.com/action_caching_test', '12345.0', :expires_in => 1.hour).once
299 get :index
300 end
301 end
302
303 def test_action_cache_with_custom_cache_path
304 get :show
305 cached_time = content_to_cache
306 assert_equal cached_time, @response.body
307 assert fragment_exist?('test.host/custom/show')
308 reset!
309
310 get :show
311 assert_equal cached_time, @response.body
312 end
313
314 def test_action_cache_with_custom_cache_path_in_block
315 get :edit
316 assert fragment_exist?('test.host/edit')
317 reset!
318
319 get :edit, :id => 1
320 assert fragment_exist?('test.host/1;edit')
321 end
322
323 def test_cache_expiration
324 get :index
325 cached_time = content_to_cache
326 reset!
327
328 get :index
329 assert_equal cached_time, @response.body
330 reset!
331
332 get :expire
333 reset!
334
335 get :index
336 new_cached_time = content_to_cache
337 assert_not_equal cached_time, @response.body
338 reset!
339
340 get :index
341 assert_response :success
342 assert_equal new_cached_time, @response.body
343 end
344
345 def test_cache_expiration_isnt_affected_by_request_format
346 get :index
347 cached_time = content_to_cache
348 reset!
349
350 @request.set_REQUEST_URI "/action_caching_test/expire.xml"
351 get :expire, :format => :xml
352 reset!
353
354 get :index
355 new_cached_time = content_to_cache
356 assert_not_equal cached_time, @response.body
357 end
358
359 def test_cache_is_scoped_by_subdomain
360 @request.host = 'jamis.hostname.com'
361 get :index
362 jamis_cache = content_to_cache
363
364 reset!
365
366 @request.host = 'david.hostname.com'
367 get :index
368 david_cache = content_to_cache
369 assert_not_equal jamis_cache, @response.body
370
371 reset!
372
373 @request.host = 'jamis.hostname.com'
374 get :index
375 assert_equal jamis_cache, @response.body
376
377 reset!
378
379 @request.host = 'david.hostname.com'
380 get :index
381 assert_equal david_cache, @response.body
382 end
383
384 def test_redirect_is_not_cached
385 get :redirected
386 assert_response :redirect
387 reset!
388
389 get :redirected
390 assert_response :redirect
391 end
392
393 def test_forbidden_is_not_cached
394 get :forbidden
395 assert_response :forbidden
396 reset!
397
398 get :forbidden
399 assert_response :forbidden
400 end
401
402 def test_xml_version_of_resource_is_treated_as_different_cache
403 with_routing do |set|
404 ActionController::Routing::Routes.draw do |map|
405 map.connect ':controller/:action.:format'
406 map.connect ':controller/:action'
407 end
408
409 get :index, :format => 'xml'
410 cached_time = content_to_cache
411 assert_equal cached_time, @response.body
412 assert fragment_exist?('hostname.com/action_caching_test/index.xml')
413 reset!
414
415 get :index, :format => 'xml'
416 assert_equal cached_time, @response.body
417 assert_equal 'application/xml', @response.content_type
418 reset!
419
420 get :expire_xml
421 reset!
422
423 get :index, :format => 'xml'
424 assert_not_equal cached_time, @response.body
425 end
426 end
427
428 def test_correct_content_type_is_returned_for_cache_hit
429 # run it twice to cache it the first time
430 get :index, :id => 'content-type.xml'
431 get :index, :id => 'content-type.xml'
432 assert_equal 'application/xml', @response.content_type
433 end
434
435 def test_empty_path_is_normalized
436 @mock_controller.mock_url_for = 'http://example.org/'
437 @mock_controller.mock_path = '/'
438
439 assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {})
440 end
441
442 def test_file_extensions
443 get :index, :id => 'kitten.jpg'
444 get :index, :id => 'kitten.jpg'
445
446 assert_response :success
447 end
448
449 private
450 def content_to_cache
451 assigns(:cache_this)
452 end
453
454 def reset!
455 @request = ActionController::TestRequest.new
456 @response = ActionController::TestResponse.new
457 @controller = ActionCachingTestController.new
458 @request.host = 'hostname.com'
459 end
460
461 def fragment_exist?(path)
462 @controller.fragment_exist?(path)
463 end
464
465 def read_fragment(path)
466 @controller.read_fragment(path)
467 end
468 end
469
470 class FragmentCachingTestController < ActionController::Base
471 def some_action; end;
472 end
473
474 class FragmentCachingTest < Test::Unit::TestCase
475 def setup
476 ActionController::Base.perform_caching = true
477 @store = ActiveSupport::Cache::MemoryStore.new
478 ActionController::Base.cache_store = @store
479 @controller = FragmentCachingTestController.new
480 @params = {:controller => 'posts', :action => 'index'}
481 @request = ActionController::TestRequest.new
482 @response = ActionController::TestResponse.new
483 @controller.params = @params
484 @controller.request = @request
485 @controller.response = @response
486 @controller.send(:initialize_current_url)
487 @controller.send(:initialize_template_class, @response)
488 @controller.send(:assign_shortcuts, @request, @response)
489 end
490
491 def test_fragment_cache_key
492 assert_equal 'views/what a key', @controller.fragment_cache_key('what a key')
493 assert_equal "views/test.host/fragment_caching_test/some_action",
494 @controller.fragment_cache_key(:controller => 'fragment_caching_test',:action => 'some_action')
495 end
496
497 def test_read_fragment_with_caching_enabled
498 @store.write('views/name', 'value')
499 assert_equal 'value', @controller.read_fragment('name')
500 end
501
502 def test_read_fragment_with_caching_disabled
503 ActionController::Base.perform_caching = false
504 @store.write('views/name', 'value')
505 assert_nil @controller.read_fragment('name')
506 end
507
508 def test_fragment_exist_with_caching_enabled
509 @store.write('views/name', 'value')
510 assert @controller.fragment_exist?('name')
511 assert !@controller.fragment_exist?('other_name')
512 end
513
514 def test_fragment_exist_with_caching_disabled
515 ActionController::Base.perform_caching = false
516 @store.write('views/name', 'value')
517 assert !@controller.fragment_exist?('name')
518 assert !@controller.fragment_exist?('other_name')
519 end
520
521 def test_write_fragment_with_caching_enabled
522 assert_nil @store.read('views/name')
523 assert_equal 'value', @controller.write_fragment('name', 'value')
524 assert_equal 'value', @store.read('views/name')
525 end
526
527 def test_write_fragment_with_caching_disabled
528 assert_nil @store.read('views/name')
529 ActionController::Base.perform_caching = false
530 assert_equal nil, @controller.write_fragment('name', 'value')
531 assert_nil @store.read('views/name')
532 end
533
534 def test_expire_fragment_with_simple_key
535 @store.write('views/name', 'value')
536 @controller.expire_fragment 'name'
537 assert_nil @store.read('views/name')
538 end
539
540 def test_expire_fragment_with_regexp
541 @store.write('views/name', 'value')
542 @store.write('views/another_name', 'another_value')
543 @store.write('views/primalgrasp', 'will not expire ;-)')
544
545 @controller.expire_fragment /name/
546
547 assert_nil @store.read('views/name')
548 assert_nil @store.read('views/another_name')
549 assert_equal 'will not expire ;-)', @store.read('views/primalgrasp')
550 end
551
552 def test_fragment_for_with_disabled_caching
553 ActionController::Base.perform_caching = false
554
555 @store.write('views/expensive', 'fragment content')
556 fragment_computed = false
557
558 buffer = 'generated till now -> '
559 @controller.fragment_for(buffer, 'expensive') { fragment_computed = true }
560
561 assert fragment_computed
562 assert_equal 'generated till now -> ', buffer
563 end
564
565 def test_fragment_for
566 @store.write('views/expensive', 'fragment content')
567 fragment_computed = false
568
569 buffer = 'generated till now -> '
570 @controller.fragment_for(buffer, 'expensive') { fragment_computed = true }
571
572 assert !fragment_computed
573 assert_equal 'generated till now -> fragment content', buffer
574 end
575 end
576
577 class FunctionalCachingController < ActionController::Base
578 def fragment_cached
579 end
580
581 def html_fragment_cached_with_partial
582 respond_to do |format|
583 format.html
584 end
585 end
586
587 def js_fragment_cached_with_partial
588 respond_to do |format|
589 format.js
590 end
591 end
592
593 def formatted_fragment_cached
594 respond_to do |format|
595 format.html
596 format.xml
597 format.js
598 end
599 end
600
601 def rescue_action(e)
602 raise e
603 end
604 end
605
606 class FunctionalFragmentCachingTest < Test::Unit::TestCase
607 def setup
608 ActionController::Base.perform_caching = true
609 @store = ActiveSupport::Cache::MemoryStore.new
610 ActionController::Base.cache_store = @store
611 @controller = FunctionalCachingController.new
612 @request = ActionController::TestRequest.new
613 @response = ActionController::TestResponse.new
614 end
615
616 def test_fragment_caching
617 get :fragment_cached
618 assert_response :success
619 expected_body = <<-CACHED
620 Hello
621 This bit's fragment cached
622 CACHED
623 assert_equal expected_body, @response.body
624
625 assert_equal "This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached')
626 end
627
628 def test_fragment_caching_in_partials
629 get :html_fragment_cached_with_partial
630 assert_response :success
631 assert_match /Fragment caching in a partial/, @response.body
632 assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')
633 end
634
635 def test_render_inline_before_fragment_caching
636 get :inline_fragment_cached
637 assert_response :success
638 assert_match /Some inline content/, @response.body
639 assert_match /Some cached content/, @response.body
640 assert_match "Some cached content", @store.read('views/test.host/functional_caching/inline_fragment_cached')
641 end
642
643 def test_fragment_caching_in_rjs_partials
644 xhr :get, :js_fragment_cached_with_partial
645 assert_response :success
646 assert_match /Fragment caching in a partial/, @response.body
647 assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial')
648 end
649
650 def test_html_formatted_fragment_caching
651 get :formatted_fragment_cached, :format => "html"
652 assert_response :success
653 expected_body = "<body>\n<p>ERB</p>\n</body>"
654
655 assert_equal expected_body, @response.body
656
657 assert_equal "<p>ERB</p>", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
658 end
659
660 def test_xml_formatted_fragment_caching
661 get :formatted_fragment_cached, :format => "xml"
662 assert_response :success
663 expected_body = "<body>\n <p>Builder</p>\n</body>\n"
664
665 assert_equal expected_body, @response.body
666
667 assert_equal " <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
668 end
669
670 def test_js_formatted_fragment_caching
671 get :formatted_fragment_cached, :format => "js"
672 assert_response :success
673 expected_body = %(title = "Hey";\n$("element_1").visualEffect("highlight");\n) +
674 %($("element_2").visualEffect("highlight");\nfooter = "Bye";)
675 assert_equal expected_body, @response.body
676
677 assert_equal ['$("element_1").visualEffect("highlight");', '$("element_2").visualEffect("highlight");'],
678 @store.read('views/test.host/functional_caching/formatted_fragment_cached')
679 end
680 end