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