##// END OF EJS Templates
Test failures (#13309)....
Jean-Philippe Lang -
r11282:4185a4ae3b1a
parent child
Show More
@@ -1,1208 +1,1208
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2013 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 < ActionView::TestCase
23 23 include ERB::Util
24 24 include Rails.application.routes.url_helpers
25 25
26 26 fixtures :projects, :roles, :enabled_modules, :users,
27 27 :repositories, :changesets,
28 28 :trackers, :issue_statuses, :issues, :versions, :documents,
29 29 :wikis, :wiki_pages, :wiki_contents,
30 30 :boards, :messages, :news,
31 31 :attachments, :enumerations
32 32
33 33 def setup
34 34 super
35 35 set_tmp_attachments_directory
36 36 end
37 37
38 38 context "#link_to_if_authorized" do
39 39 context "authorized user" do
40 40 should "be tested"
41 41 end
42 42
43 43 context "unauthorized user" do
44 44 should "be tested"
45 45 end
46 46
47 47 should "allow using the :controller and :action for the target link" do
48 48 User.current = User.find_by_login('admin')
49 49
50 50 @project = Issue.first.project # Used by helper
51 51 response = link_to_if_authorized("By controller/action",
52 52 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
53 53 assert_match /href/, response
54 54 end
55 55
56 56 end
57 57
58 58 def test_auto_links
59 59 to_test = {
60 60 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
61 61 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
62 62 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
63 63 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
64 64 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
65 65 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
66 66 '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>.',
67 67 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
68 68 '(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>)',
69 69 '(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>)',
70 70 '(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>).',
71 71 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
72 72 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
73 73 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
74 74 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
75 75 '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>',
76 76 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
77 77 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
78 78 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
79 79 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
80 80 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
81 81 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
82 82 # two exclamation marks
83 83 '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>',
84 84 # escaping
85 85 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
86 86 # wrap in angle brackets
87 87 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
88 88 # invalid urls
89 89 'http://' => 'http://',
90 90 'www.' => 'www.',
91 91 'test-www.bar.com' => 'test-www.bar.com',
92 92 }
93 93 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
94 94 end
95 95
96 96 if 'ruby'.respond_to?(:encoding)
97 97 def test_auto_links_with_non_ascii_characters
98 98 to_test = {
99 99 'http://foo.bar/тСст' => '<a class="external" href="http://foo.bar/тСст">http://foo.bar/тСст</a>'
100 100 }
101 101 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
102 102 end
103 103 else
104 104 puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
105 105 end
106 106
107 107 def test_auto_mailto
108 108 to_test = {
109 109 'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
110 110 'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
111 111 }
112 112 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
113 113 end
114 114
115 115 def test_inline_images
116 116 to_test = {
117 117 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
118 118 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
119 119 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
120 120 '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="" />',
121 121 '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" />',
122 122 '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;" />',
123 123 }
124 124 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
125 125 end
126 126
127 127 def test_inline_images_inside_tags
128 128 raw = <<-RAW
129 129 h1. !foo.png! Heading
130 130
131 131 Centered image:
132 132
133 133 p=. !bar.gif!
134 134 RAW
135 135
136 136 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
137 137 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
138 138 end
139 139
140 140 def test_attached_images
141 141 to_test = {
142 142 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
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 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
145 145 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
146 146 # link image
147 147 '!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>',
148 148 }
149 149 attachments = Attachment.all
150 150 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
151 151 end
152 152
153 153 def test_attached_images_filename_extension
154 154 set_tmp_attachments_directory
155 155 a1 = Attachment.new(
156 156 :container => Issue.find(1),
157 157 :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
158 158 :author => User.find(1))
159 159 assert a1.save
160 160 assert_equal "testtest.JPG", a1.filename
161 161 assert_equal "image/jpeg", a1.content_type
162 162 assert a1.image?
163 163
164 164 a2 = Attachment.new(
165 165 :container => Issue.find(1),
166 166 :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
167 167 :author => User.find(1))
168 168 assert a2.save
169 169 assert_equal "testtest.jpeg", a2.filename
170 170 assert_equal "image/jpeg", a2.content_type
171 171 assert a2.image?
172 172
173 173 a3 = Attachment.new(
174 174 :container => Issue.find(1),
175 175 :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
176 176 :author => User.find(1))
177 177 assert a3.save
178 178 assert_equal "testtest.JPE", a3.filename
179 179 assert_equal "image/jpeg", a3.content_type
180 180 assert a3.image?
181 181
182 182 a4 = Attachment.new(
183 183 :container => Issue.find(1),
184 184 :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
185 185 :author => User.find(1))
186 186 assert a4.save
187 187 assert_equal "Testtest.BMP", a4.filename
188 188 assert_equal "image/x-ms-bmp", a4.content_type
189 189 assert a4.image?
190 190
191 191 to_test = {
192 192 'Inline image: !testtest.jpg!' =>
193 193 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
194 194 'Inline image: !testtest.jpeg!' =>
195 195 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
196 196 'Inline image: !testtest.jpe!' =>
197 197 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
198 198 'Inline image: !testtest.bmp!' =>
199 199 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
200 200 }
201 201
202 202 attachments = [a1, a2, a3, a4]
203 203 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
204 204 end
205 205
206 206 def test_attached_images_should_read_later
207 207 set_fixtures_attachments_directory
208 208 a1 = Attachment.find(16)
209 209 assert_equal "testfile.png", a1.filename
210 210 assert a1.readable?
211 211 assert (! a1.visible?(User.anonymous))
212 212 assert a1.visible?(User.find(2))
213 213 a2 = Attachment.find(17)
214 214 assert_equal "testfile.PNG", a2.filename
215 215 assert a2.readable?
216 216 assert (! a2.visible?(User.anonymous))
217 217 assert a2.visible?(User.find(2))
218 218 assert a1.created_on < a2.created_on
219 219
220 220 to_test = {
221 221 'Inline image: !testfile.png!' =>
222 222 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
223 223 'Inline image: !Testfile.PNG!' =>
224 224 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
225 225 }
226 226 attachments = [a1, a2]
227 227 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
228 228 set_tmp_attachments_directory
229 229 end
230 230
231 231 def test_textile_external_links
232 232 to_test = {
233 233 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
234 234 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
235 235 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
236 236 '"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>',
237 237 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
238 238 # no multiline link text
239 239 "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",
240 240 # mailto link
241 241 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
242 242 # two exclamation marks
243 243 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
244 244 # escaping
245 245 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
246 246 }
247 247 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
248 248 end
249 249
250 250 if 'ruby'.respond_to?(:encoding)
251 251 def test_textile_external_links_with_non_ascii_characters
252 252 to_test = {
253 253 'This is a "link":http://foo.bar/тСст' => 'This is a <a href="http://foo.bar/тСст" class="external">link</a>'
254 254 }
255 255 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
256 256 end
257 257 else
258 258 puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
259 259 end
260 260
261 261 def test_redmine_links
262 262 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
263 :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)')
263 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
264 264 note_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
265 :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)')
265 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
266 266
267 267 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
268 268 :class => 'changeset', :title => 'My very first commit')
269 269 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
270 270 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
271 271
272 272 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
273 273 :class => 'document')
274 274
275 275 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
276 276 :class => 'version')
277 277
278 278 board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
279 279
280 280 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
281 281
282 282 news_url = {:controller => 'news', :action => 'show', :id => 1}
283 283
284 284 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
285 285
286 286 source_url = '/projects/ecookbook/repository/entry/some/file'
287 287 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
288 288 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
289 289 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
290 290 source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
291 291
292 292 export_url = '/projects/ecookbook/repository/raw/some/file'
293 293 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
294 294 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
295 295 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
296 296 export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
297 297
298 298 to_test = {
299 299 # tickets
300 300 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
301 301 # ticket notes
302 302 '#3-14' => note_link,
303 303 '#3#note-14' => note_link,
304 304 # should not ignore leading zero
305 305 '#03' => '#03',
306 306 # changesets
307 307 'r1' => changeset_link,
308 308 'r1.' => "#{changeset_link}.",
309 309 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
310 310 'r1,r2' => "#{changeset_link},#{changeset_link2}",
311 311 # documents
312 312 'document#1' => document_link,
313 313 'document:"Test document"' => document_link,
314 314 # versions
315 315 'version#2' => version_link,
316 316 'version:1.0' => version_link,
317 317 'version:"1.0"' => version_link,
318 318 # source
319 319 'source:some/file' => link_to('source:some/file', source_url, :class => 'source'),
320 320 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
321 321 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
322 322 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
323 323 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
324 324 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
325 325 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
326 326 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
327 327 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
328 328 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
329 329 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
330 330 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
331 331 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
332 332 # export
333 333 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
334 334 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
335 335 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
336 336 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
337 337 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
338 338 # forum
339 339 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
340 340 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
341 341 # message
342 342 'message#4' => link_to('Post 2', message_url, :class => 'message'),
343 343 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
344 344 # news
345 345 'news#1' => link_to('eCookbook first release !', news_url, :class => 'news'),
346 346 'news:"eCookbook first release !"' => link_to('eCookbook first release !', news_url, :class => 'news'),
347 347 # project
348 348 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
349 349 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
350 350 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
351 351 # not found
352 352 '#0123456789' => '#0123456789',
353 353 # invalid expressions
354 354 'source:' => 'source:',
355 355 # url hash
356 356 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
357 357 }
358 358 @project = Project.find(1)
359 359 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
360 360 end
361 361
362 362 def test_redmine_links_with_a_different_project_before_current_project
363 363 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
364 364 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
365 365
366 366 @project = Project.find(3)
367 367 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>),
368 368 textilizable("ecookbook:version:1.4.4 version:1.4.4")
369 369 end
370 370
371 371 def test_escaped_redmine_links_should_not_be_parsed
372 372 to_test = [
373 373 '#3.',
374 374 '#3-14.',
375 375 '#3#-note14.',
376 376 'r1',
377 377 'document#1',
378 378 'document:"Test document"',
379 379 'version#2',
380 380 'version:1.0',
381 381 'version:"1.0"',
382 382 'source:/some/file'
383 383 ]
384 384 @project = Project.find(1)
385 385 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
386 386 end
387 387
388 388 def test_cross_project_redmine_links
389 389 source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
390 390 :class => 'source')
391 391
392 392 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
393 393 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
394 394
395 395 to_test = {
396 396 # documents
397 397 'document:"Test document"' => 'document:"Test document"',
398 398 'ecookbook:document:"Test document"' => '<a href="/documents/1" class="document">Test document</a>',
399 399 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
400 400 # versions
401 401 'version:"1.0"' => 'version:"1.0"',
402 402 'ecookbook:version:"1.0"' => '<a href="/versions/2" class="version">1.0</a>',
403 403 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
404 404 # changeset
405 405 'r2' => 'r2',
406 406 'ecookbook:r2' => changeset_link,
407 407 'invalid:r2' => 'invalid:r2',
408 408 # source
409 409 'source:/some/file' => 'source:/some/file',
410 410 'ecookbook:source:/some/file' => source_link,
411 411 'invalid:source:/some/file' => 'invalid:source:/some/file',
412 412 }
413 413 @project = Project.find(3)
414 414 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
415 415 end
416 416
417 417 def test_multiple_repositories_redmine_links
418 418 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
419 419 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
420 420 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
421 421 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
422 422
423 423 changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
424 424 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
425 425 svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
426 426 :class => 'changeset', :title => '')
427 427 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
428 428 :class => 'changeset', :title => '')
429 429
430 430 source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
431 431 hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
432 432
433 433 to_test = {
434 434 'r2' => changeset_link,
435 435 'svn_repo-1|r123' => svn_changeset_link,
436 436 'invalid|r123' => 'invalid|r123',
437 437 'commit:hg1|abcd' => hg_changeset_link,
438 438 'commit:invalid|abcd' => 'commit:invalid|abcd',
439 439 # source
440 440 'source:some/file' => source_link,
441 441 'source:hg1|some/file' => hg_source_link,
442 442 'source:invalid|some/file' => 'source:invalid|some/file',
443 443 }
444 444
445 445 @project = Project.find(1)
446 446 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
447 447 end
448 448
449 449 def test_cross_project_multiple_repositories_redmine_links
450 450 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
451 451 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
452 452 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
453 453 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
454 454
455 455 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
456 456 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
457 457 svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
458 458 :class => 'changeset', :title => '')
459 459 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
460 460 :class => 'changeset', :title => '')
461 461
462 462 source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
463 463 hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
464 464
465 465 to_test = {
466 466 'ecookbook:r2' => changeset_link,
467 467 'ecookbook:svn1|r123' => svn_changeset_link,
468 468 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
469 469 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
470 470 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
471 471 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
472 472 # source
473 473 'ecookbook:source:some/file' => source_link,
474 474 'ecookbook:source:hg1|some/file' => hg_source_link,
475 475 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
476 476 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
477 477 }
478 478
479 479 @project = Project.find(3)
480 480 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
481 481 end
482 482
483 483 def test_redmine_links_git_commit
484 484 changeset_link = link_to('abcd',
485 485 {
486 486 :controller => 'repositories',
487 487 :action => 'revision',
488 488 :id => 'subproject1',
489 489 :rev => 'abcd',
490 490 },
491 491 :class => 'changeset', :title => 'test commit')
492 492 to_test = {
493 493 'commit:abcd' => changeset_link,
494 494 }
495 495 @project = Project.find(3)
496 496 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
497 497 assert r
498 498 c = Changeset.new(:repository => r,
499 499 :committed_on => Time.now,
500 500 :revision => 'abcd',
501 501 :scmid => 'abcd',
502 502 :comments => 'test commit')
503 503 assert( c.save )
504 504 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
505 505 end
506 506
507 507 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
508 508 def test_redmine_links_darcs_commit
509 509 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
510 510 {
511 511 :controller => 'repositories',
512 512 :action => 'revision',
513 513 :id => 'subproject1',
514 514 :rev => '123',
515 515 },
516 516 :class => 'changeset', :title => 'test commit')
517 517 to_test = {
518 518 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
519 519 }
520 520 @project = Project.find(3)
521 521 r = Repository::Darcs.create!(
522 522 :project => @project, :url => '/tmp/test/darcs',
523 523 :log_encoding => 'UTF-8')
524 524 assert r
525 525 c = Changeset.new(:repository => r,
526 526 :committed_on => Time.now,
527 527 :revision => '123',
528 528 :scmid => '20080308225258-98289-abcd456efg.gz',
529 529 :comments => 'test commit')
530 530 assert( c.save )
531 531 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
532 532 end
533 533
534 534 def test_redmine_links_mercurial_commit
535 535 changeset_link_rev = link_to('r123',
536 536 {
537 537 :controller => 'repositories',
538 538 :action => 'revision',
539 539 :id => 'subproject1',
540 540 :rev => '123' ,
541 541 },
542 542 :class => 'changeset', :title => 'test commit')
543 543 changeset_link_commit = link_to('abcd',
544 544 {
545 545 :controller => 'repositories',
546 546 :action => 'revision',
547 547 :id => 'subproject1',
548 548 :rev => 'abcd' ,
549 549 },
550 550 :class => 'changeset', :title => 'test commit')
551 551 to_test = {
552 552 'r123' => changeset_link_rev,
553 553 'commit:abcd' => changeset_link_commit,
554 554 }
555 555 @project = Project.find(3)
556 556 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
557 557 assert r
558 558 c = Changeset.new(:repository => r,
559 559 :committed_on => Time.now,
560 560 :revision => '123',
561 561 :scmid => 'abcd',
562 562 :comments => 'test commit')
563 563 assert( c.save )
564 564 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
565 565 end
566 566
567 567 def test_attachment_links
568 568 to_test = {
569 569 'attachment:error281.txt' => '<a href="/attachments/download/1/error281.txt" class="attachment">error281.txt</a>'
570 570 }
571 571 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
572 572 end
573 573
574 574 def test_attachment_link_should_link_to_latest_attachment
575 575 set_tmp_attachments_directory
576 576 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
577 577 a2 = Attachment.generate!(:filename => "test.txt")
578 578
579 579 assert_equal %(<p><a href="/attachments/download/#{a2.id}/test.txt" class="attachment">test.txt</a></p>),
580 580 textilizable('attachment:test.txt', :attachments => [a1, a2])
581 581 end
582 582
583 583 def test_wiki_links
584 584 to_test = {
585 585 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
586 586 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
587 587 # title content should be formatted
588 588 '[[Another page|With _styled_ *title*]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With <em>styled</em> <strong>title</strong></a>',
589 589 '[[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>',
590 590 # link with anchor
591 591 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
592 592 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
593 593 # UTF8 anchor
594 594 '[[Another_page#ВСст|ВСст]]' => %|<a href="/projects/ecookbook/wiki/Another_page##{CGI.escape 'ВСст'}" class="wiki-page">ВСст</a>|,
595 595 # page that doesn't exist
596 596 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
597 597 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
598 598 # link to another project wiki
599 599 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
600 600 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
601 601 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
602 602 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
603 603 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
604 604 # striked through link
605 605 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
606 606 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
607 607 # escaping
608 608 '![[Another page|Page]]' => '[[Another page|Page]]',
609 609 # project does not exist
610 610 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
611 611 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
612 612 }
613 613
614 614 @project = Project.find(1)
615 615 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
616 616 end
617 617
618 618 def test_wiki_links_within_local_file_generation_context
619 619
620 620 to_test = {
621 621 # link to a page
622 622 '[[CookBook documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">CookBook documentation</a>',
623 623 '[[CookBook documentation|documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">documentation</a>',
624 624 '[[CookBook documentation#One-section]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">CookBook documentation</a>',
625 625 '[[CookBook documentation#One-section|documentation]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">documentation</a>',
626 626 # page that doesn't exist
627 627 '[[Unknown page]]' => '<a href="Unknown_page.html" class="wiki-page new">Unknown page</a>',
628 628 '[[Unknown page|404]]' => '<a href="Unknown_page.html" class="wiki-page new">404</a>',
629 629 '[[Unknown page#anchor]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">Unknown page</a>',
630 630 '[[Unknown page#anchor|404]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">404</a>',
631 631 }
632 632
633 633 @project = Project.find(1)
634 634
635 635 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local) }
636 636 end
637 637
638 638 def test_wiki_links_within_wiki_page_context
639 639
640 640 page = WikiPage.find_by_title('Another_page' )
641 641
642 642 to_test = {
643 643 # link to another page
644 644 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
645 645 '[[CookBook documentation|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">documentation</a>',
646 646 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
647 647 '[[CookBook documentation#One-section|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">documentation</a>',
648 648 # link to the current page
649 649 '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>',
650 650 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
651 651 '[[Another page#anchor]]' => '<a href="#anchor" class="wiki-page">Another page</a>',
652 652 '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>',
653 653 # page that doesn't exist
654 654 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">Unknown page</a>',
655 655 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">404</a>',
656 656 '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">Unknown page</a>',
657 657 '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">404</a>',
658 658 }
659 659
660 660 @project = Project.find(1)
661 661
662 662 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
663 663 end
664 664
665 665 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
666 666
667 667 to_test = {
668 668 # link to a page
669 669 '[[CookBook documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">CookBook documentation</a>',
670 670 '[[CookBook documentation|documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">documentation</a>',
671 671 '[[CookBook documentation#One-section]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">CookBook documentation</a>',
672 672 '[[CookBook documentation#One-section|documentation]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">documentation</a>',
673 673 # page that doesn't exist
674 674 '[[Unknown page]]' => '<a href="#Unknown_page" class="wiki-page new">Unknown page</a>',
675 675 '[[Unknown page|404]]' => '<a href="#Unknown_page" class="wiki-page new">404</a>',
676 676 '[[Unknown page#anchor]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">Unknown page</a>',
677 677 '[[Unknown page#anchor|404]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">404</a>',
678 678 }
679 679
680 680 @project = Project.find(1)
681 681
682 682 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) }
683 683 end
684 684
685 685 def test_html_tags
686 686 to_test = {
687 687 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
688 688 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
689 689 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
690 690 # do not escape pre/code tags
691 691 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
692 692 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
693 693 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
694 694 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
695 695 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
696 696 # remove attributes except class
697 697 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
698 698 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
699 699 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
700 700 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
701 701 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
702 702 # xss
703 703 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
704 704 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
705 705 }
706 706 to_test.each { |text, result| assert_equal result, textilizable(text) }
707 707 end
708 708
709 709 def test_allowed_html_tags
710 710 to_test = {
711 711 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
712 712 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
713 713 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
714 714 }
715 715 to_test.each { |text, result| assert_equal result, textilizable(text) }
716 716 end
717 717
718 718 def test_pre_tags
719 719 raw = <<-RAW
720 720 Before
721 721
722 722 <pre>
723 723 <prepared-statement-cache-size>32</prepared-statement-cache-size>
724 724 </pre>
725 725
726 726 After
727 727 RAW
728 728
729 729 expected = <<-EXPECTED
730 730 <p>Before</p>
731 731 <pre>
732 732 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
733 733 </pre>
734 734 <p>After</p>
735 735 EXPECTED
736 736
737 737 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
738 738 end
739 739
740 740 def test_pre_content_should_not_parse_wiki_and_redmine_links
741 741 raw = <<-RAW
742 742 [[CookBook documentation]]
743 743
744 744 #1
745 745
746 746 <pre>
747 747 [[CookBook documentation]]
748 748
749 749 #1
750 750 </pre>
751 751 RAW
752 752
753 753 expected = <<-EXPECTED
754 754 <p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
755 <p><a href="/issues/1" class="issue status-1 priority-4 priority-lowest" title="Can&#x27;t print recipes (New)">#1</a></p>
755 <p><a href="/issues/1" class="#{Issue.find(1).css_classes}" title="Can&#x27;t print recipes (New)">#1</a></p>
756 756 <pre>
757 757 [[CookBook documentation]]
758 758
759 759 #1
760 760 </pre>
761 761 EXPECTED
762 762
763 763 @project = Project.find(1)
764 764 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
765 765 end
766 766
767 767 def test_non_closing_pre_blocks_should_be_closed
768 768 raw = <<-RAW
769 769 <pre><code>
770 770 RAW
771 771
772 772 expected = <<-EXPECTED
773 773 <pre><code>
774 774 </code></pre>
775 775 EXPECTED
776 776
777 777 @project = Project.find(1)
778 778 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
779 779 end
780 780
781 781 def test_syntax_highlight
782 782 raw = <<-RAW
783 783 <pre><code class="ruby">
784 784 # Some ruby code here
785 785 </code></pre>
786 786 RAW
787 787
788 788 expected = <<-EXPECTED
789 789 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
790 790 </code></pre>
791 791 EXPECTED
792 792
793 793 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
794 794 end
795 795
796 796 def test_to_path_param
797 797 assert_equal 'test1/test2', to_path_param('test1/test2')
798 798 assert_equal 'test1/test2', to_path_param('/test1/test2/')
799 799 assert_equal 'test1/test2', to_path_param('//test1/test2/')
800 800 assert_equal nil, to_path_param('/')
801 801 end
802 802
803 803 def test_wiki_links_in_tables
804 804 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
805 805 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
806 806 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
807 807 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
808 808 }
809 809 @project = Project.find(1)
810 810 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
811 811 end
812 812
813 813 def test_text_formatting
814 814 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
815 815 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
816 816 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
817 817 '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>',
818 818 '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',
819 819 }
820 820 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
821 821 end
822 822
823 823 def test_wiki_horizontal_rule
824 824 assert_equal '<hr />', textilizable('---')
825 825 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
826 826 end
827 827
828 828 def test_footnotes
829 829 raw = <<-RAW
830 830 This is some text[1].
831 831
832 832 fn1. This is the foot note
833 833 RAW
834 834
835 835 expected = <<-EXPECTED
836 836 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
837 837 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
838 838 EXPECTED
839 839
840 840 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
841 841 end
842 842
843 843 def test_headings
844 844 raw = 'h1. Some heading'
845 845 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
846 846
847 847 assert_equal expected, textilizable(raw)
848 848 end
849 849
850 850 def test_headings_with_special_chars
851 851 # This test makes sure that the generated anchor names match the expected
852 852 # ones even if the heading text contains unconventional characters
853 853 raw = 'h1. Some heading related to version 0.5'
854 854 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
855 855 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
856 856
857 857 assert_equal expected, textilizable(raw)
858 858 end
859 859
860 860 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
861 861 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
862 862 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
863 863
864 864 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
865 865
866 866 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
867 867 end
868 868
869 869 def test_table_of_content
870 870 raw = <<-RAW
871 871 {{toc}}
872 872
873 873 h1. Title
874 874
875 875 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
876 876
877 877 h2. Subtitle with a [[Wiki]] link
878 878
879 879 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
880 880
881 881 h2. Subtitle with [[Wiki|another Wiki]] link
882 882
883 883 h2. Subtitle with %{color:red}red text%
884 884
885 885 <pre>
886 886 some code
887 887 </pre>
888 888
889 889 h3. Subtitle with *some* _modifiers_
890 890
891 891 h3. Subtitle with @inline code@
892 892
893 893 h1. Another title
894 894
895 895 h3. An "Internet link":http://www.redmine.org/ inside subtitle
896 896
897 897 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
898 898
899 899 RAW
900 900
901 901 expected = '<ul class="toc">' +
902 902 '<li><a href="#Title">Title</a>' +
903 903 '<ul>' +
904 904 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
905 905 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
906 906 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
907 907 '<ul>' +
908 908 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
909 909 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
910 910 '</ul>' +
911 911 '</li>' +
912 912 '</ul>' +
913 913 '</li>' +
914 914 '<li><a href="#Another-title">Another title</a>' +
915 915 '<ul>' +
916 916 '<li>' +
917 917 '<ul>' +
918 918 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
919 919 '</ul>' +
920 920 '</li>' +
921 921 '<li><a href="#Project-Name">Project Name</a></li>' +
922 922 '</ul>' +
923 923 '</li>' +
924 924 '</ul>'
925 925
926 926 @project = Project.find(1)
927 927 assert textilizable(raw).gsub("\n", "").include?(expected)
928 928 end
929 929
930 930 def test_table_of_content_should_generate_unique_anchors
931 931 raw = <<-RAW
932 932 {{toc}}
933 933
934 934 h1. Title
935 935
936 936 h2. Subtitle
937 937
938 938 h2. Subtitle
939 939 RAW
940 940
941 941 expected = '<ul class="toc">' +
942 942 '<li><a href="#Title">Title</a>' +
943 943 '<ul>' +
944 944 '<li><a href="#Subtitle">Subtitle</a></li>' +
945 945 '<li><a href="#Subtitle-2">Subtitle</a></li>'
946 946 '</ul>'
947 947 '</li>' +
948 948 '</ul>'
949 949
950 950 @project = Project.find(1)
951 951 result = textilizable(raw).gsub("\n", "")
952 952 assert_include expected, result
953 953 assert_include '<a name="Subtitle">', result
954 954 assert_include '<a name="Subtitle-2">', result
955 955 end
956 956
957 957 def test_table_of_content_should_contain_included_page_headings
958 958 raw = <<-RAW
959 959 {{toc}}
960 960
961 961 h1. Included
962 962
963 963 {{include(Child_1)}}
964 964 RAW
965 965
966 966 expected = '<ul class="toc">' +
967 967 '<li><a href="#Included">Included</a></li>' +
968 968 '<li><a href="#Child-page-1">Child page 1</a></li>' +
969 969 '</ul>'
970 970
971 971 @project = Project.find(1)
972 972 assert textilizable(raw).gsub("\n", "").include?(expected)
973 973 end
974 974
975 975 def test_section_edit_links
976 976 raw = <<-RAW
977 977 h1. Title
978 978
979 979 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
980 980
981 981 h2. Subtitle with a [[Wiki]] link
982 982
983 983 h2. Subtitle with *some* _modifiers_
984 984
985 985 h2. Subtitle with @inline code@
986 986
987 987 <pre>
988 988 some code
989 989
990 990 h2. heading inside pre
991 991
992 992 <h2>html heading inside pre</h2>
993 993 </pre>
994 994
995 995 h2. Subtitle after pre tag
996 996 RAW
997 997
998 998 @project = Project.find(1)
999 999 set_language_if_valid 'en'
1000 1000 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1001 1001
1002 1002 # heading that contains inline code
1003 1003 assert_match Regexp.new('<div class="contextual" title="Edit this section">' +
1004 1004 '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1005 1005 '<a name="Subtitle-with-inline-code"></a>' +
1006 1006 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1007 1007 result
1008 1008
1009 1009 # last heading
1010 1010 assert_match Regexp.new('<div class="contextual" title="Edit this section">' +
1011 1011 '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1012 1012 '<a name="Subtitle-after-pre-tag"></a>' +
1013 1013 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1014 1014 result
1015 1015 end
1016 1016
1017 1017 def test_default_formatter
1018 1018 with_settings :text_formatting => 'unknown' do
1019 1019 text = 'a *link*: http://www.example.net/'
1020 1020 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1021 1021 end
1022 1022 end
1023 1023
1024 1024 def test_due_date_distance_in_words
1025 1025 to_test = { Date.today => 'Due in 0 days',
1026 1026 Date.today + 1 => 'Due in 1 day',
1027 1027 Date.today + 100 => 'Due in about 3 months',
1028 1028 Date.today + 20000 => 'Due in over 54 years',
1029 1029 Date.today - 1 => '1 day late',
1030 1030 Date.today - 100 => 'about 3 months late',
1031 1031 Date.today - 20000 => 'over 54 years late',
1032 1032 }
1033 1033 ::I18n.locale = :en
1034 1034 to_test.each do |date, expected|
1035 1035 assert_equal expected, due_date_distance_in_words(date)
1036 1036 end
1037 1037 end
1038 1038
1039 1039 def test_avatar_enabled
1040 1040 with_settings :gravatar_enabled => '1' do
1041 1041 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1042 1042 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1043 1043 # Default size is 50
1044 1044 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1045 1045 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1046 1046 # Non-avatar options should be considered html options
1047 1047 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1048 1048 # The default class of the img tag should be gravatar
1049 1049 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1050 1050 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1051 1051 assert_nil avatar('jsmith')
1052 1052 assert_nil avatar(nil)
1053 1053 end
1054 1054 end
1055 1055
1056 1056 def test_avatar_disabled
1057 1057 with_settings :gravatar_enabled => '0' do
1058 1058 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1059 1059 end
1060 1060 end
1061 1061
1062 1062 def test_link_to_user
1063 1063 user = User.find(2)
1064 1064 assert_equal '<a href="/users/2" class="user active">John Smith</a>', link_to_user(user)
1065 1065 end
1066 1066
1067 1067 def test_link_to_user_should_not_link_to_locked_user
1068 1068 with_current_user nil do
1069 1069 user = User.find(5)
1070 1070 assert user.locked?
1071 1071 assert_equal 'Dave2 Lopper2', link_to_user(user)
1072 1072 end
1073 1073 end
1074 1074
1075 1075 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1076 1076 with_current_user User.find(1) do
1077 1077 user = User.find(5)
1078 1078 assert user.locked?
1079 1079 assert_equal '<a href="/users/5" class="user locked">Dave2 Lopper2</a>', link_to_user(user)
1080 1080 end
1081 1081 end
1082 1082
1083 1083 def test_link_to_user_should_not_link_to_anonymous
1084 1084 user = User.anonymous
1085 1085 assert user.anonymous?
1086 1086 t = link_to_user(user)
1087 1087 assert_equal ::I18n.t(:label_user_anonymous), t
1088 1088 end
1089 1089
1090 1090 def test_link_to_attachment
1091 1091 a = Attachment.find(3)
1092 1092 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1093 1093 link_to_attachment(a)
1094 1094 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1095 1095 link_to_attachment(a, :text => 'Text')
1096 1096 assert_equal '<a href="/attachments/3/logo.gif" class="foo">logo.gif</a>',
1097 1097 link_to_attachment(a, :class => 'foo')
1098 1098 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1099 1099 link_to_attachment(a, :download => true)
1100 1100 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1101 1101 link_to_attachment(a, :only_path => false)
1102 1102 end
1103 1103
1104 1104 def test_thumbnail_tag
1105 1105 a = Attachment.find(3)
1106 1106 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1107 1107 thumbnail_tag(a)
1108 1108 end
1109 1109
1110 1110 def test_link_to_project
1111 1111 project = Project.find(1)
1112 1112 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1113 1113 link_to_project(project)
1114 1114 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1115 1115 link_to_project(project, :action => 'settings')
1116 1116 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1117 1117 link_to_project(project, {:only_path => false, :jump => 'blah'})
1118 1118 assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
1119 1119 link_to_project(project, {:action => 'settings'}, :class => "project")
1120 1120 end
1121 1121
1122 1122 def test_link_to_project_settings
1123 1123 project = Project.find(1)
1124 1124 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1125 1125
1126 1126 project.status = Project::STATUS_CLOSED
1127 1127 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1128 1128
1129 1129 project.status = Project::STATUS_ARCHIVED
1130 1130 assert_equal 'eCookbook', link_to_project_settings(project)
1131 1131 end
1132 1132
1133 1133 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1134 1134 # numeric identifier are no longer allowed
1135 1135 Project.update_all "identifier=25", "id=1"
1136 1136
1137 1137 assert_equal '<a href="/projects/1">eCookbook</a>',
1138 1138 link_to_project(Project.find(1))
1139 1139 end
1140 1140
1141 1141 def test_principals_options_for_select_with_users
1142 1142 User.current = nil
1143 1143 users = [User.find(2), User.find(4)]
1144 1144 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1145 1145 principals_options_for_select(users)
1146 1146 end
1147 1147
1148 1148 def test_principals_options_for_select_with_selected
1149 1149 User.current = nil
1150 1150 users = [User.find(2), User.find(4)]
1151 1151 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1152 1152 principals_options_for_select(users, User.find(4))
1153 1153 end
1154 1154
1155 1155 def test_principals_options_for_select_with_users_and_groups
1156 1156 User.current = nil
1157 1157 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1158 1158 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1159 1159 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1160 1160 principals_options_for_select(users)
1161 1161 end
1162 1162
1163 1163 def test_principals_options_for_select_with_empty_collection
1164 1164 assert_equal '', principals_options_for_select([])
1165 1165 end
1166 1166
1167 1167 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1168 1168 users = [User.find(2), User.find(4)]
1169 1169 User.current = User.find(4)
1170 1170 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1171 1171 end
1172 1172
1173 1173 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1174 1174 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1175 1175 end
1176 1176
1177 1177 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1178 1178 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1179 1179 end
1180 1180
1181 1181 def test_image_tag_should_pick_the_default_image
1182 1182 assert_match 'src="/images/image.png"', image_tag("image.png")
1183 1183 end
1184 1184
1185 1185 def test_image_tag_should_pick_the_theme_image_if_it_exists
1186 1186 theme = Redmine::Themes.themes.last
1187 1187 theme.images << 'image.png'
1188 1188
1189 1189 with_settings :ui_theme => theme.id do
1190 1190 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1191 1191 assert_match %|src="/images/other.png"|, image_tag("other.png")
1192 1192 end
1193 1193 ensure
1194 1194 theme.images.delete 'image.png'
1195 1195 end
1196 1196
1197 1197 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1198 1198 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1199 1199 end
1200 1200
1201 1201 def test_javascript_include_tag_should_pick_the_default_javascript
1202 1202 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1203 1203 end
1204 1204
1205 1205 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1206 1206 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1207 1207 end
1208 1208 end
General Comments 0
You need to be logged in to leave comments. Login now