##// END OF EJS Templates
Fixes version url....
Jean-Philippe Lang -
r6065:da69f086e7e0
parent child
Show More
@@ -1,678 +1,678
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 21
22 22 fixtures :projects, :roles, :enabled_modules, :users,
23 23 :repositories, :changesets,
24 24 :trackers, :issue_statuses, :issues, :versions, :documents,
25 25 :wikis, :wiki_pages, :wiki_contents,
26 26 :boards, :messages,
27 27 :attachments,
28 28 :enumerations
29 29
30 30 def setup
31 31 super
32 32 end
33 33
34 34 context "#link_to_if_authorized" do
35 35 context "authorized user" do
36 36 should "be tested"
37 37 end
38 38
39 39 context "unauthorized user" do
40 40 should "be tested"
41 41 end
42 42
43 43 should "allow using the :controller and :action for the target link" do
44 44 User.current = User.find_by_login('admin')
45 45
46 46 @project = Issue.first.project # Used by helper
47 47 response = link_to_if_authorized("By controller/action",
48 48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
49 49 assert_match /href/, response
50 50 end
51 51
52 52 end
53 53
54 54 def test_auto_links
55 55 to_test = {
56 56 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
57 57 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
58 58 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
59 59 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
60 60 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
61 61 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
62 62 '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>.',
63 63 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
64 64 '(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>)',
65 65 '(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 66 '(see inline link : http://www.foo.bar/Test).' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>).',
67 67 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
68 68 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
69 69 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
70 70 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
71 71 '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>',
72 72 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
73 73 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
74 74 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
75 75 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
76 76 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
77 77 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
78 78 # two exclamation marks
79 79 '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>',
80 80 # escaping
81 81 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo"bar</a>',
82 82 # wrap in angle brackets
83 83 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
84 84 }
85 85 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
86 86 end
87 87
88 88 def test_auto_mailto
89 89 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
90 90 textilizable('test@foo.bar')
91 91 end
92 92
93 93 def test_inline_images
94 94 to_test = {
95 95 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
96 96 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
97 97 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
98 98 # inline styles should be stripped
99 99 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" alt="" />',
100 100 'with title !http://foo.bar/image.jpg(This is a title)!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a title" alt="This is a title" />',
101 101 'with title !http://foo.bar/image.jpg(This is a double-quoted "title")!' => 'with title <img src="http://foo.bar/image.jpg" title="This is a double-quoted &quot;title&quot;" alt="This is a double-quoted &quot;title&quot;" />',
102 102 }
103 103 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
104 104 end
105 105
106 106 def test_inline_images_inside_tags
107 107 raw = <<-RAW
108 108 h1. !foo.png! Heading
109 109
110 110 Centered image:
111 111
112 112 p=. !bar.gif!
113 113 RAW
114 114
115 115 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
116 116 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
117 117 end
118 118
119 119 def test_attached_images
120 120 to_test = {
121 121 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
122 122 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
123 123 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
124 124 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
125 125 # link image
126 126 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3" title="This is a logo" alt="This is a logo" /></a>',
127 127 }
128 128 attachments = Attachment.find(:all)
129 129 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
130 130 end
131 131
132 132 def test_textile_external_links
133 133 to_test = {
134 134 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
135 135 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
136 136 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
137 137 '"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>',
138 138 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
139 139 # no multiline link text
140 140 "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",
141 141 # mailto link
142 142 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
143 143 # two exclamation marks
144 144 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
145 145 # escaping
146 146 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
147 147 }
148 148 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
149 149 end
150 150
151 151 def test_redmine_links
152 152 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
153 153 :class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)')
154 154
155 155 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
156 156 :class => 'changeset', :title => 'My very first commit')
157 157 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
158 158 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
159 159
160 160 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
161 161 :class => 'document')
162 162
163 163 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
164 164 :class => 'version')
165 165
166 166 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
167 167
168 168 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
169 169
170 170 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
171 171 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
172 172
173 173 to_test = {
174 174 # tickets
175 175 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
176 176 # changesets
177 177 'r1' => changeset_link,
178 178 'r1.' => "#{changeset_link}.",
179 179 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
180 180 'r1,r2' => "#{changeset_link},#{changeset_link2}",
181 181 # documents
182 182 'document#1' => document_link,
183 183 'document:"Test document"' => document_link,
184 184 # versions
185 185 'version#2' => version_link,
186 186 'version:1.0' => version_link,
187 187 'version:"1.0"' => version_link,
188 188 # source
189 189 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
190 190 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
191 191 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
192 192 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
193 193 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
194 194 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
195 195 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
196 196 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
197 197 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
198 198 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
199 199 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
200 200 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
201 201 # message
202 202 'message#4' => link_to('Post 2', message_url, :class => 'message'),
203 203 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
204 204 # project
205 205 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
206 206 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
207 207 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
208 208 # escaping
209 209 '!#3.' => '#3.',
210 210 '!r1' => 'r1',
211 211 '!document#1' => 'document#1',
212 212 '!document:"Test document"' => 'document:"Test document"',
213 213 '!version#2' => 'version#2',
214 214 '!version:1.0' => 'version:1.0',
215 215 '!version:"1.0"' => 'version:"1.0"',
216 216 '!source:/some/file' => 'source:/some/file',
217 217 # not found
218 218 '#0123456789' => '#0123456789',
219 219 # invalid expressions
220 220 'source:' => 'source:',
221 221 # url hash
222 222 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
223 223 }
224 224 @project = Project.find(1)
225 225 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
226 226 end
227 227
228 228 def test_cross_project_redmine_links
229 229 source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
230 230 :class => 'source')
231 231
232 232 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
233 233 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
234 234
235 235 to_test = {
236 236 # documents
237 237 'document:"Test document"' => 'document:"Test document"',
238 238 'ecookbook:document:"Test document"' => '<a href="/documents/1" class="document">Test document</a>',
239 239 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
240 240 # versions
241 241 'version:"1.0"' => 'version:"1.0"',
242 'ecookbook:version:"1.0"' => '<a href="/versions/show/2" class="version">1.0</a>',
242 'ecookbook:version:"1.0"' => '<a href="/versions/2" class="version">1.0</a>',
243 243 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
244 244 # changeset
245 245 'r2' => 'r2',
246 246 'ecookbook:r2' => changeset_link,
247 247 'invalid:r2' => 'invalid:r2',
248 248 # source
249 249 'source:/some/file' => 'source:/some/file',
250 250 'ecookbook:source:/some/file' => source_link,
251 251 'invalid:source:/some/file' => 'invalid:source:/some/file',
252 252 }
253 253 @project = Project.find(3)
254 254 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
255 255 end
256 256
257 257 def test_redmine_links_git_commit
258 258 changeset_link = link_to('abcd',
259 259 {
260 260 :controller => 'repositories',
261 261 :action => 'revision',
262 262 :id => 'subproject1',
263 263 :rev => 'abcd',
264 264 },
265 265 :class => 'changeset', :title => 'test commit')
266 266 to_test = {
267 267 'commit:abcd' => changeset_link,
268 268 }
269 269 @project = Project.find(3)
270 270 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
271 271 assert r
272 272 c = Changeset.new(:repository => r,
273 273 :committed_on => Time.now,
274 274 :revision => 'abcd',
275 275 :scmid => 'abcd',
276 276 :comments => 'test commit')
277 277 assert( c.save )
278 278 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
279 279 end
280 280
281 281 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
282 282 def test_redmine_links_darcs_commit
283 283 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
284 284 {
285 285 :controller => 'repositories',
286 286 :action => 'revision',
287 287 :id => 'subproject1',
288 288 :rev => '123',
289 289 },
290 290 :class => 'changeset', :title => 'test commit')
291 291 to_test = {
292 292 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
293 293 }
294 294 @project = Project.find(3)
295 295 r = Repository::Darcs.create!(
296 296 :project => @project, :url => '/tmp/test/darcs',
297 297 :log_encoding => 'UTF-8')
298 298 assert r
299 299 c = Changeset.new(:repository => r,
300 300 :committed_on => Time.now,
301 301 :revision => '123',
302 302 :scmid => '20080308225258-98289-abcd456efg.gz',
303 303 :comments => 'test commit')
304 304 assert( c.save )
305 305 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
306 306 end
307 307
308 308 def test_redmine_links_mercurial_commit
309 309 changeset_link_rev = link_to('r123',
310 310 {
311 311 :controller => 'repositories',
312 312 :action => 'revision',
313 313 :id => 'subproject1',
314 314 :rev => '123' ,
315 315 },
316 316 :class => 'changeset', :title => 'test commit')
317 317 changeset_link_commit = link_to('abcd',
318 318 {
319 319 :controller => 'repositories',
320 320 :action => 'revision',
321 321 :id => 'subproject1',
322 322 :rev => 'abcd' ,
323 323 },
324 324 :class => 'changeset', :title => 'test commit')
325 325 to_test = {
326 326 'r123' => changeset_link_rev,
327 327 'commit:abcd' => changeset_link_commit,
328 328 }
329 329 @project = Project.find(3)
330 330 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
331 331 assert r
332 332 c = Changeset.new(:repository => r,
333 333 :committed_on => Time.now,
334 334 :revision => '123',
335 335 :scmid => 'abcd',
336 336 :comments => 'test commit')
337 337 assert( c.save )
338 338 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
339 339 end
340 340
341 341 def test_attachment_links
342 342 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment')
343 343 to_test = {
344 344 'attachment:error281.txt' => attachment_link
345 345 }
346 346 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
347 347 end
348 348
349 349 def test_wiki_links
350 350 to_test = {
351 351 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
352 352 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
353 353 # link with anchor
354 354 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
355 355 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
356 356 # page that doesn't exist
357 357 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
358 358 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
359 359 # link to another project wiki
360 360 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
361 361 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
362 362 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
363 363 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
364 364 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
365 365 # striked through link
366 366 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
367 367 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
368 368 # escaping
369 369 '![[Another page|Page]]' => '[[Another page|Page]]',
370 370 # project does not exist
371 371 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
372 372 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
373 373 }
374 374 @project = Project.find(1)
375 375 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
376 376 end
377 377
378 378 def test_html_tags
379 379 to_test = {
380 380 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
381 381 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
382 382 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
383 383 # do not escape pre/code tags
384 384 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
385 385 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
386 386 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
387 387 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
388 388 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
389 389 # remove attributes except class
390 390 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
391 391 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
392 392 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
393 393 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
394 394 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
395 395 # xss
396 396 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
397 397 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
398 398 }
399 399 to_test.each { |text, result| assert_equal result, textilizable(text) }
400 400 end
401 401
402 402 def test_allowed_html_tags
403 403 to_test = {
404 404 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
405 405 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
406 406 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
407 407 }
408 408 to_test.each { |text, result| assert_equal result, textilizable(text) }
409 409 end
410 410
411 411 def test_pre_tags
412 412 raw = <<-RAW
413 413 Before
414 414
415 415 <pre>
416 416 <prepared-statement-cache-size>32</prepared-statement-cache-size>
417 417 </pre>
418 418
419 419 After
420 420 RAW
421 421
422 422 expected = <<-EXPECTED
423 423 <p>Before</p>
424 424 <pre>
425 425 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
426 426 </pre>
427 427 <p>After</p>
428 428 EXPECTED
429 429
430 430 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
431 431 end
432 432
433 433 def test_pre_content_should_not_parse_wiki_and_redmine_links
434 434 raw = <<-RAW
435 435 [[CookBook documentation]]
436 436
437 437 #1
438 438
439 439 <pre>
440 440 [[CookBook documentation]]
441 441
442 442 #1
443 443 </pre>
444 444 RAW
445 445
446 446 expected = <<-EXPECTED
447 447 <p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
448 448 <p><a href="/issues/1" class="issue status-1 priority-1" title="Can't print recipes (New)">#1</a></p>
449 449 <pre>
450 450 [[CookBook documentation]]
451 451
452 452 #1
453 453 </pre>
454 454 EXPECTED
455 455
456 456 @project = Project.find(1)
457 457 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
458 458 end
459 459
460 460 def test_non_closing_pre_blocks_should_be_closed
461 461 raw = <<-RAW
462 462 <pre><code>
463 463 RAW
464 464
465 465 expected = <<-EXPECTED
466 466 <pre><code>
467 467 </code></pre>
468 468 EXPECTED
469 469
470 470 @project = Project.find(1)
471 471 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
472 472 end
473 473
474 474 def test_syntax_highlight
475 475 raw = <<-RAW
476 476 <pre><code class="ruby">
477 477 # Some ruby code here
478 478 </code></pre>
479 479 RAW
480 480
481 481 expected = <<-EXPECTED
482 482 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="no">1</span> <span class="c"># Some ruby code here</span></span>
483 483 </code></pre>
484 484 EXPECTED
485 485
486 486 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
487 487 end
488 488
489 489 def test_wiki_links_in_tables
490 490 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
491 491 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
492 492 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
493 493 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
494 494 }
495 495 @project = Project.find(1)
496 496 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
497 497 end
498 498
499 499 def test_text_formatting
500 500 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
501 501 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
502 502 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
503 503 '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>',
504 504 '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',
505 505 }
506 506 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
507 507 end
508 508
509 509 def test_wiki_horizontal_rule
510 510 assert_equal '<hr />', textilizable('---')
511 511 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
512 512 end
513 513
514 514 def test_footnotes
515 515 raw = <<-RAW
516 516 This is some text[1].
517 517
518 518 fn1. This is the foot note
519 519 RAW
520 520
521 521 expected = <<-EXPECTED
522 522 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
523 523 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
524 524 EXPECTED
525 525
526 526 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
527 527 end
528 528
529 529 def test_headings
530 530 raw = 'h1. Some heading'
531 531 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
532 532
533 533 assert_equal expected, textilizable(raw)
534 534 end
535 535
536 536 def test_table_of_content
537 537 raw = <<-RAW
538 538 {{toc}}
539 539
540 540 h1. Title
541 541
542 542 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
543 543
544 544 h2. Subtitle with a [[Wiki]] link
545 545
546 546 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
547 547
548 548 h2. Subtitle with [[Wiki|another Wiki]] link
549 549
550 550 h2. Subtitle with %{color:red}red text%
551 551
552 552 <pre>
553 553 some code
554 554 </pre>
555 555
556 556 h3. Subtitle with *some* _modifiers_
557 557
558 558 h1. Another title
559 559
560 560 h3. An "Internet link":http://www.redmine.org/ inside subtitle
561 561
562 562 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
563 563
564 564 RAW
565 565
566 566 expected = '<ul class="toc">' +
567 567 '<li><a href="#Title">Title</a>' +
568 568 '<ul>' +
569 569 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
570 570 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
571 571 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
572 572 '<ul>' +
573 573 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
574 574 '</ul>' +
575 575 '</li>' +
576 576 '</ul>' +
577 577 '</li>' +
578 578 '<li><a href="#Another-title">Another title</a>' +
579 579 '<ul>' +
580 580 '<li>' +
581 581 '<ul>' +
582 582 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
583 583 '</ul>' +
584 584 '</li>' +
585 585 '<li><a href="#Project-Name">Project Name</a></li>' +
586 586 '</ul>' +
587 587 '</li>' +
588 588 '</ul>'
589 589
590 590 @project = Project.find(1)
591 591 assert textilizable(raw).gsub("\n", "").include?(expected), textilizable(raw)
592 592 end
593 593
594 594 def test_table_of_content_should_contain_included_page_headings
595 595 raw = <<-RAW
596 596 {{toc}}
597 597
598 598 h1. Included
599 599
600 600 {{include(Child_1)}}
601 601 RAW
602 602
603 603 expected = '<ul class="toc">' +
604 604 '<li><a href="#Included">Included</a></li>' +
605 605 '<li><a href="#Child-page-1">Child page 1</a></li>' +
606 606 '</ul>'
607 607
608 608 @project = Project.find(1)
609 609 assert textilizable(raw).gsub("\n", "").include?(expected)
610 610 end
611 611
612 612 def test_default_formatter
613 613 Setting.text_formatting = 'unknown'
614 614 text = 'a *link*: http://www.example.net/'
615 615 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
616 616 Setting.text_formatting = 'textile'
617 617 end
618 618
619 619 def test_due_date_distance_in_words
620 620 to_test = { Date.today => 'Due in 0 days',
621 621 Date.today + 1 => 'Due in 1 day',
622 622 Date.today + 100 => 'Due in about 3 months',
623 623 Date.today + 20000 => 'Due in over 54 years',
624 624 Date.today - 1 => '1 day late',
625 625 Date.today - 100 => 'about 3 months late',
626 626 Date.today - 20000 => 'over 54 years late',
627 627 }
628 628 ::I18n.locale = :en
629 629 to_test.each do |date, expected|
630 630 assert_equal expected, due_date_distance_in_words(date)
631 631 end
632 632 end
633 633
634 634 def test_avatar
635 635 # turn on avatars
636 636 Setting.gravatar_enabled = '1'
637 637 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
638 638 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
639 639 assert_nil avatar('jsmith')
640 640 assert_nil avatar(nil)
641 641
642 642 # turn off avatars
643 643 Setting.gravatar_enabled = '0'
644 644 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
645 645 end
646 646
647 647 def test_link_to_user
648 648 user = User.find(2)
649 649 t = link_to_user(user)
650 650 assert_equal "<a href=\"/users/2\">#{ user.name }</a>", t
651 651 end
652 652
653 653 def test_link_to_user_should_not_link_to_locked_user
654 654 user = User.find(5)
655 655 assert user.locked?
656 656 t = link_to_user(user)
657 657 assert_equal user.name, t
658 658 end
659 659
660 660 def test_link_to_user_should_not_link_to_anonymous
661 661 user = User.anonymous
662 662 assert user.anonymous?
663 663 t = link_to_user(user)
664 664 assert_equal ::I18n.t(:label_user_anonymous), t
665 665 end
666 666
667 667 def test_link_to_project
668 668 project = Project.find(1)
669 669 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
670 670 link_to_project(project)
671 671 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
672 672 link_to_project(project, :action => 'settings')
673 673 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
674 674 link_to_project(project, {:only_path => false, :jump => 'blah'})
675 675 assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
676 676 link_to_project(project, {:action => 'settings'}, :class => "project")
677 677 end
678 678 end
@@ -1,68 +1,68
1 1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
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 23
24 24 fixtures :all
25 25
26 26 def setup
27 27 super
28 28 set_language_if_valid('en')
29 29 User.current = nil
30 30 end
31 31
32 32 def test_link_to_version_within_project
33 33 @project = Project.find(2)
34 34 User.current = User.find(1)
35 assert_equal '<a href="/versions/show/5">Alpha</a>', link_to_version(Version.find(5))
35 assert_equal '<a href="/versions/5">Alpha</a>', link_to_version(Version.find(5))
36 36 end
37 37
38 38 def test_link_to_version
39 39 User.current = User.find(1)
40 assert_equal '<a href="/versions/show/5">OnlineStore - Alpha</a>', link_to_version(Version.find(5))
40 assert_equal '<a href="/versions/5">OnlineStore - Alpha</a>', link_to_version(Version.find(5))
41 41 end
42 42
43 43 def test_link_to_private_version
44 44 assert_equal 'OnlineStore - Alpha', link_to_version(Version.find(5))
45 45 end
46 46
47 47 def test_link_to_version_invalid_version
48 48 assert_equal '', link_to_version(Object)
49 49 end
50 50
51 51 def test_format_version_name_within_project
52 52 @project = Project.find(1)
53 53 assert_equal "0.1", format_version_name(Version.find(1))
54 54 end
55 55
56 56 def test_format_version_name
57 57 assert_equal "eCookbook - 0.1", format_version_name(Version.find(1))
58 58 end
59 59
60 60 def test_format_version_name_for_system_version
61 61 assert_equal "OnlineStore - Systemwide visible version", format_version_name(Version.find(7))
62 62 end
63 63
64 64 def test_version_options_for_select_with_no_versions
65 65 assert_equal '', version_options_for_select([])
66 66 assert_equal '<option value="1" selected="selected">0.1</option>', version_options_for_select([], Version.find(1))
67 67 end
68 68 end
@@ -1,779 +1,779
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 Redmine::Helpers::GanttTest < ActiveSupport::TestCase
21 21 # Utility methods and classes so assert_select can be used.
22 22 class GanttViewTest < ActionView::Base
23 23 include ActionView::Helpers::UrlHelper
24 24 include ActionView::Helpers::TextHelper
25 25 include ActionController::UrlWriter
26 26 include ApplicationHelper
27 27 include ProjectsHelper
28 28 include IssuesHelper
29 29
30 30 def self.default_url_options
31 31 {:only_path => true }
32 32 end
33 33
34 34 end
35 35
36 36 include ActionController::Assertions::SelectorAssertions
37 37
38 38 def setup
39 39 @response = ActionController::TestResponse.new
40 40 # Fixtures
41 41 ProjectCustomField.delete_all
42 42 Project.destroy_all
43 43
44 44 User.current = User.find(1)
45 45 end
46 46
47 47 def build_view
48 48 @view = GanttViewTest.new
49 49 end
50 50
51 51 def html_document
52 52 HTML::Document.new(@response.body)
53 53 end
54 54
55 55 # Creates a Gantt chart for a 4 week span
56 56 def create_gantt(project=Project.generate!, options={})
57 57 @project = project
58 58 @gantt = Redmine::Helpers::Gantt.new(options)
59 59 @gantt.project = @project
60 60 @gantt.query = Query.generate_default!(:project => @project)
61 61 @gantt.view = build_view
62 62 @gantt.instance_variable_set('@date_from', options[:date_from] || 2.weeks.ago.to_date)
63 63 @gantt.instance_variable_set('@date_to', options[:date_to] || 2.weeks.from_now.to_date)
64 64 end
65 65
66 66 context "#number_of_rows" do
67 67
68 68 context "with one project" do
69 69 should "return the number of rows just for that project"
70 70 end
71 71
72 72 context "with no project" do
73 73 should "return the total number of rows for all the projects, resursively"
74 74 end
75 75
76 76 should "not exceed max_rows option" do
77 77 p = Project.generate!
78 78 5.times do
79 79 Issue.generate_for_project!(p)
80 80 end
81 81
82 82 create_gantt(p)
83 83 @gantt.render
84 84 assert_equal 6, @gantt.number_of_rows
85 85 assert !@gantt.truncated
86 86
87 87 create_gantt(p, :max_rows => 3)
88 88 @gantt.render
89 89 assert_equal 3, @gantt.number_of_rows
90 90 assert @gantt.truncated
91 91 end
92 92 end
93 93
94 94 context "#number_of_rows_on_project" do
95 95 setup do
96 96 create_gantt
97 97 end
98 98
99 99 should "count 0 for an empty the project" do
100 100 assert_equal 0, @gantt.number_of_rows_on_project(@project)
101 101 end
102 102
103 103 should "count the number of issues without a version" do
104 104 @project.issues << Issue.generate_for_project!(@project, :fixed_version => nil)
105 105 assert_equal 2, @gantt.number_of_rows_on_project(@project)
106 106 end
107 107
108 108 should "count the number of issues on versions, including cross-project" do
109 109 version = Version.generate!
110 110 @project.versions << version
111 111 @project.issues << Issue.generate_for_project!(@project, :fixed_version => version)
112 112
113 113 assert_equal 3, @gantt.number_of_rows_on_project(@project)
114 114 end
115 115 end
116 116
117 117 # TODO: more of an integration test
118 118 context "#subjects" do
119 119 setup do
120 120 create_gantt
121 121 @project.enabled_module_names = [:issue_tracking]
122 122 @tracker = Tracker.generate!
123 123 @project.trackers << @tracker
124 124 @version = Version.generate!(:effective_date => 1.week.from_now.to_date, :sharing => 'none')
125 125 @project.versions << @version
126 126
127 127 @issue = Issue.generate!(:fixed_version => @version,
128 128 :subject => "gantt#line_for_project",
129 129 :tracker => @tracker,
130 130 :project => @project,
131 131 :done_ratio => 30,
132 132 :start_date => Date.yesterday,
133 133 :due_date => 1.week.from_now.to_date)
134 134 @project.issues << @issue
135 135 end
136 136
137 137 context "project" do
138 138 should "be rendered" do
139 139 @response.body = @gantt.subjects
140 140 assert_select "div.project-name a", /#{@project.name}/
141 141 end
142 142
143 143 should "have an indent of 4" do
144 144 @response.body = @gantt.subjects
145 145 assert_select "div.project-name[style*=left:4px]"
146 146 end
147 147 end
148 148
149 149 context "version" do
150 150 should "be rendered" do
151 151 @response.body = @gantt.subjects
152 152 assert_select "div.version-name a", /#{@version.name}/
153 153 end
154 154
155 155 should "be indented 24 (one level)" do
156 156 @response.body = @gantt.subjects
157 157 assert_select "div.version-name[style*=left:24px]"
158 158 end
159 159
160 160 context "without assigned issues" do
161 161 setup do
162 162 @version = Version.generate!(:effective_date => 2.week.from_now.to_date, :sharing => 'none', :name => 'empty_version')
163 163 @project.versions << @version
164 164 end
165 165
166 166 should "not be rendered" do
167 167 @response.body = @gantt.subjects
168 168 assert_select "div.version-name a", :text => /#{@version.name}/, :count => 0
169 169 end
170 170 end
171 171 end
172 172
173 173 context "issue" do
174 174 should "be rendered" do
175 175 @response.body = @gantt.subjects
176 176 assert_select "div.issue-subject", /#{@issue.subject}/
177 177 end
178 178
179 179 should "be indented 44 (two levels)" do
180 180 @response.body = @gantt.subjects
181 181 assert_select "div.issue-subject[style*=left:44px]"
182 182 end
183 183
184 184 context "assigned to a shared version of another project" do
185 185 setup do
186 186 p = Project.generate!
187 187 p.trackers << @tracker
188 188 p.enabled_module_names = [:issue_tracking]
189 189 @shared_version = Version.generate!(:sharing => 'system')
190 190 p.versions << @shared_version
191 191 # Reassign the issue to a shared version of another project
192 192
193 193 @issue = Issue.generate!(:fixed_version => @shared_version,
194 194 :subject => "gantt#assigned_to_shared_version",
195 195 :tracker => @tracker,
196 196 :project => @project,
197 197 :done_ratio => 30,
198 198 :start_date => Date.yesterday,
199 199 :due_date => 1.week.from_now.to_date)
200 200 @project.issues << @issue
201 201 end
202 202
203 203 should "be rendered" do
204 204 @response.body = @gantt.subjects
205 205 assert_select "div.issue-subject", /#{@issue.subject}/
206 206 end
207 207 end
208 208
209 209 context "with subtasks" do
210 210 setup do
211 211 attrs = {:project => @project, :tracker => @tracker, :fixed_version => @version}
212 212 @child1 = Issue.generate!(attrs.merge(:subject => 'child1', :parent_issue_id => @issue.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date))
213 213 @child2 = Issue.generate!(attrs.merge(:subject => 'child2', :parent_issue_id => @issue.id, :start_date => Date.today, :due_date => 1.week.from_now.to_date))
214 214 @grandchild = Issue.generate!(attrs.merge(:subject => 'grandchild', :parent_issue_id => @child1.id, :start_date => Date.yesterday, :due_date => 2.day.from_now.to_date))
215 215 end
216 216
217 217 should "indent subtasks" do
218 218 @response.body = @gantt.subjects
219 219 # parent task 44px
220 220 assert_select "div.issue-subject[style*=left:44px]", /#{@issue.subject}/
221 221 # children 64px
222 222 assert_select "div.issue-subject[style*=left:64px]", /child1/
223 223 assert_select "div.issue-subject[style*=left:64px]", /child2/
224 224 # grandchild 84px
225 225 assert_select "div.issue-subject[style*=left:84px]", /grandchild/, @response.body
226 226 end
227 227 end
228 228 end
229 229 end
230 230
231 231 context "#lines" do
232 232 setup do
233 233 create_gantt
234 234 @project.enabled_module_names = [:issue_tracking]
235 235 @tracker = Tracker.generate!
236 236 @project.trackers << @tracker
237 237 @version = Version.generate!(:effective_date => 1.week.from_now.to_date)
238 238 @project.versions << @version
239 239 @issue = Issue.generate!(:fixed_version => @version,
240 240 :subject => "gantt#line_for_project",
241 241 :tracker => @tracker,
242 242 :project => @project,
243 243 :done_ratio => 30,
244 244 :start_date => Date.yesterday,
245 245 :due_date => 1.week.from_now.to_date)
246 246 @project.issues << @issue
247 247
248 248 @response.body = @gantt.lines
249 249 end
250 250
251 251 context "project" do
252 252 should "be rendered" do
253 253 assert_select "div.project.task_todo"
254 254 assert_select "div.project.starting"
255 255 assert_select "div.project.ending"
256 256 assert_select "div.label.project", /#{@project.name}/
257 257 end
258 258 end
259 259
260 260 context "version" do
261 261 should "be rendered" do
262 262 assert_select "div.version.task_todo"
263 263 assert_select "div.version.starting"
264 264 assert_select "div.version.ending"
265 265 assert_select "div.label.version", /#{@version.name}/
266 266 end
267 267 end
268 268
269 269 context "issue" do
270 270 should "be rendered" do
271 271 assert_select "div.task_todo"
272 272 assert_select "div.task.label", /#{@issue.done_ratio}/
273 273 assert_select "div.tooltip", /#{@issue.subject}/
274 274 end
275 275 end
276 276 end
277 277
278 278 context "#render_project" do
279 279 should "be tested"
280 280 end
281 281
282 282 context "#render_issues" do
283 283 should "be tested"
284 284 end
285 285
286 286 context "#render_version" do
287 287 should "be tested"
288 288 end
289 289
290 290 context "#subject_for_project" do
291 291 setup do
292 292 create_gantt
293 293 end
294 294
295 295 context ":html format" do
296 296 should "add an absolute positioned div" do
297 297 @response.body = @gantt.subject_for_project(@project, {:format => :html})
298 298 assert_select "div[style*=absolute]"
299 299 end
300 300
301 301 should "use the indent option to move the div to the right" do
302 302 @response.body = @gantt.subject_for_project(@project, {:format => :html, :indent => 40})
303 303 assert_select "div[style*=left:40]"
304 304 end
305 305
306 306 should "include the project name" do
307 307 @response.body = @gantt.subject_for_project(@project, {:format => :html})
308 308 assert_select 'div', :text => /#{@project.name}/
309 309 end
310 310
311 311 should "include a link to the project" do
312 312 @response.body = @gantt.subject_for_project(@project, {:format => :html})
313 313 assert_select 'a[href=?]', "/projects/#{@project.identifier}", :text => /#{@project.name}/
314 314 end
315 315
316 316 should "style overdue projects" do
317 317 @project.enabled_module_names = [:issue_tracking]
318 318 @project.versions << Version.generate!(:effective_date => Date.yesterday)
319 319
320 320 assert @project.overdue?, "Need an overdue project for this test"
321 321 @response.body = @gantt.subject_for_project(@project, {:format => :html})
322 322
323 323 assert_select 'div span.project-overdue'
324 324 end
325 325
326 326
327 327 end
328 328
329 329 should "test the PNG format"
330 330 should "test the PDF format"
331 331 end
332 332
333 333 context "#line_for_project" do
334 334 setup do
335 335 create_gantt
336 336 @project.enabled_module_names = [:issue_tracking]
337 337 @tracker = Tracker.generate!
338 338 @project.trackers << @tracker
339 339 @version = Version.generate!(:effective_date => Date.yesterday)
340 340 @project.versions << @version
341 341
342 342 @project.issues << Issue.generate!(:fixed_version => @version,
343 343 :subject => "gantt#line_for_project",
344 344 :tracker => @tracker,
345 345 :project => @project,
346 346 :done_ratio => 30,
347 347 :start_date => 1.week.ago.to_date,
348 348 :due_date => 1.week.from_now.to_date)
349 349 end
350 350
351 351 context ":html format" do
352 352 context "todo line" do
353 353 should "start from the starting point on the left" do
354 354 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
355 355 assert_select "div.project.task_todo[style*=left:28px]", true, @response.body
356 356 end
357 357
358 358 should "be the total width of the project" do
359 359 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
360 360 assert_select "div.project.task_todo[style*=width:58px]", true, @response.body
361 361 end
362 362
363 363 end
364 364
365 365 context "late line" do
366 366 should_eventually "start from the starting point on the left" do
367 367 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
368 368 assert_select "div.project.task_late[style*=left:28px]", true, @response.body
369 369 end
370 370
371 371 should_eventually "be the total delayed width of the project" do
372 372 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
373 373 assert_select "div.project.task_late[style*=width:30px]", true, @response.body
374 374 end
375 375 end
376 376
377 377 context "done line" do
378 378 should_eventually "start from the starting point on the left" do
379 379 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
380 380 assert_select "div.project.task_done[style*=left:28px]", true, @response.body
381 381 end
382 382
383 383 should_eventually "Be the total done width of the project" do
384 384 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
385 385 assert_select "div.project.task_done[style*=width:18px]", true, @response.body
386 386 end
387 387 end
388 388
389 389 context "starting marker" do
390 390 should "not appear if the starting point is off the gantt chart" do
391 391 # Shift the date range of the chart
392 392 @gantt.instance_variable_set('@date_from', Date.today)
393 393
394 394 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
395 395 assert_select "div.project.starting", false, @response.body
396 396 end
397 397
398 398 should "appear at the starting point" do
399 399 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
400 400 assert_select "div.project.starting[style*=left:28px]", true, @response.body
401 401 end
402 402 end
403 403
404 404 context "ending marker" do
405 405 should "not appear if the starting point is off the gantt chart" do
406 406 # Shift the date range of the chart
407 407 @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
408 408
409 409 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
410 410 assert_select "div.project.ending", false, @response.body
411 411
412 412 end
413 413
414 414 should "appear at the end of the date range" do
415 415 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
416 416 assert_select "div.project.ending[style*=left:88px]", true, @response.body
417 417 end
418 418 end
419 419
420 420 context "status content" do
421 421 should "appear at the far left, even if it's far in the past" do
422 422 @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
423 423
424 424 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
425 425 assert_select "div.project.label", /#{@project.name}/
426 426 end
427 427
428 428 should "show the project name" do
429 429 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
430 430 assert_select "div.project.label", /#{@project.name}/
431 431 end
432 432
433 433 should_eventually "show the percent complete" do
434 434 @response.body = @gantt.line_for_project(@project, {:format => :html, :zoom => 4})
435 435 assert_select "div.project.label", /0%/
436 436 end
437 437 end
438 438 end
439 439
440 440 should "test the PNG format"
441 441 should "test the PDF format"
442 442 end
443 443
444 444 context "#subject_for_version" do
445 445 setup do
446 446 create_gantt
447 447 @project.enabled_module_names = [:issue_tracking]
448 448 @tracker = Tracker.generate!
449 449 @project.trackers << @tracker
450 450 @version = Version.generate!(:effective_date => Date.yesterday)
451 451 @project.versions << @version
452 452
453 453 @project.issues << Issue.generate!(:fixed_version => @version,
454 454 :subject => "gantt#subject_for_version",
455 455 :tracker => @tracker,
456 456 :project => @project,
457 457 :start_date => Date.today)
458 458
459 459 end
460 460
461 461 context ":html format" do
462 462 should "add an absolute positioned div" do
463 463 @response.body = @gantt.subject_for_version(@version, {:format => :html})
464 464 assert_select "div[style*=absolute]"
465 465 end
466 466
467 467 should "use the indent option to move the div to the right" do
468 468 @response.body = @gantt.subject_for_version(@version, {:format => :html, :indent => 40})
469 469 assert_select "div[style*=left:40]"
470 470 end
471 471
472 472 should "include the version name" do
473 473 @response.body = @gantt.subject_for_version(@version, {:format => :html})
474 474 assert_select 'div', :text => /#{@version.name}/
475 475 end
476 476
477 477 should "include a link to the version" do
478 478 @response.body = @gantt.subject_for_version(@version, {:format => :html})
479 assert_select 'a[href=?]', Regexp.escape("/versions/show/#{@version.to_param}"), :text => /#{@version.name}/
479 assert_select 'a[href=?]', Regexp.escape("/versions/#{@version.to_param}"), :text => /#{@version.name}/
480 480 end
481 481
482 482 should "style late versions" do
483 483 assert @version.overdue?, "Need an overdue version for this test"
484 484 @response.body = @gantt.subject_for_version(@version, {:format => :html})
485 485
486 486 assert_select 'div span.version-behind-schedule'
487 487 end
488 488
489 489 should "style behind schedule versions" do
490 490 assert @version.behind_schedule?, "Need a behind schedule version for this test"
491 491 @response.body = @gantt.subject_for_version(@version, {:format => :html})
492 492
493 493 assert_select 'div span.version-behind-schedule'
494 494 end
495 495 end
496 496 should "test the PNG format"
497 497 should "test the PDF format"
498 498 end
499 499
500 500 context "#line_for_version" do
501 501 setup do
502 502 create_gantt
503 503 @project.enabled_module_names = [:issue_tracking]
504 504 @tracker = Tracker.generate!
505 505 @project.trackers << @tracker
506 506 @version = Version.generate!(:effective_date => 1.week.from_now.to_date)
507 507 @project.versions << @version
508 508
509 509 @project.issues << Issue.generate!(:fixed_version => @version,
510 510 :subject => "gantt#line_for_project",
511 511 :tracker => @tracker,
512 512 :project => @project,
513 513 :done_ratio => 30,
514 514 :start_date => 1.week.ago.to_date,
515 515 :due_date => 1.week.from_now.to_date)
516 516 end
517 517
518 518 context ":html format" do
519 519 context "todo line" do
520 520 should "start from the starting point on the left" do
521 521 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
522 522 assert_select "div.version.task_todo[style*=left:28px]", true, @response.body
523 523 end
524 524
525 525 should "be the total width of the version" do
526 526 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
527 527 assert_select "div.version.task_todo[style*=width:58px]", true, @response.body
528 528 end
529 529
530 530 end
531 531
532 532 context "late line" do
533 533 should "start from the starting point on the left" do
534 534 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
535 535 assert_select "div.version.task_late[style*=left:28px]", true, @response.body
536 536 end
537 537
538 538 should "be the total delayed width of the version" do
539 539 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
540 540 assert_select "div.version.task_late[style*=width:30px]", true, @response.body
541 541 end
542 542 end
543 543
544 544 context "done line" do
545 545 should "start from the starting point on the left" do
546 546 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
547 547 assert_select "div.version.task_done[style*=left:28px]", true, @response.body
548 548 end
549 549
550 550 should "be the total done width of the version" do
551 551 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
552 552 assert_select "div.version.task_done[style*=width:16px]", true, @response.body
553 553 end
554 554 end
555 555
556 556 context "starting marker" do
557 557 should "not appear if the starting point is off the gantt chart" do
558 558 # Shift the date range of the chart
559 559 @gantt.instance_variable_set('@date_from', Date.today)
560 560
561 561 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
562 562 assert_select "div.version.starting", false
563 563 end
564 564
565 565 should "appear at the starting point" do
566 566 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
567 567 assert_select "div.version.starting[style*=left:28px]", true, @response.body
568 568 end
569 569 end
570 570
571 571 context "ending marker" do
572 572 should "not appear if the starting point is off the gantt chart" do
573 573 # Shift the date range of the chart
574 574 @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
575 575
576 576 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
577 577 assert_select "div.version.ending", false
578 578
579 579 end
580 580
581 581 should "appear at the end of the date range" do
582 582 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
583 583 assert_select "div.version.ending[style*=left:88px]", true, @response.body
584 584 end
585 585 end
586 586
587 587 context "status content" do
588 588 should "appear at the far left, even if it's far in the past" do
589 589 @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
590 590
591 591 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
592 592 assert_select "div.version.label", /#{@version.name}/
593 593 end
594 594
595 595 should "show the version name" do
596 596 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
597 597 assert_select "div.version.label", /#{@version.name}/
598 598 end
599 599
600 600 should "show the percent complete" do
601 601 @response.body = @gantt.line_for_version(@version, {:format => :html, :zoom => 4})
602 602 assert_select "div.version.label", /30%/
603 603 end
604 604 end
605 605 end
606 606
607 607 should "test the PNG format"
608 608 should "test the PDF format"
609 609 end
610 610
611 611 context "#subject_for_issue" do
612 612 setup do
613 613 create_gantt
614 614 @project.enabled_module_names = [:issue_tracking]
615 615 @tracker = Tracker.generate!
616 616 @project.trackers << @tracker
617 617
618 618 @issue = Issue.generate!(:subject => "gantt#subject_for_issue",
619 619 :tracker => @tracker,
620 620 :project => @project,
621 621 :start_date => 3.days.ago.to_date,
622 622 :due_date => Date.yesterday)
623 623 @project.issues << @issue
624 624
625 625 end
626 626
627 627 context ":html format" do
628 628 should "add an absolute positioned div" do
629 629 @response.body = @gantt.subject_for_issue(@issue, {:format => :html})
630 630 assert_select "div[style*=absolute]"
631 631 end
632 632
633 633 should "use the indent option to move the div to the right" do
634 634 @response.body = @gantt.subject_for_issue(@issue, {:format => :html, :indent => 40})
635 635 assert_select "div[style*=left:40]"
636 636 end
637 637
638 638 should "include the issue subject" do
639 639 @response.body = @gantt.subject_for_issue(@issue, {:format => :html})
640 640 assert_select 'div', :text => /#{@issue.subject}/
641 641 end
642 642
643 643 should "include a link to the issue" do
644 644 @response.body = @gantt.subject_for_issue(@issue, {:format => :html})
645 645 assert_select 'a[href=?]', Regexp.escape("/issues/#{@issue.to_param}"), :text => /#{@tracker.name} ##{@issue.id}/
646 646 end
647 647
648 648 should "style overdue issues" do
649 649 assert @issue.overdue?, "Need an overdue issue for this test"
650 650 @response.body = @gantt.subject_for_issue(@issue, {:format => :html})
651 651
652 652 assert_select 'div span.issue-overdue'
653 653 end
654 654
655 655 end
656 656 should "test the PNG format"
657 657 should "test the PDF format"
658 658 end
659 659
660 660 context "#line_for_issue" do
661 661 setup do
662 662 create_gantt
663 663 @project.enabled_module_names = [:issue_tracking]
664 664 @tracker = Tracker.generate!
665 665 @project.trackers << @tracker
666 666 @version = Version.generate!(:effective_date => 1.week.from_now.to_date)
667 667 @project.versions << @version
668 668 @issue = Issue.generate!(:fixed_version => @version,
669 669 :subject => "gantt#line_for_project",
670 670 :tracker => @tracker,
671 671 :project => @project,
672 672 :done_ratio => 30,
673 673 :start_date => 1.week.ago.to_date,
674 674 :due_date => 1.week.from_now.to_date)
675 675 @project.issues << @issue
676 676 end
677 677
678 678 context ":html format" do
679 679 context "todo line" do
680 680 should "start from the starting point on the left" do
681 681 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
682 682 assert_select "div.task_todo[style*=left:28px]", true, @response.body
683 683 end
684 684
685 685 should "be the total width of the issue" do
686 686 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
687 687 assert_select "div.task_todo[style*=width:58px]", true, @response.body
688 688 end
689 689
690 690 end
691 691
692 692 context "late line" do
693 693 should "start from the starting point on the left" do
694 694 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
695 695 assert_select "div.task_late[style*=left:28px]", true, @response.body
696 696 end
697 697
698 698 should "be the total delayed width of the issue" do
699 699 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
700 700 assert_select "div.task_late[style*=width:30px]", true, @response.body
701 701 end
702 702 end
703 703
704 704 context "done line" do
705 705 should "start from the starting point on the left" do
706 706 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
707 707 assert_select "div.task_done[style*=left:28px]", true, @response.body
708 708 end
709 709
710 710 should "be the total done width of the issue" do
711 711 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
712 712 # 15 days * 4 px * 30% - 2 px for borders = 16 px
713 713 assert_select "div.task_done[style*=width:16px]", true, @response.body
714 714 end
715 715
716 716 should "not be the total done width if the chart starts after issue start date" do
717 717 create_gantt(@project, :date_from => 5.days.ago.to_date)
718 718
719 719 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
720 720 assert_select "div.task_done[style*=left:0px]", true, @response.body
721 721 assert_select "div.task_done[style*=width:8px]", true, @response.body
722 722 end
723 723
724 724 context "for completed issue" do
725 725 setup do
726 726 @issue.done_ratio = 100
727 727 end
728 728
729 729 should "be the total width of the issue" do
730 730 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
731 731 assert_select "div.task_done[style*=width:58px]", true, @response.body
732 732 end
733 733
734 734 should "be the total width of the issue with due_date=start_date" do
735 735 @issue.due_date = @issue.start_date
736 736 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
737 737 assert_select "div.task_done[style*=width:2px]", true, @response.body
738 738 end
739 739 end
740 740 end
741 741
742 742 context "status content" do
743 743 should "appear at the far left, even if it's far in the past" do
744 744 @gantt.instance_variable_set('@date_to', 2.weeks.ago.to_date)
745 745
746 746 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
747 747 assert_select "div.task.label", true, @response.body
748 748 end
749 749
750 750 should "show the issue status" do
751 751 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
752 752 assert_select "div.task.label", /#{@issue.status.name}/
753 753 end
754 754
755 755 should "show the percent complete" do
756 756 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
757 757 assert_select "div.task.label", /30%/
758 758 end
759 759 end
760 760 end
761 761
762 762 should "have an issue tooltip" do
763 763 @response.body = @gantt.line_for_issue(@issue, {:format => :html, :zoom => 4})
764 764 assert_select "div.tooltip", /#{@issue.subject}/
765 765 end
766 766
767 767 should "test the PNG format"
768 768 should "test the PDF format"
769 769 end
770 770
771 771 context "#to_image" do
772 772 should "be tested"
773 773 end
774 774
775 775 context "#to_pdf" do
776 776 should "be tested"
777 777 end
778 778
779 779 end
General Comments 0
You need to be logged in to leave comments. Login now