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