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