##// END OF EJS Templates
Adds a test for #24922....
Jean-Philippe Lang -
r15930:6ef7a0fc2dc3
parent child
Show More
@@ -1,1579 +1,1585
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2016 Jean-Philippe Lang
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; either version 2
9 9 # of the License, or (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 20 require File.expand_path('../../../test_helper', __FILE__)
21 21
22 22 class ApplicationHelperTest < Redmine::HelperTest
23 23 include ERB::Util
24 24 include Rails.application.routes.url_helpers
25 25
26 26 fixtures :projects, :enabled_modules,
27 27 :users, :email_addresses,
28 28 :members, :member_roles, :roles,
29 29 :repositories, :changesets,
30 30 :projects_trackers,
31 31 :trackers, :issue_statuses, :issues, :versions, :documents,
32 32 :wikis, :wiki_pages, :wiki_contents,
33 33 :boards, :messages, :news,
34 34 :attachments, :enumerations
35 35
36 36 def setup
37 37 super
38 38 set_tmp_attachments_directory
39 39 @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".force_encoding('UTF-8')
40 40 end
41 41
42 42 test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
43 43 User.current = User.find_by_login('admin')
44 44
45 45 @project = Issue.first.project # Used by helper
46 46 response = link_to_if_authorized('By controller/actionr',
47 47 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
48 48 assert_match /href/, response
49 49 end
50 50
51 51 test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
52 52 User.current = User.find_by_login('dlopper')
53 53 @project = Project.find('private-child')
54 54 issue = @project.issues.first
55 55 assert !issue.visible?
56 56
57 57 response = link_to_if_authorized('Never displayed',
58 58 {:controller => 'issues', :action => 'show', :id => issue})
59 59 assert_nil response
60 60 end
61 61
62 62 def test_auto_links
63 63 to_test = {
64 64 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
65 65 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
66 66 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
67 67 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
68 68 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
69 69 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
70 70 'http://foo.bar/foo.bar#foo.bar.' => '<a class="external" href="http://foo.bar/foo.bar#foo.bar">http://foo.bar/foo.bar#foo.bar</a>.',
71 71 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
72 72 '(see inline link : http://www.foo.bar/Test_(foobar))' => '(see inline link : <a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>)',
73 73 '(see inline link : http://www.foo.bar/Test)' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>)',
74 74 '(see inline link : http://www.foo.bar/Test).' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>).',
75 75 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
76 76 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
77 77 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
78 78 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
79 79 'http://foo.bar/page?p=1&t=z&s=' => '<a class="external" href="http://foo.bar/page?p=1&#38;t=z&#38;s=">http://foo.bar/page?p=1&#38;t=z&#38;s=</a>',
80 80 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
81 81 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
82 82 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
83 83 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
84 84 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
85 85 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
86 86 # two exclamation marks
87 87 '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 88 # escaping
89 89 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
90 90 # wrap in angle brackets
91 91 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
92 92 # invalid urls
93 93 'http://' => 'http://',
94 94 'www.' => 'www.',
95 95 'test-www.bar.com' => 'test-www.bar.com',
96 96 }
97 97 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
98 98 end
99 99
100 100 def test_auto_links_with_non_ascii_characters
101 101 to_test = {
102 102 "http://foo.bar/#{@russian_test}" =>
103 103 %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
104 104 }
105 105 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
106 106 end
107 107
108 108 def test_auto_mailto
109 109 to_test = {
110 110 'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
111 111 'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
112 112 }
113 113 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
114 114 end
115 115
116 116 def test_inline_images
117 117 to_test = {
118 118 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
119 119 'floating !>http://foo.bar/image.jpg!' => 'floating <span style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></span>',
120 120 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
121 121 'with style !{width:100px;height:100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height:100px;" alt="" />',
122 122 '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" />',
123 123 '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;" />',
124 124 }
125 125 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
126 126 end
127 127
128 128 def test_inline_images_inside_tags
129 129 raw = <<-RAW
130 130 h1. !foo.png! Heading
131 131
132 132 Centered image:
133 133
134 134 p=. !bar.gif!
135 135 RAW
136 136
137 137 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
138 138 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
139 139 end
140 140
141 141 def test_attached_images
142 142 to_test = {
143 143 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
144 144 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
145 145 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
146 146 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
147 147 # link image
148 148 '!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>',
149 149 }
150 150 attachments = Attachment.all
151 151 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
152 152 end
153 153
154 154 def test_attached_images_with_textile_and_non_ascii_filename
155 155 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
156 156 with_settings :text_formatting => 'textile' do
157 157 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="" />),
158 158 textilizable("!cafΓ©.jpg!)", :attachments => [attachment])
159 159 end
160 160 end
161 161
162 162 def test_attached_images_with_markdown_and_non_ascii_filename
163 163 skip unless Object.const_defined?(:Redcarpet)
164 164
165 165 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
166 166 with_settings :text_formatting => 'markdown' do
167 167 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="" />),
168 168 textilizable("![](cafΓ©.jpg)", :attachments => [attachment])
169 169 end
170 170 end
171 171
172 def test_attached_images_with_hires_naming
173 attachment = Attachment.generate!(:filename => 'image@2x.png')
174 assert_equal %(<p><img src="/attachments/download/#{attachment.id}/image@2x.png" srcset="/attachments/download/#{attachment.id}/image@2x.png 2x" alt="" /></p>),
175 textilizable("!image@2x.png!", :attachments => [attachment])
176 end
177
172 178 def test_attached_images_filename_extension
173 179 set_tmp_attachments_directory
174 180 a1 = Attachment.new(
175 181 :container => Issue.find(1),
176 182 :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
177 183 :author => User.find(1))
178 184 assert a1.save
179 185 assert_equal "testtest.JPG", a1.filename
180 186 assert_equal "image/jpeg", a1.content_type
181 187 assert a1.image?
182 188
183 189 a2 = Attachment.new(
184 190 :container => Issue.find(1),
185 191 :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
186 192 :author => User.find(1))
187 193 assert a2.save
188 194 assert_equal "testtest.jpeg", a2.filename
189 195 assert_equal "image/jpeg", a2.content_type
190 196 assert a2.image?
191 197
192 198 a3 = Attachment.new(
193 199 :container => Issue.find(1),
194 200 :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
195 201 :author => User.find(1))
196 202 assert a3.save
197 203 assert_equal "testtest.JPE", a3.filename
198 204 assert_equal "image/jpeg", a3.content_type
199 205 assert a3.image?
200 206
201 207 a4 = Attachment.new(
202 208 :container => Issue.find(1),
203 209 :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
204 210 :author => User.find(1))
205 211 assert a4.save
206 212 assert_equal "Testtest.BMP", a4.filename
207 213 assert_equal "image/x-ms-bmp", a4.content_type
208 214 assert a4.image?
209 215
210 216 to_test = {
211 217 'Inline image: !testtest.jpg!' =>
212 218 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
213 219 'Inline image: !testtest.jpeg!' =>
214 220 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
215 221 'Inline image: !testtest.jpe!' =>
216 222 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
217 223 'Inline image: !testtest.bmp!' =>
218 224 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
219 225 }
220 226
221 227 attachments = [a1, a2, a3, a4]
222 228 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
223 229 end
224 230
225 231 def test_attached_images_should_read_later
226 232 set_fixtures_attachments_directory
227 233 a1 = Attachment.find(16)
228 234 assert_equal "testfile.png", a1.filename
229 235 assert a1.readable?
230 236 assert (! a1.visible?(User.anonymous))
231 237 assert a1.visible?(User.find(2))
232 238 a2 = Attachment.find(17)
233 239 assert_equal "testfile.PNG", a2.filename
234 240 assert a2.readable?
235 241 assert (! a2.visible?(User.anonymous))
236 242 assert a2.visible?(User.find(2))
237 243 assert a1.created_on < a2.created_on
238 244
239 245 to_test = {
240 246 'Inline image: !testfile.png!' =>
241 247 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
242 248 'Inline image: !Testfile.PNG!' =>
243 249 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
244 250 }
245 251 attachments = [a1, a2]
246 252 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
247 253 set_tmp_attachments_directory
248 254 end
249 255
250 256 def test_textile_external_links
251 257 to_test = {
252 258 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
253 259 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
254 260 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
255 261 '"link (Link title with "double-quotes")":http://foo.bar' => '<a href="http://foo.bar" title="Link title with &quot;double-quotes&quot;" class="external">link</a>',
256 262 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
257 263 # no multiline link text
258 264 "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line<br />and another on a second line\":test",
259 265 # mailto link
260 266 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
261 267 # two exclamation marks
262 268 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
263 269 # escaping
264 270 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
265 271 }
266 272 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
267 273 end
268 274
269 275 def test_textile_external_links_with_non_ascii_characters
270 276 to_test = {
271 277 %|This is a "link":http://foo.bar/#{@russian_test}| =>
272 278 %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
273 279 }
274 280 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
275 281 end
276 282
277 283 def test_redmine_links
278 284 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
279 285 :class => Issue.find(3).css_classes, :title => 'Bug: Error 281 when updating a recipe (New)')
280 286 note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
281 287 :class => Issue.find(3).css_classes, :title => 'Bug: Error 281 when updating a recipe (New)')
282 288 note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
283 289 :class => Issue.find(3).css_classes, :title => 'Bug: Error 281 when updating a recipe (New)')
284 290
285 291 revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
286 292 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
287 293 revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
288 294 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
289 295
290 296 changeset_link2 = link_to('691322a8eb01e11fd7',
291 297 {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
292 298 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
293 299
294 300 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
295 301 :class => 'document')
296 302
297 303 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
298 304 :class => 'version')
299 305
300 306 board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
301 307
302 308 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
303 309
304 310 news_url = {:controller => 'news', :action => 'show', :id => 1}
305 311
306 312 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
307 313
308 314 source_url = '/projects/ecookbook/repository/entry/some/file'
309 315 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
310 316 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
311 317 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
312 318 source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
313 319
314 320 export_url = '/projects/ecookbook/repository/raw/some/file'
315 321 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
316 322 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
317 323 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
318 324 export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
319 325
320 326 to_test = {
321 327 # tickets
322 328 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
323 329 # ticket notes
324 330 '#3-14' => note_link,
325 331 '#3#note-14' => note_link2,
326 332 # should not ignore leading zero
327 333 '#03' => '#03',
328 334 # changesets
329 335 'r1' => revision_link,
330 336 'r1.' => "#{revision_link}.",
331 337 'r1, r2' => "#{revision_link}, #{revision_link2}",
332 338 'r1,r2' => "#{revision_link},#{revision_link2}",
333 339 'commit:691322a8eb01e11fd7' => changeset_link2,
334 340 # documents
335 341 'document#1' => document_link,
336 342 'document:"Test document"' => document_link,
337 343 # versions
338 344 'version#2' => version_link,
339 345 'version:1.0' => version_link,
340 346 'version:"1.0"' => version_link,
341 347 # source
342 348 'source:some/file' => link_to('source:some/file', source_url, :class => 'source'),
343 349 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
344 350 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
345 351 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
346 352 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
347 353 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
348 354 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
349 355 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
350 356 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
351 357 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
352 358 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
353 359 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
354 360 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
355 361 # export
356 362 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
357 363 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
358 364 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
359 365 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
360 366 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
361 367 # forum
362 368 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
363 369 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
364 370 # message
365 371 'message#4' => link_to('Post 2', message_url, :class => 'message'),
366 372 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
367 373 # news
368 374 'news#1' => link_to('eCookbook first release !', news_url, :class => 'news'),
369 375 'news:"eCookbook first release !"' => link_to('eCookbook first release !', news_url, :class => 'news'),
370 376 # project
371 377 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
372 378 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
373 379 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
374 380 # not found
375 381 '#0123456789' => '#0123456789',
376 382 # invalid expressions
377 383 'source:' => 'source:',
378 384 # url hash
379 385 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
380 386 }
381 387 @project = Project.find(1)
382 388 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
383 389 end
384 390
385 391 def test_should_not_parse_redmine_links_inside_link
386 392 raw = "r1 should not be parsed in http://example.com/url-r1/"
387 393 assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
388 394 textilizable(raw, :project => Project.find(1))
389 395 end
390 396
391 397 def test_redmine_links_with_a_different_project_before_current_project
392 398 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
393 399 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
394 400 @project = Project.find(3)
395 401 result1 = link_to("1.4.4", "/versions/#{vp1.id}", :class => "version")
396 402 result2 = link_to("1.4.4", "/versions/#{vp3.id}", :class => "version")
397 403 assert_equal "<p>#{result1} #{result2}</p>",
398 404 textilizable("ecookbook:version:1.4.4 version:1.4.4")
399 405 end
400 406
401 407 def test_escaped_redmine_links_should_not_be_parsed
402 408 to_test = [
403 409 '#3.',
404 410 '#3-14.',
405 411 '#3#-note14.',
406 412 'r1',
407 413 'document#1',
408 414 'document:"Test document"',
409 415 'version#2',
410 416 'version:1.0',
411 417 'version:"1.0"',
412 418 'source:/some/file'
413 419 ]
414 420 @project = Project.find(1)
415 421 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
416 422 end
417 423
418 424 def test_cross_project_redmine_links
419 425 source_link = link_to('ecookbook:source:/some/file',
420 426 {:controller => 'repositories', :action => 'entry',
421 427 :id => 'ecookbook', :path => ['some', 'file']},
422 428 :class => 'source')
423 429 changeset_link = link_to('ecookbook:r2',
424 430 {:controller => 'repositories', :action => 'revision',
425 431 :id => 'ecookbook', :rev => 2},
426 432 :class => 'changeset',
427 433 :title => 'This commit fixes #1, #2 and references #1 & #3')
428 434 to_test = {
429 435 # documents
430 436 'document:"Test document"' => 'document:"Test document"',
431 437 'ecookbook:document:"Test document"' =>
432 438 link_to("Test document", "/documents/1", :class => "document"),
433 439 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
434 440 # versions
435 441 'version:"1.0"' => 'version:"1.0"',
436 442 'ecookbook:version:"1.0"' =>
437 443 link_to("1.0", "/versions/2", :class => "version"),
438 444 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
439 445 # changeset
440 446 'r2' => 'r2',
441 447 'ecookbook:r2' => changeset_link,
442 448 'invalid:r2' => 'invalid:r2',
443 449 # source
444 450 'source:/some/file' => 'source:/some/file',
445 451 'ecookbook:source:/some/file' => source_link,
446 452 'invalid:source:/some/file' => 'invalid:source:/some/file',
447 453 }
448 454 @project = Project.find(3)
449 455 to_test.each do |text, result|
450 456 assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed"
451 457 end
452 458 end
453 459
454 460 def test_redmine_links_by_name_should_work_with_html_escaped_characters
455 461 v = Version.generate!(:name => "Test & Show.txt", :project_id => 1)
456 462 link = link_to("Test & Show.txt", "/versions/#{v.id}", :class => "version")
457 463
458 464 @project = v.project
459 465 assert_equal "<p>#{link}</p>", textilizable('version:"Test & Show.txt"')
460 466 end
461 467
462 468 def test_link_to_issue_subject
463 469 issue = Issue.generate!(:subject => "01234567890123456789")
464 470 str = link_to_issue(issue, :truncate => 10)
465 471 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
466 472 assert_equal "#{result}: 0123456...", str
467 473
468 474 issue = Issue.generate!(:subject => "<&>")
469 475 str = link_to_issue(issue)
470 476 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
471 477 assert_equal "#{result}: &lt;&amp;&gt;", str
472 478
473 479 issue = Issue.generate!(:subject => "<&>0123456789012345")
474 480 str = link_to_issue(issue, :truncate => 10)
475 481 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
476 482 assert_equal "#{result}: &lt;&amp;&gt;0123...", str
477 483 end
478 484
479 485 def test_link_to_issue_title
480 486 long_str = "0123456789" * 5
481 487
482 488 issue = Issue.generate!(:subject => "#{long_str}01234567890123456789")
483 489 str = link_to_issue(issue, :subject => false)
484 490 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
485 491 :class => issue.css_classes,
486 492 :title => "#{long_str}0123456...")
487 493 assert_equal result, str
488 494
489 495 issue = Issue.generate!(:subject => "<&>#{long_str}01234567890123456789")
490 496 str = link_to_issue(issue, :subject => false)
491 497 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
492 498 :class => issue.css_classes,
493 499 :title => "<&>#{long_str}0123...")
494 500 assert_equal result, str
495 501 end
496 502
497 503 def test_multiple_repositories_redmine_links
498 504 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
499 505 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
500 506 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
501 507 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
502 508
503 509 changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
504 510 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
505 511 svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
506 512 :class => 'changeset', :title => '')
507 513 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
508 514 :class => 'changeset', :title => '')
509 515
510 516 source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
511 517 hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
512 518
513 519 to_test = {
514 520 'r2' => changeset_link,
515 521 'svn_repo-1|r123' => svn_changeset_link,
516 522 'invalid|r123' => 'invalid|r123',
517 523 'commit:hg1|abcd' => hg_changeset_link,
518 524 'commit:invalid|abcd' => 'commit:invalid|abcd',
519 525 # source
520 526 'source:some/file' => source_link,
521 527 'source:hg1|some/file' => hg_source_link,
522 528 'source:invalid|some/file' => 'source:invalid|some/file',
523 529 }
524 530
525 531 @project = Project.find(1)
526 532 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
527 533 end
528 534
529 535 def test_cross_project_multiple_repositories_redmine_links
530 536 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
531 537 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
532 538 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
533 539 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
534 540
535 541 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
536 542 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
537 543 svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
538 544 :class => 'changeset', :title => '')
539 545 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
540 546 :class => 'changeset', :title => '')
541 547
542 548 source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
543 549 hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
544 550
545 551 to_test = {
546 552 'ecookbook:r2' => changeset_link,
547 553 'ecookbook:svn1|r123' => svn_changeset_link,
548 554 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
549 555 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
550 556 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
551 557 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
552 558 # source
553 559 'ecookbook:source:some/file' => source_link,
554 560 'ecookbook:source:hg1|some/file' => hg_source_link,
555 561 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
556 562 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
557 563 }
558 564
559 565 @project = Project.find(3)
560 566 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
561 567 end
562 568
563 569 def test_redmine_links_git_commit
564 570 changeset_link = link_to('abcd',
565 571 {
566 572 :controller => 'repositories',
567 573 :action => 'revision',
568 574 :id => 'subproject1',
569 575 :rev => 'abcd',
570 576 },
571 577 :class => 'changeset', :title => 'test commit')
572 578 to_test = {
573 579 'commit:abcd' => changeset_link,
574 580 }
575 581 @project = Project.find(3)
576 582 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
577 583 assert r
578 584 c = Changeset.new(:repository => r,
579 585 :committed_on => Time.now,
580 586 :revision => 'abcd',
581 587 :scmid => 'abcd',
582 588 :comments => 'test commit')
583 589 assert( c.save )
584 590 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
585 591 end
586 592
587 593 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
588 594 def test_redmine_links_darcs_commit
589 595 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
590 596 {
591 597 :controller => 'repositories',
592 598 :action => 'revision',
593 599 :id => 'subproject1',
594 600 :rev => '123',
595 601 },
596 602 :class => 'changeset', :title => 'test commit')
597 603 to_test = {
598 604 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
599 605 }
600 606 @project = Project.find(3)
601 607 r = Repository::Darcs.create!(
602 608 :project => @project, :url => '/tmp/test/darcs',
603 609 :log_encoding => 'UTF-8')
604 610 assert r
605 611 c = Changeset.new(:repository => r,
606 612 :committed_on => Time.now,
607 613 :revision => '123',
608 614 :scmid => '20080308225258-98289-abcd456efg.gz',
609 615 :comments => 'test commit')
610 616 assert( c.save )
611 617 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
612 618 end
613 619
614 620 def test_redmine_links_mercurial_commit
615 621 changeset_link_rev = link_to('r123',
616 622 {
617 623 :controller => 'repositories',
618 624 :action => 'revision',
619 625 :id => 'subproject1',
620 626 :rev => '123' ,
621 627 },
622 628 :class => 'changeset', :title => 'test commit')
623 629 changeset_link_commit = link_to('abcd',
624 630 {
625 631 :controller => 'repositories',
626 632 :action => 'revision',
627 633 :id => 'subproject1',
628 634 :rev => 'abcd' ,
629 635 },
630 636 :class => 'changeset', :title => 'test commit')
631 637 to_test = {
632 638 'r123' => changeset_link_rev,
633 639 'commit:abcd' => changeset_link_commit,
634 640 }
635 641 @project = Project.find(3)
636 642 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
637 643 assert r
638 644 c = Changeset.new(:repository => r,
639 645 :committed_on => Time.now,
640 646 :revision => '123',
641 647 :scmid => 'abcd',
642 648 :comments => 'test commit')
643 649 assert( c.save )
644 650 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
645 651 end
646 652
647 653 def test_attachment_links
648 654 text = 'attachment:error281.txt'
649 655 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
650 656 :class => "attachment")
651 657 assert_equal "<p>#{result}</p>",
652 658 textilizable(text,
653 659 :attachments => Issue.find(3).attachments),
654 660 "#{text} failed"
655 661 end
656 662
657 663 def test_attachment_link_should_link_to_latest_attachment
658 664 set_tmp_attachments_directory
659 665 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
660 666 a2 = Attachment.generate!(:filename => "test.txt")
661 667 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
662 668 :class => "attachment")
663 669 assert_equal "<p>#{result}</p>",
664 670 textilizable('attachment:test.txt', :attachments => [a1, a2])
665 671 end
666 672
667 673 def test_wiki_links
668 674 User.current = User.find_by_login('jsmith')
669 675 russian_eacape = CGI.escape(@russian_test)
670 676 to_test = {
671 677 '[[CookBook documentation]]' =>
672 678 link_to("CookBook documentation",
673 679 "/projects/ecookbook/wiki/CookBook_documentation",
674 680 :class => "wiki-page"),
675 681 '[[Another page|Page]]' =>
676 682 link_to("Page",
677 683 "/projects/ecookbook/wiki/Another_page",
678 684 :class => "wiki-page"),
679 685 # title content should be formatted
680 686 '[[Another page|With _styled_ *title*]]' =>
681 687 link_to("With <em>styled</em> <strong>title</strong>".html_safe,
682 688 "/projects/ecookbook/wiki/Another_page",
683 689 :class => "wiki-page"),
684 690 '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' =>
685 691 link_to("With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;".html_safe,
686 692 "/projects/ecookbook/wiki/Another_page",
687 693 :class => "wiki-page"),
688 694 # link with anchor
689 695 '[[CookBook documentation#One-section]]' =>
690 696 link_to("CookBook documentation",
691 697 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
692 698 :class => "wiki-page"),
693 699 '[[Another page#anchor|Page]]' =>
694 700 link_to("Page",
695 701 "/projects/ecookbook/wiki/Another_page#anchor",
696 702 :class => "wiki-page"),
697 703 # UTF8 anchor
698 704 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
699 705 link_to(@russian_test,
700 706 "/projects/ecookbook/wiki/Another_page##{russian_eacape}",
701 707 :class => "wiki-page"),
702 708 # page that doesn't exist
703 709 '[[Unknown page]]' =>
704 710 link_to("Unknown page",
705 711 "/projects/ecookbook/wiki/Unknown_page",
706 712 :class => "wiki-page new"),
707 713 '[[Unknown page|404]]' =>
708 714 link_to("404",
709 715 "/projects/ecookbook/wiki/Unknown_page",
710 716 :class => "wiki-page new"),
711 717 # link to another project wiki
712 718 '[[onlinestore:]]' =>
713 719 link_to("onlinestore",
714 720 "/projects/onlinestore/wiki",
715 721 :class => "wiki-page"),
716 722 '[[onlinestore:|Wiki]]' =>
717 723 link_to("Wiki",
718 724 "/projects/onlinestore/wiki",
719 725 :class => "wiki-page"),
720 726 '[[onlinestore:Start page]]' =>
721 727 link_to("Start page",
722 728 "/projects/onlinestore/wiki/Start_page",
723 729 :class => "wiki-page"),
724 730 '[[onlinestore:Start page|Text]]' =>
725 731 link_to("Text",
726 732 "/projects/onlinestore/wiki/Start_page",
727 733 :class => "wiki-page"),
728 734 '[[onlinestore:Unknown page]]' =>
729 735 link_to("Unknown page",
730 736 "/projects/onlinestore/wiki/Unknown_page",
731 737 :class => "wiki-page new"),
732 738 # struck through link
733 739 '-[[Another page|Page]]-' =>
734 740 "<del>".html_safe +
735 741 link_to("Page",
736 742 "/projects/ecookbook/wiki/Another_page",
737 743 :class => "wiki-page").html_safe +
738 744 "</del>".html_safe,
739 745 '-[[Another page|Page]] link-' =>
740 746 "<del>".html_safe +
741 747 link_to("Page",
742 748 "/projects/ecookbook/wiki/Another_page",
743 749 :class => "wiki-page").html_safe +
744 750 " link</del>".html_safe,
745 751 # escaping
746 752 '![[Another page|Page]]' => '[[Another page|Page]]',
747 753 # project does not exist
748 754 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
749 755 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
750 756 # missing permission to view wiki in project
751 757 '[[private-child:]]' => '[[private-child:]]',
752 758 '[[private-child:Wiki]]' => '[[private-child:Wiki]]',
753 759 }
754 760 @project = Project.find(1)
755 761 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
756 762 end
757 763
758 764 def test_wiki_links_within_local_file_generation_context
759 765 to_test = {
760 766 # link to a page
761 767 '[[CookBook documentation]]' =>
762 768 link_to("CookBook documentation", "CookBook_documentation.html",
763 769 :class => "wiki-page"),
764 770 '[[CookBook documentation|documentation]]' =>
765 771 link_to("documentation", "CookBook_documentation.html",
766 772 :class => "wiki-page"),
767 773 '[[CookBook documentation#One-section]]' =>
768 774 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
769 775 :class => "wiki-page"),
770 776 '[[CookBook documentation#One-section|documentation]]' =>
771 777 link_to("documentation", "CookBook_documentation.html#One-section",
772 778 :class => "wiki-page"),
773 779 # page that doesn't exist
774 780 '[[Unknown page]]' =>
775 781 link_to("Unknown page", "Unknown_page.html",
776 782 :class => "wiki-page new"),
777 783 '[[Unknown page|404]]' =>
778 784 link_to("404", "Unknown_page.html",
779 785 :class => "wiki-page new"),
780 786 '[[Unknown page#anchor]]' =>
781 787 link_to("Unknown page", "Unknown_page.html#anchor",
782 788 :class => "wiki-page new"),
783 789 '[[Unknown page#anchor|404]]' =>
784 790 link_to("404", "Unknown_page.html#anchor",
785 791 :class => "wiki-page new"),
786 792 }
787 793 @project = Project.find(1)
788 794 to_test.each do |text, result|
789 795 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
790 796 end
791 797 end
792 798
793 799 def test_wiki_links_within_wiki_page_context
794 800 page = WikiPage.find_by_title('Another_page' )
795 801 to_test = {
796 802 '[[CookBook documentation]]' =>
797 803 link_to("CookBook documentation",
798 804 "/projects/ecookbook/wiki/CookBook_documentation",
799 805 :class => "wiki-page"),
800 806 '[[CookBook documentation|documentation]]' =>
801 807 link_to("documentation",
802 808 "/projects/ecookbook/wiki/CookBook_documentation",
803 809 :class => "wiki-page"),
804 810 '[[CookBook documentation#One-section]]' =>
805 811 link_to("CookBook documentation",
806 812 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
807 813 :class => "wiki-page"),
808 814 '[[CookBook documentation#One-section|documentation]]' =>
809 815 link_to("documentation",
810 816 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
811 817 :class => "wiki-page"),
812 818 # link to the current page
813 819 '[[Another page]]' =>
814 820 link_to("Another page",
815 821 "/projects/ecookbook/wiki/Another_page",
816 822 :class => "wiki-page"),
817 823 '[[Another page|Page]]' =>
818 824 link_to("Page",
819 825 "/projects/ecookbook/wiki/Another_page",
820 826 :class => "wiki-page"),
821 827 '[[Another page#anchor]]' =>
822 828 link_to("Another page",
823 829 "#anchor",
824 830 :class => "wiki-page"),
825 831 '[[Another page#anchor|Page]]' =>
826 832 link_to("Page",
827 833 "#anchor",
828 834 :class => "wiki-page"),
829 835 # page that doesn't exist
830 836 '[[Unknown page]]' =>
831 837 link_to("Unknown page",
832 838 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
833 839 :class => "wiki-page new"),
834 840 '[[Unknown page|404]]' =>
835 841 link_to("404",
836 842 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
837 843 :class => "wiki-page new"),
838 844 '[[Unknown page#anchor]]' =>
839 845 link_to("Unknown page",
840 846 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
841 847 :class => "wiki-page new"),
842 848 '[[Unknown page#anchor|404]]' =>
843 849 link_to("404",
844 850 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
845 851 :class => "wiki-page new"),
846 852 }
847 853 @project = Project.find(1)
848 854 to_test.each do |text, result|
849 855 assert_equal "<p>#{result}</p>",
850 856 textilizable(WikiContent.new( :text => text, :page => page ), :text)
851 857 end
852 858 end
853 859
854 860 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
855 861 to_test = {
856 862 # link to a page
857 863 '[[CookBook documentation]]' =>
858 864 link_to("CookBook documentation",
859 865 "#CookBook_documentation",
860 866 :class => "wiki-page"),
861 867 '[[CookBook documentation|documentation]]' =>
862 868 link_to("documentation",
863 869 "#CookBook_documentation",
864 870 :class => "wiki-page"),
865 871 '[[CookBook documentation#One-section]]' =>
866 872 link_to("CookBook documentation",
867 873 "#CookBook_documentation_One-section",
868 874 :class => "wiki-page"),
869 875 '[[CookBook documentation#One-section|documentation]]' =>
870 876 link_to("documentation",
871 877 "#CookBook_documentation_One-section",
872 878 :class => "wiki-page"),
873 879 # page that doesn't exist
874 880 '[[Unknown page]]' =>
875 881 link_to("Unknown page",
876 882 "#Unknown_page",
877 883 :class => "wiki-page new"),
878 884 '[[Unknown page|404]]' =>
879 885 link_to("404",
880 886 "#Unknown_page",
881 887 :class => "wiki-page new"),
882 888 '[[Unknown page#anchor]]' =>
883 889 link_to("Unknown page",
884 890 "#Unknown_page_anchor",
885 891 :class => "wiki-page new"),
886 892 '[[Unknown page#anchor|404]]' =>
887 893 link_to("404",
888 894 "#Unknown_page_anchor",
889 895 :class => "wiki-page new"),
890 896 }
891 897 @project = Project.find(1)
892 898 to_test.each do |text, result|
893 899 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
894 900 end
895 901 end
896 902
897 903 def test_html_tags
898 904 to_test = {
899 905 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
900 906 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
901 907 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
902 908 # do not escape pre/code tags
903 909 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
904 910 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
905 911 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
906 912 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
907 913 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
908 914 # remove attributes except class
909 915 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
910 916 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
911 917 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
912 918 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
913 919 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
914 920 # xss
915 921 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
916 922 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
917 923 }
918 924 to_test.each { |text, result| assert_equal result, textilizable(text) }
919 925 end
920 926
921 927 def test_allowed_html_tags
922 928 to_test = {
923 929 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
924 930 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
925 931 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
926 932 }
927 933 to_test.each { |text, result| assert_equal result, textilizable(text) }
928 934 end
929 935
930 936 def test_pre_tags
931 937 raw = <<-RAW
932 938 Before
933 939
934 940 <pre>
935 941 <prepared-statement-cache-size>32</prepared-statement-cache-size>
936 942 </pre>
937 943
938 944 After
939 945 RAW
940 946
941 947 expected = <<-EXPECTED
942 948 <p>Before</p>
943 949 <pre>
944 950 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
945 951 </pre>
946 952 <p>After</p>
947 953 EXPECTED
948 954
949 955 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
950 956 end
951 957
952 958 def test_pre_content_should_not_parse_wiki_and_redmine_links
953 959 raw = <<-RAW
954 960 [[CookBook documentation]]
955 961
956 962 #1
957 963
958 964 <pre>
959 965 [[CookBook documentation]]
960 966
961 967 #1
962 968 </pre>
963 969 RAW
964 970
965 971 result1 = link_to("CookBook documentation",
966 972 "/projects/ecookbook/wiki/CookBook_documentation",
967 973 :class => "wiki-page")
968 974 result2 = link_to('#1',
969 975 "/issues/1",
970 976 :class => Issue.find(1).css_classes,
971 977 :title => "Bug: Cannot print recipes (New)")
972 978
973 979 expected = <<-EXPECTED
974 980 <p>#{result1}</p>
975 981 <p>#{result2}</p>
976 982 <pre>
977 983 [[CookBook documentation]]
978 984
979 985 #1
980 986 </pre>
981 987 EXPECTED
982 988
983 989 @project = Project.find(1)
984 990 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
985 991 end
986 992
987 993 def test_non_closing_pre_blocks_should_be_closed
988 994 raw = <<-RAW
989 995 <pre><code>
990 996 RAW
991 997
992 998 expected = <<-EXPECTED
993 999 <pre><code>
994 1000 </code></pre>
995 1001 EXPECTED
996 1002
997 1003 @project = Project.find(1)
998 1004 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
999 1005 end
1000 1006
1001 1007 def test_unbalanced_closing_pre_tag_should_not_error
1002 1008 assert_nothing_raised do
1003 1009 textilizable("unbalanced</pre>")
1004 1010 end
1005 1011 end
1006 1012
1007 1013 def test_syntax_highlight
1008 1014 raw = <<-RAW
1009 1015 <pre><code class="ruby">
1010 1016 # Some ruby code here
1011 1017 </code></pre>
1012 1018 RAW
1013 1019
1014 1020 expected = <<-EXPECTED
1015 1021 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
1016 1022 </code></pre>
1017 1023 EXPECTED
1018 1024
1019 1025 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1020 1026 end
1021 1027
1022 1028 def test_to_path_param
1023 1029 assert_equal 'test1/test2', to_path_param('test1/test2')
1024 1030 assert_equal 'test1/test2', to_path_param('/test1/test2/')
1025 1031 assert_equal 'test1/test2', to_path_param('//test1/test2/')
1026 1032 assert_nil to_path_param('/')
1027 1033 end
1028 1034
1029 1035 def test_wiki_links_in_tables
1030 1036 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
1031 1037 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
1032 1038 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
1033 1039 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
1034 1040 result = "<tr><td>#{link1}</td>" +
1035 1041 "<td>#{link2}</td>" +
1036 1042 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
1037 1043 @project = Project.find(1)
1038 1044 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
1039 1045 end
1040 1046
1041 1047 def test_text_formatting
1042 1048 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
1043 1049 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
1044 1050 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
1045 1051 '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>',
1046 1052 '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',
1047 1053 }
1048 1054 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
1049 1055 end
1050 1056
1051 1057 def test_wiki_horizontal_rule
1052 1058 assert_equal '<hr />', textilizable('---')
1053 1059 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
1054 1060 end
1055 1061
1056 1062 def test_footnotes
1057 1063 raw = <<-RAW
1058 1064 This is some text[1].
1059 1065
1060 1066 fn1. This is the foot note
1061 1067 RAW
1062 1068
1063 1069 expected = <<-EXPECTED
1064 1070 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
1065 1071 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
1066 1072 EXPECTED
1067 1073
1068 1074 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1069 1075 end
1070 1076
1071 1077 def test_headings
1072 1078 raw = 'h1. Some heading'
1073 1079 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
1074 1080
1075 1081 assert_equal expected, textilizable(raw)
1076 1082 end
1077 1083
1078 1084 def test_headings_with_special_chars
1079 1085 # This test makes sure that the generated anchor names match the expected
1080 1086 # ones even if the heading text contains unconventional characters
1081 1087 raw = 'h1. Some heading related to version 0.5'
1082 1088 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
1083 1089 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
1084 1090
1085 1091 assert_equal expected, textilizable(raw)
1086 1092 end
1087 1093
1088 1094 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
1089 1095 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
1090 1096 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
1091 1097
1092 1098 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
1093 1099
1094 1100 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
1095 1101 end
1096 1102
1097 1103 def test_table_of_content
1098 1104 set_language_if_valid 'en'
1099 1105
1100 1106 raw = <<-RAW
1101 1107 {{toc}}
1102 1108
1103 1109 h1. Title
1104 1110
1105 1111 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1106 1112
1107 1113 h2. Subtitle with a [[Wiki]] link
1108 1114
1109 1115 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
1110 1116
1111 1117 h2. Subtitle with [[Wiki|another Wiki]] link
1112 1118
1113 1119 h2. Subtitle with %{color:red}red text%
1114 1120
1115 1121 <pre>
1116 1122 some code
1117 1123 </pre>
1118 1124
1119 1125 h3. Subtitle with *some* _modifiers_
1120 1126
1121 1127 h3. Subtitle with @inline code@
1122 1128
1123 1129 h1. Another title
1124 1130
1125 1131 h3. An "Internet link":http://www.redmine.org/ inside subtitle
1126 1132
1127 1133 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
1128 1134
1129 1135 RAW
1130 1136
1131 1137 expected = '<ul class="toc">' +
1132 1138 '<li><strong>Table of contents</strong></li>' +
1133 1139 '<li><a href="#Title">Title</a>' +
1134 1140 '<ul>' +
1135 1141 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
1136 1142 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
1137 1143 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
1138 1144 '<ul>' +
1139 1145 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
1140 1146 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
1141 1147 '</ul>' +
1142 1148 '</li>' +
1143 1149 '</ul>' +
1144 1150 '</li>' +
1145 1151 '<li><a href="#Another-title">Another title</a>' +
1146 1152 '<ul>' +
1147 1153 '<li>' +
1148 1154 '<ul>' +
1149 1155 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
1150 1156 '</ul>' +
1151 1157 '</li>' +
1152 1158 '<li><a href="#Project-Name">Project Name</a></li>' +
1153 1159 '</ul>' +
1154 1160 '</li>' +
1155 1161 '</ul>'
1156 1162
1157 1163 @project = Project.find(1)
1158 1164 assert textilizable(raw).gsub("\n", "").include?(expected)
1159 1165 end
1160 1166
1161 1167 def test_table_of_content_should_generate_unique_anchors
1162 1168 set_language_if_valid 'en'
1163 1169
1164 1170 raw = <<-RAW
1165 1171 {{toc}}
1166 1172
1167 1173 h1. Title
1168 1174
1169 1175 h2. Subtitle
1170 1176
1171 1177 h2. Subtitle
1172 1178 RAW
1173 1179
1174 1180 expected = '<ul class="toc">' +
1175 1181 '<li><strong>Table of contents</strong></li>' +
1176 1182 '<li><a href="#Title">Title</a>' +
1177 1183 '<ul>' +
1178 1184 '<li><a href="#Subtitle">Subtitle</a></li>' +
1179 1185 '<li><a href="#Subtitle-2">Subtitle</a></li>' +
1180 1186 '</ul>' +
1181 1187 '</li>' +
1182 1188 '</ul>'
1183 1189
1184 1190 @project = Project.find(1)
1185 1191 result = textilizable(raw).gsub("\n", "")
1186 1192 assert_include expected, result
1187 1193 assert_include '<a name="Subtitle">', result
1188 1194 assert_include '<a name="Subtitle-2">', result
1189 1195 end
1190 1196
1191 1197 def test_table_of_content_should_contain_included_page_headings
1192 1198 set_language_if_valid 'en'
1193 1199
1194 1200 raw = <<-RAW
1195 1201 {{toc}}
1196 1202
1197 1203 h1. Included
1198 1204
1199 1205 {{include(Child_1)}}
1200 1206 RAW
1201 1207
1202 1208 expected = '<ul class="toc">' +
1203 1209 '<li><strong>Table of contents</strong></li>' +
1204 1210 '<li><a href="#Included">Included</a></li>' +
1205 1211 '<li><a href="#Child-page-1">Child page 1</a></li>' +
1206 1212 '</ul>'
1207 1213
1208 1214 @project = Project.find(1)
1209 1215 assert textilizable(raw).gsub("\n", "").include?(expected)
1210 1216 end
1211 1217
1212 1218 def test_toc_with_textile_formatting_should_be_parsed
1213 1219 with_settings :text_formatting => 'textile' do
1214 1220 assert_select_in textilizable("{{toc}}\n\nh1. Heading"), 'ul.toc li', :text => 'Heading'
1215 1221 assert_select_in textilizable("{{<toc}}\n\nh1. Heading"), 'ul.toc.left li', :text => 'Heading'
1216 1222 assert_select_in textilizable("{{>toc}}\n\nh1. Heading"), 'ul.toc.right li', :text => 'Heading'
1217 1223 end
1218 1224 end
1219 1225
1220 1226 if Object.const_defined?(:Redcarpet)
1221 1227 def test_toc_with_markdown_formatting_should_be_parsed
1222 1228 with_settings :text_formatting => 'markdown' do
1223 1229 assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
1224 1230 assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
1225 1231 assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
1226 1232 end
1227 1233 end
1228 1234 end
1229 1235
1230 1236 def test_section_edit_links
1231 1237 raw = <<-RAW
1232 1238 h1. Title
1233 1239
1234 1240 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1235 1241
1236 1242 h2. Subtitle with a [[Wiki]] link
1237 1243
1238 1244 h2. Subtitle with *some* _modifiers_
1239 1245
1240 1246 h2. Subtitle with @inline code@
1241 1247
1242 1248 <pre>
1243 1249 some code
1244 1250
1245 1251 h2. heading inside pre
1246 1252
1247 1253 <h2>html heading inside pre</h2>
1248 1254 </pre>
1249 1255
1250 1256 h2. Subtitle after pre tag
1251 1257 RAW
1252 1258
1253 1259 @project = Project.find(1)
1254 1260 set_language_if_valid 'en'
1255 1261 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1256 1262
1257 1263 # heading that contains inline code
1258 1264 assert_match Regexp.new('<div class="contextual heading-2" title="Edit this section" id="section-4">' +
1259 1265 '<a class="icon-only icon-edit" href="/projects/1/wiki/Test/edit\?section=4">Edit this section</a></div>' +
1260 1266 '<a name="Subtitle-with-inline-code"></a>' +
1261 1267 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1262 1268 result
1263 1269
1264 1270 # last heading
1265 1271 assert_match Regexp.new('<div class="contextual heading-2" title="Edit this section" id="section-5">' +
1266 1272 '<a class="icon-only icon-edit" href="/projects/1/wiki/Test/edit\?section=5">Edit this section</a></div>' +
1267 1273 '<a name="Subtitle-after-pre-tag"></a>' +
1268 1274 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1269 1275 result
1270 1276 end
1271 1277
1272 1278 def test_default_formatter
1273 1279 with_settings :text_formatting => 'unknown' do
1274 1280 text = 'a *link*: http://www.example.net/'
1275 1281 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1276 1282 end
1277 1283 end
1278 1284
1279 1285 def test_parse_redmine_links_should_handle_a_tag_without_attributes
1280 1286 text = '<a>http://example.com</a>'
1281 1287 expected = text.dup
1282 1288 parse_redmine_links(text, nil, nil, nil, true, {})
1283 1289 assert_equal expected, text
1284 1290 end
1285 1291
1286 1292 def test_due_date_distance_in_words
1287 1293 to_test = { Date.today => 'Due in 0 days',
1288 1294 Date.today + 1 => 'Due in 1 day',
1289 1295 Date.today + 100 => 'Due in about 3 months',
1290 1296 Date.today + 20000 => 'Due in over 54 years',
1291 1297 Date.today - 1 => '1 day late',
1292 1298 Date.today - 100 => 'about 3 months late',
1293 1299 Date.today - 20000 => 'over 54 years late',
1294 1300 }
1295 1301 ::I18n.locale = :en
1296 1302 to_test.each do |date, expected|
1297 1303 assert_equal expected, due_date_distance_in_words(date)
1298 1304 end
1299 1305 end
1300 1306
1301 1307 def test_avatar_enabled
1302 1308 with_settings :gravatar_enabled => '1' do
1303 1309 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1304 1310 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1305 1311 # Default size is 50
1306 1312 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1307 1313 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1308 1314 # Non-avatar options should be considered html options
1309 1315 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1310 1316 # The default class of the img tag should be gravatar
1311 1317 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1312 1318 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1313 1319 assert_nil avatar('jsmith')
1314 1320 assert_nil avatar(nil)
1315 1321 end
1316 1322 end
1317 1323
1318 1324 def test_avatar_disabled
1319 1325 with_settings :gravatar_enabled => '0' do
1320 1326 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1321 1327 end
1322 1328 end
1323 1329
1324 1330 def test_link_to_user
1325 1331 user = User.find(2)
1326 1332 result = link_to("John Smith", "/users/2", :class => "user active")
1327 1333 assert_equal result, link_to_user(user)
1328 1334 end
1329 1335
1330 1336 def test_link_to_user_should_not_link_to_locked_user
1331 1337 with_current_user nil do
1332 1338 user = User.find(5)
1333 1339 assert user.locked?
1334 1340 assert_equal 'Dave2 Lopper2', link_to_user(user)
1335 1341 end
1336 1342 end
1337 1343
1338 1344 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1339 1345 with_current_user User.find(1) do
1340 1346 user = User.find(5)
1341 1347 assert user.locked?
1342 1348 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1343 1349 assert_equal result, link_to_user(user)
1344 1350 end
1345 1351 end
1346 1352
1347 1353 def test_link_to_user_should_not_link_to_anonymous
1348 1354 user = User.anonymous
1349 1355 assert user.anonymous?
1350 1356 t = link_to_user(user)
1351 1357 assert_equal ::I18n.t(:label_user_anonymous), t
1352 1358 end
1353 1359
1354 1360 def test_link_to_attachment
1355 1361 a = Attachment.find(3)
1356 1362 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1357 1363 link_to_attachment(a)
1358 1364 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1359 1365 link_to_attachment(a, :text => 'Text')
1360 1366 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1361 1367 assert_equal result,
1362 1368 link_to_attachment(a, :class => 'foo')
1363 1369 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1364 1370 link_to_attachment(a, :download => true)
1365 1371 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1366 1372 link_to_attachment(a, :only_path => false)
1367 1373 end
1368 1374
1369 1375 def test_thumbnail_tag
1370 1376 a = Attachment.find(3)
1371 1377 assert_select_in thumbnail_tag(a),
1372 1378 'a[href=?][title=?] img[alt="3"][src=?]',
1373 1379 "/attachments/3/logo.gif", "logo.gif", "/attachments/thumbnail/3"
1374 1380 end
1375 1381
1376 1382 def test_link_to_project
1377 1383 project = Project.find(1)
1378 1384 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1379 1385 link_to_project(project)
1380 1386 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1381 1387 link_to_project(project, {:only_path => false, :jump => 'blah'})
1382 1388 end
1383 1389
1384 1390 def test_link_to_project_settings
1385 1391 project = Project.find(1)
1386 1392 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1387 1393
1388 1394 project.status = Project::STATUS_CLOSED
1389 1395 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1390 1396
1391 1397 project.status = Project::STATUS_ARCHIVED
1392 1398 assert_equal 'eCookbook', link_to_project_settings(project)
1393 1399 end
1394 1400
1395 1401 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1396 1402 # numeric identifier are no longer allowed
1397 1403 Project.where(:id => 1).update_all(:identifier => 25)
1398 1404 assert_equal '<a href="/projects/1">eCookbook</a>',
1399 1405 link_to_project(Project.find(1))
1400 1406 end
1401 1407
1402 1408 def test_principals_options_for_select_with_users
1403 1409 User.current = nil
1404 1410 users = [User.find(2), User.find(4)]
1405 1411 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1406 1412 principals_options_for_select(users)
1407 1413 end
1408 1414
1409 1415 def test_principals_options_for_select_with_selected
1410 1416 User.current = nil
1411 1417 users = [User.find(2), User.find(4)]
1412 1418 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1413 1419 principals_options_for_select(users, User.find(4))
1414 1420 end
1415 1421
1416 1422 def test_principals_options_for_select_with_users_and_groups
1417 1423 User.current = nil
1418 1424 set_language_if_valid 'en'
1419 1425 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1420 1426 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1421 1427 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1422 1428 principals_options_for_select(users)
1423 1429 end
1424 1430
1425 1431 def test_principals_options_for_select_with_empty_collection
1426 1432 assert_equal '', principals_options_for_select([])
1427 1433 end
1428 1434
1429 1435 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1430 1436 set_language_if_valid 'en'
1431 1437 users = [User.find(2), User.find(4)]
1432 1438 User.current = User.find(4)
1433 1439 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1434 1440 end
1435 1441
1436 1442 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1437 1443 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1438 1444 end
1439 1445
1440 1446 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1441 1447 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1442 1448 end
1443 1449
1444 1450 def test_image_tag_should_pick_the_default_image
1445 1451 assert_match 'src="/images/image.png"', image_tag("image.png")
1446 1452 end
1447 1453
1448 1454 def test_image_tag_should_pick_the_theme_image_if_it_exists
1449 1455 theme = Redmine::Themes.themes.last
1450 1456 theme.images << 'image.png'
1451 1457
1452 1458 with_settings :ui_theme => theme.id do
1453 1459 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1454 1460 assert_match %|src="/images/other.png"|, image_tag("other.png")
1455 1461 end
1456 1462 ensure
1457 1463 theme.images.delete 'image.png'
1458 1464 end
1459 1465
1460 1466 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1461 1467 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1462 1468 end
1463 1469
1464 1470 def test_javascript_include_tag_should_pick_the_default_javascript
1465 1471 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1466 1472 end
1467 1473
1468 1474 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1469 1475 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1470 1476 end
1471 1477
1472 1478 def test_raw_json_should_escape_closing_tags
1473 1479 s = raw_json(["<foo>bar</foo>"])
1474 1480 assert_include '\/foo', s
1475 1481 end
1476 1482
1477 1483 def test_raw_json_should_be_html_safe
1478 1484 s = raw_json(["foo"])
1479 1485 assert s.html_safe?
1480 1486 end
1481 1487
1482 1488 def test_html_title_should_app_title_if_not_set
1483 1489 assert_equal 'Redmine', html_title
1484 1490 end
1485 1491
1486 1492 def test_html_title_should_join_items
1487 1493 html_title 'Foo', 'Bar'
1488 1494 assert_equal 'Foo - Bar - Redmine', html_title
1489 1495 end
1490 1496
1491 1497 def test_html_title_should_append_current_project_name
1492 1498 @project = Project.find(1)
1493 1499 html_title 'Foo', 'Bar'
1494 1500 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1495 1501 end
1496 1502
1497 1503 def test_title_should_return_a_h2_tag
1498 1504 assert_equal '<h2>Foo</h2>', title('Foo')
1499 1505 end
1500 1506
1501 1507 def test_title_should_set_html_title
1502 1508 title('Foo')
1503 1509 assert_equal 'Foo - Redmine', html_title
1504 1510 end
1505 1511
1506 1512 def test_title_should_turn_arrays_into_links
1507 1513 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1508 1514 assert_equal 'Foo - Redmine', html_title
1509 1515 end
1510 1516
1511 1517 def test_title_should_join_items
1512 1518 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1513 1519 assert_equal 'Bar - Foo - Redmine', html_title
1514 1520 end
1515 1521
1516 1522 def test_favicon_path
1517 1523 assert_match %r{^/favicon\.ico}, favicon_path
1518 1524 end
1519 1525
1520 1526 def test_favicon_path_with_suburi
1521 1527 Redmine::Utils.relative_url_root = '/foo'
1522 1528 assert_match %r{^/foo/favicon\.ico}, favicon_path
1523 1529 ensure
1524 1530 Redmine::Utils.relative_url_root = ''
1525 1531 end
1526 1532
1527 1533 def test_favicon_url
1528 1534 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1529 1535 end
1530 1536
1531 1537 def test_favicon_url_with_suburi
1532 1538 Redmine::Utils.relative_url_root = '/foo'
1533 1539 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1534 1540 ensure
1535 1541 Redmine::Utils.relative_url_root = ''
1536 1542 end
1537 1543
1538 1544 def test_truncate_single_line
1539 1545 str = "01234"
1540 1546 result = truncate_single_line_raw("#{str}\n#{str}", 10)
1541 1547 assert_equal "01234 0...", result
1542 1548 assert !result.html_safe?
1543 1549 result = truncate_single_line_raw("#{str}<&#>\n#{str}#{str}", 16)
1544 1550 assert_equal "01234<&#> 012...", result
1545 1551 assert !result.html_safe?
1546 1552 end
1547 1553
1548 1554 def test_truncate_single_line_non_ascii
1549 1555 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
1550 1556 result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10)
1551 1557 assert_equal "#{ja} #{ja}...", result
1552 1558 assert !result.html_safe?
1553 1559 end
1554 1560
1555 1561 def test_back_url_should_remove_utf8_checkmark_from_referer
1556 1562 stubs(:request).returns(stub(:env => {'HTTP_REFERER' => "/path?utf8=\u2713&foo=bar"}))
1557 1563 assert_equal "/path?foo=bar", back_url
1558 1564 end
1559 1565
1560 1566 def test_hours_formatting
1561 1567 set_language_if_valid 'en'
1562 1568
1563 1569 with_settings :timespan_format => 'minutes' do
1564 1570 assert_equal '0:45', format_hours(0.75)
1565 1571 assert_equal '0:45 h', l_hours_short(0.75)
1566 1572 assert_equal '0:45 hour', l_hours(0.75)
1567 1573 end
1568 1574 with_settings :timespan_format => 'decimal' do
1569 1575 assert_equal '0.75', format_hours(0.75)
1570 1576 assert_equal '0.75 h', l_hours_short(0.75)
1571 1577 assert_equal '0.75 hour', l_hours(0.75)
1572 1578 end
1573 1579 end
1574 1580
1575 1581 def test_html_hours
1576 1582 assert_equal '<span class="hours hours-int">0</span><span class="hours hours-dec">:45</span>', html_hours('0:45')
1577 1583 assert_equal '<span class="hours hours-int">0</span><span class="hours hours-dec">.75</span>', html_hours('0.75')
1578 1584 end
1579 1585 end
General Comments 0
You need to be logged in to leave comments. Login now