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