2 require 'abstract_unit'
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
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
23 redirect_to
:action => 'ok'
31 render
:text => "Super soaker"
32 cache_page("Super soaker", "/index.html")
35 def expire_custom_path
36 expire_page("/index.html")
41 render
:text => "Sneak attack"
45 class PageCachingTest
< ActionController
::TestCase
47 ActionController
::Base.perform_caching
= true
49 ActionController
::Routing::Routes.draw
do |map
|
50 map
.main
'', :controller => 'posts'
51 map
.formatted_posts
'posts.:format', :controller => 'posts'
53 map
.connect
':controller/:action/:id'
56 @request = ActionController
::TestRequest.new
57 @request.host
= 'hostname.com'
59 @response = ActionController
::TestResponse.new
60 @controller = PageCachingTestController
.new
62 @params = {:controller => 'posts', :action => 'index', :only_path => true, :skip_relative_url_root => true}
63 @rewriter = ActionController
::UrlRewriter.new(@request, @params)
65 FileUtils
.rm_rf(File
.dirname(FILE_STORE_PATH
))
66 FileUtils
.mkdir_p(FILE_STORE_PATH
)
70 FileUtils
.rm_rf(File
.dirname(FILE_STORE_PATH
))
71 ActionController
::Routing::Routes.clear
!
72 ActionController
::Base.perform_caching
= false
75 def test_page_caching_resources_saves_to_correct_path_with_extension_even_if_default_route
76 @params[:format] = 'rss'
77 assert_equal
'/posts.rss', @rewriter.rewrite(@params)
78 @params[:format] = nil
79 assert_equal
'/', @rewriter.rewrite(@params)
82 def test_should_cache_get_with_ok_status
85 assert_page_cached
:ok, "get with ok status should have been cached"
88 def test_should_cache_with_custom_path
90 assert File
.exist
?("#{FILE_STORE_PATH}/index.html")
93 def test_should_expire_cache_with_custom_path
95 assert File
.exist
?("#{FILE_STORE_PATH}/index.html")
97 get
:expire_custom_path
98 assert
!File
.exist
?("#{FILE_STORE_PATH}/index.html")
101 def test_should_cache_without_trailing_slash_on_url
102 @controller.class.cache_page
'cached content', '/page_caching_test/trailing_slash'
103 assert File
.exist
?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
106 def test_should_cache_with_trailing_slash_on_url
107 @controller.class.cache_page
'cached content', '/page_caching_test/trailing_slash/'
108 assert File
.exist
?("#{FILE_STORE_PATH}/page_caching_test/trailing_slash.html")
111 def test_should_cache_ok_at_custom_path
112 @request.stubs(:path).returns("/index.html")
115 assert File
.exist
?("#{FILE_STORE_PATH}/index.html")
118 [:ok, :no_content, :found, :not_found].each
do |status
|
119 [:get, :post, :put, :delete].each
do |method
|
120 unless method
== :get and status
== :ok
121 define_method
"test_shouldnt_cache_#{method}_with_#{status}_status" do
123 assert_response status
124 assert_page_not_cached status
, "#{method} with #{status} status shouldn't have been cached"
130 def test_page_caching_conditional_options
131 get
:ok, :format=>'json'
132 assert_page_not_cached
:ok
136 def assert_page_cached(action
, message
= "#{action} should have been cached")
137 assert page_cached
?(action
), message
140 def assert_page_not_cached(action
, message
= "#{action} shouldn't have been cached")
141 assert
!page_cached
?(action
), message
144 def page_cached
?(action
)
145 File
.exist
? "#{FILE_STORE_PATH}/page_caching_test/#{action}.html"
149 class ActionCachingTestController
< ActionController
::Base
150 caches_action
:index, :redirected, :forbidden, :if => Proc
.new
{ |c
| !c
.request
.format
.json
? }, :expires_in => 1.hour
151 caches_action
:show, :cache_path => 'http://test.host/custom/show'
152 caches_action
:edit, :cache_path => Proc
.new
{ |c
| c
.params
[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" }
153 caches_action
:with_layout
154 caches_action
:layout_false, :layout => false
156 layout
'talk_from_action.erb'
159 @cache_this = MockTime
.now
.to_f
.to_s
160 render
:text => @cache_this
164 redirect_to
:action => 'index'
168 render
:text => "Forbidden"
169 response
.status
= "403 Forbidden"
173 @cache_this = MockTime
.now
.to_f
.to_s
174 render
:text => @cache_this, :layout => true
177 alias_method
:show, :index
178 alias_method
:edit, :index
179 alias_method
:destroy, :index
180 alias_method
:layout_false, :with_layout
183 expire_action
:controller => 'action_caching_test', :action => 'index'
184 render
:nothing => true
188 expire_action
:controller => 'action_caching_test', :action => 'index', :format => 'xml'
189 render
:nothing => true
193 class MockTime
< Time
194 # Let Time spicy to assure that Time.now != Time.now
200 class ActionCachingMockController
201 attr_accessor
:mock_url_for
202 attr_accessor
:mock_path
205 yield self if block_given
?
213 mocked_path
= @mock_path
214 Object
.new
.instance_eval(<<-EVAL)
215 def path; '#{@mock_path}' end
216 def format; 'all' end
217 def cache_format; nil end
223 class ActionCacheTest
< ActionController
::TestCase
226 FileUtils
.mkdir_p(FILE_STORE_PATH
)
227 @path_class = ActionController
::Caching::Actions::ActionCachePath
228 @mock_controller = ActionCachingMockController
.new
232 FileUtils
.rm_rf(File
.dirname(FILE_STORE_PATH
))
235 def test_simple_action_cache
237 cached_time
= content_to_cache
238 assert_equal cached_time
, @response.body
239 assert fragment_exist
?('hostname.com/action_caching_test')
243 assert_equal cached_time
, @response.body
246 def test_simple_action_not_cached
248 cached_time
= content_to_cache
249 assert_equal cached_time
, @response.body
250 assert
!fragment_exist
?('hostname.com/action_caching_test/destroy')
254 assert_not_equal cached_time
, @response.body
257 def test_action_cache_with_layout
259 cached_time
= content_to_cache
260 assert_not_equal cached_time
, @response.body
261 assert fragment_exist
?('hostname.com/action_caching_test/with_layout')
265 assert_not_equal cached_time
, @response.body
267 assert_equal
@response.body
, read_fragment('hostname.com/action_caching_test/with_layout')
270 def test_action_cache_with_layout_and_layout_cache_false
272 cached_time
= content_to_cache
273 assert_not_equal cached_time
, @response.body
274 assert fragment_exist
?('hostname.com/action_caching_test/layout_false')
278 assert_not_equal cached_time
, @response.body
280 assert_equal cached_time
, read_fragment('hostname.com/action_caching_test/layout_false')
283 def test_action_cache_conditional_options
284 old_use_accept_header
= ActionController
::Base.use_accept_header
285 ActionController
::Base.use_accept_header
= true
286 @request.env['HTTP_ACCEPT'] = 'application/json'
288 assert
!fragment_exist
?('hostname.com/action_caching_test')
289 ActionController
::Base.use_accept_header
= old_use_accept_header
292 def test_action_cache_with_store_options
293 MockTime
.expects(:now).returns(12345).once
294 @controller.expects(:read_fragment).with('hostname.com/action_caching_test', :expires_in => 1.hour
).once
295 @controller.expects(:write_fragment).with('hostname.com/action_caching_test', '12345.0', :expires_in => 1.hour
).once
299 def test_action_cache_with_custom_cache_path
301 cached_time
= content_to_cache
302 assert_equal cached_time
, @response.body
303 assert fragment_exist
?('test.host/custom/show')
307 assert_equal cached_time
, @response.body
310 def test_action_cache_with_custom_cache_path_in_block
312 assert fragment_exist
?('test.host/edit')
316 assert fragment_exist
?('test.host/1;edit')
319 def test_cache_expiration
321 cached_time
= content_to_cache
325 assert_equal cached_time
, @response.body
332 new_cached_time
= content_to_cache
333 assert_not_equal cached_time
, @response.body
337 assert_response
:success
338 assert_equal new_cached_time
, @response.body
341 def test_cache_expiration_isnt_affected_by_request_format
343 cached_time
= content_to_cache
346 @request.set_REQUEST_URI
"/action_caching_test/expire.xml"
347 get
:expire, :format => :xml
351 new_cached_time
= content_to_cache
352 assert_not_equal cached_time
, @response.body
355 def test_cache_is_scoped_by_subdomain
356 @request.host
= 'jamis.hostname.com'
358 jamis_cache
= content_to_cache
362 @request.host
= 'david.hostname.com'
364 david_cache
= content_to_cache
365 assert_not_equal jamis_cache
, @response.body
369 @request.host
= 'jamis.hostname.com'
371 assert_equal jamis_cache
, @response.body
375 @request.host
= 'david.hostname.com'
377 assert_equal david_cache
, @response.body
380 def test_redirect_is_not_cached
382 assert_response
:redirect
386 assert_response
:redirect
389 def test_forbidden_is_not_cached
391 assert_response
:forbidden
395 assert_response
:forbidden
398 def test_xml_version_of_resource_is_treated_as_different_cache
399 with_routing
do |set
|
401 map
.connect
':controller/:action.:format'
402 map
.connect
':controller/:action'
405 get
:index, :format => 'xml'
406 cached_time
= content_to_cache
407 assert_equal cached_time
, @response.body
408 assert fragment_exist
?('hostname.com/action_caching_test/index.xml')
411 get
:index, :format => 'xml'
412 assert_equal cached_time
, @response.body
413 assert_equal
'application/xml', @response.content_type
419 get
:index, :format => 'xml'
420 assert_not_equal cached_time
, @response.body
424 def test_correct_content_type_is_returned_for_cache_hit
425 # run it twice to cache it the first time
426 get
:index, :id => 'content-type.xml'
427 get
:index, :id => 'content-type.xml'
428 assert_equal
'application/xml', @response.content_type
431 def test_correct_content_type_is_returned_for_cache_hit_on_action_with_string_key
432 # run it twice to cache it the first time
433 get
:show, :format => 'xml'
434 get
:show, :format => 'xml'
435 assert_equal
'application/xml', @response.content_type
438 def test_correct_content_type_is_returned_for_cache_hit_on_action_with_string_key_from_proc
439 # run it twice to cache it the first time
440 get
:edit, :id => 1, :format => 'xml'
441 get
:edit, :id => 1, :format => 'xml'
442 assert_equal
'application/xml', @response.content_type
445 def test_empty_path_is_normalized
446 @mock_controller.mock_url_for
= 'http://example.org/'
447 @mock_controller.mock_path
= '/'
449 assert_equal
'example.org/index', @path_class.path_for(@mock_controller, {})
452 def test_file_extensions
453 get
:index, :id => 'kitten.jpg'
454 get
:index, :id => 'kitten.jpg'
456 assert_response
:success
465 @request = ActionController
::TestRequest.new
466 @response = ActionController
::TestResponse.new
467 @controller = ActionCachingTestController
.new
468 @request.host
= 'hostname.com'
471 def fragment_exist
?(path
)
472 @controller.fragment_exist
?(path
)
475 def read_fragment(path
)
476 @controller.read_fragment(path
)
480 class FragmentCachingTestController
< ActionController
::Base
481 def some_action
; end;
484 class FragmentCachingTest
< ActionController
::TestCase
486 ActionController
::Base.perform_caching
= true
487 @store = ActiveSupport
::Cache::MemoryStore.new
488 ActionController
::Base.cache_store
= @store
489 @controller = FragmentCachingTestController
.new
490 @params = {:controller => 'posts', :action => 'index'}
491 @request = ActionController
::TestRequest.new
492 @response = ActionController
::TestResponse.new
493 @controller.params
= @params
494 @controller.request
= @request
495 @controller.response
= @response
496 @controller.send(:initialize_current_url)
497 @controller.send(:initialize_template_class, @response)
498 @controller.send(:assign_shortcuts, @request, @response)
501 def test_fragment_cache_key
502 assert_equal
'views/what a key', @controller.fragment_cache_key('what a key')
503 assert_equal
"views/test.host/fragment_caching_test/some_action",
504 @controller.fragment_cache_key(:controller => 'fragment_caching_test',:action => 'some_action')
507 def test_read_fragment_with_caching_enabled
508 @store.write('views/name', 'value')
509 assert_equal
'value', @controller.read_fragment('name')
512 def test_read_fragment_with_caching_disabled
513 ActionController
::Base.perform_caching
= false
514 @store.write('views/name', 'value')
515 assert_nil
@controller.read_fragment('name')
518 def test_fragment_exist_with_caching_enabled
519 @store.write('views/name', 'value')
520 assert
@controller.fragment_exist
?('name')
521 assert
!@controller.fragment_exist
?('other_name')
524 def test_fragment_exist_with_caching_disabled
525 ActionController
::Base.perform_caching
= false
526 @store.write('views/name', 'value')
527 assert
!@controller.fragment_exist
?('name')
528 assert
!@controller.fragment_exist
?('other_name')
531 def test_write_fragment_with_caching_enabled
532 assert_nil
@store.read('views/name')
533 assert_equal
'value', @controller.write_fragment('name', 'value')
534 assert_equal
'value', @store.read('views/name')
537 def test_write_fragment_with_caching_disabled
538 assert_nil
@store.read('views/name')
539 ActionController
::Base.perform_caching
= false
540 assert_equal
'value', @controller.write_fragment('name', 'value')
541 assert_nil
@store.read('views/name')
544 def test_expire_fragment_with_simple_key
545 @store.write('views/name', 'value')
546 @controller.expire_fragment
'name'
547 assert_nil
@store.read('views/name')
550 def test_expire_fragment_with_regexp
551 @store.write('views/name', 'value')
552 @store.write('views/another_name', 'another_value')
553 @store.write('views/primalgrasp', 'will not expire ;-)')
555 @controller.expire_fragment
/name/
557 assert_nil
@store.read('views/name')
558 assert_nil
@store.read('views/another_name')
559 assert_equal
'will not expire ;-)', @store.read('views/primalgrasp')
562 def test_fragment_for_with_disabled_caching
563 ActionController
::Base.perform_caching
= false
565 @store.write('views/expensive', 'fragment content')
566 fragment_computed
= false
568 buffer
= 'generated till now -> '
569 @controller.fragment_for(buffer
, 'expensive') { fragment_computed
= true }
571 assert fragment_computed
572 assert_equal
'generated till now -> ', buffer
575 def test_fragment_for
576 @store.write('views/expensive', 'fragment content')
577 fragment_computed
= false
579 buffer
= 'generated till now -> '
580 @controller.fragment_for(buffer
, 'expensive') { fragment_computed
= true }
582 assert
!fragment_computed
583 assert_equal
'generated till now -> fragment content', buffer
587 class FunctionalCachingController
< ActionController
::Base
591 def html_fragment_cached_with_partial
592 respond_to
do |format
|
597 def js_fragment_cached_with_partial
598 respond_to
do |format
|
603 def formatted_fragment_cached
604 respond_to
do |format
|
616 class FunctionalFragmentCachingTest
< ActionController
::TestCase
618 ActionController
::Base.perform_caching
= true
619 @store = ActiveSupport
::Cache::MemoryStore.new
620 ActionController
::Base.cache_store
= @store
621 @controller = FunctionalCachingController
.new
622 @request = ActionController
::TestRequest.new
623 @response = ActionController
::TestResponse.new
626 def test_fragment_caching
628 assert_response
:success
629 expected_body
= <<-CACHED
631 This bit's fragment cached
633 assert_equal expected_body
, @response.body
635 assert_equal
"This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached')
638 def test_fragment_caching_in_partials
639 get
:html_fragment_cached_with_partial
640 assert_response
:success
641 assert_match
/Fragment caching in a partial/, @response.body
642 assert_match
"Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial')
645 def test_render_inline_before_fragment_caching
646 get
:inline_fragment_cached
647 assert_response
:success
648 assert_match
/Some inline content/, @response.body
649 assert_match
/Some cached content/, @response.body
650 assert_match
"Some cached content", @store.read('views/test.host/functional_caching/inline_fragment_cached')
653 def test_fragment_caching_in_rjs_partials
654 xhr
:get, :js_fragment_cached_with_partial
655 assert_response
:success
656 assert_match
/Fragment caching in a partial/, @response.body
657 assert_match
"Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial')
660 def test_html_formatted_fragment_caching
661 get
:formatted_fragment_cached, :format => "html"
662 assert_response
:success
663 expected_body
= "<body>\n<p>ERB</p>\n</body>"
665 assert_equal expected_body
, @response.body
667 assert_equal
"<p>ERB</p>", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
670 def test_xml_formatted_fragment_caching
671 get
:formatted_fragment_cached, :format => "xml"
672 assert_response
:success
673 expected_body
= "<body>\n <p>Builder</p>\n</body>\n"
675 assert_equal expected_body
, @response.body
677 assert_equal
" <p>Builder</p>\n", @store.read('views/test.host/functional_caching/formatted_fragment_cached')
680 def test_js_formatted_fragment_caching
681 get
:formatted_fragment_cached, :format => "js"
682 assert_response
:success
683 expected_body
= %(title = "Hey";\n$("element_1").visualEffect("highlight");\n) +
684 %($("element_2").visualEffect("highlight");\nfooter = "Bye";)
685 assert_equal expected_body, @response.body
687 assert_equal ['$("element_1").visualEffect("highlight");', '$("element_2").visualEffect("highlight");'],
688 @store.read('views/test.host/functional_caching/formatted_fragment_cached')