comparison test/unit/helpers/application_helper_test.rb @ 524:1248a47e81b3 feature_36

Merge from branch "luisf"
author luisf <luis.figueira@eecs.qmul.ac.uk>
date Mon, 25 Jul 2011 14:39:38 +0100
parents 753f1380d6bc
children 5e80956cc792
comparison
equal deleted inserted replaced
519:3be6bc3c2a17 524:1248a47e81b3
1 # Redmine - project management software 1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang 2 # Copyright (C) 2006-2011 Jean-Philippe Lang
3 # 3 #
4 # This program is free software; you can redistribute it and/or 4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License 5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2 6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version. 7 # of the License, or (at your option) any later version.
8 # 8 #
9 # This program is distributed in the hope that it will be useful, 9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details. 12 # GNU General Public License for more details.
13 # 13 #
14 # You should have received a copy of the GNU General Public License 14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software 15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 17
18 require File.dirname(__FILE__) + '/../../test_helper' 18 require File.expand_path('../../../test_helper', __FILE__)
19 19
20 class ApplicationHelperTest < ActionView::TestCase 20 class ApplicationHelperTest < ActionView::TestCase
21 21
22 fixtures :projects, :roles, :enabled_modules, :users, 22 fixtures :projects, :roles, :enabled_modules, :users,
23 :repositories, :changesets, 23 :repositories, :changesets,
24 :trackers, :issue_statuses, :issues, :versions, :documents, 24 :trackers, :issue_statuses, :issues, :versions, :documents,
25 :wikis, :wiki_pages, :wiki_contents, 25 :wikis, :wiki_pages, :wiki_contents,
26 :boards, :messages, 26 :boards, :messages,
27 :attachments, 27 :attachments,
28 :enumerations 28 :enumerations
33 33
34 context "#link_to_if_authorized" do 34 context "#link_to_if_authorized" do
35 context "authorized user" do 35 context "authorized user" do
36 should "be tested" 36 should "be tested"
37 end 37 end
38 38
39 context "unauthorized user" do 39 context "unauthorized user" do
40 should "be tested" 40 should "be tested"
41 end 41 end
42 42
43 should "allow using the :controller and :action for the target link" do 43 should "allow using the :controller and :action for the target link" do
44 User.current = User.find_by_login('admin') 44 User.current = User.find_by_login('admin')
45 45
46 @project = Issue.first.project # Used by helper 46 @project = Issue.first.project # Used by helper
47 response = link_to_if_authorized("By controller/action", 47 response = link_to_if_authorized("By controller/action",
48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id}) 48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
49 assert_match /href/, response 49 assert_match /href/, response
50 end 50 end
51 51
52 end 52 end
53 53
54 def test_auto_links 54 def test_auto_links
55 to_test = { 55 to_test = {
56 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>', 56 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
57 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>', 57 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
58 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.', 58 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
82 # wrap in angle brackets 82 # wrap in angle brackets
83 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;' 83 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
84 } 84 }
85 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 85 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
86 end 86 end
87 87
88 def test_auto_mailto 88 def test_auto_mailto
89 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>', 89 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
90 textilizable('test@foo.bar') 90 textilizable('test@foo.bar')
91 end 91 end
92 92
93 def test_inline_images 93 def test_inline_images
94 to_test = { 94 to_test = {
95 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />', 95 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
96 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>', 96 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
97 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />', 97 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
100 'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a title" alt="This is a title" />', 100 'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a title" alt="This is a title" />',
101 'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a double-quoted &quot;title&quot;" alt="This is a double-quoted &quot;title&quot;" />', 101 'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a double-quoted &quot;title&quot;" alt="This is a double-quoted &quot;title&quot;" />',
102 } 102 }
103 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 103 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
104 end 104 end
105 105
106 def test_inline_images_inside_tags 106 def test_inline_images_inside_tags
107 raw = <<-RAW 107 raw = <<-RAW
108 h1. !foo.png! Heading 108 h1. !foo.png! Heading
109 109
110 Centered image: 110 Centered image:
113 RAW 113 RAW
114 114
115 assert textilizable(raw).include?('<img src="foo.png" alt="" />') 115 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
116 assert textilizable(raw).include?('<img src="bar.gif" alt="" />') 116 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
117 end 117 end
118 118
119 def test_attached_images 119 def test_attached_images
120 to_test = { 120 to_test = {
121 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', 121 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
122 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', 122 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
123 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />', 123 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
126 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3" title="This is a logo" alt="This is a logo" /></a>', 126 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3" title="This is a logo" alt="This is a logo" /></a>',
127 } 127 }
128 attachments = Attachment.find(:all) 128 attachments = Attachment.find(:all)
129 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) } 129 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
130 end 130 end
131 131
132 def test_textile_external_links 132 def test_textile_external_links
133 to_test = { 133 to_test = {
134 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>', 134 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
135 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>', 135 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
136 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>', 136 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
145 # escaping 145 # escaping
146 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>', 146 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
147 } 147 }
148 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 148 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
149 end 149 end
150 150
151 def test_redmine_links 151 def test_redmine_links
152 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3}, 152 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
153 :class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)') 153 :class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)')
154 154
155 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1}, 155 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
156 :class => 'changeset', :title => 'My very first commit') 156 :class => 'changeset', :title => 'My very first commit')
157 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2}, 157 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
158 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') 158 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
159 159
160 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1}, 160 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
161 :class => 'document') 161 :class => 'document')
162 162
163 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2}, 163 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
164 :class => 'version') 164 :class => 'version')
165 165
166 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4} 166 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
167 167
168 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'} 168 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
169 169
170 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']} 170 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
171 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']} 171 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
172 172
173 to_test = { 173 to_test = {
174 # tickets 174 # tickets
175 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.", 175 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
176 # changesets 176 # changesets
177 'r1' => changeset_link, 177 'r1' => changeset_link,
198 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'), 198 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
199 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'), 199 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
200 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'), 200 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
201 # message 201 # message
202 'message#4' => link_to('Post 2', message_url, :class => 'message'), 202 'message#4' => link_to('Post 2', message_url, :class => 'message'),
203 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5'), :class => 'message'), 203 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
204 # project 204 # project
205 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'), 205 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
206 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'), 206 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
207 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'), 207 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
208 # escaping 208 # escaping
222 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>', 222 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
223 } 223 }
224 @project = Project.find(1) 224 @project = Project.find(1)
225 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" } 225 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
226 end 226 end
227 227
228 def test_cross_project_redmine_links
229 source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
230 :class => 'source')
231
232 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
233 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
234
235 to_test = {
236 # documents
237 'document:"Test document"' => 'document:"Test document"',
238 'ecookbook:document:"Test document"' => '<a href="/documents/1" class="document">Test document</a>',
239 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
240 # versions
241 'version:"1.0"' => 'version:"1.0"',
242 'ecookbook:version:"1.0"' => '<a href="/versions/show/2" class="version">1.0</a>',
243 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
244 # changeset
245 'r2' => 'r2',
246 'ecookbook:r2' => changeset_link,
247 'invalid:r2' => 'invalid:r2',
248 # source
249 'source:/some/file' => 'source:/some/file',
250 'ecookbook:source:/some/file' => source_link,
251 'invalid:source:/some/file' => 'invalid:source:/some/file',
252 }
253 @project = Project.find(3)
254 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
255 end
256
257 def test_redmine_links_git_commit
258 changeset_link = link_to('abcd',
259 {
260 :controller => 'repositories',
261 :action => 'revision',
262 :id => 'subproject1',
263 :rev => 'abcd',
264 },
265 :class => 'changeset', :title => 'test commit')
266 to_test = {
267 'commit:abcd' => changeset_link,
268 }
269 @project = Project.find(3)
270 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
271 assert r
272 c = Changeset.new(:repository => r,
273 :committed_on => Time.now,
274 :revision => 'abcd',
275 :scmid => 'abcd',
276 :comments => 'test commit')
277 assert( c.save )
278 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
279 end
280
281 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
282 def test_redmine_links_darcs_commit
283 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
284 {
285 :controller => 'repositories',
286 :action => 'revision',
287 :id => 'subproject1',
288 :rev => '123',
289 },
290 :class => 'changeset', :title => 'test commit')
291 to_test = {
292 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
293 }
294 @project = Project.find(3)
295 r = Repository::Darcs.create!(
296 :project => @project, :url => '/tmp/test/darcs',
297 :log_encoding => 'UTF-8')
298 assert r
299 c = Changeset.new(:repository => r,
300 :committed_on => Time.now,
301 :revision => '123',
302 :scmid => '20080308225258-98289-abcd456efg.gz',
303 :comments => 'test commit')
304 assert( c.save )
305 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
306 end
307
308 def test_redmine_links_mercurial_commit
309 changeset_link_rev = link_to('r123',
310 {
311 :controller => 'repositories',
312 :action => 'revision',
313 :id => 'subproject1',
314 :rev => '123' ,
315 },
316 :class => 'changeset', :title => 'test commit')
317 changeset_link_commit = link_to('abcd',
318 {
319 :controller => 'repositories',
320 :action => 'revision',
321 :id => 'subproject1',
322 :rev => 'abcd' ,
323 },
324 :class => 'changeset', :title => 'test commit')
325 to_test = {
326 'r123' => changeset_link_rev,
327 'commit:abcd' => changeset_link_commit,
328 }
329 @project = Project.find(3)
330 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
331 assert r
332 c = Changeset.new(:repository => r,
333 :committed_on => Time.now,
334 :revision => '123',
335 :scmid => 'abcd',
336 :comments => 'test commit')
337 assert( c.save )
338 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
339 end
340
228 def test_attachment_links 341 def test_attachment_links
229 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment') 342 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment')
230 to_test = { 343 to_test = {
231 'attachment:error281.txt' => attachment_link 344 'attachment:error281.txt' => attachment_link
232 } 345 }
233 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" } 346 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
234 end 347 end
235 348
236 def test_wiki_links 349 def test_wiki_links
237 to_test = { 350 to_test = {
238 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>', 351 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
239 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>', 352 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
240 # link with anchor 353 # link with anchor
259 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]', 372 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
260 } 373 }
261 @project = Project.find(1) 374 @project = Project.find(1)
262 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 375 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
263 end 376 end
264 377
265 def test_html_tags 378 def test_html_tags
266 to_test = { 379 to_test = {
267 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>", 380 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
268 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>", 381 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
269 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>", 382 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
273 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>", 386 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
274 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>", 387 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
275 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>", 388 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
276 # remove attributes except class 389 # remove attributes except class
277 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>", 390 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
391 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
392 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
393 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
278 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>", 394 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
395 # xss
396 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
397 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
279 } 398 }
280 to_test.each { |text, result| assert_equal result, textilizable(text) } 399 to_test.each { |text, result| assert_equal result, textilizable(text) }
281 end 400 end
282 401
283 def test_allowed_html_tags 402 def test_allowed_html_tags
284 to_test = { 403 to_test = {
285 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>", 404 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
286 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting", 405 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
287 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;" 406 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
288 } 407 }
289 to_test.each { |text, result| assert_equal result, textilizable(text) } 408 to_test.each { |text, result| assert_equal result, textilizable(text) }
290 end 409 end
291 410
292 def test_pre_tags 411 def test_pre_tags
293 raw = <<-RAW 412 raw = <<-RAW
294 Before 413 Before
295 414
296 <pre> 415 <pre>
305 <pre> 424 <pre>
306 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt; 425 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
307 </pre> 426 </pre>
308 <p>After</p> 427 <p>After</p>
309 EXPECTED 428 EXPECTED
310 429
311 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '') 430 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
312 end 431 end
313 432
314 def test_pre_content_should_not_parse_wiki_and_redmine_links 433 def test_pre_content_should_not_parse_wiki_and_redmine_links
315 raw = <<-RAW 434 raw = <<-RAW
316 [[CookBook documentation]] 435 [[CookBook documentation]]
317 436
318 #1 437 #1
331 [[CookBook documentation]] 450 [[CookBook documentation]]
332 451
333 #1 452 #1
334 </pre> 453 </pre>
335 EXPECTED 454 EXPECTED
336 455
337 @project = Project.find(1) 456 @project = Project.find(1)
338 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '') 457 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
339 end 458 end
340 459
341 def test_non_closing_pre_blocks_should_be_closed 460 def test_non_closing_pre_blocks_should_be_closed
342 raw = <<-RAW 461 raw = <<-RAW
343 <pre><code> 462 <pre><code>
344 RAW 463 RAW
345 464
346 expected = <<-EXPECTED 465 expected = <<-EXPECTED
347 <pre><code> 466 <pre><code>
348 </code></pre> 467 </code></pre>
349 EXPECTED 468 EXPECTED
350 469
351 @project = Project.find(1) 470 @project = Project.find(1)
352 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '') 471 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
353 end 472 end
354 473
355 def test_syntax_highlight 474 def test_syntax_highlight
356 raw = <<-RAW 475 raw = <<-RAW
357 <pre><code class="ruby"> 476 <pre><code class="ruby">
358 # Some ruby code here 477 # Some ruby code here
359 </code></pre> 478 </code></pre>
364 </code></pre> 483 </code></pre>
365 EXPECTED 484 EXPECTED
366 485
367 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '') 486 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
368 end 487 end
369 488
370 def test_wiki_links_in_tables 489 def test_wiki_links_in_tables
371 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" => 490 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
372 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' + 491 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
373 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' + 492 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
374 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>' 493 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
375 } 494 }
376 @project = Project.find(1) 495 @project = Project.find(1)
377 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') } 496 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
378 end 497 end
379 498
380 def test_text_formatting 499 def test_text_formatting
381 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>', 500 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
382 '(_text within parentheses_)' => '(<em>text within parentheses</em>)', 501 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
383 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator', 502 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
384 'a H *umane* W *eb* T *ext* G *enerator*' => 'a H <strong>umane</strong> W <strong>eb</strong> T <strong>ext</strong> G <strong>enerator</strong>', 503 'a H *umane* W *eb* T *ext* G *enerator*' => 'a H <strong>umane</strong> W <strong>eb</strong> T <strong>ext</strong> G <strong>enerator</strong>',
385 'a *H* umane *W* eb *T* ext *G* enerator' => 'a <strong>H</strong> umane <strong>W</strong> eb <strong>T</strong> ext <strong>G</strong> enerator', 504 'a *H* umane *W* eb *T* ext *G* enerator' => 'a <strong>H</strong> umane <strong>W</strong> eb <strong>T</strong> ext <strong>G</strong> enerator',
386 } 505 }
387 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 506 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
388 end 507 end
389 508
390 def test_wiki_horizontal_rule 509 def test_wiki_horizontal_rule
391 assert_equal '<hr />', textilizable('---') 510 assert_equal '<hr />', textilizable('---')
392 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---') 511 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
393 end 512 end
394 513
395 def test_footnotes 514 def test_footnotes
396 raw = <<-RAW 515 raw = <<-RAW
397 This is some text[1]. 516 This is some text[1].
398 517
399 fn1. This is the foot note 518 fn1. This is the foot note
404 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p> 523 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
405 EXPECTED 524 EXPECTED
406 525
407 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '') 526 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
408 end 527 end
409 528
529 def test_headings
530 raw = 'h1. Some heading'
531 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
532
533 assert_equal expected, textilizable(raw)
534 end
535
410 def test_table_of_content 536 def test_table_of_content
411 raw = <<-RAW 537 raw = <<-RAW
412 {{toc}} 538 {{toc}}
413 539
414 h1. Title 540 h1. Title
420 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor. 546 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
421 547
422 h2. Subtitle with [[Wiki|another Wiki]] link 548 h2. Subtitle with [[Wiki|another Wiki]] link
423 549
424 h2. Subtitle with %{color:red}red text% 550 h2. Subtitle with %{color:red}red text%
425 551
552 <pre>
553 some code
554 </pre>
555
426 h3. Subtitle with *some* _modifiers_ 556 h3. Subtitle with *some* _modifiers_
427 557
428 h1. Another title 558 h1. Another title
429 559
430 h3. An "Internet link":http://www.redmine.org/ inside subtitle 560 h3. An "Internet link":http://www.redmine.org/ inside subtitle
434 RAW 564 RAW
435 565
436 expected = '<ul class="toc">' + 566 expected = '<ul class="toc">' +
437 '<li><a href="#Title">Title</a>' + 567 '<li><a href="#Title">Title</a>' +
438 '<ul>' + 568 '<ul>' +
439 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' + 569 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
440 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' + 570 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
441 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' + 571 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
442 '<ul>' + 572 '<ul>' +
443 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' + 573 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
444 '</ul>' + 574 '</ul>' +
445 '</li>' + 575 '</li>' +
456 '</ul>' + 586 '</ul>' +
457 '</li>' + 587 '</li>' +
458 '</ul>' 588 '</ul>'
459 589
460 @project = Project.find(1) 590 @project = Project.find(1)
461 assert textilizable(raw).gsub("\n", "").include?(expected) 591 assert textilizable(raw).gsub("\n", "").include?(expected), textilizable(raw)
462 end 592 end
463 593
464 def test_table_of_content_should_contain_included_page_headings 594 def test_table_of_content_should_contain_included_page_headings
465 raw = <<-RAW 595 raw = <<-RAW
466 {{toc}} 596 {{toc}}
467 597
468 h1. Included 598 h1. Included
470 {{include(Child_1)}} 600 {{include(Child_1)}}
471 RAW 601 RAW
472 602
473 expected = '<ul class="toc">' + 603 expected = '<ul class="toc">' +
474 '<li><a href="#Included">Included</a></li>' + 604 '<li><a href="#Included">Included</a></li>' +
475 '<li><a href="#Child-page-1">Child page 1</a></li>' + 605 '<li><a href="#Child-page-1">Child page 1</a></li>' +
476 '</ul>' 606 '</ul>'
477 607
478 @project = Project.find(1) 608 @project = Project.find(1)
479 assert textilizable(raw).gsub("\n", "").include?(expected) 609 assert textilizable(raw).gsub("\n", "").include?(expected)
480 end 610 end
481 611
482 def test_blockquote
483 # orig raw text
484 raw = <<-RAW
485 John said:
486 > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
487 > Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
488 > * Donec odio lorem,
489 > * sagittis ac,
490 > * malesuada in,
491 > * adipiscing eu, dolor.
492 >
493 > >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
494 > Proin a tellus. Nam vel neque.
495
496 He's right.
497 RAW
498
499 # expected html
500 expected = <<-EXPECTED
501 <p>John said:</p>
502 <blockquote>
503 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
504 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
505 <ul>
506 <li>Donec odio lorem,</li>
507 <li>sagittis ac,</li>
508 <li>malesuada in,</li>
509 <li>adipiscing eu, dolor.</li>
510 </ul>
511 <blockquote>
512 <p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
513 </blockquote>
514 <p>Proin a tellus. Nam vel neque.</p>
515 </blockquote>
516 <p>He's right.</p>
517 EXPECTED
518
519 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
520 end
521
522 def test_table
523 raw = <<-RAW
524 This is a table with empty cells:
525
526 |cell11|cell12||
527 |cell21||cell23|
528 |cell31|cell32|cell33|
529 RAW
530
531 expected = <<-EXPECTED
532 <p>This is a table with empty cells:</p>
533
534 <table>
535 <tr><td>cell11</td><td>cell12</td><td></td></tr>
536 <tr><td>cell21</td><td></td><td>cell23</td></tr>
537 <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
538 </table>
539 EXPECTED
540
541 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
542 end
543
544 def test_table_with_line_breaks
545 raw = <<-RAW
546 This is a table with line breaks:
547
548 |cell11
549 continued|cell12||
550 |-cell21-||cell23
551 cell23 line2
552 cell23 *line3*|
553 |cell31|cell32
554 cell32 line2|cell33|
555
556 RAW
557
558 expected = <<-EXPECTED
559 <p>This is a table with line breaks:</p>
560
561 <table>
562 <tr>
563 <td>cell11<br />continued</td>
564 <td>cell12</td>
565 <td></td>
566 </tr>
567 <tr>
568 <td><del>cell21</del></td>
569 <td></td>
570 <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
571 </tr>
572 <tr>
573 <td>cell31</td>
574 <td>cell32<br/>cell32 line2</td>
575 <td>cell33</td>
576 </tr>
577 </table>
578 EXPECTED
579
580 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
581 end
582
583 def test_textile_should_not_mangle_brackets
584 assert_equal '<p>[msg1][msg2]</p>', textilizable('[msg1][msg2]')
585 end
586
587 def test_default_formatter 612 def test_default_formatter
588 Setting.text_formatting = 'unknown' 613 Setting.text_formatting = 'unknown'
589 text = 'a *link*: http://www.example.net/' 614 text = 'a *link*: http://www.example.net/'
590 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text) 615 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
591 Setting.text_formatting = 'textile' 616 Setting.text_formatting = 'textile'
592 end 617 end
593 618
594 def test_due_date_distance_in_words 619 def test_due_date_distance_in_words
595 to_test = { Date.today => 'Due in 0 days', 620 to_test = { Date.today => 'Due in 0 days',
596 Date.today + 1 => 'Due in 1 day', 621 Date.today + 1 => 'Due in 1 day',
597 Date.today + 100 => 'Due in about 3 months', 622 Date.today + 100 => 'Due in about 3 months',
598 Date.today + 20000 => 'Due in over 54 years', 623 Date.today + 20000 => 'Due in over 54 years',
599 Date.today - 1 => '1 day late', 624 Date.today - 1 => '1 day late',
600 Date.today - 100 => 'about 3 months late', 625 Date.today - 100 => 'about 3 months late',
601 Date.today - 20000 => 'over 54 years late', 626 Date.today - 20000 => 'over 54 years late',
602 } 627 }
628 ::I18n.locale = :en
603 to_test.each do |date, expected| 629 to_test.each do |date, expected|
604 assert_equal expected, due_date_distance_in_words(date) 630 assert_equal expected, due_date_distance_in_words(date)
605 end 631 end
606 end 632 end
607 633
608 def test_avatar 634 def test_avatar
609 # turn on avatars 635 # turn on avatars
610 Setting.gravatar_enabled = '1' 636 Setting.gravatar_enabled = '1'
611 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo')) 637 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
612 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo')) 638 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
613 assert_nil avatar('jsmith') 639 assert_nil avatar('jsmith')
614 assert_nil avatar(nil) 640 assert_nil avatar(nil)
615 641
616 # turn off avatars 642 # turn off avatars
617 Setting.gravatar_enabled = '0' 643 Setting.gravatar_enabled = '0'
618 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo')) 644 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
619 end 645 end
620 646
621 def test_link_to_user 647 def test_link_to_user
622 user = User.find(2) 648 user = User.find(2)
623 t = link_to_user(user) 649 t = link_to_user(user)
624 assert_equal "<a href=\"/users/2\">#{ user.name }</a>", t 650 assert_equal "<a href=\"/users/2\">#{ user.name }</a>", t
625 end 651 end
626 652
627 def test_link_to_user_should_not_link_to_locked_user 653 def test_link_to_user_should_not_link_to_locked_user
628 user = User.find(5) 654 user = User.find(5)
629 assert user.locked? 655 assert user.locked?
630 t = link_to_user(user) 656 t = link_to_user(user)
631 assert_equal user.name, t 657 assert_equal user.name, t
632 end 658 end
633 659
634 def test_link_to_user_should_not_link_to_anonymous 660 def test_link_to_user_should_not_link_to_anonymous
635 user = User.anonymous 661 user = User.anonymous
636 assert user.anonymous? 662 assert user.anonymous?
637 t = link_to_user(user) 663 t = link_to_user(user)
638 assert_equal ::I18n.t(:label_user_anonymous), t 664 assert_equal ::I18n.t(:label_user_anonymous), t