motiro 0.6.8 → 0.6.9
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.
- data/AUTHORS +15 -0
- data/README +2 -2
- data/README.en +1 -2
- data/README.pt-br +1 -2
- data/app/controllers/account_controller.rb +1 -1
- data/app/controllers/application.rb +13 -12
- data/app/controllers/javascript_controller.rb +1 -1
- data/app/controllers/report_controller.rb +1 -1
- data/app/controllers/wiki_controller.rb +3 -5
- data/app/core/cache_reporter.rb +1 -1
- data/app/core/cache_reporter_fetcher.rb +1 -1
- data/app/core/chief_editor.rb +1 -1
- data/app/core/reporter.rb +1 -1
- data/app/core/reporter_driver.rb +1 -1
- data/app/core/reporter_fetcher.rb +1 -1
- data/app/core/settings.rb +1 -1
- data/app/core/version.rb +1 -1
- data/app/core/wiki_reporter.rb +1 -1
- data/app/helpers/application_helper.rb +5 -1
- data/app/helpers/default_page_provider.rb +6 -2
- data/app/helpers/report_helper.rb +14 -1
- data/app/models/change.rb +1 -1
- data/app/models/chunk.rb +1 -1
- data/app/models/feed_observer.rb +1 -1
- data/app/models/headline.rb +1 -1
- data/app/models/page.rb +38 -4
- data/app/models/revision.rb +1 -1
- data/app/models/user.rb +1 -1
- data/app/models/wiki_reference.rb +21 -0
- data/app/models/wiki_sweeper.rb +17 -2
- data/app/ports/chdir_runner.rb +1 -1
- data/app/ports/runner.rb +1 -1
- data/app/reporters/darcs_connection.rb +1 -1
- data/app/reporters/darcs_reporter.rb +1 -1
- data/app/reporters/darcs_temp_repo.rb +1 -1
- data/app/reporters/events_reporter.rb +1 -1
- data/app/reporters/features_reporter.rb +1 -1
- data/app/reporters/subversion_reporter.rb +1 -1
- data/app/reporters/svn_connection.rb +1 -1
- data/app/reporters/svn_settings.rb +1 -1
- data/app/views/report/list.rhtml +6 -7
- data/app/views/report/older.rhtml +1 -2
- data/app/views/report/rss.rxml +1 -1
- data/app/views/report/show.rhtml +2 -2
- data/app/views/wiki/_edit_event.rhtml +2 -0
- data/app/views/wiki/_edit_feature.rhtml +2 -0
- data/app/views/wiki/_properties_edit.rhtml +3 -5
- data/app/views/wiki/_properties_show.rhtml +4 -5
- data/app/views/wiki/_show_event.rhtml +3 -0
- data/app/views/wiki/_show_feature.rhtml +2 -0
- data/app/views/wiki/show.rhtml +1 -1
- data/bin/motiro +3 -3
- data/config/routes.rb +1 -1
- data/db/migrate/024_add_feature_status.rb +11 -0
- data/db/migrate/025_add_page_references.rb +12 -0
- data/db/migrate/026_convert_link_syntax.rb +12 -0
- data/db/migrate/027_register_page_references.rb +12 -0
- data/db/motirodb.sqlite.initial +0 -0
- data/db/schema_version +1 -1
- data/db/translation/pt-BR.rb +7 -1
- data/lib/array_extensions.rb +1 -1
- data/lib/diff_chunk_builder.rb +1 -1
- data/lib/differ.rb +1 -1
- data/lib/string_extensions.rb +13 -6
- data/lib/stub_hash.rb +1 -1
- data/lib/tasks/packaging.rake +10 -12
- data/lib/tasks/testing.rake +1 -1
- data/lib/tick_daemon.rb +1 -1
- data/lib/{wiki_url_generator.rb → wiki_link_handler.rb} +13 -3
- data/lib/wiki_renderer.rb +63 -34
- data/public/images/done.png +0 -0
- data/public/images/not-done.png +0 -0
- data/public/stylesheets/motiro.css +8 -0
- data/script/ticker +1 -1
- data/test/acceptance/account_test.rb +1 -1
- data/test/acceptance/darcs_test.rb +1 -1
- data/test/acceptance/events_test.rb +1 -1
- data/test/acceptance/main_page_test.rb +1 -1
- data/test/acceptance/subversion_test.rb +1 -1
- data/test/acceptance/ts_all_suites.rb +1 -1
- data/test/acceptance/wiki_test.rb +3 -3
- data/test/contract/darcs_test.rb +1 -1
- data/test/contract/remote_darcs_test.rb +1 -1
- data/test/contract/svn_test.rb +1 -1
- data/test/fixtures/pages.yml +20 -1
- data/test/fixtures/revisions.yml +40 -1
- data/test/fixtures/wiki_references.yml +5 -0
- data/test/functional/report_controller_test.rb +1 -1
- data/test/functional/report_features_test.rb +8 -1
- data/test/functional/report_subversion_test.rb +1 -1
- data/test/functional/root_controller_test.rb +1 -1
- data/test/functional/wiki_controller_test.rb +67 -2
- data/test/lib/acceptance_test_case.rb +1 -1
- data/test/lib/darcs_excerpts.rb +1 -1
- data/test/lib/darcs_repo.rb +1 -1
- data/test/lib/hash_extensions.rb +22 -0
- data/test/lib/live_mode_test.rb +1 -1
- data/test/lib/netutils.rb +1 -1
- data/test/lib/platform_thread.rb +1 -1
- data/test/lib/selenium_extensions.rb +1 -1
- data/test/lib/stubio.rb +1 -1
- data/test/lib/webserver.rb +1 -1
- data/test/meta/darcs_repo_test.rb +1 -1
- data/test/meta/local_svn_test.rb +1 -1
- data/test/meta/platform_thread_test.rb +1 -1
- data/test/meta/stubio_test.rb +1 -1
- data/test/stubs/{url_generator.rb → wiki_link_handler.rb} +8 -4
- data/test/test_helper.rb +3 -1
- data/test/unit/array_extensions_test.rb +1 -1
- data/test/unit/cache_reporter_fetcher_test.rb +1 -1
- data/test/unit/cache_reporter_test.rb +1 -1
- data/test/unit/change_test.rb +1 -1
- data/test/unit/chdir_runner_test.rb +1 -1
- data/test/unit/chief_editor_test.rb +1 -1
- data/test/unit/darcs_connection_test.rb +1 -1
- data/test/unit/darcs_reporter_test.rb +4 -4
- data/test/unit/darcs_temp_repo_test.rb +1 -1
- data/test/unit/default_page_provider_test.rb +23 -13
- data/test/unit/diff_chunk_builder_test.rb +1 -1
- data/test/unit/page_test.rb +67 -4
- data/test/unit/reporter_driver_test.rb +1 -1
- data/test/unit/reporter_test.rb +1 -1
- data/test/unit/revision_test.rb +1 -1
- data/test/unit/runner_test.rb +1 -1
- data/test/unit/string_extensions_test.rb +15 -3
- data/test/unit/svn_connection_test.rb +1 -1
- data/test/unit/svn_reporter_interaction_test.rb +1 -1
- data/test/unit/svn_reporter_test.rb +1 -1
- data/test/unit/svn_settings_test.rb +1 -1
- data/test/unit/user_test.rb +1 -1
- data/test/unit/{wiki_url_generator_test.rb → wiki_link_handler_test.rb} +3 -3
- data/test/unit/wiki_renderer_test.rb +75 -20
- data/test/unit/wiki_reporter_test.rb +1 -1
- data/vendor/mediacloth-trunk/MIT-LICENSE +20 -0
- data/vendor/mediacloth-trunk/README +32 -0
- data/vendor/mediacloth-trunk/Rakefile +33 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiast.rb +122 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikihtmlgenerator.rb +252 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikilexer.rb +821 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikilinkhandler.rb +68 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparams.rb +33 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparser.rb +1218 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparser.y +493 -0
- data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiwalker.rb +146 -0
- data/vendor/mediacloth-trunk/lib/mediacloth.rb +29 -0
- data/vendor/mediacloth-trunk/mediacloth.gemspec +24 -0
- data/vendor/mediacloth-trunk/mediacloth.kdevelop +117 -0
- data/vendor/mediacloth-trunk/setup.rb +1585 -0
- data/vendor/mediacloth-trunk/test/data/html1 +26 -0
- data/vendor/mediacloth-trunk/test/data/html10 +130 -0
- data/vendor/mediacloth-trunk/test/data/html11 +17 -0
- data/vendor/mediacloth-trunk/test/data/html12 +12 -0
- data/vendor/mediacloth-trunk/test/data/html13 +11 -0
- data/vendor/mediacloth-trunk/test/data/html2 +2 -0
- data/vendor/mediacloth-trunk/test/data/html3 +1 -0
- data/vendor/mediacloth-trunk/test/data/html4 +47 -0
- data/vendor/mediacloth-trunk/test/data/html5 +57 -0
- data/vendor/mediacloth-trunk/test/data/html6 +8 -0
- data/vendor/mediacloth-trunk/test/data/html7 +45 -0
- data/vendor/mediacloth-trunk/test/data/html8 +1 -0
- data/vendor/mediacloth-trunk/test/data/html9 +14 -0
- data/vendor/mediacloth-trunk/test/data/input1 +34 -0
- data/vendor/mediacloth-trunk/test/data/input10 +124 -0
- data/vendor/mediacloth-trunk/test/data/input11 +17 -0
- data/vendor/mediacloth-trunk/test/data/input12 +15 -0
- data/vendor/mediacloth-trunk/test/data/input13 +10 -0
- data/vendor/mediacloth-trunk/test/data/input2 +2 -0
- data/vendor/mediacloth-trunk/test/data/input3 +2 -0
- data/vendor/mediacloth-trunk/test/data/input4 +50 -0
- data/vendor/mediacloth-trunk/test/data/input5 +63 -0
- data/vendor/mediacloth-trunk/test/data/input6 +8 -0
- data/vendor/mediacloth-trunk/test/data/input7 +45 -0
- data/vendor/mediacloth-trunk/test/data/input8 +1 -0
- data/vendor/mediacloth-trunk/test/data/input9 +14 -0
- data/vendor/mediacloth-trunk/test/data/lex1 +26 -0
- data/vendor/mediacloth-trunk/test/data/lex10 +85 -0
- data/vendor/mediacloth-trunk/test/data/lex11 +17 -0
- data/vendor/mediacloth-trunk/test/data/lex12 +15 -0
- data/vendor/mediacloth-trunk/test/data/lex13 +3 -0
- data/vendor/mediacloth-trunk/test/data/lex2 +2 -0
- data/vendor/mediacloth-trunk/test/data/lex3 +1 -0
- data/vendor/mediacloth-trunk/test/data/lex4 +47 -0
- data/vendor/mediacloth-trunk/test/data/lex5 +57 -0
- data/vendor/mediacloth-trunk/test/data/lex6 +8 -0
- data/vendor/mediacloth-trunk/test/data/lex7 +45 -0
- data/vendor/mediacloth-trunk/test/data/lex8 +1 -0
- data/vendor/mediacloth-trunk/test/data/lex9 +14 -0
- data/vendor/mediacloth-trunk/test/data/result1 +48 -0
- data/vendor/mediacloth-trunk/test/dataproducers/html.rb +18 -0
- data/vendor/mediacloth-trunk/test/dataproducers/lex.rb +15 -0
- data/vendor/mediacloth-trunk/test/debugwalker.rb +68 -0
- data/vendor/mediacloth-trunk/test/htmlgenerator.rb +97 -0
- data/vendor/mediacloth-trunk/test/lexer.rb +542 -0
- data/vendor/mediacloth-trunk/test/linkhandler.rb +39 -0
- data/vendor/mediacloth-trunk/test/parser.rb +22 -0
- data/vendor/mediacloth-trunk/test/testhelper.rb +27 -0
- data/vendor/mediacloth.rb +3 -0
- data/vendor/motiro-installer.rb +1 -1
- data/vendor/plugins/cache_test-0.2/CHANGELOG +14 -0
- data/vendor/plugins/cache_test-0.2/MIT-LICENSE +20 -0
- data/vendor/plugins/cache_test-0.2/README +124 -0
- data/vendor/plugins/cache_test-0.2/init.rb +8 -0
- data/vendor/plugins/cache_test-0.2/lib/fragment_cache_test.rb +205 -0
- data/vendor/plugins/cache_test-0.2/lib/page_cache_test.rb +140 -0
- data/vendor/plugins/global_routing/init.rb +1 -1
- metadata +517 -455
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'mediacloth/mediawikilinkhandler'
|
|
2
|
+
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
require 'testhelper'
|
|
5
|
+
|
|
6
|
+
class LinkHandler_Test < Test::Unit::TestCase
|
|
7
|
+
|
|
8
|
+
def test_resolves_single_links
|
|
9
|
+
handler = create_handler
|
|
10
|
+
assert_equal '<a href="http://example.com/wiki/MyPage">this is my page</a>',
|
|
11
|
+
handler.link_for('MyPage', 'this is my page')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_forgets_previous_links
|
|
15
|
+
handler = create_handler
|
|
16
|
+
handler.link_for('MyPage', 'this is my page')
|
|
17
|
+
assert_equal '<a href="http://example.com/wiki/YourPage">this page is yours</a>',
|
|
18
|
+
handler.link_for('YourPage', 'this page is yours')
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_provides_suitable_elem_method_for_subclasses
|
|
22
|
+
handler = create_handler
|
|
23
|
+
def handler.link_for(page, text)
|
|
24
|
+
elem.span(:class => 'empty') {|x| x << text }
|
|
25
|
+
end
|
|
26
|
+
assert_equal '<span class="empty">Here is my page</span>',
|
|
27
|
+
handler.link_for('MyPage', 'Here is my page')
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def create_handler
|
|
33
|
+
handler = MediaWikiLinkHandler.new
|
|
34
|
+
def handler.url_for(page); "http://example.com/wiki/#{page}"; end
|
|
35
|
+
handler
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'mediacloth/mediawikilexer'
|
|
2
|
+
require 'mediacloth/mediawikiparser'
|
|
3
|
+
|
|
4
|
+
require 'test/unit'
|
|
5
|
+
require 'testhelper'
|
|
6
|
+
require 'debugwalker'
|
|
7
|
+
|
|
8
|
+
class Parser_Test < Test::Unit::TestCase
|
|
9
|
+
|
|
10
|
+
include TestHelper
|
|
11
|
+
|
|
12
|
+
def test_input
|
|
13
|
+
test_files("result") { |input,result|
|
|
14
|
+
parser = MediaWikiParser.new
|
|
15
|
+
parser.lexer = MediaWikiLexer.new
|
|
16
|
+
ast = parser.parse(input)
|
|
17
|
+
walker = DebugWalker.new
|
|
18
|
+
walker.parse(ast)
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
module TestHelper
|
|
2
|
+
|
|
3
|
+
#Helper method for file-based comparison tests.
|
|
4
|
+
#
|
|
5
|
+
#Looks in "data/" directory for files named "inputXXX",
|
|
6
|
+
#substitutes "input" with baseName and loads the contents
|
|
7
|
+
#of "inputXXX" file into the "input" variable and the
|
|
8
|
+
#contents of "baseNameXXX" into the "result" variable.
|
|
9
|
+
#
|
|
10
|
+
#Then it calls the block with input and result as parameters.
|
|
11
|
+
def test_files(baseName, &action)
|
|
12
|
+
Dir.glob(File.dirname(__FILE__) + "/data/input*").each do |filename|
|
|
13
|
+
resultname = filename.gsub(/input(.*)/, "#{baseName}\\1")
|
|
14
|
+
#exclude backup files
|
|
15
|
+
if not resultname.include?("~")
|
|
16
|
+
input_file = File.new(filename, "r")
|
|
17
|
+
input = input_file.read
|
|
18
|
+
if File.exists?(resultname)
|
|
19
|
+
result_file = File.new(resultname, "r")
|
|
20
|
+
result = result_file.read
|
|
21
|
+
|
|
22
|
+
yield(input, result, resultname)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
data/vendor/motiro-installer.rb
CHANGED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
*0.2* (October 17th, 2006)
|
|
2
|
+
|
|
3
|
+
* overrides default page caching method to record page cached and
|
|
4
|
+
expired and use that information instead of going to the filesystem
|
|
5
|
+
to see if cached file exists or not.
|
|
6
|
+
|
|
7
|
+
* add unit testing
|
|
8
|
+
|
|
9
|
+
* add method for action and fragment caching
|
|
10
|
+
|
|
11
|
+
*0.1* (October 5th, 2006)
|
|
12
|
+
|
|
13
|
+
* first plugin release
|
|
14
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2006 Damien Merenne
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
= Cache Test Plugin
|
|
2
|
+
|
|
3
|
+
This plugin adds assertions in test cases to check the caching
|
|
4
|
+
logic of your application.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
== 1. Installation
|
|
8
|
+
|
|
9
|
+
Unpack into the vendor/plugin and that should be it.
|
|
10
|
+
|
|
11
|
+
== 2. Usage
|
|
12
|
+
|
|
13
|
+
=== Testing page caching
|
|
14
|
+
|
|
15
|
+
First create an integration test. Then, to test caching of the
|
|
16
|
+
"/pages/about" and "/pages/contact" pages, add a method like this:
|
|
17
|
+
|
|
18
|
+
def test_caching
|
|
19
|
+
assert_cache_pages("/pages/about", "/pages/contact")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
The assert_cache_pages method will
|
|
23
|
+
|
|
24
|
+
- first make sure that the urls are not cached,
|
|
25
|
+
- execute a get on each request,
|
|
26
|
+
- assert that the corresponding cache files have been created.
|
|
27
|
+
|
|
28
|
+
You can also give a block to the assert_cache_pages method. Instead
|
|
29
|
+
of executing a get on each url, it will yield the urls. For example:
|
|
30
|
+
|
|
31
|
+
def test_caching
|
|
32
|
+
assert_cache_pages("/pages/about", "/pages/contact") do |url_about, url_contact|
|
|
33
|
+
post url_about
|
|
34
|
+
post url_contact
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
=== Testing expiration of pages
|
|
39
|
+
|
|
40
|
+
You will also certainly want (and that's really the most interesting
|
|
41
|
+
part) to check if your cached pages expires when the user is doing
|
|
42
|
+
some action. For that, here is the assert_expire method:
|
|
43
|
+
|
|
44
|
+
def test_expiring
|
|
45
|
+
assert_expire_pages("/news/list", "/news/show/1") do |*urls|
|
|
46
|
+
post "/news/delete/1"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
Here the assert_expire_pages method will
|
|
51
|
+
|
|
52
|
+
- check that the urls are cached,
|
|
53
|
+
- execute the post request,
|
|
54
|
+
- and assert that the urls are no more cached.
|
|
55
|
+
|
|
56
|
+
This is great for testing your cache sweepers logic.
|
|
57
|
+
|
|
58
|
+
=== Testing action caching
|
|
59
|
+
|
|
60
|
+
To test caching of the "bar" action of the foo "controller"
|
|
61
|
+
in an integration test, do
|
|
62
|
+
|
|
63
|
+
assert_cache_actions(:controller => "foo", :action => "bar") do
|
|
64
|
+
get "/foo/bar"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
The assert_cache_actions method will
|
|
68
|
+
- first make sure that the actions are not cached,
|
|
69
|
+
- yield the given block
|
|
70
|
+
- assert that the corresponding action fragment have been stored.
|
|
71
|
+
|
|
72
|
+
=== Testing expiration of actions
|
|
73
|
+
|
|
74
|
+
To check that some actions are expired, use the assert_expire_actions method:
|
|
75
|
+
|
|
76
|
+
assert_expire_actions(:controller => "foo", :action => "bar") do |*urls|
|
|
77
|
+
post "/foo/expire_cache"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
Here the assert_expire_actions method will
|
|
81
|
+
|
|
82
|
+
- check that the actions fragments are cached,
|
|
83
|
+
- execute the post request,
|
|
84
|
+
- and assert that the fragments are no more cached.
|
|
85
|
+
|
|
86
|
+
In functional test, there can be only one controller, so you are
|
|
87
|
+
not required to give the :controller option and if they are no
|
|
88
|
+
parameters to the action, you can simply call
|
|
89
|
+
|
|
90
|
+
assert_cache_actions(:foo, :bar) do
|
|
91
|
+
get :bar
|
|
92
|
+
get :foo
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
== Testing fragments caching
|
|
96
|
+
|
|
97
|
+
To check that your fragments are cached when doing some action,
|
|
98
|
+
do
|
|
99
|
+
|
|
100
|
+
assert_cache_fragments(:controller => "foo", :action => "bar", :action_suffix => "baz") do
|
|
101
|
+
get "/foo/bar"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
== Testing expiration of fragments
|
|
105
|
+
|
|
106
|
+
To check that your fragments are expired when doing some action,
|
|
107
|
+
do
|
|
108
|
+
|
|
109
|
+
assert_expire_fragments(:controller => "foo", :action => "bar", :action_suffix => "baz") do
|
|
110
|
+
get "/foo/expire"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
In functional test, your not required to give the :controller option.
|
|
114
|
+
|
|
115
|
+
== 3. License
|
|
116
|
+
|
|
117
|
+
This plugin is licensed under the MIT license. Complete license text
|
|
118
|
+
is included in the MIT-LICENSE[link:files/MIT-LICENSE.html] file.
|
|
119
|
+
|
|
120
|
+
== 4. Author
|
|
121
|
+
|
|
122
|
+
This plugin was created by Damien Merenne <dam@cosinux.org> and is
|
|
123
|
+
located at http://blog.cosinux.org/pages/page-cache-test.
|
|
124
|
+
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
module Cosinux
|
|
2
|
+
module FragmentCacheTest #:nodoc:
|
|
3
|
+
class NoRequestInBlockError < StandardError #:nodoc:
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
class NoControllerDefinedError < StandardError #:nodoc:
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
# This fragment store remembers the fragments that have been
|
|
10
|
+
# cached or deleted so that we can use it to check if
|
|
11
|
+
# caching or expiring of fragment was done or not.
|
|
12
|
+
class TestStore < ActionController::Caching::Fragments::MemoryStore #:nodoc:
|
|
13
|
+
attr_reader :written, :deleted, :deleted_matchers
|
|
14
|
+
|
|
15
|
+
def initialize
|
|
16
|
+
super
|
|
17
|
+
@written = []
|
|
18
|
+
@deleted = []
|
|
19
|
+
@deleted_matchers = []
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def reset
|
|
23
|
+
@data.clear
|
|
24
|
+
@written.clear
|
|
25
|
+
@deleted.clear
|
|
26
|
+
@deleted_matchers.clear
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def write(name, value, options = nil)
|
|
30
|
+
@written.push(name)
|
|
31
|
+
super
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def delete(name, options = nil)
|
|
35
|
+
@deleted.push(name)
|
|
36
|
+
super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def delete_matched(matcher, options = nil)
|
|
40
|
+
@deleted_matchers.push(matcher)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def written?(name)
|
|
44
|
+
@written.include?(name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def deleted?(name)
|
|
48
|
+
@deleted.include?(name) || @deleted_matchers.detect { |matcher| name =~ matcher }
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.configure #:nodoc:
|
|
53
|
+
ActionController::Base.perform_caching = true
|
|
54
|
+
ActionController::Base.fragment_cache_store = TestStore.new
|
|
55
|
+
|
|
56
|
+
Test::Unit::TestCase.class_eval do
|
|
57
|
+
include Assertions
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# This module define method to validate the fragment and action caching logic of
|
|
62
|
+
# your application in both integration and functional tests.
|
|
63
|
+
#
|
|
64
|
+
# == Testing action caching
|
|
65
|
+
#
|
|
66
|
+
# To test caching of the "bar" action of the foo "controller"
|
|
67
|
+
# in an integration test, do
|
|
68
|
+
#
|
|
69
|
+
# assert_cache_actions(:controller => "foo", :action => "bar") do
|
|
70
|
+
# get "/foo/bar"
|
|
71
|
+
# end
|
|
72
|
+
#
|
|
73
|
+
# The assert_cache_actions method will
|
|
74
|
+
# - first make sure that the actions are not cached,
|
|
75
|
+
# - yield the given block
|
|
76
|
+
# - assert that the corresponding action fragment have been stored.
|
|
77
|
+
#
|
|
78
|
+
# == Testing expiring of actions
|
|
79
|
+
#
|
|
80
|
+
# To check that some actions are expired, use the assert_expire_actions method:
|
|
81
|
+
#
|
|
82
|
+
# assert_expire_actions(:controller => "foo", :action => "bar") do |*urls|
|
|
83
|
+
# post "/foo/expire_cache"
|
|
84
|
+
# end
|
|
85
|
+
#
|
|
86
|
+
# Here the assert_expire_actions method will
|
|
87
|
+
#
|
|
88
|
+
# - check that the actions fragments are cached,
|
|
89
|
+
# - execute the post request,
|
|
90
|
+
# - and assert that the fragments are no more cached.
|
|
91
|
+
#
|
|
92
|
+
# In functional test, there can be only one controller, so you are
|
|
93
|
+
# not required to give the :controller option and if they are no
|
|
94
|
+
# parameters to the action, you can simply call
|
|
95
|
+
#
|
|
96
|
+
# assert_cache_actions(:foo, :bar) do
|
|
97
|
+
# get :bar
|
|
98
|
+
# get :foo
|
|
99
|
+
# end
|
|
100
|
+
#
|
|
101
|
+
# == Testing fragments caching
|
|
102
|
+
#
|
|
103
|
+
# To check that your fragments are cached when doing some action,
|
|
104
|
+
# do
|
|
105
|
+
#
|
|
106
|
+
# assert_cache_fragments(:controller => "foo", :action => "bar", :action_suffix => "baz") do
|
|
107
|
+
# get "/foo/bar"
|
|
108
|
+
# end
|
|
109
|
+
#
|
|
110
|
+
# == Testing expiration of fragments
|
|
111
|
+
#
|
|
112
|
+
# To check that your fragments are expired when doing some action,
|
|
113
|
+
# do
|
|
114
|
+
#
|
|
115
|
+
# assert_expire_fragments(:controller => "foo", :action => "bar", :action_suffix => "baz") do
|
|
116
|
+
# get "/foo/expire"
|
|
117
|
+
# end
|
|
118
|
+
#
|
|
119
|
+
# In functional test, your not required to give the :controller option.
|
|
120
|
+
module Assertions
|
|
121
|
+
# asserts that the list of given fragment name are being cached
|
|
122
|
+
def assert_cache_fragments(*names)
|
|
123
|
+
# in integration test, we need the know the controller
|
|
124
|
+
check_options_has_controller(names) if self.is_a?(ActionController::IntegrationTest)
|
|
125
|
+
|
|
126
|
+
fragment_cache_store.reset
|
|
127
|
+
|
|
128
|
+
yield *names
|
|
129
|
+
|
|
130
|
+
# if there is no variable @controller, then we haven't done any request
|
|
131
|
+
raise NoRequestInBlockError.new("no request was send while executing block.") if @controller.nil?
|
|
132
|
+
|
|
133
|
+
names.each do |name|
|
|
134
|
+
assert_block("#{name.inspect} is not cached after executing block") do
|
|
135
|
+
fragment_cache_store.written?(@controller.fragment_cache_key(name))
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# assert that the list of given fragment are being expired
|
|
141
|
+
def assert_expire_fragments(*names)
|
|
142
|
+
check_options_has_controller(names) if self.is_a?(ActionController::IntegrationTest)
|
|
143
|
+
|
|
144
|
+
fragment_cache_store.reset
|
|
145
|
+
|
|
146
|
+
yield *names
|
|
147
|
+
|
|
148
|
+
raise NoRequestInBlockError.new("no request was send while executing block.") if @controller.nil?
|
|
149
|
+
|
|
150
|
+
names.each do |name|
|
|
151
|
+
assert_block("#{name.inspect} is cached after executing block") do
|
|
152
|
+
fragment_cache_store.deleted?(@controller.fragment_cache_key(name))
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
# assert that the given actions are being cached
|
|
158
|
+
def assert_cache_actions(*actions)
|
|
159
|
+
check_options_has_controller(actions) if self.is_a?(ActionController::IntegrationTest)
|
|
160
|
+
|
|
161
|
+
fragment_cache_store.reset
|
|
162
|
+
|
|
163
|
+
yield *actions
|
|
164
|
+
|
|
165
|
+
raise NoRequestInBlockError.new("no request was send while executing block.") if @controller.nil?
|
|
166
|
+
|
|
167
|
+
actions.each do |action|
|
|
168
|
+
action = { :action => action } unless action.is_a?(Hash)
|
|
169
|
+
assert_block("#{action.inspect} is not cached after executing block") do
|
|
170
|
+
fragment_cache_store.written?(@controller.fragment_cache_key(action))
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# assert that the given actions are being expired
|
|
176
|
+
def assert_expire_actions(*actions)
|
|
177
|
+
check_options_has_controller(actions) if self.is_a?(ActionController::IntegrationTest)
|
|
178
|
+
|
|
179
|
+
fragment_cache_store.reset
|
|
180
|
+
|
|
181
|
+
yield *actions
|
|
182
|
+
|
|
183
|
+
raise NoRequestInBlockError.new("no request was send while executing block.") if @controller.nil?
|
|
184
|
+
|
|
185
|
+
actions.each do |action|
|
|
186
|
+
action = { :action => action } unless action.is_a?(Hash)
|
|
187
|
+
assert_block("#{action.inspect} is cached after executing block") do
|
|
188
|
+
fragment_cache_store.deleted?(@controller.fragment_cache_key(action))
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
private
|
|
194
|
+
def fragment_cache_store
|
|
195
|
+
ActionController::Base.fragment_cache_store
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def check_options_has_controller(options)
|
|
199
|
+
if option = options.detect { |option| option[:controller].nil? }
|
|
200
|
+
raise NoControllerDefinedError.new("no controller given in option #{option.inspect} in integration test")
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module Cosinux #:nodoc:
|
|
2
|
+
module PageCacheTest #:nodoc:
|
|
3
|
+
|
|
4
|
+
def self.configure #:nodoc:
|
|
5
|
+
ActionController::Base.perform_caching = true
|
|
6
|
+
|
|
7
|
+
# overwrite class caching methods
|
|
8
|
+
ActionController::Base.class_eval do
|
|
9
|
+
include ClassCachingMethods
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# include integration test methods
|
|
13
|
+
Test::Unit::TestCase.class_eval do
|
|
14
|
+
include IntegrationTestMethods
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
module ClassCachingMethods #:nodoc:
|
|
19
|
+
def self.included(base)
|
|
20
|
+
base.extend(ClassMethods)
|
|
21
|
+
base.class_eval do
|
|
22
|
+
@@test_page_cached = []
|
|
23
|
+
cattr_accessor :test_page_cached
|
|
24
|
+
@@test_page_expired = []
|
|
25
|
+
cattr_accessor :test_page_expired
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
module ClassMethods #:nodoc:
|
|
30
|
+
def cache_page(content, path)
|
|
31
|
+
logger.info "Cached page: #{page_cache_file(path)}"
|
|
32
|
+
test_page_cached.push(path)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def expire_page(path)
|
|
36
|
+
logger.info "Expired page: #{page_cache_file(path)}"
|
|
37
|
+
test_page_expired.push(path)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def cached?(path)
|
|
41
|
+
test_page_cached.include?(path)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def expired?(path)
|
|
45
|
+
test_page_expired.include?(path)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def reset_cache
|
|
49
|
+
test_page_cached.clear
|
|
50
|
+
test_page_expired.clear
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def cached?(options = {})
|
|
55
|
+
self.class.cached?(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true })))
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def expired?(options = {})
|
|
59
|
+
self.class.expired?(url_for(options.merge({ :only_path => true, :skip_relative_url_root => true })))
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# This module define method to validate the page caching logic of
|
|
64
|
+
# your application in integration tests.
|
|
65
|
+
#
|
|
66
|
+
# == Testing page caching
|
|
67
|
+
#
|
|
68
|
+
# To test caching of the "/pages/about" and "/pages/contact"
|
|
69
|
+
# pages, add a method like this:
|
|
70
|
+
#
|
|
71
|
+
# def test_caching
|
|
72
|
+
# assert_cache_pages("/pages/about", "/pages/contact")
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# The assert_cache method will
|
|
76
|
+
# - first make sure that the urls are not cached,
|
|
77
|
+
# - execute a get on each request,
|
|
78
|
+
# - assert that the corresponding cache files have been created.
|
|
79
|
+
#
|
|
80
|
+
# You can also give a block to the assert_cache method. Instead
|
|
81
|
+
# of executing a get on each url, it will yield the urls. For example:
|
|
82
|
+
#
|
|
83
|
+
# def test_caching
|
|
84
|
+
# assert_cache_pages("/pages/about", "/pages/contact") do |url_about, url_contact|
|
|
85
|
+
# post url_about
|
|
86
|
+
# post url_contact
|
|
87
|
+
# end
|
|
88
|
+
# end
|
|
89
|
+
#
|
|
90
|
+
# == Testing expiring of pages
|
|
91
|
+
#
|
|
92
|
+
# You will also certainly want to check if your cached pages
|
|
93
|
+
# expires when the user is doing some action. For that, here is
|
|
94
|
+
# the assert_expire method:
|
|
95
|
+
#
|
|
96
|
+
# def test_expiring
|
|
97
|
+
# assert_expire_pages("/news/list", "/news/show/1") do |*urls|
|
|
98
|
+
# post "/news/delete/1"
|
|
99
|
+
# end
|
|
100
|
+
# end
|
|
101
|
+
#
|
|
102
|
+
# Here the assert_expire_pages method will
|
|
103
|
+
#
|
|
104
|
+
# - check that the urls are cached,
|
|
105
|
+
# - execute the post request,
|
|
106
|
+
# - and assert that the urls are no more cached.
|
|
107
|
+
#
|
|
108
|
+
module IntegrationTestMethods
|
|
109
|
+
# asserts that the list of given url are being cached
|
|
110
|
+
def assert_cache_pages(*urls)
|
|
111
|
+
ActionController::Base.reset_cache
|
|
112
|
+
|
|
113
|
+
if block_given?
|
|
114
|
+
yield *urls
|
|
115
|
+
else
|
|
116
|
+
urls.each { |url| get url }
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
urls.each do |url|
|
|
120
|
+
assert_block("#{url.inspect} is not cached after executing block") do
|
|
121
|
+
ActionController::Base.cached?(url)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# asserts that the list of given url are being expired
|
|
127
|
+
def assert_expire_pages(*urls)
|
|
128
|
+
ActionController::Base.reset_cache
|
|
129
|
+
|
|
130
|
+
yield *urls
|
|
131
|
+
|
|
132
|
+
urls.each do |url|
|
|
133
|
+
assert_block("#{url.inspect} is cached after executing block") do
|
|
134
|
+
ActionController::Base.expired?(url)
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|