##// END OF EJS Templates
Moved wiki links tests together....
Jean-Philippe Lang -
r8134:c8066879dba8
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
490
491 page = WikiPage.find_by_title('Another_page' )
492
493 to_test = {
494 # link to another page
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>',
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>',
499 # link to the current page
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>',
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>',
504 # page that doesn't exist
505 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
506 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
507 '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page#anchor" class="wiki-page new">Unknown page</a>',
508 '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page#anchor" class="wiki-page new">404</a>',
509 }
510
511 @project = Project.find(1)
512
513 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.generate!( :text => text, :page => page ), :text) }
514 end
515
516 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
517
518 to_test = {
519 # link to a page
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>',
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>',
524 # page that doesn't exist
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>',
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>',
529 }
530
531 @project = Project.find(1)
532
533 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) }
534 end
535
489 def test_html_tags
536 def test_html_tags
490 to_test = {
537 to_test = {
491 "<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>",
492 "<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>",
493 "<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>",
494 # do not escape pre/code tags
541 # do not escape pre/code tags
495 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
542 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
496 "<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>",
497 "<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>",
498 "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>",
499 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
546 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
500 # remove attributes except class
547 # remove attributes except class
501 "<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>",
502 '<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>',
503 "<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>",
504 '<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>',
505 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
552 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
506 # xss
553 # xss
507 '<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>',
508 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
555 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
509 }
556 }
510 to_test.each { |text, result| assert_equal result, textilizable(text) }
557 to_test.each { |text, result| assert_equal result, textilizable(text) }
511 end
558 end
512
559
513 def test_allowed_html_tags
560 def test_allowed_html_tags
514 to_test = {
561 to_test = {
515 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
562 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
516 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
563 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
517 "<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;"
518 }
565 }
519 to_test.each { |text, result| assert_equal result, textilizable(text) }
566 to_test.each { |text, result| assert_equal result, textilizable(text) }
520 end
567 end
521
568
522 def test_pre_tags
569 def test_pre_tags
523 raw = <<-RAW
570 raw = <<-RAW
524 Before
571 Before
525
572
526 <pre>
573 <pre>
527 <prepared-statement-cache-size>32</prepared-statement-cache-size>
574 <prepared-statement-cache-size>32</prepared-statement-cache-size>
528 </pre>
575 </pre>
529
576
530 After
577 After
531 RAW
578 RAW
532
579
533 expected = <<-EXPECTED
580 expected = <<-EXPECTED
534 <p>Before</p>
581 <p>Before</p>
535 <pre>
582 <pre>
536 &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;
537 </pre>
584 </pre>
538 <p>After</p>
585 <p>After</p>
539 EXPECTED
586 EXPECTED
540
587
541 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]}, '')
542 end
589 end
543
590
544 def test_pre_content_should_not_parse_wiki_and_redmine_links
591 def test_pre_content_should_not_parse_wiki_and_redmine_links
545 raw = <<-RAW
592 raw = <<-RAW
546 [[CookBook documentation]]
593 [[CookBook documentation]]
547
594
548 #1
595 #1
549
596
550 <pre>
597 <pre>
551 [[CookBook documentation]]
598 [[CookBook documentation]]
552
599
553 #1
600 #1
554 </pre>
601 </pre>
555 RAW
602 RAW
556
603
557 expected = <<-EXPECTED
604 expected = <<-EXPECTED
558 <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>
559 <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>
560 <pre>
607 <pre>
561 [[CookBook documentation]]
608 [[CookBook documentation]]
562
609
563 #1
610 #1
564 </pre>
611 </pre>
565 EXPECTED
612 EXPECTED
566
613
567 @project = Project.find(1)
614 @project = Project.find(1)
568 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]}, '')
569 end
616 end
570
617
571 def test_non_closing_pre_blocks_should_be_closed
618 def test_non_closing_pre_blocks_should_be_closed
572 raw = <<-RAW
619 raw = <<-RAW
573 <pre><code>
620 <pre><code>
574 RAW
621 RAW
575
622
576 expected = <<-EXPECTED
623 expected = <<-EXPECTED
577 <pre><code>
624 <pre><code>
578 </code></pre>
625 </code></pre>
579 EXPECTED
626 EXPECTED
580
627
581 @project = Project.find(1)
628 @project = Project.find(1)
582 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]}, '')
583 end
630 end
584
631
585 def test_syntax_highlight
632 def test_syntax_highlight
586 raw = <<-RAW
633 raw = <<-RAW
587 <pre><code class="ruby">
634 <pre><code class="ruby">
588 # Some ruby code here
635 # Some ruby code here
589 </code></pre>
636 </code></pre>
590 RAW
637 RAW
591
638
592 expected = <<-EXPECTED
639 expected = <<-EXPECTED
593 <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>
594 </code></pre>
641 </code></pre>
595 EXPECTED
642 EXPECTED
596
643
597 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]}, '')
598 end
645 end
599
646
600 def test_wiki_links_in_tables
647 def test_wiki_links_in_tables
601 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]]|" =>
602 '<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>' +
603 '<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>' +
604 '</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>'
605 }
652 }
606 @project = Project.find(1)
653 @project = Project.find(1)
607 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]/, '') }
608 end
655 end
609
656
610 def test_text_formatting
657 def test_text_formatting
611 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>',
612 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
659 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
613 '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',
614 '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>',
615 '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',
616 }
663 }
617 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) }
618 end
665 end
619
666
620 def test_wiki_horizontal_rule
667 def test_wiki_horizontal_rule
621 assert_equal '<hr />', textilizable('---')
668 assert_equal '<hr />', textilizable('---')
622 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
669 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
623 end
670 end
624
671
625 def test_footnotes
672 def test_footnotes
626 raw = <<-RAW
673 raw = <<-RAW
627 This is some text[1].
674 This is some text[1].
628
675
629 fn1. This is the foot note
676 fn1. This is the foot note
630 RAW
677 RAW
631
678
632 expected = <<-EXPECTED
679 expected = <<-EXPECTED
633 <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>
634 <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>
635 EXPECTED
682 EXPECTED
636
683
637 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]}, '')
638 end
685 end
639
686
640 def test_headings
687 def test_headings
641 raw = 'h1. Some heading'
688 raw = 'h1. Some heading'
642 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>|
643
690
644 assert_equal expected, textilizable(raw)
691 assert_equal expected, textilizable(raw)
645 end
692 end
646
693
647 def test_headings_with_special_chars
694 def test_headings_with_special_chars
648 # 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
649 # ones even if the heading text contains unconventional characters
696 # ones even if the heading text contains unconventional characters
650 raw = 'h1. Some heading related to version 0.5'
697 raw = 'h1. Some heading related to version 0.5'
651 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
698 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
652 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>|
653
700
654 assert_equal expected, textilizable(raw)
701 assert_equal expected, textilizable(raw)
655 end
702 end
656
703
657 def test_wiki_links_within_wiki_page_context
658
659 page = WikiPage.find_by_title('Another_page' )
660
661 to_test = {
662 # link to another page
663 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
664 '[[CookBook documentation|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">documentation</a>',
665 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
666 '[[CookBook documentation#One-section|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">documentation</a>',
667 # link to the current page
668 '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>',
669 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
670 '[[Another page#anchor]]' => '<a href="#anchor" class="wiki-page">Another page</a>',
671 '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>',
672 # page that doesn't exist
673 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
674 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
675 '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page#anchor" class="wiki-page new">Unknown page</a>',
676 '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page#anchor" class="wiki-page new">404</a>',
677 }
678
679 @project = Project.find(1)
680
681 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.generate!( :text => text, :page => page ), :text) }
682 end
683
684 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
685
686 to_test = {
687 # link to a page
688 '[[CookBook documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">CookBook documentation</a>',
689 '[[CookBook documentation|documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">documentation</a>',
690 '[[CookBook documentation#One-section]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">CookBook documentation</a>',
691 '[[CookBook documentation#One-section|documentation]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">documentation</a>',
692 # page that doesn't exist
693 '[[Unknown page]]' => '<a href="#Unknown_page" class="wiki-page new">Unknown page</a>',
694 '[[Unknown page|404]]' => '<a href="#Unknown_page" class="wiki-page new">404</a>',
695 '[[Unknown page#anchor]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">Unknown page</a>',
696 '[[Unknown page#anchor|404]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">404</a>',
697 }
698
699 @project = Project.find(1)
700
701 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) }
702 end
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 Setting.text_formatting = 'unknown'
790 Setting.text_formatting = 'unknown'
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 Setting.text_formatting = 'textile'
793 Setting.text_formatting = 'textile'
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