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