comparison test/unit/helpers/application_helper_test.rb @ 1526:404aa68d4227

Merge from live branch
author Chris Cannam
date Thu, 11 Sep 2014 12:46:20 +0100
parents fb9a13467253
children
comparison
equal deleted inserted replaced
1493:a5f2bdf3b486 1526:404aa68d4227
1 # encoding: utf-8 1 # encoding: utf-8
2 # 2 #
3 # Redmine - project management software 3 # Redmine - project management software
4 # Copyright (C) 2006-2012 Jean-Philippe Lang 4 # Copyright (C) 2006-2014 Jean-Philippe Lang
5 # 5 #
6 # This program is free software; you can redistribute it and/or 6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License 7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2 8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version. 9 # of the License, or (at your option) any later version.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 require File.expand_path('../../../test_helper', __FILE__) 20 require File.expand_path('../../../test_helper', __FILE__)
21 21
22 class ApplicationHelperTest < ActionView::TestCase 22 class ApplicationHelperTest < ActionView::TestCase
23 include Redmine::I18n
23 include ERB::Util 24 include ERB::Util
25 include Rails.application.routes.url_helpers
24 26
25 fixtures :projects, :roles, :enabled_modules, :users, 27 fixtures :projects, :roles, :enabled_modules, :users,
26 :repositories, :changesets, 28 :repositories, :changesets,
27 :trackers, :issue_statuses, :issues, :versions, :documents, 29 :trackers, :issue_statuses, :issues, :versions, :documents,
28 :wikis, :wiki_pages, :wiki_contents, 30 :wikis, :wiki_pages, :wiki_contents,
30 :attachments, :enumerations 32 :attachments, :enumerations
31 33
32 def setup 34 def setup
33 super 35 super
34 set_tmp_attachments_directory 36 set_tmp_attachments_directory
35 end 37 @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82"
36 38 if @russian_test.respond_to?(:force_encoding)
37 context "#link_to_if_authorized" do 39 @russian_test.force_encoding('UTF-8')
38 context "authorized user" do
39 should "be tested"
40 end 40 end
41 41 end
42 context "unauthorized user" do 42
43 should "be tested" 43 test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
44 end 44 User.current = User.find_by_login('admin')
45 45
46 should "allow using the :controller and :action for the target link" do 46 @project = Issue.first.project # Used by helper
47 User.current = User.find_by_login('admin') 47 response = link_to_if_authorized('By controller/actionr',
48 48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
49 @project = Issue.first.project # Used by helper 49 assert_match /href/, response
50 response = link_to_if_authorized("By controller/action", 50 end
51 {:controller => 'issues', :action => 'edit', :id => Issue.first.id}) 51
52 assert_match /href/, response 52 test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
53 end 53 User.current = User.find_by_login('dlopper')
54 54 @project = Project.find('private-child')
55 issue = @project.issues.first
56 assert !issue.visible?
57
58 response = link_to_if_authorized('Never displayed',
59 {:controller => 'issues', :action => 'show', :id => issue})
60 assert_nil response
55 end 61 end
56 62
57 def test_auto_links 63 def test_auto_links
58 to_test = { 64 to_test = {
59 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>', 65 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
81 # two exclamation marks 87 # two exclamation marks
82 'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>', 88 'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
83 # escaping 89 # escaping
84 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>', 90 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
85 # wrap in angle brackets 91 # wrap in angle brackets
86 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;' 92 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
93 # invalid urls
94 'http://' => 'http://',
95 'www.' => 'www.',
96 'test-www.bar.com' => 'test-www.bar.com',
87 } 97 }
88 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 98 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
89 end 99 end
90 100
91 if 'ruby'.respond_to?(:encoding) 101 if 'ruby'.respond_to?(:encoding)
92 def test_auto_links_with_non_ascii_characters 102 def test_auto_links_with_non_ascii_characters
93 to_test = { 103 to_test = {
94 'http://foo.bar/тест' => '<a class="external" href="http://foo.bar/тест">http://foo.bar/тест</a>' 104 "http://foo.bar/#{@russian_test}" =>
105 %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
95 } 106 }
96 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 107 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
97 end 108 end
98 else 109 else
99 puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version' 110 puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
100 end 111 end
101 112
102 def test_auto_mailto 113 def test_auto_mailto
103 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>', 114 to_test = {
104 textilizable('test@foo.bar') 115 'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
116 'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
117 }
118 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
105 end 119 end
106 120
107 def test_inline_images 121 def test_inline_images
108 to_test = { 122 to_test = {
109 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />', 123 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
129 assert textilizable(raw).include?('<img src="bar.gif" alt="" />') 143 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
130 end 144 end
131 145
132 def test_attached_images 146 def test_attached_images
133 to_test = { 147 to_test = {
134 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', 148 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
135 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', 149 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
136 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />', 150 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
137 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />', 151 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
138 # link image 152 # link image
139 '!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>', 153 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" /></a>',
140 } 154 }
141 attachments = Attachment.find(:all) 155 attachments = Attachment.all
142 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) } 156 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
143 end 157 end
144 158
145 def test_attached_images_filename_extension 159 def test_attached_images_filename_extension
146 set_tmp_attachments_directory 160 set_tmp_attachments_directory
180 assert_equal "image/x-ms-bmp", a4.content_type 194 assert_equal "image/x-ms-bmp", a4.content_type
181 assert a4.image? 195 assert a4.image?
182 196
183 to_test = { 197 to_test = {
184 'Inline image: !testtest.jpg!' => 198 'Inline image: !testtest.jpg!' =>
185 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '" alt="" />', 199 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
186 'Inline image: !testtest.jpeg!' => 200 'Inline image: !testtest.jpeg!' =>
187 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />', 201 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
188 'Inline image: !testtest.jpe!' => 202 'Inline image: !testtest.jpe!' =>
189 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '" alt="" />', 203 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
190 'Inline image: !testtest.bmp!' => 204 'Inline image: !testtest.bmp!' =>
191 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '" alt="" />', 205 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
192 } 206 }
193 207
194 attachments = [a1, a2, a3, a4] 208 attachments = [a1, a2, a3, a4]
195 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) } 209 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
196 end 210 end
209 assert a2.visible?(User.find(2)) 223 assert a2.visible?(User.find(2))
210 assert a1.created_on < a2.created_on 224 assert a1.created_on < a2.created_on
211 225
212 to_test = { 226 to_test = {
213 'Inline image: !testfile.png!' => 227 'Inline image: !testfile.png!' =>
214 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />', 228 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
215 'Inline image: !Testfile.PNG!' => 229 'Inline image: !Testfile.PNG!' =>
216 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />', 230 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
217 } 231 }
218 attachments = [a1, a2] 232 attachments = [a1, a2]
219 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) } 233 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
220 set_tmp_attachments_directory 234 set_tmp_attachments_directory
221 end 235 end
240 end 254 end
241 255
242 if 'ruby'.respond_to?(:encoding) 256 if 'ruby'.respond_to?(:encoding)
243 def test_textile_external_links_with_non_ascii_characters 257 def test_textile_external_links_with_non_ascii_characters
244 to_test = { 258 to_test = {
245 'This is a "link":http://foo.bar/тест' => 'This is a <a href="http://foo.bar/тест" class="external">link</a>' 259 %|This is a "link":http://foo.bar/#{@russian_test}| =>
260 %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
246 } 261 }
247 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 262 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
248 end 263 end
249 else 264 else
250 puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version' 265 puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
251 end 266 end
252 267
253 def test_redmine_links 268 def test_redmine_links
254 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3}, 269 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
255 :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)') 270 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
256 note_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'}, 271 note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
257 :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)') 272 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
258 273 note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
259 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1}, 274 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
260 :class => 'changeset', :title => 'My very first commit') 275
261 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2}, 276 revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
277 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
278 revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
262 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') 279 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
280
281 changeset_link2 = link_to('691322a8eb01e11fd7',
282 {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
283 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
263 284
264 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1}, 285 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
265 :class => 'document') 286 :class => 'document')
266 287
267 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2}, 288 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
277 298
278 source_url = '/projects/ecookbook/repository/entry/some/file' 299 source_url = '/projects/ecookbook/repository/entry/some/file'
279 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file' 300 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
280 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext' 301 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
281 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext' 302 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
303 source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
282 304
283 export_url = '/projects/ecookbook/repository/raw/some/file' 305 export_url = '/projects/ecookbook/repository/raw/some/file'
284 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file' 306 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
285 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext' 307 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
286 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext' 308 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
309 export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
287 310
288 to_test = { 311 to_test = {
289 # tickets 312 # tickets
290 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.", 313 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
291 # ticket notes 314 # ticket notes
292 '#3-14' => note_link, 315 '#3-14' => note_link,
293 '#3#note-14' => note_link, 316 '#3#note-14' => note_link2,
294 # should not ignore leading zero 317 # should not ignore leading zero
295 '#03' => '#03', 318 '#03' => '#03',
296 # changesets 319 # changesets
297 'r1' => changeset_link, 320 'r1' => revision_link,
298 'r1.' => "#{changeset_link}.", 321 'r1.' => "#{revision_link}.",
299 'r1, r2' => "#{changeset_link}, #{changeset_link2}", 322 'r1, r2' => "#{revision_link}, #{revision_link2}",
300 'r1,r2' => "#{changeset_link},#{changeset_link2}", 323 'r1,r2' => "#{revision_link},#{revision_link2}",
324 'commit:691322a8eb01e11fd7' => changeset_link2,
301 # documents 325 # documents
302 'document#1' => document_link, 326 'document#1' => document_link,
303 'document:"Test document"' => document_link, 327 'document:"Test document"' => document_link,
304 # versions 328 # versions
305 'version#2' => version_link, 329 'version#2' => version_link,
312 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", 336 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
313 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".", 337 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
314 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".", 338 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
315 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",", 339 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
316 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'), 340 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
341 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
317 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'), 342 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
318 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'), 343 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
319 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'), 344 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
320 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'), 345 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
321 # export 346 # export
322 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'), 347 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
323 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'), 348 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
324 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'), 349 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
325 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'), 350 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
351 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
326 # forum 352 # forum
327 'forum#2' => link_to('Discussion', board_url, :class => 'board'), 353 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
328 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'), 354 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
329 # message 355 # message
330 'message#4' => link_to('Post 2', message_url, :class => 'message'), 356 'message#4' => link_to('Post 2', message_url, :class => 'message'),
348 end 374 end
349 375
350 def test_redmine_links_with_a_different_project_before_current_project 376 def test_redmine_links_with_a_different_project_before_current_project
351 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4') 377 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
352 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4') 378 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
353
354 @project = Project.find(3) 379 @project = Project.find(3)
355 assert_equal %(<p><a href="/versions/#{vp1.id}" class="version">1.4.4</a> <a href="/versions/#{vp3.id}" class="version">1.4.4</a></p>), 380 result1 = link_to("1.4.4", "/versions/#{vp1.id}", :class => "version")
356 textilizable("ecookbook:version:1.4.4 version:1.4.4") 381 result2 = link_to("1.4.4", "/versions/#{vp3.id}", :class => "version")
382 assert_equal "<p>#{result1} #{result2}</p>",
383 textilizable("ecookbook:version:1.4.4 version:1.4.4")
357 end 384 end
358 385
359 def test_escaped_redmine_links_should_not_be_parsed 386 def test_escaped_redmine_links_should_not_be_parsed
360 to_test = [ 387 to_test = [
361 '#3.', 388 '#3.',
372 @project = Project.find(1) 399 @project = Project.find(1)
373 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" } 400 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
374 end 401 end
375 402
376 def test_cross_project_redmine_links 403 def test_cross_project_redmine_links
377 source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, 404 source_link = link_to('ecookbook:source:/some/file',
378 :class => 'source') 405 {:controller => 'repositories', :action => 'entry',
379 406 :id => 'ecookbook', :path => ['some', 'file']},
380 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2}, 407 :class => 'source')
381 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3') 408 changeset_link = link_to('ecookbook:r2',
382 409 {:controller => 'repositories', :action => 'revision',
410 :id => 'ecookbook', :rev => 2},
411 :class => 'changeset',
412 :title => 'This commit fixes #1, #2 and references #1 & #3')
383 to_test = { 413 to_test = {
384 # documents 414 # documents
385 'document:"Test document"' => 'document:"Test document"', 415 'document:"Test document"' => 'document:"Test document"',
386 'ecookbook:document:"Test document"' => '<a href="/documents/1" class="document">Test document</a>', 416 'ecookbook:document:"Test document"' =>
417 link_to("Test document", "/documents/1", :class => "document"),
387 'invalid:document:"Test document"' => 'invalid:document:"Test document"', 418 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
388 # versions 419 # versions
389 'version:"1.0"' => 'version:"1.0"', 420 'version:"1.0"' => 'version:"1.0"',
390 'ecookbook:version:"1.0"' => '<a href="/versions/2" class="version">1.0</a>', 421 'ecookbook:version:"1.0"' =>
422 link_to("1.0", "/versions/2", :class => "version"),
391 'invalid:version:"1.0"' => 'invalid:version:"1.0"', 423 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
392 # changeset 424 # changeset
393 'r2' => 'r2', 425 'r2' => 'r2',
394 'ecookbook:r2' => changeset_link, 426 'ecookbook:r2' => changeset_link,
395 'invalid:r2' => 'invalid:r2', 427 'invalid:r2' => 'invalid:r2',
397 'source:/some/file' => 'source:/some/file', 429 'source:/some/file' => 'source:/some/file',
398 'ecookbook:source:/some/file' => source_link, 430 'ecookbook:source:/some/file' => source_link,
399 'invalid:source:/some/file' => 'invalid:source:/some/file', 431 'invalid:source:/some/file' => 'invalid:source:/some/file',
400 } 432 }
401 @project = Project.find(3) 433 @project = Project.find(3)
402 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" } 434 to_test.each do |text, result|
435 assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed"
436 end
437 end
438
439 def test_redmine_links_by_name_should_work_with_html_escaped_characters
440 v = Version.generate!(:name => "Test & Show.txt", :project_id => 1)
441 link = link_to("Test & Show.txt", "/versions/#{v.id}", :class => "version")
442
443 @project = v.project
444 assert_equal "<p>#{link}</p>", textilizable('version:"Test & Show.txt"')
445 end
446
447 def test_link_to_issue_subject
448 issue = Issue.generate!(:subject => "01234567890123456789")
449 str = link_to_issue(issue, :truncate => 10)
450 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
451 assert_equal "#{result}: 0123456...", str
452
453 issue = Issue.generate!(:subject => "<&>")
454 str = link_to_issue(issue)
455 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
456 assert_equal "#{result}: &lt;&amp;&gt;", str
457
458 issue = Issue.generate!(:subject => "<&>0123456789012345")
459 str = link_to_issue(issue, :truncate => 10)
460 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
461 assert_equal "#{result}: &lt;&amp;&gt;0123...", str
462 end
463
464 def test_link_to_issue_title
465 long_str = "0123456789" * 5
466
467 issue = Issue.generate!(:subject => "#{long_str}01234567890123456789")
468 str = link_to_issue(issue, :subject => false)
469 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
470 :class => issue.css_classes,
471 :title => "#{long_str}0123456...")
472 assert_equal result, str
473
474 issue = Issue.generate!(:subject => "<&>#{long_str}01234567890123456789")
475 str = link_to_issue(issue, :subject => false)
476 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
477 :class => issue.css_classes,
478 :title => "<&>#{long_str}0123...")
479 assert_equal result, str
403 end 480 end
404 481
405 def test_multiple_repositories_redmine_links 482 def test_multiple_repositories_redmine_links
406 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg') 483 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
407 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123') 484 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
551 assert( c.save ) 628 assert( c.save )
552 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 629 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
553 end 630 end
554 631
555 def test_attachment_links 632 def test_attachment_links
556 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment') 633 text = 'attachment:error281.txt'
557 to_test = { 634 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
558 'attachment:error281.txt' => attachment_link 635 :class => "attachment")
559 } 636 assert_equal "<p>#{result}</p>",
560 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" } 637 textilizable(text,
638 :attachments => Issue.find(3).attachments),
639 "#{text} failed"
561 end 640 end
562 641
563 def test_attachment_link_should_link_to_latest_attachment 642 def test_attachment_link_should_link_to_latest_attachment
564 set_tmp_attachments_directory 643 set_tmp_attachments_directory
565 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago) 644 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
566 a2 = Attachment.generate!(:filename => "test.txt") 645 a2 = Attachment.generate!(:filename => "test.txt")
567 646 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
568 assert_equal %(<p><a href="/attachments/download/#{a2.id}" class="attachment">test.txt</a></p>), 647 :class => "attachment")
569 textilizable('attachment:test.txt', :attachments => [a1, a2]) 648 assert_equal "<p>#{result}</p>",
649 textilizable('attachment:test.txt', :attachments => [a1, a2])
570 end 650 end
571 651
572 def test_wiki_links 652 def test_wiki_links
573 to_test = { 653 russian_eacape = CGI.escape(@russian_test)
574 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>', 654 to_test = {
575 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>', 655 '[[CookBook documentation]]' =>
656 link_to("CookBook documentation",
657 "/projects/ecookbook/wiki/CookBook_documentation",
658 :class => "wiki-page"),
659 '[[Another page|Page]]' =>
660 link_to("Page",
661 "/projects/ecookbook/wiki/Another_page",
662 :class => "wiki-page"),
576 # title content should be formatted 663 # title content should be formatted
577 '[[Another page|With _styled_ *title*]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With <em>styled</em> <strong>title</strong></a>', 664 '[[Another page|With _styled_ *title*]]' =>
578 '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;</a>', 665 link_to("With <em>styled</em> <strong>title</strong>".html_safe,
666 "/projects/ecookbook/wiki/Another_page",
667 :class => "wiki-page"),
668 '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' =>
669 link_to("With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;".html_safe,
670 "/projects/ecookbook/wiki/Another_page",
671 :class => "wiki-page"),
579 # link with anchor 672 # link with anchor
580 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>', 673 '[[CookBook documentation#One-section]]' =>
581 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>', 674 link_to("CookBook documentation",
675 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
676 :class => "wiki-page"),
677 '[[Another page#anchor|Page]]' =>
678 link_to("Page",
679 "/projects/ecookbook/wiki/Another_page#anchor",
680 :class => "wiki-page"),
582 # UTF8 anchor 681 # UTF8 anchor
583 '[[Another_page#Тест|Тест]]' => %|<a href="/projects/ecookbook/wiki/Another_page##{CGI.escape 'Тест'}" class="wiki-page">Тест</a>|, 682 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
683 link_to(@russian_test,
684 "/projects/ecookbook/wiki/Another_page##{russian_eacape}",
685 :class => "wiki-page"),
584 # page that doesn't exist 686 # page that doesn't exist
585 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>', 687 '[[Unknown page]]' =>
586 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>', 688 link_to("Unknown page",
689 "/projects/ecookbook/wiki/Unknown_page",
690 :class => "wiki-page new"),
691 '[[Unknown page|404]]' =>
692 link_to("404",
693 "/projects/ecookbook/wiki/Unknown_page",
694 :class => "wiki-page new"),
587 # link to another project wiki 695 # link to another project wiki
588 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>', 696 '[[onlinestore:]]' =>
589 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>', 697 link_to("onlinestore",
590 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>', 698 "/projects/onlinestore/wiki",
591 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>', 699 :class => "wiki-page"),
592 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>', 700 '[[onlinestore:|Wiki]]' =>
701 link_to("Wiki",
702 "/projects/onlinestore/wiki",
703 :class => "wiki-page"),
704 '[[onlinestore:Start page]]' =>
705 link_to("Start page",
706 "/projects/onlinestore/wiki/Start_page",
707 :class => "wiki-page"),
708 '[[onlinestore:Start page|Text]]' =>
709 link_to("Text",
710 "/projects/onlinestore/wiki/Start_page",
711 :class => "wiki-page"),
712 '[[onlinestore:Unknown page]]' =>
713 link_to("Unknown page",
714 "/projects/onlinestore/wiki/Unknown_page",
715 :class => "wiki-page new"),
593 # striked through link 716 # striked through link
594 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>', 717 '-[[Another page|Page]]-' =>
595 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>', 718 "<del>".html_safe +
719 link_to("Page",
720 "/projects/ecookbook/wiki/Another_page",
721 :class => "wiki-page").html_safe +
722 "</del>".html_safe,
723 '-[[Another page|Page]] link-' =>
724 "<del>".html_safe +
725 link_to("Page",
726 "/projects/ecookbook/wiki/Another_page",
727 :class => "wiki-page").html_safe +
728 " link</del>".html_safe,
596 # escaping 729 # escaping
597 '![[Another page|Page]]' => '[[Another page|Page]]', 730 '![[Another page|Page]]' => '[[Another page|Page]]',
598 # project does not exist 731 # project does not exist
599 '[[unknowproject:Start]]' => '[[unknowproject:Start]]', 732 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
600 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]', 733 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
601 } 734 }
602
603 @project = Project.find(1) 735 @project = Project.find(1)
604 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } 736 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
605 end 737 end
606 738
607 def test_wiki_links_within_local_file_generation_context 739 def test_wiki_links_within_local_file_generation_context
608
609 to_test = { 740 to_test = {
610 # link to a page 741 # link to a page
611 '[[CookBook documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">CookBook documentation</a>', 742 '[[CookBook documentation]]' =>
612 '[[CookBook documentation|documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">documentation</a>', 743 link_to("CookBook documentation", "CookBook_documentation.html",
613 '[[CookBook documentation#One-section]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">CookBook documentation</a>', 744 :class => "wiki-page"),
614 '[[CookBook documentation#One-section|documentation]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">documentation</a>', 745 '[[CookBook documentation|documentation]]' =>
746 link_to("documentation", "CookBook_documentation.html",
747 :class => "wiki-page"),
748 '[[CookBook documentation#One-section]]' =>
749 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
750 :class => "wiki-page"),
751 '[[CookBook documentation#One-section|documentation]]' =>
752 link_to("documentation", "CookBook_documentation.html#One-section",
753 :class => "wiki-page"),
615 # page that doesn't exist 754 # page that doesn't exist
616 '[[Unknown page]]' => '<a href="Unknown_page.html" class="wiki-page new">Unknown page</a>', 755 '[[Unknown page]]' =>
617 '[[Unknown page|404]]' => '<a href="Unknown_page.html" class="wiki-page new">404</a>', 756 link_to("Unknown page", "Unknown_page.html",
618 '[[Unknown page#anchor]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">Unknown page</a>', 757 :class => "wiki-page new"),
619 '[[Unknown page#anchor|404]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">404</a>', 758 '[[Unknown page|404]]' =>
620 } 759 link_to("404", "Unknown_page.html",
621 760 :class => "wiki-page new"),
761 '[[Unknown page#anchor]]' =>
762 link_to("Unknown page", "Unknown_page.html#anchor",
763 :class => "wiki-page new"),
764 '[[Unknown page#anchor|404]]' =>
765 link_to("404", "Unknown_page.html#anchor",
766 :class => "wiki-page new"),
767 }
622 @project = Project.find(1) 768 @project = Project.find(1)
623 769 to_test.each do |text, result|
624 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local) } 770 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
771 end
625 end 772 end
626 773
627 def test_wiki_links_within_wiki_page_context 774 def test_wiki_links_within_wiki_page_context
628
629 page = WikiPage.find_by_title('Another_page' ) 775 page = WikiPage.find_by_title('Another_page' )
630 776 to_test = {
631 to_test = { 777 '[[CookBook documentation]]' =>
632 # link to another page 778 link_to("CookBook documentation",
633 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>', 779 "/projects/ecookbook/wiki/CookBook_documentation",
634 '[[CookBook documentation|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">documentation</a>', 780 :class => "wiki-page"),
635 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>', 781 '[[CookBook documentation|documentation]]' =>
636 '[[CookBook documentation#One-section|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">documentation</a>', 782 link_to("documentation",
783 "/projects/ecookbook/wiki/CookBook_documentation",
784 :class => "wiki-page"),
785 '[[CookBook documentation#One-section]]' =>
786 link_to("CookBook documentation",
787 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
788 :class => "wiki-page"),
789 '[[CookBook documentation#One-section|documentation]]' =>
790 link_to("documentation",
791 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
792 :class => "wiki-page"),
637 # link to the current page 793 # link to the current page
638 '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>', 794 '[[Another page]]' =>
639 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>', 795 link_to("Another page",
640 '[[Another page#anchor]]' => '<a href="#anchor" class="wiki-page">Another page</a>', 796 "/projects/ecookbook/wiki/Another_page",
641 '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>', 797 :class => "wiki-page"),
798 '[[Another page|Page]]' =>
799 link_to("Page",
800 "/projects/ecookbook/wiki/Another_page",
801 :class => "wiki-page"),
802 '[[Another page#anchor]]' =>
803 link_to("Another page",
804 "#anchor",
805 :class => "wiki-page"),
806 '[[Another page#anchor|Page]]' =>
807 link_to("Page",
808 "#anchor",
809 :class => "wiki-page"),
642 # page that doesn't exist 810 # page that doesn't exist
643 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">Unknown page</a>', 811 '[[Unknown page]]' =>
644 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">404</a>', 812 link_to("Unknown page",
645 '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">Unknown page</a>', 813 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
646 '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">404</a>', 814 :class => "wiki-page new"),
647 } 815 '[[Unknown page|404]]' =>
648 816 link_to("404",
817 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
818 :class => "wiki-page new"),
819 '[[Unknown page#anchor]]' =>
820 link_to("Unknown page",
821 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
822 :class => "wiki-page new"),
823 '[[Unknown page#anchor|404]]' =>
824 link_to("404",
825 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
826 :class => "wiki-page new"),
827 }
649 @project = Project.find(1) 828 @project = Project.find(1)
650 829 to_test.each do |text, result|
651 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) } 830 assert_equal "<p>#{result}</p>",
831 textilizable(WikiContent.new( :text => text, :page => page ), :text)
832 end
652 end 833 end
653 834
654 def test_wiki_links_anchor_option_should_prepend_page_title_to_href 835 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
655
656 to_test = { 836 to_test = {
657 # link to a page 837 # link to a page
658 '[[CookBook documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">CookBook documentation</a>', 838 '[[CookBook documentation]]' =>
659 '[[CookBook documentation|documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">documentation</a>', 839 link_to("CookBook documentation",
660 '[[CookBook documentation#One-section]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">CookBook documentation</a>', 840 "#CookBook_documentation",
661 '[[CookBook documentation#One-section|documentation]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">documentation</a>', 841 :class => "wiki-page"),
842 '[[CookBook documentation|documentation]]' =>
843 link_to("documentation",
844 "#CookBook_documentation",
845 :class => "wiki-page"),
846 '[[CookBook documentation#One-section]]' =>
847 link_to("CookBook documentation",
848 "#CookBook_documentation_One-section",
849 :class => "wiki-page"),
850 '[[CookBook documentation#One-section|documentation]]' =>
851 link_to("documentation",
852 "#CookBook_documentation_One-section",
853 :class => "wiki-page"),
662 # page that doesn't exist 854 # page that doesn't exist
663 '[[Unknown page]]' => '<a href="#Unknown_page" class="wiki-page new">Unknown page</a>', 855 '[[Unknown page]]' =>
664 '[[Unknown page|404]]' => '<a href="#Unknown_page" class="wiki-page new">404</a>', 856 link_to("Unknown page",
665 '[[Unknown page#anchor]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">Unknown page</a>', 857 "#Unknown_page",
666 '[[Unknown page#anchor|404]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">404</a>', 858 :class => "wiki-page new"),
667 } 859 '[[Unknown page|404]]' =>
668 860 link_to("404",
861 "#Unknown_page",
862 :class => "wiki-page new"),
863 '[[Unknown page#anchor]]' =>
864 link_to("Unknown page",
865 "#Unknown_page_anchor",
866 :class => "wiki-page new"),
867 '[[Unknown page#anchor|404]]' =>
868 link_to("404",
869 "#Unknown_page_anchor",
870 :class => "wiki-page new"),
871 }
669 @project = Project.find(1) 872 @project = Project.find(1)
670 873 to_test.each do |text, result|
671 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) } 874 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
875 end
672 end 876 end
673 877
674 def test_html_tags 878 def test_html_tags
675 to_test = { 879 to_test = {
676 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>", 880 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
737 941
738 #1 942 #1
739 </pre> 943 </pre>
740 RAW 944 RAW
741 945
946 result1 = link_to("CookBook documentation",
947 "/projects/ecookbook/wiki/CookBook_documentation",
948 :class => "wiki-page")
949 result2 = link_to('#1',
950 "/issues/1",
951 :class => Issue.find(1).css_classes,
952 :title => "Can't print recipes (New)")
953
742 expected = <<-EXPECTED 954 expected = <<-EXPECTED
743 <p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p> 955 <p>#{result1}</p>
744 <p><a href="/issues/1" class="issue status-1 priority-4 priority-lowest" title="Can&#x27;t print recipes (New)">#1</a></p> 956 <p>#{result2}</p>
745 <pre> 957 <pre>
746 [[CookBook documentation]] 958 [[CookBook documentation]]
747 959
748 #1 960 #1
749 </pre> 961 </pre>
788 assert_equal 'test1/test2', to_path_param('//test1/test2/') 1000 assert_equal 'test1/test2', to_path_param('//test1/test2/')
789 assert_equal nil, to_path_param('/') 1001 assert_equal nil, to_path_param('/')
790 end 1002 end
791 1003
792 def test_wiki_links_in_tables 1004 def test_wiki_links_in_tables
793 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" => 1005 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
794 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' + 1006 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
795 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' + 1007 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
796 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>' 1008 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
797 } 1009 result = "<tr><td>#{link1}</td>" +
1010 "<td>#{link2}</td>" +
1011 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
798 @project = Project.find(1) 1012 @project = Project.find(1)
799 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') } 1013 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
800 end 1014 end
801 1015
802 def test_text_formatting 1016 def test_text_formatting
803 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>', 1017 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
804 '(_text within parentheses_)' => '(<em>text within parentheses</em>)', 1018 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
959 1173
960 @project = Project.find(1) 1174 @project = Project.find(1)
961 assert textilizable(raw).gsub("\n", "").include?(expected) 1175 assert textilizable(raw).gsub("\n", "").include?(expected)
962 end 1176 end
963 1177
1178 def test_toc_with_textile_formatting_should_be_parsed
1179 with_settings :text_formatting => 'textile' do
1180 assert_select_in textilizable("{{toc}}\n\nh1. Heading"), 'ul.toc li', :text => 'Heading'
1181 assert_select_in textilizable("{{<toc}}\n\nh1. Heading"), 'ul.toc.left li', :text => 'Heading'
1182 assert_select_in textilizable("{{>toc}}\n\nh1. Heading"), 'ul.toc.right li', :text => 'Heading'
1183 end
1184 end
1185
1186 if Object.const_defined?(:Redcarpet)
1187 def test_toc_with_markdown_formatting_should_be_parsed
1188 with_settings :text_formatting => 'markdown' do
1189 assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
1190 assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
1191 assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
1192 end
1193 end
1194 end
1195
964 def test_section_edit_links 1196 def test_section_edit_links
965 raw = <<-RAW 1197 raw = <<-RAW
966 h1. Title 1198 h1. Title
967 1199
968 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero. 1200 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
987 @project = Project.find(1) 1219 @project = Project.find(1)
988 set_language_if_valid 'en' 1220 set_language_if_valid 'en'
989 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "") 1221 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
990 1222
991 # heading that contains inline code 1223 # heading that contains inline code
992 assert_match Regexp.new('<div class="contextual" title="Edit this section">' + 1224 assert_match Regexp.new('<div class="contextual" id="section-4" title="Edit this section">' +
993 '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' + 1225 '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
994 '<a name="Subtitle-with-inline-code"></a>' + 1226 '<a name="Subtitle-with-inline-code"></a>' +
995 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'), 1227 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
996 result 1228 result
997 1229
998 # last heading 1230 # last heading
999 assert_match Regexp.new('<div class="contextual" title="Edit this section">' + 1231 assert_match Regexp.new('<div class="contextual" id="section-5" title="Edit this section">' +
1000 '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' + 1232 '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1001 '<a name="Subtitle-after-pre-tag"></a>' + 1233 '<a name="Subtitle-after-pre-tag"></a>' +
1002 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'), 1234 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1003 result 1235 result
1004 end 1236 end
1048 end 1280 end
1049 end 1281 end
1050 1282
1051 def test_link_to_user 1283 def test_link_to_user
1052 user = User.find(2) 1284 user = User.find(2)
1053 assert_equal '<a href="/users/2" class="user active">John Smith</a>', link_to_user(user) 1285 result = link_to("John Smith", "/users/2", :class => "user active")
1286 assert_equal result, link_to_user(user)
1054 end 1287 end
1055 1288
1056 def test_link_to_user_should_not_link_to_locked_user 1289 def test_link_to_user_should_not_link_to_locked_user
1057 with_current_user nil do 1290 with_current_user nil do
1058 user = User.find(5) 1291 user = User.find(5)
1063 1296
1064 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin 1297 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1065 with_current_user User.find(1) do 1298 with_current_user User.find(1) do
1066 user = User.find(5) 1299 user = User.find(5)
1067 assert user.locked? 1300 assert user.locked?
1068 assert_equal '<a href="/users/5" class="user locked">Dave2 Lopper2</a>', link_to_user(user) 1301 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1302 assert_equal result, link_to_user(user)
1069 end 1303 end
1070 end 1304 end
1071 1305
1072 def test_link_to_user_should_not_link_to_anonymous 1306 def test_link_to_user_should_not_link_to_anonymous
1073 user = User.anonymous 1307 user = User.anonymous
1074 assert user.anonymous? 1308 assert user.anonymous?
1075 t = link_to_user(user) 1309 t = link_to_user(user)
1076 assert_equal ::I18n.t(:label_user_anonymous), t 1310 assert_equal ::I18n.t(:label_user_anonymous), t
1311 end
1312
1313 def test_link_to_attachment
1314 a = Attachment.find(3)
1315 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1316 link_to_attachment(a)
1317 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1318 link_to_attachment(a, :text => 'Text')
1319 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1320 assert_equal result,
1321 link_to_attachment(a, :class => 'foo')
1322 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1323 link_to_attachment(a, :download => true)
1324 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1325 link_to_attachment(a, :only_path => false)
1326 end
1327
1328 def test_thumbnail_tag
1329 a = Attachment.find(3)
1330 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1331 thumbnail_tag(a)
1077 end 1332 end
1078 1333
1079 def test_link_to_project 1334 def test_link_to_project
1080 project = Project.find(1) 1335 project = Project.find(1)
1081 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>), 1336 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1082 link_to_project(project) 1337 link_to_project(project)
1083 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>), 1338 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1084 link_to_project(project, :action => 'settings') 1339 link_to_project(project, :action => 'settings')
1085 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>), 1340 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1086 link_to_project(project, {:only_path => false, :jump => 'blah'}) 1341 link_to_project(project, {:only_path => false, :jump => 'blah'})
1087 assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>), 1342 result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
1343 assert_equal result,
1088 link_to_project(project, {:action => 'settings'}, :class => "project") 1344 link_to_project(project, {:action => 'settings'}, :class => "project")
1345 end
1346
1347 def test_link_to_project_settings
1348 project = Project.find(1)
1349 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1350
1351 project.status = Project::STATUS_CLOSED
1352 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1353
1354 project.status = Project::STATUS_ARCHIVED
1355 assert_equal 'eCookbook', link_to_project_settings(project)
1089 end 1356 end
1090 1357
1091 def test_link_to_legacy_project_with_numerical_identifier_should_use_id 1358 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1092 # numeric identifier are no longer allowed 1359 # numeric identifier are no longer allowed
1093 Project.update_all "identifier=25", "id=1" 1360 Project.where(:id => 1).update_all(:identifier => 25)
1094
1095 assert_equal '<a href="/projects/1">eCookbook</a>', 1361 assert_equal '<a href="/projects/1">eCookbook</a>',
1096 link_to_project(Project.find(1)) 1362 link_to_project(Project.find(1))
1097 end 1363 end
1098 1364
1099 def test_principals_options_for_select_with_users 1365 def test_principals_options_for_select_with_users
1162 1428
1163 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript 1429 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1164 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo) 1430 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1165 end 1431 end
1166 1432
1167 def test_per_page_links_should_show_usefull_values 1433 def test_raw_json_should_escape_closing_tags
1168 set_language_if_valid 'en' 1434 s = raw_json(["<foo>bar</foo>"])
1169 stubs(:link_to).returns("[link]") 1435 assert_equal '["<foo>bar<\/foo>"]', s
1170 1436 end
1171 with_settings :per_page_options => '10, 25, 50, 100' do 1437
1172 assert_nil per_page_links(10, 3) 1438 def test_raw_json_should_be_html_safe
1173 assert_nil per_page_links(25, 3) 1439 s = raw_json(["foo"])
1174 assert_equal "Per page: 10, [link]", per_page_links(10, 22) 1440 assert s.html_safe?
1175 assert_equal "Per page: [link], 25", per_page_links(25, 22) 1441 end
1176 assert_equal "Per page: [link], [link], 50", per_page_links(50, 22) 1442
1177 assert_equal "Per page: [link], 25, [link]", per_page_links(25, 26) 1443 def test_html_title_should_app_title_if_not_set
1178 assert_equal "Per page: [link], 25, [link], [link]", per_page_links(25, 120) 1444 assert_equal 'Redmine', html_title
1179 end 1445 end
1446
1447 def test_html_title_should_join_items
1448 html_title 'Foo', 'Bar'
1449 assert_equal 'Foo - Bar - Redmine', html_title
1450 end
1451
1452 def test_html_title_should_append_current_project_name
1453 @project = Project.find(1)
1454 html_title 'Foo', 'Bar'
1455 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1456 end
1457
1458 def test_title_should_return_a_h2_tag
1459 assert_equal '<h2>Foo</h2>', title('Foo')
1460 end
1461
1462 def test_title_should_set_html_title
1463 title('Foo')
1464 assert_equal 'Foo - Redmine', html_title
1465 end
1466
1467 def test_title_should_turn_arrays_into_links
1468 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1469 assert_equal 'Foo - Redmine', html_title
1470 end
1471
1472 def test_title_should_join_items
1473 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1474 assert_equal 'Bar - Foo - Redmine', html_title
1475 end
1476
1477 def test_favicon_path
1478 assert_match %r{^/favicon\.ico}, favicon_path
1479 end
1480
1481 def test_favicon_path_with_suburi
1482 Redmine::Utils.relative_url_root = '/foo'
1483 assert_match %r{^/foo/favicon\.ico}, favicon_path
1484 ensure
1485 Redmine::Utils.relative_url_root = ''
1486 end
1487
1488 def test_favicon_url
1489 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1490 end
1491
1492 def test_favicon_url_with_suburi
1493 Redmine::Utils.relative_url_root = '/foo'
1494 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1495 ensure
1496 Redmine::Utils.relative_url_root = ''
1497 end
1498
1499 def test_truncate_single_line
1500 str = "01234"
1501 result = truncate_single_line_raw("#{str}\n#{str}", 10)
1502 assert_equal "01234 0...", result
1503 assert !result.html_safe?
1504 result = truncate_single_line_raw("#{str}<&#>\n#{str}#{str}", 16)
1505 assert_equal "01234<&#> 012...", result
1506 assert !result.html_safe?
1507 end
1508
1509 def test_truncate_single_line_non_ascii
1510 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
1511 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
1512 result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10)
1513 assert_equal "#{ja} #{ja}...", result
1514 assert !result.html_safe?
1180 end 1515 end
1181 end 1516 end