motiro 0.6.8 → 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. data/AUTHORS +15 -0
  2. data/README +2 -2
  3. data/README.en +1 -2
  4. data/README.pt-br +1 -2
  5. data/app/controllers/account_controller.rb +1 -1
  6. data/app/controllers/application.rb +13 -12
  7. data/app/controllers/javascript_controller.rb +1 -1
  8. data/app/controllers/report_controller.rb +1 -1
  9. data/app/controllers/wiki_controller.rb +3 -5
  10. data/app/core/cache_reporter.rb +1 -1
  11. data/app/core/cache_reporter_fetcher.rb +1 -1
  12. data/app/core/chief_editor.rb +1 -1
  13. data/app/core/reporter.rb +1 -1
  14. data/app/core/reporter_driver.rb +1 -1
  15. data/app/core/reporter_fetcher.rb +1 -1
  16. data/app/core/settings.rb +1 -1
  17. data/app/core/version.rb +1 -1
  18. data/app/core/wiki_reporter.rb +1 -1
  19. data/app/helpers/application_helper.rb +5 -1
  20. data/app/helpers/default_page_provider.rb +6 -2
  21. data/app/helpers/report_helper.rb +14 -1
  22. data/app/models/change.rb +1 -1
  23. data/app/models/chunk.rb +1 -1
  24. data/app/models/feed_observer.rb +1 -1
  25. data/app/models/headline.rb +1 -1
  26. data/app/models/page.rb +38 -4
  27. data/app/models/revision.rb +1 -1
  28. data/app/models/user.rb +1 -1
  29. data/app/models/wiki_reference.rb +21 -0
  30. data/app/models/wiki_sweeper.rb +17 -2
  31. data/app/ports/chdir_runner.rb +1 -1
  32. data/app/ports/runner.rb +1 -1
  33. data/app/reporters/darcs_connection.rb +1 -1
  34. data/app/reporters/darcs_reporter.rb +1 -1
  35. data/app/reporters/darcs_temp_repo.rb +1 -1
  36. data/app/reporters/events_reporter.rb +1 -1
  37. data/app/reporters/features_reporter.rb +1 -1
  38. data/app/reporters/subversion_reporter.rb +1 -1
  39. data/app/reporters/svn_connection.rb +1 -1
  40. data/app/reporters/svn_settings.rb +1 -1
  41. data/app/views/report/list.rhtml +6 -7
  42. data/app/views/report/older.rhtml +1 -2
  43. data/app/views/report/rss.rxml +1 -1
  44. data/app/views/report/show.rhtml +2 -2
  45. data/app/views/wiki/_edit_event.rhtml +2 -0
  46. data/app/views/wiki/_edit_feature.rhtml +2 -0
  47. data/app/views/wiki/_properties_edit.rhtml +3 -5
  48. data/app/views/wiki/_properties_show.rhtml +4 -5
  49. data/app/views/wiki/_show_event.rhtml +3 -0
  50. data/app/views/wiki/_show_feature.rhtml +2 -0
  51. data/app/views/wiki/show.rhtml +1 -1
  52. data/bin/motiro +3 -3
  53. data/config/routes.rb +1 -1
  54. data/db/migrate/024_add_feature_status.rb +11 -0
  55. data/db/migrate/025_add_page_references.rb +12 -0
  56. data/db/migrate/026_convert_link_syntax.rb +12 -0
  57. data/db/migrate/027_register_page_references.rb +12 -0
  58. data/db/motirodb.sqlite.initial +0 -0
  59. data/db/schema_version +1 -1
  60. data/db/translation/pt-BR.rb +7 -1
  61. data/lib/array_extensions.rb +1 -1
  62. data/lib/diff_chunk_builder.rb +1 -1
  63. data/lib/differ.rb +1 -1
  64. data/lib/string_extensions.rb +13 -6
  65. data/lib/stub_hash.rb +1 -1
  66. data/lib/tasks/packaging.rake +10 -12
  67. data/lib/tasks/testing.rake +1 -1
  68. data/lib/tick_daemon.rb +1 -1
  69. data/lib/{wiki_url_generator.rb → wiki_link_handler.rb} +13 -3
  70. data/lib/wiki_renderer.rb +63 -34
  71. data/public/images/done.png +0 -0
  72. data/public/images/not-done.png +0 -0
  73. data/public/stylesheets/motiro.css +8 -0
  74. data/script/ticker +1 -1
  75. data/test/acceptance/account_test.rb +1 -1
  76. data/test/acceptance/darcs_test.rb +1 -1
  77. data/test/acceptance/events_test.rb +1 -1
  78. data/test/acceptance/main_page_test.rb +1 -1
  79. data/test/acceptance/subversion_test.rb +1 -1
  80. data/test/acceptance/ts_all_suites.rb +1 -1
  81. data/test/acceptance/wiki_test.rb +3 -3
  82. data/test/contract/darcs_test.rb +1 -1
  83. data/test/contract/remote_darcs_test.rb +1 -1
  84. data/test/contract/svn_test.rb +1 -1
  85. data/test/fixtures/pages.yml +20 -1
  86. data/test/fixtures/revisions.yml +40 -1
  87. data/test/fixtures/wiki_references.yml +5 -0
  88. data/test/functional/report_controller_test.rb +1 -1
  89. data/test/functional/report_features_test.rb +8 -1
  90. data/test/functional/report_subversion_test.rb +1 -1
  91. data/test/functional/root_controller_test.rb +1 -1
  92. data/test/functional/wiki_controller_test.rb +67 -2
  93. data/test/lib/acceptance_test_case.rb +1 -1
  94. data/test/lib/darcs_excerpts.rb +1 -1
  95. data/test/lib/darcs_repo.rb +1 -1
  96. data/test/lib/hash_extensions.rb +22 -0
  97. data/test/lib/live_mode_test.rb +1 -1
  98. data/test/lib/netutils.rb +1 -1
  99. data/test/lib/platform_thread.rb +1 -1
  100. data/test/lib/selenium_extensions.rb +1 -1
  101. data/test/lib/stubio.rb +1 -1
  102. data/test/lib/webserver.rb +1 -1
  103. data/test/meta/darcs_repo_test.rb +1 -1
  104. data/test/meta/local_svn_test.rb +1 -1
  105. data/test/meta/platform_thread_test.rb +1 -1
  106. data/test/meta/stubio_test.rb +1 -1
  107. data/test/stubs/{url_generator.rb → wiki_link_handler.rb} +8 -4
  108. data/test/test_helper.rb +3 -1
  109. data/test/unit/array_extensions_test.rb +1 -1
  110. data/test/unit/cache_reporter_fetcher_test.rb +1 -1
  111. data/test/unit/cache_reporter_test.rb +1 -1
  112. data/test/unit/change_test.rb +1 -1
  113. data/test/unit/chdir_runner_test.rb +1 -1
  114. data/test/unit/chief_editor_test.rb +1 -1
  115. data/test/unit/darcs_connection_test.rb +1 -1
  116. data/test/unit/darcs_reporter_test.rb +4 -4
  117. data/test/unit/darcs_temp_repo_test.rb +1 -1
  118. data/test/unit/default_page_provider_test.rb +23 -13
  119. data/test/unit/diff_chunk_builder_test.rb +1 -1
  120. data/test/unit/page_test.rb +67 -4
  121. data/test/unit/reporter_driver_test.rb +1 -1
  122. data/test/unit/reporter_test.rb +1 -1
  123. data/test/unit/revision_test.rb +1 -1
  124. data/test/unit/runner_test.rb +1 -1
  125. data/test/unit/string_extensions_test.rb +15 -3
  126. data/test/unit/svn_connection_test.rb +1 -1
  127. data/test/unit/svn_reporter_interaction_test.rb +1 -1
  128. data/test/unit/svn_reporter_test.rb +1 -1
  129. data/test/unit/svn_settings_test.rb +1 -1
  130. data/test/unit/user_test.rb +1 -1
  131. data/test/unit/{wiki_url_generator_test.rb → wiki_link_handler_test.rb} +3 -3
  132. data/test/unit/wiki_renderer_test.rb +75 -20
  133. data/test/unit/wiki_reporter_test.rb +1 -1
  134. data/vendor/mediacloth-trunk/MIT-LICENSE +20 -0
  135. data/vendor/mediacloth-trunk/README +32 -0
  136. data/vendor/mediacloth-trunk/Rakefile +33 -0
  137. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiast.rb +122 -0
  138. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikihtmlgenerator.rb +252 -0
  139. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikilexer.rb +821 -0
  140. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikilinkhandler.rb +68 -0
  141. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparams.rb +33 -0
  142. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparser.rb +1218 -0
  143. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiparser.y +493 -0
  144. data/vendor/mediacloth-trunk/lib/mediacloth/mediawikiwalker.rb +146 -0
  145. data/vendor/mediacloth-trunk/lib/mediacloth.rb +29 -0
  146. data/vendor/mediacloth-trunk/mediacloth.gemspec +24 -0
  147. data/vendor/mediacloth-trunk/mediacloth.kdevelop +117 -0
  148. data/vendor/mediacloth-trunk/setup.rb +1585 -0
  149. data/vendor/mediacloth-trunk/test/data/html1 +26 -0
  150. data/vendor/mediacloth-trunk/test/data/html10 +130 -0
  151. data/vendor/mediacloth-trunk/test/data/html11 +17 -0
  152. data/vendor/mediacloth-trunk/test/data/html12 +12 -0
  153. data/vendor/mediacloth-trunk/test/data/html13 +11 -0
  154. data/vendor/mediacloth-trunk/test/data/html2 +2 -0
  155. data/vendor/mediacloth-trunk/test/data/html3 +1 -0
  156. data/vendor/mediacloth-trunk/test/data/html4 +47 -0
  157. data/vendor/mediacloth-trunk/test/data/html5 +57 -0
  158. data/vendor/mediacloth-trunk/test/data/html6 +8 -0
  159. data/vendor/mediacloth-trunk/test/data/html7 +45 -0
  160. data/vendor/mediacloth-trunk/test/data/html8 +1 -0
  161. data/vendor/mediacloth-trunk/test/data/html9 +14 -0
  162. data/vendor/mediacloth-trunk/test/data/input1 +34 -0
  163. data/vendor/mediacloth-trunk/test/data/input10 +124 -0
  164. data/vendor/mediacloth-trunk/test/data/input11 +17 -0
  165. data/vendor/mediacloth-trunk/test/data/input12 +15 -0
  166. data/vendor/mediacloth-trunk/test/data/input13 +10 -0
  167. data/vendor/mediacloth-trunk/test/data/input2 +2 -0
  168. data/vendor/mediacloth-trunk/test/data/input3 +2 -0
  169. data/vendor/mediacloth-trunk/test/data/input4 +50 -0
  170. data/vendor/mediacloth-trunk/test/data/input5 +63 -0
  171. data/vendor/mediacloth-trunk/test/data/input6 +8 -0
  172. data/vendor/mediacloth-trunk/test/data/input7 +45 -0
  173. data/vendor/mediacloth-trunk/test/data/input8 +1 -0
  174. data/vendor/mediacloth-trunk/test/data/input9 +14 -0
  175. data/vendor/mediacloth-trunk/test/data/lex1 +26 -0
  176. data/vendor/mediacloth-trunk/test/data/lex10 +85 -0
  177. data/vendor/mediacloth-trunk/test/data/lex11 +17 -0
  178. data/vendor/mediacloth-trunk/test/data/lex12 +15 -0
  179. data/vendor/mediacloth-trunk/test/data/lex13 +3 -0
  180. data/vendor/mediacloth-trunk/test/data/lex2 +2 -0
  181. data/vendor/mediacloth-trunk/test/data/lex3 +1 -0
  182. data/vendor/mediacloth-trunk/test/data/lex4 +47 -0
  183. data/vendor/mediacloth-trunk/test/data/lex5 +57 -0
  184. data/vendor/mediacloth-trunk/test/data/lex6 +8 -0
  185. data/vendor/mediacloth-trunk/test/data/lex7 +45 -0
  186. data/vendor/mediacloth-trunk/test/data/lex8 +1 -0
  187. data/vendor/mediacloth-trunk/test/data/lex9 +14 -0
  188. data/vendor/mediacloth-trunk/test/data/result1 +48 -0
  189. data/vendor/mediacloth-trunk/test/dataproducers/html.rb +18 -0
  190. data/vendor/mediacloth-trunk/test/dataproducers/lex.rb +15 -0
  191. data/vendor/mediacloth-trunk/test/debugwalker.rb +68 -0
  192. data/vendor/mediacloth-trunk/test/htmlgenerator.rb +97 -0
  193. data/vendor/mediacloth-trunk/test/lexer.rb +542 -0
  194. data/vendor/mediacloth-trunk/test/linkhandler.rb +39 -0
  195. data/vendor/mediacloth-trunk/test/parser.rb +22 -0
  196. data/vendor/mediacloth-trunk/test/testhelper.rb +27 -0
  197. data/vendor/mediacloth.rb +3 -0
  198. data/vendor/motiro-installer.rb +1 -1
  199. data/vendor/plugins/cache_test-0.2/CHANGELOG +14 -0
  200. data/vendor/plugins/cache_test-0.2/MIT-LICENSE +20 -0
  201. data/vendor/plugins/cache_test-0.2/README +124 -0
  202. data/vendor/plugins/cache_test-0.2/init.rb +8 -0
  203. data/vendor/plugins/cache_test-0.2/lib/fragment_cache_test.rb +205 -0
  204. data/vendor/plugins/cache_test-0.2/lib/page_cache_test.rb +140 -0
  205. data/vendor/plugins/global_routing/init.rb +1 -1
  206. 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
@@ -0,0 +1,3 @@
1
+ $:.push File.expand_path(File.dirname(__FILE__) + '/mediacloth-trunk/lib/')
2
+
3
+ require 'mediacloth-trunk/lib/mediacloth'
@@ -1,5 +1,5 @@
1
1
  # Motiro - A project tracking tool
2
- # Copyright (C) 2006-2007 Thiago Arrais
2
+ # Copyright (C) 2006-2008 Thiago Arrais
3
3
  #
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by
@@ -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,8 @@
1
+ if RAILS_ENV == "test"
2
+ require 'page_cache_test'
3
+ require 'fragment_cache_test'
4
+
5
+ Cosinux::PageCacheTest.configure
6
+ Cosinux::FragmentCacheTest.configure
7
+ end
8
+
@@ -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
@@ -1,5 +1,5 @@
1
1
  # Motiro - A project tracking tool
2
- # Copyright (C) 2006-2007 Thiago Arrais
2
+ # Copyright (C) 2006-2008 Thiago Arrais
3
3
  #
4
4
  # This program is free software; you can redistribute it and/or modify
5
5
  # it under the terms of the GNU General Public License as published by