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