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