##// END OF EJS Templates
Don't run test if Redcarpet is not available (#19313)....
Jean-Philippe Lang -
r13724:e920e951e752
parent child
Show More
@@ -1,1526 +1,1528
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2015 Jean-Philippe Lang
4 # Copyright (C) 2006-2015 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require File.expand_path('../../../test_helper', __FILE__)
20 require File.expand_path('../../../test_helper', __FILE__)
21
21
22 class ApplicationHelperTest < ActionView::TestCase
22 class ApplicationHelperTest < ActionView::TestCase
23 include Redmine::I18n
23 include Redmine::I18n
24 include ERB::Util
24 include ERB::Util
25 include Rails.application.routes.url_helpers
25 include Rails.application.routes.url_helpers
26
26
27 fixtures :projects, :roles, :enabled_modules, :users,
27 fixtures :projects, :roles, :enabled_modules, :users,
28 :email_addresses,
28 :email_addresses,
29 :repositories, :changesets,
29 :repositories, :changesets,
30 :projects_trackers,
30 :projects_trackers,
31 :trackers, :issue_statuses, :issues, :versions, :documents,
31 :trackers, :issue_statuses, :issues, :versions, :documents,
32 :wikis, :wiki_pages, :wiki_contents,
32 :wikis, :wiki_pages, :wiki_contents,
33 :boards, :messages, :news,
33 :boards, :messages, :news,
34 :attachments, :enumerations
34 :attachments, :enumerations
35
35
36 def setup
36 def setup
37 super
37 super
38 set_tmp_attachments_directory
38 set_tmp_attachments_directory
39 @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".force_encoding('UTF-8')
39 @russian_test = "\xd1\x82\xd0\xb5\xd1\x81\xd1\x82".force_encoding('UTF-8')
40 end
40 end
41
41
42 test "#link_to_if_authorized for authorized user should allow using the :controller and :action for the target link" do
42 test "#link_to_if_authorized for authorized user 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/actionr',
46 response = link_to_if_authorized('By controller/actionr',
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 test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
51 test "#link_to_if_authorized for unauthorized user should display nothing if user isn't authorized" do
52 User.current = User.find_by_login('dlopper')
52 User.current = User.find_by_login('dlopper')
53 @project = Project.find('private-child')
53 @project = Project.find('private-child')
54 issue = @project.issues.first
54 issue = @project.issues.first
55 assert !issue.visible?
55 assert !issue.visible?
56
56
57 response = link_to_if_authorized('Never displayed',
57 response = link_to_if_authorized('Never displayed',
58 {:controller => 'issues', :action => 'show', :id => issue})
58 {:controller => 'issues', :action => 'show', :id => issue})
59 assert_nil response
59 assert_nil response
60 end
60 end
61
61
62 def test_auto_links
62 def test_auto_links
63 to_test = {
63 to_test = {
64 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
64 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
65 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
65 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
66 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
66 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
67 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
67 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
68 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
68 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
69 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
69 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
70 '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>.',
70 '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>.',
71 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
71 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
72 '(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>)',
72 '(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>)',
73 '(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>)',
73 '(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>)',
74 '(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>).',
74 '(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>).',
75 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
75 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
76 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
76 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
77 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
77 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
78 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
78 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
79 '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>',
79 '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>',
80 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
80 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
81 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
81 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
82 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
82 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
83 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
83 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
84 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
84 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
85 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
85 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
86 # two exclamation marks
86 # two exclamation marks
87 '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>',
87 '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>',
88 # escaping
88 # escaping
89 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
89 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
90 # wrap in angle brackets
90 # wrap in angle brackets
91 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
91 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;',
92 # invalid urls
92 # invalid urls
93 'http://' => 'http://',
93 'http://' => 'http://',
94 'www.' => 'www.',
94 'www.' => 'www.',
95 'test-www.bar.com' => 'test-www.bar.com',
95 'test-www.bar.com' => 'test-www.bar.com',
96 }
96 }
97 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
97 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
98 end
98 end
99
99
100 def test_auto_links_with_non_ascii_characters
100 def test_auto_links_with_non_ascii_characters
101 to_test = {
101 to_test = {
102 "http://foo.bar/#{@russian_test}" =>
102 "http://foo.bar/#{@russian_test}" =>
103 %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
103 %|<a class="external" href="http://foo.bar/#{@russian_test}">http://foo.bar/#{@russian_test}</a>|
104 }
104 }
105 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
105 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
106 end
106 end
107
107
108 def test_auto_mailto
108 def test_auto_mailto
109 to_test = {
109 to_test = {
110 'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
110 'test@foo.bar' => '<a class="email" href="mailto:test@foo.bar">test@foo.bar</a>',
111 'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
111 'test@www.foo.bar' => '<a class="email" href="mailto:test@www.foo.bar">test@www.foo.bar</a>',
112 }
112 }
113 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
113 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
114 end
114 end
115
115
116 def test_inline_images
116 def test_inline_images
117 to_test = {
117 to_test = {
118 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
118 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
119 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
119 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
120 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
120 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
121 'with style !{width:100px;height:100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height:100px;" alt="" />',
121 'with style !{width:100px;height:100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" style="width:100px;height:100px;" alt="" />',
122 '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" />',
122 '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" />',
123 '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;" />',
123 '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;" />',
124 }
124 }
125 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
125 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
126 end
126 end
127
127
128 def test_inline_images_inside_tags
128 def test_inline_images_inside_tags
129 raw = <<-RAW
129 raw = <<-RAW
130 h1. !foo.png! Heading
130 h1. !foo.png! Heading
131
131
132 Centered image:
132 Centered image:
133
133
134 p=. !bar.gif!
134 p=. !bar.gif!
135 RAW
135 RAW
136
136
137 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
137 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
138 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
138 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
139 end
139 end
140
140
141 def test_attached_images
141 def test_attached_images
142 to_test = {
142 to_test = {
143 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
143 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
144 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
144 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" />',
145 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
145 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
146 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
146 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
147 # link image
147 # link image
148 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" /></a>',
148 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3/logo.gif" title="This is a logo" alt="This is a logo" /></a>',
149 }
149 }
150 attachments = Attachment.all
150 attachments = Attachment.all
151 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
151 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
152 end
152 end
153
153
154 def test_attached_images_with_textile_and_non_ascii_filename
154 def test_attached_images_with_textile_and_non_ascii_filename
155 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
155 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
156 with_settings :text_formatting => 'textile' do
156 with_settings :text_formatting => 'textile' do
157 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="" />),
157 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="" />),
158 textilizable("!cafΓ©.jpg!)", :attachments => [attachment])
158 textilizable("!cafΓ©.jpg!)", :attachments => [attachment])
159 end
159 end
160 end
160 end
161
161
162 def test_attached_images_with_markdown_and_non_ascii_filename
162 def test_attached_images_with_markdown_and_non_ascii_filename
163 skip unless Object.const_defined?(:Redcarpet)
164
163 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
165 attachment = Attachment.generate!(:filename => 'cafΓ©.jpg')
164 with_settings :text_formatting => 'markdown' do
166 with_settings :text_formatting => 'markdown' do
165 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="">),
167 assert_include %(<img src="/attachments/download/#{attachment.id}/caf%C3%A9.jpg" alt="">),
166 textilizable("![](cafΓ©.jpg)", :attachments => [attachment])
168 textilizable("![](cafΓ©.jpg)", :attachments => [attachment])
167 end
169 end
168 end
170 end
169
171
170 def test_attached_images_filename_extension
172 def test_attached_images_filename_extension
171 set_tmp_attachments_directory
173 set_tmp_attachments_directory
172 a1 = Attachment.new(
174 a1 = Attachment.new(
173 :container => Issue.find(1),
175 :container => Issue.find(1),
174 :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
176 :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
175 :author => User.find(1))
177 :author => User.find(1))
176 assert a1.save
178 assert a1.save
177 assert_equal "testtest.JPG", a1.filename
179 assert_equal "testtest.JPG", a1.filename
178 assert_equal "image/jpeg", a1.content_type
180 assert_equal "image/jpeg", a1.content_type
179 assert a1.image?
181 assert a1.image?
180
182
181 a2 = Attachment.new(
183 a2 = Attachment.new(
182 :container => Issue.find(1),
184 :container => Issue.find(1),
183 :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
185 :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
184 :author => User.find(1))
186 :author => User.find(1))
185 assert a2.save
187 assert a2.save
186 assert_equal "testtest.jpeg", a2.filename
188 assert_equal "testtest.jpeg", a2.filename
187 assert_equal "image/jpeg", a2.content_type
189 assert_equal "image/jpeg", a2.content_type
188 assert a2.image?
190 assert a2.image?
189
191
190 a3 = Attachment.new(
192 a3 = Attachment.new(
191 :container => Issue.find(1),
193 :container => Issue.find(1),
192 :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
194 :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
193 :author => User.find(1))
195 :author => User.find(1))
194 assert a3.save
196 assert a3.save
195 assert_equal "testtest.JPE", a3.filename
197 assert_equal "testtest.JPE", a3.filename
196 assert_equal "image/jpeg", a3.content_type
198 assert_equal "image/jpeg", a3.content_type
197 assert a3.image?
199 assert a3.image?
198
200
199 a4 = Attachment.new(
201 a4 = Attachment.new(
200 :container => Issue.find(1),
202 :container => Issue.find(1),
201 :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
203 :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
202 :author => User.find(1))
204 :author => User.find(1))
203 assert a4.save
205 assert a4.save
204 assert_equal "Testtest.BMP", a4.filename
206 assert_equal "Testtest.BMP", a4.filename
205 assert_equal "image/x-ms-bmp", a4.content_type
207 assert_equal "image/x-ms-bmp", a4.content_type
206 assert a4.image?
208 assert a4.image?
207
209
208 to_test = {
210 to_test = {
209 'Inline image: !testtest.jpg!' =>
211 'Inline image: !testtest.jpg!' =>
210 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
212 'Inline image: <img src="/attachments/download/' + a1.id.to_s + '/testtest.JPG" alt="" />',
211 'Inline image: !testtest.jpeg!' =>
213 'Inline image: !testtest.jpeg!' =>
212 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
214 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testtest.jpeg" alt="" />',
213 'Inline image: !testtest.jpe!' =>
215 'Inline image: !testtest.jpe!' =>
214 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
216 'Inline image: <img src="/attachments/download/' + a3.id.to_s + '/testtest.JPE" alt="" />',
215 'Inline image: !testtest.bmp!' =>
217 'Inline image: !testtest.bmp!' =>
216 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
218 'Inline image: <img src="/attachments/download/' + a4.id.to_s + '/Testtest.BMP" alt="" />',
217 }
219 }
218
220
219 attachments = [a1, a2, a3, a4]
221 attachments = [a1, a2, a3, a4]
220 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
222 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
221 end
223 end
222
224
223 def test_attached_images_should_read_later
225 def test_attached_images_should_read_later
224 set_fixtures_attachments_directory
226 set_fixtures_attachments_directory
225 a1 = Attachment.find(16)
227 a1 = Attachment.find(16)
226 assert_equal "testfile.png", a1.filename
228 assert_equal "testfile.png", a1.filename
227 assert a1.readable?
229 assert a1.readable?
228 assert (! a1.visible?(User.anonymous))
230 assert (! a1.visible?(User.anonymous))
229 assert a1.visible?(User.find(2))
231 assert a1.visible?(User.find(2))
230 a2 = Attachment.find(17)
232 a2 = Attachment.find(17)
231 assert_equal "testfile.PNG", a2.filename
233 assert_equal "testfile.PNG", a2.filename
232 assert a2.readable?
234 assert a2.readable?
233 assert (! a2.visible?(User.anonymous))
235 assert (! a2.visible?(User.anonymous))
234 assert a2.visible?(User.find(2))
236 assert a2.visible?(User.find(2))
235 assert a1.created_on < a2.created_on
237 assert a1.created_on < a2.created_on
236
238
237 to_test = {
239 to_test = {
238 'Inline image: !testfile.png!' =>
240 'Inline image: !testfile.png!' =>
239 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
241 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
240 'Inline image: !Testfile.PNG!' =>
242 'Inline image: !Testfile.PNG!' =>
241 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
243 'Inline image: <img src="/attachments/download/' + a2.id.to_s + '/testfile.PNG" alt="" />',
242 }
244 }
243 attachments = [a1, a2]
245 attachments = [a1, a2]
244 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
246 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
245 set_tmp_attachments_directory
247 set_tmp_attachments_directory
246 end
248 end
247
249
248 def test_textile_external_links
250 def test_textile_external_links
249 to_test = {
251 to_test = {
250 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
252 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
251 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
253 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
252 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
254 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
253 '"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>',
255 '"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>',
254 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
256 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
255 # no multiline link text
257 # no multiline link text
256 "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",
258 "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",
257 # mailto link
259 # mailto link
258 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
260 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
259 # two exclamation marks
261 # two exclamation marks
260 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
262 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
261 # escaping
263 # escaping
262 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
264 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
263 }
265 }
264 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
266 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
265 end
267 end
266
268
267 def test_textile_external_links_with_non_ascii_characters
269 def test_textile_external_links_with_non_ascii_characters
268 to_test = {
270 to_test = {
269 %|This is a "link":http://foo.bar/#{@russian_test}| =>
271 %|This is a "link":http://foo.bar/#{@russian_test}| =>
270 %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
272 %|This is a <a href="http://foo.bar/#{@russian_test}" class="external">link</a>|
271 }
273 }
272 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
274 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
273 end
275 end
274
276
275 def test_redmine_links
277 def test_redmine_links
276 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
278 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
277 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
279 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
278 note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
280 note_link = link_to('#3-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
279 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
281 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
280 note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
282 note_link2 = link_to('#3#note-14', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
281 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
283 :class => Issue.find(3).css_classes, :title => 'Error 281 when updating a recipe (New)')
282
284
283 revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
285 revision_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
284 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
286 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
285 revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
287 revision_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
286 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
288 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
287
289
288 changeset_link2 = link_to('691322a8eb01e11fd7',
290 changeset_link2 = link_to('691322a8eb01e11fd7',
289 {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
291 {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
290 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
292 :class => 'changeset', :title => 'My very first commit do not escaping #<>&')
291
293
292 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
294 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
293 :class => 'document')
295 :class => 'document')
294
296
295 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
297 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
296 :class => 'version')
298 :class => 'version')
297
299
298 board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
300 board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
299
301
300 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
302 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
301
303
302 news_url = {:controller => 'news', :action => 'show', :id => 1}
304 news_url = {:controller => 'news', :action => 'show', :id => 1}
303
305
304 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
306 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
305
307
306 source_url = '/projects/ecookbook/repository/entry/some/file'
308 source_url = '/projects/ecookbook/repository/entry/some/file'
307 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
309 source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
308 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
310 source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
309 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
311 source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
310 source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
312 source_url_with_branch = '/projects/ecookbook/repository/revisions/branch/entry/some/file'
311
313
312 export_url = '/projects/ecookbook/repository/raw/some/file'
314 export_url = '/projects/ecookbook/repository/raw/some/file'
313 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
315 export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
314 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
316 export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
315 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
317 export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
316 export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
318 export_url_with_branch = '/projects/ecookbook/repository/revisions/branch/raw/some/file'
317
319
318 to_test = {
320 to_test = {
319 # tickets
321 # tickets
320 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
322 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
321 # ticket notes
323 # ticket notes
322 '#3-14' => note_link,
324 '#3-14' => note_link,
323 '#3#note-14' => note_link2,
325 '#3#note-14' => note_link2,
324 # should not ignore leading zero
326 # should not ignore leading zero
325 '#03' => '#03',
327 '#03' => '#03',
326 # changesets
328 # changesets
327 'r1' => revision_link,
329 'r1' => revision_link,
328 'r1.' => "#{revision_link}.",
330 'r1.' => "#{revision_link}.",
329 'r1, r2' => "#{revision_link}, #{revision_link2}",
331 'r1, r2' => "#{revision_link}, #{revision_link2}",
330 'r1,r2' => "#{revision_link},#{revision_link2}",
332 'r1,r2' => "#{revision_link},#{revision_link2}",
331 'commit:691322a8eb01e11fd7' => changeset_link2,
333 'commit:691322a8eb01e11fd7' => changeset_link2,
332 # documents
334 # documents
333 'document#1' => document_link,
335 'document#1' => document_link,
334 'document:"Test document"' => document_link,
336 'document:"Test document"' => document_link,
335 # versions
337 # versions
336 'version#2' => version_link,
338 'version#2' => version_link,
337 'version:1.0' => version_link,
339 'version:1.0' => version_link,
338 'version:"1.0"' => version_link,
340 'version:"1.0"' => version_link,
339 # source
341 # source
340 'source:some/file' => link_to('source:some/file', source_url, :class => 'source'),
342 'source:some/file' => link_to('source:some/file', source_url, :class => 'source'),
341 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
343 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
342 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
344 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
343 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
345 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
344 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
346 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
345 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
347 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
346 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
348 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
347 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
349 'source:/some/file@52' => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
348 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
350 'source:/some/file@branch' => link_to('source:/some/file@branch', source_url_with_branch, :class => 'source'),
349 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
351 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
350 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
352 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
351 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
353 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
352 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
354 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
353 # export
355 # export
354 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
356 'export:/some/file' => link_to('export:/some/file', export_url, :class => 'source download'),
355 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
357 'export:/some/file.ext' => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
356 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
358 'export:/some/file@52' => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
357 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
359 'export:/some/file.ext@52' => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
358 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
360 'export:/some/file@branch' => link_to('export:/some/file@branch', export_url_with_branch, :class => 'source download'),
359 # forum
361 # forum
360 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
362 'forum#2' => link_to('Discussion', board_url, :class => 'board'),
361 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
363 'forum:Discussion' => link_to('Discussion', board_url, :class => 'board'),
362 # message
364 # message
363 'message#4' => link_to('Post 2', message_url, :class => 'message'),
365 'message#4' => link_to('Post 2', message_url, :class => 'message'),
364 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
366 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
365 # news
367 # news
366 'news#1' => link_to('eCookbook first release !', news_url, :class => 'news'),
368 'news#1' => link_to('eCookbook first release !', news_url, :class => 'news'),
367 'news:"eCookbook first release !"' => link_to('eCookbook first release !', news_url, :class => 'news'),
369 'news:"eCookbook first release !"' => link_to('eCookbook first release !', news_url, :class => 'news'),
368 # project
370 # project
369 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
371 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
370 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
372 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
371 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
373 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
372 # not found
374 # not found
373 '#0123456789' => '#0123456789',
375 '#0123456789' => '#0123456789',
374 # invalid expressions
376 # invalid expressions
375 'source:' => 'source:',
377 'source:' => 'source:',
376 # url hash
378 # url hash
377 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
379 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
378 }
380 }
379 @project = Project.find(1)
381 @project = Project.find(1)
380 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
382 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
381 end
383 end
382
384
383 def test_should_not_parse_redmine_links_inside_link
385 def test_should_not_parse_redmine_links_inside_link
384 raw = "r1 should not be parsed in http://example.com/url-r1/"
386 raw = "r1 should not be parsed in http://example.com/url-r1/"
385 assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
387 assert_match %r{<p><a class="changeset".*>r1</a> should not be parsed in <a class="external" href="http://example.com/url-r1/">http://example.com/url-r1/</a></p>},
386 textilizable(raw, :project => Project.find(1))
388 textilizable(raw, :project => Project.find(1))
387 end
389 end
388
390
389 def test_redmine_links_with_a_different_project_before_current_project
391 def test_redmine_links_with_a_different_project_before_current_project
390 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
392 vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
391 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
393 vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
392 @project = Project.find(3)
394 @project = Project.find(3)
393 result1 = link_to("1.4.4", "/versions/#{vp1.id}", :class => "version")
395 result1 = link_to("1.4.4", "/versions/#{vp1.id}", :class => "version")
394 result2 = link_to("1.4.4", "/versions/#{vp3.id}", :class => "version")
396 result2 = link_to("1.4.4", "/versions/#{vp3.id}", :class => "version")
395 assert_equal "<p>#{result1} #{result2}</p>",
397 assert_equal "<p>#{result1} #{result2}</p>",
396 textilizable("ecookbook:version:1.4.4 version:1.4.4")
398 textilizable("ecookbook:version:1.4.4 version:1.4.4")
397 end
399 end
398
400
399 def test_escaped_redmine_links_should_not_be_parsed
401 def test_escaped_redmine_links_should_not_be_parsed
400 to_test = [
402 to_test = [
401 '#3.',
403 '#3.',
402 '#3-14.',
404 '#3-14.',
403 '#3#-note14.',
405 '#3#-note14.',
404 'r1',
406 'r1',
405 'document#1',
407 'document#1',
406 'document:"Test document"',
408 'document:"Test document"',
407 'version#2',
409 'version#2',
408 'version:1.0',
410 'version:1.0',
409 'version:"1.0"',
411 'version:"1.0"',
410 'source:/some/file'
412 'source:/some/file'
411 ]
413 ]
412 @project = Project.find(1)
414 @project = Project.find(1)
413 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
415 to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
414 end
416 end
415
417
416 def test_cross_project_redmine_links
418 def test_cross_project_redmine_links
417 source_link = link_to('ecookbook:source:/some/file',
419 source_link = link_to('ecookbook:source:/some/file',
418 {:controller => 'repositories', :action => 'entry',
420 {:controller => 'repositories', :action => 'entry',
419 :id => 'ecookbook', :path => ['some', 'file']},
421 :id => 'ecookbook', :path => ['some', 'file']},
420 :class => 'source')
422 :class => 'source')
421 changeset_link = link_to('ecookbook:r2',
423 changeset_link = link_to('ecookbook:r2',
422 {:controller => 'repositories', :action => 'revision',
424 {:controller => 'repositories', :action => 'revision',
423 :id => 'ecookbook', :rev => 2},
425 :id => 'ecookbook', :rev => 2},
424 :class => 'changeset',
426 :class => 'changeset',
425 :title => 'This commit fixes #1, #2 and references #1 & #3')
427 :title => 'This commit fixes #1, #2 and references #1 & #3')
426 to_test = {
428 to_test = {
427 # documents
429 # documents
428 'document:"Test document"' => 'document:"Test document"',
430 'document:"Test document"' => 'document:"Test document"',
429 'ecookbook:document:"Test document"' =>
431 'ecookbook:document:"Test document"' =>
430 link_to("Test document", "/documents/1", :class => "document"),
432 link_to("Test document", "/documents/1", :class => "document"),
431 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
433 'invalid:document:"Test document"' => 'invalid:document:"Test document"',
432 # versions
434 # versions
433 'version:"1.0"' => 'version:"1.0"',
435 'version:"1.0"' => 'version:"1.0"',
434 'ecookbook:version:"1.0"' =>
436 'ecookbook:version:"1.0"' =>
435 link_to("1.0", "/versions/2", :class => "version"),
437 link_to("1.0", "/versions/2", :class => "version"),
436 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
438 'invalid:version:"1.0"' => 'invalid:version:"1.0"',
437 # changeset
439 # changeset
438 'r2' => 'r2',
440 'r2' => 'r2',
439 'ecookbook:r2' => changeset_link,
441 'ecookbook:r2' => changeset_link,
440 'invalid:r2' => 'invalid:r2',
442 'invalid:r2' => 'invalid:r2',
441 # source
443 # source
442 'source:/some/file' => 'source:/some/file',
444 'source:/some/file' => 'source:/some/file',
443 'ecookbook:source:/some/file' => source_link,
445 'ecookbook:source:/some/file' => source_link,
444 'invalid:source:/some/file' => 'invalid:source:/some/file',
446 'invalid:source:/some/file' => 'invalid:source:/some/file',
445 }
447 }
446 @project = Project.find(3)
448 @project = Project.find(3)
447 to_test.each do |text, result|
449 to_test.each do |text, result|
448 assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed"
450 assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed"
449 end
451 end
450 end
452 end
451
453
452 def test_redmine_links_by_name_should_work_with_html_escaped_characters
454 def test_redmine_links_by_name_should_work_with_html_escaped_characters
453 v = Version.generate!(:name => "Test & Show.txt", :project_id => 1)
455 v = Version.generate!(:name => "Test & Show.txt", :project_id => 1)
454 link = link_to("Test & Show.txt", "/versions/#{v.id}", :class => "version")
456 link = link_to("Test & Show.txt", "/versions/#{v.id}", :class => "version")
455
457
456 @project = v.project
458 @project = v.project
457 assert_equal "<p>#{link}</p>", textilizable('version:"Test & Show.txt"')
459 assert_equal "<p>#{link}</p>", textilizable('version:"Test & Show.txt"')
458 end
460 end
459
461
460 def test_link_to_issue_subject
462 def test_link_to_issue_subject
461 issue = Issue.generate!(:subject => "01234567890123456789")
463 issue = Issue.generate!(:subject => "01234567890123456789")
462 str = link_to_issue(issue, :truncate => 10)
464 str = link_to_issue(issue, :truncate => 10)
463 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
465 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
464 assert_equal "#{result}: 0123456...", str
466 assert_equal "#{result}: 0123456...", str
465
467
466 issue = Issue.generate!(:subject => "<&>")
468 issue = Issue.generate!(:subject => "<&>")
467 str = link_to_issue(issue)
469 str = link_to_issue(issue)
468 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
470 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
469 assert_equal "#{result}: &lt;&amp;&gt;", str
471 assert_equal "#{result}: &lt;&amp;&gt;", str
470
472
471 issue = Issue.generate!(:subject => "<&>0123456789012345")
473 issue = Issue.generate!(:subject => "<&>0123456789012345")
472 str = link_to_issue(issue, :truncate => 10)
474 str = link_to_issue(issue, :truncate => 10)
473 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
475 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
474 assert_equal "#{result}: &lt;&amp;&gt;0123...", str
476 assert_equal "#{result}: &lt;&amp;&gt;0123...", str
475 end
477 end
476
478
477 def test_link_to_issue_title
479 def test_link_to_issue_title
478 long_str = "0123456789" * 5
480 long_str = "0123456789" * 5
479
481
480 issue = Issue.generate!(:subject => "#{long_str}01234567890123456789")
482 issue = Issue.generate!(:subject => "#{long_str}01234567890123456789")
481 str = link_to_issue(issue, :subject => false)
483 str = link_to_issue(issue, :subject => false)
482 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
484 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
483 :class => issue.css_classes,
485 :class => issue.css_classes,
484 :title => "#{long_str}0123456...")
486 :title => "#{long_str}0123456...")
485 assert_equal result, str
487 assert_equal result, str
486
488
487 issue = Issue.generate!(:subject => "<&>#{long_str}01234567890123456789")
489 issue = Issue.generate!(:subject => "<&>#{long_str}01234567890123456789")
488 str = link_to_issue(issue, :subject => false)
490 str = link_to_issue(issue, :subject => false)
489 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
491 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
490 :class => issue.css_classes,
492 :class => issue.css_classes,
491 :title => "<&>#{long_str}0123...")
493 :title => "<&>#{long_str}0123...")
492 assert_equal result, str
494 assert_equal result, str
493 end
495 end
494
496
495 def test_multiple_repositories_redmine_links
497 def test_multiple_repositories_redmine_links
496 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
498 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
497 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
499 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
498 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
500 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
499 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
501 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
500
502
501 changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
503 changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
502 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
504 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
503 svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
505 svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
504 :class => 'changeset', :title => '')
506 :class => 'changeset', :title => '')
505 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
507 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
506 :class => 'changeset', :title => '')
508 :class => 'changeset', :title => '')
507
509
508 source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
510 source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
509 hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
511 hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
510
512
511 to_test = {
513 to_test = {
512 'r2' => changeset_link,
514 'r2' => changeset_link,
513 'svn_repo-1|r123' => svn_changeset_link,
515 'svn_repo-1|r123' => svn_changeset_link,
514 'invalid|r123' => 'invalid|r123',
516 'invalid|r123' => 'invalid|r123',
515 'commit:hg1|abcd' => hg_changeset_link,
517 'commit:hg1|abcd' => hg_changeset_link,
516 'commit:invalid|abcd' => 'commit:invalid|abcd',
518 'commit:invalid|abcd' => 'commit:invalid|abcd',
517 # source
519 # source
518 'source:some/file' => source_link,
520 'source:some/file' => source_link,
519 'source:hg1|some/file' => hg_source_link,
521 'source:hg1|some/file' => hg_source_link,
520 'source:invalid|some/file' => 'source:invalid|some/file',
522 'source:invalid|some/file' => 'source:invalid|some/file',
521 }
523 }
522
524
523 @project = Project.find(1)
525 @project = Project.find(1)
524 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
526 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
525 end
527 end
526
528
527 def test_cross_project_multiple_repositories_redmine_links
529 def test_cross_project_multiple_repositories_redmine_links
528 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
530 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
529 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
531 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
530 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
532 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
531 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
533 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
532
534
533 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
535 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
534 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
536 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
535 svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
537 svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
536 :class => 'changeset', :title => '')
538 :class => 'changeset', :title => '')
537 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
539 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
538 :class => 'changeset', :title => '')
540 :class => 'changeset', :title => '')
539
541
540 source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
542 source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
541 hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
543 hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
542
544
543 to_test = {
545 to_test = {
544 'ecookbook:r2' => changeset_link,
546 'ecookbook:r2' => changeset_link,
545 'ecookbook:svn1|r123' => svn_changeset_link,
547 'ecookbook:svn1|r123' => svn_changeset_link,
546 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
548 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
547 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
549 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
548 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
550 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
549 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
551 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
550 # source
552 # source
551 'ecookbook:source:some/file' => source_link,
553 'ecookbook:source:some/file' => source_link,
552 'ecookbook:source:hg1|some/file' => hg_source_link,
554 'ecookbook:source:hg1|some/file' => hg_source_link,
553 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
555 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
554 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
556 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
555 }
557 }
556
558
557 @project = Project.find(3)
559 @project = Project.find(3)
558 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
560 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
559 end
561 end
560
562
561 def test_redmine_links_git_commit
563 def test_redmine_links_git_commit
562 changeset_link = link_to('abcd',
564 changeset_link = link_to('abcd',
563 {
565 {
564 :controller => 'repositories',
566 :controller => 'repositories',
565 :action => 'revision',
567 :action => 'revision',
566 :id => 'subproject1',
568 :id => 'subproject1',
567 :rev => 'abcd',
569 :rev => 'abcd',
568 },
570 },
569 :class => 'changeset', :title => 'test commit')
571 :class => 'changeset', :title => 'test commit')
570 to_test = {
572 to_test = {
571 'commit:abcd' => changeset_link,
573 'commit:abcd' => changeset_link,
572 }
574 }
573 @project = Project.find(3)
575 @project = Project.find(3)
574 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
576 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
575 assert r
577 assert r
576 c = Changeset.new(:repository => r,
578 c = Changeset.new(:repository => r,
577 :committed_on => Time.now,
579 :committed_on => Time.now,
578 :revision => 'abcd',
580 :revision => 'abcd',
579 :scmid => 'abcd',
581 :scmid => 'abcd',
580 :comments => 'test commit')
582 :comments => 'test commit')
581 assert( c.save )
583 assert( c.save )
582 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
584 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
583 end
585 end
584
586
585 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
587 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
586 def test_redmine_links_darcs_commit
588 def test_redmine_links_darcs_commit
587 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
589 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
588 {
590 {
589 :controller => 'repositories',
591 :controller => 'repositories',
590 :action => 'revision',
592 :action => 'revision',
591 :id => 'subproject1',
593 :id => 'subproject1',
592 :rev => '123',
594 :rev => '123',
593 },
595 },
594 :class => 'changeset', :title => 'test commit')
596 :class => 'changeset', :title => 'test commit')
595 to_test = {
597 to_test = {
596 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
598 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
597 }
599 }
598 @project = Project.find(3)
600 @project = Project.find(3)
599 r = Repository::Darcs.create!(
601 r = Repository::Darcs.create!(
600 :project => @project, :url => '/tmp/test/darcs',
602 :project => @project, :url => '/tmp/test/darcs',
601 :log_encoding => 'UTF-8')
603 :log_encoding => 'UTF-8')
602 assert r
604 assert r
603 c = Changeset.new(:repository => r,
605 c = Changeset.new(:repository => r,
604 :committed_on => Time.now,
606 :committed_on => Time.now,
605 :revision => '123',
607 :revision => '123',
606 :scmid => '20080308225258-98289-abcd456efg.gz',
608 :scmid => '20080308225258-98289-abcd456efg.gz',
607 :comments => 'test commit')
609 :comments => 'test commit')
608 assert( c.save )
610 assert( c.save )
609 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
611 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
610 end
612 end
611
613
612 def test_redmine_links_mercurial_commit
614 def test_redmine_links_mercurial_commit
613 changeset_link_rev = link_to('r123',
615 changeset_link_rev = link_to('r123',
614 {
616 {
615 :controller => 'repositories',
617 :controller => 'repositories',
616 :action => 'revision',
618 :action => 'revision',
617 :id => 'subproject1',
619 :id => 'subproject1',
618 :rev => '123' ,
620 :rev => '123' ,
619 },
621 },
620 :class => 'changeset', :title => 'test commit')
622 :class => 'changeset', :title => 'test commit')
621 changeset_link_commit = link_to('abcd',
623 changeset_link_commit = link_to('abcd',
622 {
624 {
623 :controller => 'repositories',
625 :controller => 'repositories',
624 :action => 'revision',
626 :action => 'revision',
625 :id => 'subproject1',
627 :id => 'subproject1',
626 :rev => 'abcd' ,
628 :rev => 'abcd' ,
627 },
629 },
628 :class => 'changeset', :title => 'test commit')
630 :class => 'changeset', :title => 'test commit')
629 to_test = {
631 to_test = {
630 'r123' => changeset_link_rev,
632 'r123' => changeset_link_rev,
631 'commit:abcd' => changeset_link_commit,
633 'commit:abcd' => changeset_link_commit,
632 }
634 }
633 @project = Project.find(3)
635 @project = Project.find(3)
634 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
636 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
635 assert r
637 assert r
636 c = Changeset.new(:repository => r,
638 c = Changeset.new(:repository => r,
637 :committed_on => Time.now,
639 :committed_on => Time.now,
638 :revision => '123',
640 :revision => '123',
639 :scmid => 'abcd',
641 :scmid => 'abcd',
640 :comments => 'test commit')
642 :comments => 'test commit')
641 assert( c.save )
643 assert( c.save )
642 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
644 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
643 end
645 end
644
646
645 def test_attachment_links
647 def test_attachment_links
646 text = 'attachment:error281.txt'
648 text = 'attachment:error281.txt'
647 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
649 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
648 :class => "attachment")
650 :class => "attachment")
649 assert_equal "<p>#{result}</p>",
651 assert_equal "<p>#{result}</p>",
650 textilizable(text,
652 textilizable(text,
651 :attachments => Issue.find(3).attachments),
653 :attachments => Issue.find(3).attachments),
652 "#{text} failed"
654 "#{text} failed"
653 end
655 end
654
656
655 def test_attachment_link_should_link_to_latest_attachment
657 def test_attachment_link_should_link_to_latest_attachment
656 set_tmp_attachments_directory
658 set_tmp_attachments_directory
657 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
659 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
658 a2 = Attachment.generate!(:filename => "test.txt")
660 a2 = Attachment.generate!(:filename => "test.txt")
659 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
661 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
660 :class => "attachment")
662 :class => "attachment")
661 assert_equal "<p>#{result}</p>",
663 assert_equal "<p>#{result}</p>",
662 textilizable('attachment:test.txt', :attachments => [a1, a2])
664 textilizable('attachment:test.txt', :attachments => [a1, a2])
663 end
665 end
664
666
665 def test_wiki_links
667 def test_wiki_links
666 russian_eacape = CGI.escape(@russian_test)
668 russian_eacape = CGI.escape(@russian_test)
667 to_test = {
669 to_test = {
668 '[[CookBook documentation]]' =>
670 '[[CookBook documentation]]' =>
669 link_to("CookBook documentation",
671 link_to("CookBook documentation",
670 "/projects/ecookbook/wiki/CookBook_documentation",
672 "/projects/ecookbook/wiki/CookBook_documentation",
671 :class => "wiki-page"),
673 :class => "wiki-page"),
672 '[[Another page|Page]]' =>
674 '[[Another page|Page]]' =>
673 link_to("Page",
675 link_to("Page",
674 "/projects/ecookbook/wiki/Another_page",
676 "/projects/ecookbook/wiki/Another_page",
675 :class => "wiki-page"),
677 :class => "wiki-page"),
676 # title content should be formatted
678 # title content should be formatted
677 '[[Another page|With _styled_ *title*]]' =>
679 '[[Another page|With _styled_ *title*]]' =>
678 link_to("With <em>styled</em> <strong>title</strong>".html_safe,
680 link_to("With <em>styled</em> <strong>title</strong>".html_safe,
679 "/projects/ecookbook/wiki/Another_page",
681 "/projects/ecookbook/wiki/Another_page",
680 :class => "wiki-page"),
682 :class => "wiki-page"),
681 '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' =>
683 '[[Another page|With title containing <strong>HTML entities &amp; markups</strong>]]' =>
682 link_to("With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;".html_safe,
684 link_to("With title containing &lt;strong&gt;HTML entities &amp; markups&lt;/strong&gt;".html_safe,
683 "/projects/ecookbook/wiki/Another_page",
685 "/projects/ecookbook/wiki/Another_page",
684 :class => "wiki-page"),
686 :class => "wiki-page"),
685 # link with anchor
687 # link with anchor
686 '[[CookBook documentation#One-section]]' =>
688 '[[CookBook documentation#One-section]]' =>
687 link_to("CookBook documentation",
689 link_to("CookBook documentation",
688 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
690 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
689 :class => "wiki-page"),
691 :class => "wiki-page"),
690 '[[Another page#anchor|Page]]' =>
692 '[[Another page#anchor|Page]]' =>
691 link_to("Page",
693 link_to("Page",
692 "/projects/ecookbook/wiki/Another_page#anchor",
694 "/projects/ecookbook/wiki/Another_page#anchor",
693 :class => "wiki-page"),
695 :class => "wiki-page"),
694 # UTF8 anchor
696 # UTF8 anchor
695 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
697 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
696 link_to(@russian_test,
698 link_to(@russian_test,
697 "/projects/ecookbook/wiki/Another_page##{russian_eacape}",
699 "/projects/ecookbook/wiki/Another_page##{russian_eacape}",
698 :class => "wiki-page"),
700 :class => "wiki-page"),
699 # page that doesn't exist
701 # page that doesn't exist
700 '[[Unknown page]]' =>
702 '[[Unknown page]]' =>
701 link_to("Unknown page",
703 link_to("Unknown page",
702 "/projects/ecookbook/wiki/Unknown_page",
704 "/projects/ecookbook/wiki/Unknown_page",
703 :class => "wiki-page new"),
705 :class => "wiki-page new"),
704 '[[Unknown page|404]]' =>
706 '[[Unknown page|404]]' =>
705 link_to("404",
707 link_to("404",
706 "/projects/ecookbook/wiki/Unknown_page",
708 "/projects/ecookbook/wiki/Unknown_page",
707 :class => "wiki-page new"),
709 :class => "wiki-page new"),
708 # link to another project wiki
710 # link to another project wiki
709 '[[onlinestore:]]' =>
711 '[[onlinestore:]]' =>
710 link_to("onlinestore",
712 link_to("onlinestore",
711 "/projects/onlinestore/wiki",
713 "/projects/onlinestore/wiki",
712 :class => "wiki-page"),
714 :class => "wiki-page"),
713 '[[onlinestore:|Wiki]]' =>
715 '[[onlinestore:|Wiki]]' =>
714 link_to("Wiki",
716 link_to("Wiki",
715 "/projects/onlinestore/wiki",
717 "/projects/onlinestore/wiki",
716 :class => "wiki-page"),
718 :class => "wiki-page"),
717 '[[onlinestore:Start page]]' =>
719 '[[onlinestore:Start page]]' =>
718 link_to("Start page",
720 link_to("Start page",
719 "/projects/onlinestore/wiki/Start_page",
721 "/projects/onlinestore/wiki/Start_page",
720 :class => "wiki-page"),
722 :class => "wiki-page"),
721 '[[onlinestore:Start page|Text]]' =>
723 '[[onlinestore:Start page|Text]]' =>
722 link_to("Text",
724 link_to("Text",
723 "/projects/onlinestore/wiki/Start_page",
725 "/projects/onlinestore/wiki/Start_page",
724 :class => "wiki-page"),
726 :class => "wiki-page"),
725 '[[onlinestore:Unknown page]]' =>
727 '[[onlinestore:Unknown page]]' =>
726 link_to("Unknown page",
728 link_to("Unknown page",
727 "/projects/onlinestore/wiki/Unknown_page",
729 "/projects/onlinestore/wiki/Unknown_page",
728 :class => "wiki-page new"),
730 :class => "wiki-page new"),
729 # struck through link
731 # struck through link
730 '-[[Another page|Page]]-' =>
732 '-[[Another page|Page]]-' =>
731 "<del>".html_safe +
733 "<del>".html_safe +
732 link_to("Page",
734 link_to("Page",
733 "/projects/ecookbook/wiki/Another_page",
735 "/projects/ecookbook/wiki/Another_page",
734 :class => "wiki-page").html_safe +
736 :class => "wiki-page").html_safe +
735 "</del>".html_safe,
737 "</del>".html_safe,
736 '-[[Another page|Page]] link-' =>
738 '-[[Another page|Page]] link-' =>
737 "<del>".html_safe +
739 "<del>".html_safe +
738 link_to("Page",
740 link_to("Page",
739 "/projects/ecookbook/wiki/Another_page",
741 "/projects/ecookbook/wiki/Another_page",
740 :class => "wiki-page").html_safe +
742 :class => "wiki-page").html_safe +
741 " link</del>".html_safe,
743 " link</del>".html_safe,
742 # escaping
744 # escaping
743 '![[Another page|Page]]' => '[[Another page|Page]]',
745 '![[Another page|Page]]' => '[[Another page|Page]]',
744 # project does not exist
746 # project does not exist
745 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
747 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
746 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
748 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
747 }
749 }
748 @project = Project.find(1)
750 @project = Project.find(1)
749 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
751 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
750 end
752 end
751
753
752 def test_wiki_links_within_local_file_generation_context
754 def test_wiki_links_within_local_file_generation_context
753 to_test = {
755 to_test = {
754 # link to a page
756 # link to a page
755 '[[CookBook documentation]]' =>
757 '[[CookBook documentation]]' =>
756 link_to("CookBook documentation", "CookBook_documentation.html",
758 link_to("CookBook documentation", "CookBook_documentation.html",
757 :class => "wiki-page"),
759 :class => "wiki-page"),
758 '[[CookBook documentation|documentation]]' =>
760 '[[CookBook documentation|documentation]]' =>
759 link_to("documentation", "CookBook_documentation.html",
761 link_to("documentation", "CookBook_documentation.html",
760 :class => "wiki-page"),
762 :class => "wiki-page"),
761 '[[CookBook documentation#One-section]]' =>
763 '[[CookBook documentation#One-section]]' =>
762 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
764 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
763 :class => "wiki-page"),
765 :class => "wiki-page"),
764 '[[CookBook documentation#One-section|documentation]]' =>
766 '[[CookBook documentation#One-section|documentation]]' =>
765 link_to("documentation", "CookBook_documentation.html#One-section",
767 link_to("documentation", "CookBook_documentation.html#One-section",
766 :class => "wiki-page"),
768 :class => "wiki-page"),
767 # page that doesn't exist
769 # page that doesn't exist
768 '[[Unknown page]]' =>
770 '[[Unknown page]]' =>
769 link_to("Unknown page", "Unknown_page.html",
771 link_to("Unknown page", "Unknown_page.html",
770 :class => "wiki-page new"),
772 :class => "wiki-page new"),
771 '[[Unknown page|404]]' =>
773 '[[Unknown page|404]]' =>
772 link_to("404", "Unknown_page.html",
774 link_to("404", "Unknown_page.html",
773 :class => "wiki-page new"),
775 :class => "wiki-page new"),
774 '[[Unknown page#anchor]]' =>
776 '[[Unknown page#anchor]]' =>
775 link_to("Unknown page", "Unknown_page.html#anchor",
777 link_to("Unknown page", "Unknown_page.html#anchor",
776 :class => "wiki-page new"),
778 :class => "wiki-page new"),
777 '[[Unknown page#anchor|404]]' =>
779 '[[Unknown page#anchor|404]]' =>
778 link_to("404", "Unknown_page.html#anchor",
780 link_to("404", "Unknown_page.html#anchor",
779 :class => "wiki-page new"),
781 :class => "wiki-page new"),
780 }
782 }
781 @project = Project.find(1)
783 @project = Project.find(1)
782 to_test.each do |text, result|
784 to_test.each do |text, result|
783 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
785 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
784 end
786 end
785 end
787 end
786
788
787 def test_wiki_links_within_wiki_page_context
789 def test_wiki_links_within_wiki_page_context
788 page = WikiPage.find_by_title('Another_page' )
790 page = WikiPage.find_by_title('Another_page' )
789 to_test = {
791 to_test = {
790 '[[CookBook documentation]]' =>
792 '[[CookBook documentation]]' =>
791 link_to("CookBook documentation",
793 link_to("CookBook documentation",
792 "/projects/ecookbook/wiki/CookBook_documentation",
794 "/projects/ecookbook/wiki/CookBook_documentation",
793 :class => "wiki-page"),
795 :class => "wiki-page"),
794 '[[CookBook documentation|documentation]]' =>
796 '[[CookBook documentation|documentation]]' =>
795 link_to("documentation",
797 link_to("documentation",
796 "/projects/ecookbook/wiki/CookBook_documentation",
798 "/projects/ecookbook/wiki/CookBook_documentation",
797 :class => "wiki-page"),
799 :class => "wiki-page"),
798 '[[CookBook documentation#One-section]]' =>
800 '[[CookBook documentation#One-section]]' =>
799 link_to("CookBook documentation",
801 link_to("CookBook documentation",
800 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
802 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
801 :class => "wiki-page"),
803 :class => "wiki-page"),
802 '[[CookBook documentation#One-section|documentation]]' =>
804 '[[CookBook documentation#One-section|documentation]]' =>
803 link_to("documentation",
805 link_to("documentation",
804 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
806 "/projects/ecookbook/wiki/CookBook_documentation#One-section",
805 :class => "wiki-page"),
807 :class => "wiki-page"),
806 # link to the current page
808 # link to the current page
807 '[[Another page]]' =>
809 '[[Another page]]' =>
808 link_to("Another page",
810 link_to("Another page",
809 "/projects/ecookbook/wiki/Another_page",
811 "/projects/ecookbook/wiki/Another_page",
810 :class => "wiki-page"),
812 :class => "wiki-page"),
811 '[[Another page|Page]]' =>
813 '[[Another page|Page]]' =>
812 link_to("Page",
814 link_to("Page",
813 "/projects/ecookbook/wiki/Another_page",
815 "/projects/ecookbook/wiki/Another_page",
814 :class => "wiki-page"),
816 :class => "wiki-page"),
815 '[[Another page#anchor]]' =>
817 '[[Another page#anchor]]' =>
816 link_to("Another page",
818 link_to("Another page",
817 "#anchor",
819 "#anchor",
818 :class => "wiki-page"),
820 :class => "wiki-page"),
819 '[[Another page#anchor|Page]]' =>
821 '[[Another page#anchor|Page]]' =>
820 link_to("Page",
822 link_to("Page",
821 "#anchor",
823 "#anchor",
822 :class => "wiki-page"),
824 :class => "wiki-page"),
823 # page that doesn't exist
825 # page that doesn't exist
824 '[[Unknown page]]' =>
826 '[[Unknown page]]' =>
825 link_to("Unknown page",
827 link_to("Unknown page",
826 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
828 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
827 :class => "wiki-page new"),
829 :class => "wiki-page new"),
828 '[[Unknown page|404]]' =>
830 '[[Unknown page|404]]' =>
829 link_to("404",
831 link_to("404",
830 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
832 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page",
831 :class => "wiki-page new"),
833 :class => "wiki-page new"),
832 '[[Unknown page#anchor]]' =>
834 '[[Unknown page#anchor]]' =>
833 link_to("Unknown page",
835 link_to("Unknown page",
834 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
836 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
835 :class => "wiki-page new"),
837 :class => "wiki-page new"),
836 '[[Unknown page#anchor|404]]' =>
838 '[[Unknown page#anchor|404]]' =>
837 link_to("404",
839 link_to("404",
838 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
840 "/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor",
839 :class => "wiki-page new"),
841 :class => "wiki-page new"),
840 }
842 }
841 @project = Project.find(1)
843 @project = Project.find(1)
842 to_test.each do |text, result|
844 to_test.each do |text, result|
843 assert_equal "<p>#{result}</p>",
845 assert_equal "<p>#{result}</p>",
844 textilizable(WikiContent.new( :text => text, :page => page ), :text)
846 textilizable(WikiContent.new( :text => text, :page => page ), :text)
845 end
847 end
846 end
848 end
847
849
848 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
850 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
849 to_test = {
851 to_test = {
850 # link to a page
852 # link to a page
851 '[[CookBook documentation]]' =>
853 '[[CookBook documentation]]' =>
852 link_to("CookBook documentation",
854 link_to("CookBook documentation",
853 "#CookBook_documentation",
855 "#CookBook_documentation",
854 :class => "wiki-page"),
856 :class => "wiki-page"),
855 '[[CookBook documentation|documentation]]' =>
857 '[[CookBook documentation|documentation]]' =>
856 link_to("documentation",
858 link_to("documentation",
857 "#CookBook_documentation",
859 "#CookBook_documentation",
858 :class => "wiki-page"),
860 :class => "wiki-page"),
859 '[[CookBook documentation#One-section]]' =>
861 '[[CookBook documentation#One-section]]' =>
860 link_to("CookBook documentation",
862 link_to("CookBook documentation",
861 "#CookBook_documentation_One-section",
863 "#CookBook_documentation_One-section",
862 :class => "wiki-page"),
864 :class => "wiki-page"),
863 '[[CookBook documentation#One-section|documentation]]' =>
865 '[[CookBook documentation#One-section|documentation]]' =>
864 link_to("documentation",
866 link_to("documentation",
865 "#CookBook_documentation_One-section",
867 "#CookBook_documentation_One-section",
866 :class => "wiki-page"),
868 :class => "wiki-page"),
867 # page that doesn't exist
869 # page that doesn't exist
868 '[[Unknown page]]' =>
870 '[[Unknown page]]' =>
869 link_to("Unknown page",
871 link_to("Unknown page",
870 "#Unknown_page",
872 "#Unknown_page",
871 :class => "wiki-page new"),
873 :class => "wiki-page new"),
872 '[[Unknown page|404]]' =>
874 '[[Unknown page|404]]' =>
873 link_to("404",
875 link_to("404",
874 "#Unknown_page",
876 "#Unknown_page",
875 :class => "wiki-page new"),
877 :class => "wiki-page new"),
876 '[[Unknown page#anchor]]' =>
878 '[[Unknown page#anchor]]' =>
877 link_to("Unknown page",
879 link_to("Unknown page",
878 "#Unknown_page_anchor",
880 "#Unknown_page_anchor",
879 :class => "wiki-page new"),
881 :class => "wiki-page new"),
880 '[[Unknown page#anchor|404]]' =>
882 '[[Unknown page#anchor|404]]' =>
881 link_to("404",
883 link_to("404",
882 "#Unknown_page_anchor",
884 "#Unknown_page_anchor",
883 :class => "wiki-page new"),
885 :class => "wiki-page new"),
884 }
886 }
885 @project = Project.find(1)
887 @project = Project.find(1)
886 to_test.each do |text, result|
888 to_test.each do |text, result|
887 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
889 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
888 end
890 end
889 end
891 end
890
892
891 def test_html_tags
893 def test_html_tags
892 to_test = {
894 to_test = {
893 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
895 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
894 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
896 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
895 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
897 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
896 # do not escape pre/code tags
898 # do not escape pre/code tags
897 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
899 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
898 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
900 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
899 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
901 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
900 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
902 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
901 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
903 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
902 # remove attributes except class
904 # remove attributes except class
903 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
905 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
904 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
906 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
905 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
907 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
906 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
908 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
907 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
909 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
908 # xss
910 # xss
909 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
911 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
910 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
912 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
911 }
913 }
912 to_test.each { |text, result| assert_equal result, textilizable(text) }
914 to_test.each { |text, result| assert_equal result, textilizable(text) }
913 end
915 end
914
916
915 def test_allowed_html_tags
917 def test_allowed_html_tags
916 to_test = {
918 to_test = {
917 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
919 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
918 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
920 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
919 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
921 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
920 }
922 }
921 to_test.each { |text, result| assert_equal result, textilizable(text) }
923 to_test.each { |text, result| assert_equal result, textilizable(text) }
922 end
924 end
923
925
924 def test_pre_tags
926 def test_pre_tags
925 raw = <<-RAW
927 raw = <<-RAW
926 Before
928 Before
927
929
928 <pre>
930 <pre>
929 <prepared-statement-cache-size>32</prepared-statement-cache-size>
931 <prepared-statement-cache-size>32</prepared-statement-cache-size>
930 </pre>
932 </pre>
931
933
932 After
934 After
933 RAW
935 RAW
934
936
935 expected = <<-EXPECTED
937 expected = <<-EXPECTED
936 <p>Before</p>
938 <p>Before</p>
937 <pre>
939 <pre>
938 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
940 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
939 </pre>
941 </pre>
940 <p>After</p>
942 <p>After</p>
941 EXPECTED
943 EXPECTED
942
944
943 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
945 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
944 end
946 end
945
947
946 def test_pre_content_should_not_parse_wiki_and_redmine_links
948 def test_pre_content_should_not_parse_wiki_and_redmine_links
947 raw = <<-RAW
949 raw = <<-RAW
948 [[CookBook documentation]]
950 [[CookBook documentation]]
949
951
950 #1
952 #1
951
953
952 <pre>
954 <pre>
953 [[CookBook documentation]]
955 [[CookBook documentation]]
954
956
955 #1
957 #1
956 </pre>
958 </pre>
957 RAW
959 RAW
958
960
959 result1 = link_to("CookBook documentation",
961 result1 = link_to("CookBook documentation",
960 "/projects/ecookbook/wiki/CookBook_documentation",
962 "/projects/ecookbook/wiki/CookBook_documentation",
961 :class => "wiki-page")
963 :class => "wiki-page")
962 result2 = link_to('#1',
964 result2 = link_to('#1',
963 "/issues/1",
965 "/issues/1",
964 :class => Issue.find(1).css_classes,
966 :class => Issue.find(1).css_classes,
965 :title => "Cannot print recipes (New)")
967 :title => "Cannot print recipes (New)")
966
968
967 expected = <<-EXPECTED
969 expected = <<-EXPECTED
968 <p>#{result1}</p>
970 <p>#{result1}</p>
969 <p>#{result2}</p>
971 <p>#{result2}</p>
970 <pre>
972 <pre>
971 [[CookBook documentation]]
973 [[CookBook documentation]]
972
974
973 #1
975 #1
974 </pre>
976 </pre>
975 EXPECTED
977 EXPECTED
976
978
977 @project = Project.find(1)
979 @project = Project.find(1)
978 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
980 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
979 end
981 end
980
982
981 def test_non_closing_pre_blocks_should_be_closed
983 def test_non_closing_pre_blocks_should_be_closed
982 raw = <<-RAW
984 raw = <<-RAW
983 <pre><code>
985 <pre><code>
984 RAW
986 RAW
985
987
986 expected = <<-EXPECTED
988 expected = <<-EXPECTED
987 <pre><code>
989 <pre><code>
988 </code></pre>
990 </code></pre>
989 EXPECTED
991 EXPECTED
990
992
991 @project = Project.find(1)
993 @project = Project.find(1)
992 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
994 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
993 end
995 end
994
996
995 def test_syntax_highlight
997 def test_syntax_highlight
996 raw = <<-RAW
998 raw = <<-RAW
997 <pre><code class="ruby">
999 <pre><code class="ruby">
998 # Some ruby code here
1000 # Some ruby code here
999 </code></pre>
1001 </code></pre>
1000 RAW
1002 RAW
1001
1003
1002 expected = <<-EXPECTED
1004 expected = <<-EXPECTED
1003 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
1005 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
1004 </code></pre>
1006 </code></pre>
1005 EXPECTED
1007 EXPECTED
1006
1008
1007 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1009 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1008 end
1010 end
1009
1011
1010 def test_to_path_param
1012 def test_to_path_param
1011 assert_equal 'test1/test2', to_path_param('test1/test2')
1013 assert_equal 'test1/test2', to_path_param('test1/test2')
1012 assert_equal 'test1/test2', to_path_param('/test1/test2/')
1014 assert_equal 'test1/test2', to_path_param('/test1/test2/')
1013 assert_equal 'test1/test2', to_path_param('//test1/test2/')
1015 assert_equal 'test1/test2', to_path_param('//test1/test2/')
1014 assert_equal nil, to_path_param('/')
1016 assert_equal nil, to_path_param('/')
1015 end
1017 end
1016
1018
1017 def test_wiki_links_in_tables
1019 def test_wiki_links_in_tables
1018 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
1020 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
1019 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
1021 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
1020 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
1022 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
1021 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
1023 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
1022 result = "<tr><td>#{link1}</td>" +
1024 result = "<tr><td>#{link1}</td>" +
1023 "<td>#{link2}</td>" +
1025 "<td>#{link2}</td>" +
1024 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
1026 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
1025 @project = Project.find(1)
1027 @project = Project.find(1)
1026 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
1028 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
1027 end
1029 end
1028
1030
1029 def test_text_formatting
1031 def test_text_formatting
1030 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
1032 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
1031 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
1033 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
1032 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
1034 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
1033 '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>',
1035 '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>',
1034 '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',
1036 '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',
1035 }
1037 }
1036 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
1038 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
1037 end
1039 end
1038
1040
1039 def test_wiki_horizontal_rule
1041 def test_wiki_horizontal_rule
1040 assert_equal '<hr />', textilizable('---')
1042 assert_equal '<hr />', textilizable('---')
1041 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
1043 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
1042 end
1044 end
1043
1045
1044 def test_footnotes
1046 def test_footnotes
1045 raw = <<-RAW
1047 raw = <<-RAW
1046 This is some text[1].
1048 This is some text[1].
1047
1049
1048 fn1. This is the foot note
1050 fn1. This is the foot note
1049 RAW
1051 RAW
1050
1052
1051 expected = <<-EXPECTED
1053 expected = <<-EXPECTED
1052 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
1054 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
1053 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
1055 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
1054 EXPECTED
1056 EXPECTED
1055
1057
1056 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1058 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
1057 end
1059 end
1058
1060
1059 def test_headings
1061 def test_headings
1060 raw = 'h1. Some heading'
1062 raw = 'h1. Some heading'
1061 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
1063 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
1062
1064
1063 assert_equal expected, textilizable(raw)
1065 assert_equal expected, textilizable(raw)
1064 end
1066 end
1065
1067
1066 def test_headings_with_special_chars
1068 def test_headings_with_special_chars
1067 # This test makes sure that the generated anchor names match the expected
1069 # This test makes sure that the generated anchor names match the expected
1068 # ones even if the heading text contains unconventional characters
1070 # ones even if the heading text contains unconventional characters
1069 raw = 'h1. Some heading related to version 0.5'
1071 raw = 'h1. Some heading related to version 0.5'
1070 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
1072 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
1071 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
1073 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
1072
1074
1073 assert_equal expected, textilizable(raw)
1075 assert_equal expected, textilizable(raw)
1074 end
1076 end
1075
1077
1076 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
1078 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
1077 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
1079 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
1078 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
1080 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
1079
1081
1080 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
1082 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
1081
1083
1082 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
1084 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
1083 end
1085 end
1084
1086
1085 def test_table_of_content
1087 def test_table_of_content
1086 raw = <<-RAW
1088 raw = <<-RAW
1087 {{toc}}
1089 {{toc}}
1088
1090
1089 h1. Title
1091 h1. Title
1090
1092
1091 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1093 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1092
1094
1093 h2. Subtitle with a [[Wiki]] link
1095 h2. Subtitle with a [[Wiki]] link
1094
1096
1095 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
1097 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
1096
1098
1097 h2. Subtitle with [[Wiki|another Wiki]] link
1099 h2. Subtitle with [[Wiki|another Wiki]] link
1098
1100
1099 h2. Subtitle with %{color:red}red text%
1101 h2. Subtitle with %{color:red}red text%
1100
1102
1101 <pre>
1103 <pre>
1102 some code
1104 some code
1103 </pre>
1105 </pre>
1104
1106
1105 h3. Subtitle with *some* _modifiers_
1107 h3. Subtitle with *some* _modifiers_
1106
1108
1107 h3. Subtitle with @inline code@
1109 h3. Subtitle with @inline code@
1108
1110
1109 h1. Another title
1111 h1. Another title
1110
1112
1111 h3. An "Internet link":http://www.redmine.org/ inside subtitle
1113 h3. An "Internet link":http://www.redmine.org/ inside subtitle
1112
1114
1113 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
1115 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
1114
1116
1115 RAW
1117 RAW
1116
1118
1117 expected = '<ul class="toc">' +
1119 expected = '<ul class="toc">' +
1118 '<li><a href="#Title">Title</a>' +
1120 '<li><a href="#Title">Title</a>' +
1119 '<ul>' +
1121 '<ul>' +
1120 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
1122 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
1121 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
1123 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
1122 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
1124 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
1123 '<ul>' +
1125 '<ul>' +
1124 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
1126 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
1125 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
1127 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
1126 '</ul>' +
1128 '</ul>' +
1127 '</li>' +
1129 '</li>' +
1128 '</ul>' +
1130 '</ul>' +
1129 '</li>' +
1131 '</li>' +
1130 '<li><a href="#Another-title">Another title</a>' +
1132 '<li><a href="#Another-title">Another title</a>' +
1131 '<ul>' +
1133 '<ul>' +
1132 '<li>' +
1134 '<li>' +
1133 '<ul>' +
1135 '<ul>' +
1134 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
1136 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
1135 '</ul>' +
1137 '</ul>' +
1136 '</li>' +
1138 '</li>' +
1137 '<li><a href="#Project-Name">Project Name</a></li>' +
1139 '<li><a href="#Project-Name">Project Name</a></li>' +
1138 '</ul>' +
1140 '</ul>' +
1139 '</li>' +
1141 '</li>' +
1140 '</ul>'
1142 '</ul>'
1141
1143
1142 @project = Project.find(1)
1144 @project = Project.find(1)
1143 assert textilizable(raw).gsub("\n", "").include?(expected)
1145 assert textilizable(raw).gsub("\n", "").include?(expected)
1144 end
1146 end
1145
1147
1146 def test_table_of_content_should_generate_unique_anchors
1148 def test_table_of_content_should_generate_unique_anchors
1147 raw = <<-RAW
1149 raw = <<-RAW
1148 {{toc}}
1150 {{toc}}
1149
1151
1150 h1. Title
1152 h1. Title
1151
1153
1152 h2. Subtitle
1154 h2. Subtitle
1153
1155
1154 h2. Subtitle
1156 h2. Subtitle
1155 RAW
1157 RAW
1156
1158
1157 expected = '<ul class="toc">' +
1159 expected = '<ul class="toc">' +
1158 '<li><a href="#Title">Title</a>' +
1160 '<li><a href="#Title">Title</a>' +
1159 '<ul>' +
1161 '<ul>' +
1160 '<li><a href="#Subtitle">Subtitle</a></li>' +
1162 '<li><a href="#Subtitle">Subtitle</a></li>' +
1161 '<li><a href="#Subtitle-2">Subtitle</a></li>'
1163 '<li><a href="#Subtitle-2">Subtitle</a></li>'
1162 '</ul>'
1164 '</ul>'
1163 '</li>' +
1165 '</li>' +
1164 '</ul>'
1166 '</ul>'
1165
1167
1166 @project = Project.find(1)
1168 @project = Project.find(1)
1167 result = textilizable(raw).gsub("\n", "")
1169 result = textilizable(raw).gsub("\n", "")
1168 assert_include expected, result
1170 assert_include expected, result
1169 assert_include '<a name="Subtitle">', result
1171 assert_include '<a name="Subtitle">', result
1170 assert_include '<a name="Subtitle-2">', result
1172 assert_include '<a name="Subtitle-2">', result
1171 end
1173 end
1172
1174
1173 def test_table_of_content_should_contain_included_page_headings
1175 def test_table_of_content_should_contain_included_page_headings
1174 raw = <<-RAW
1176 raw = <<-RAW
1175 {{toc}}
1177 {{toc}}
1176
1178
1177 h1. Included
1179 h1. Included
1178
1180
1179 {{include(Child_1)}}
1181 {{include(Child_1)}}
1180 RAW
1182 RAW
1181
1183
1182 expected = '<ul class="toc">' +
1184 expected = '<ul class="toc">' +
1183 '<li><a href="#Included">Included</a></li>' +
1185 '<li><a href="#Included">Included</a></li>' +
1184 '<li><a href="#Child-page-1">Child page 1</a></li>' +
1186 '<li><a href="#Child-page-1">Child page 1</a></li>' +
1185 '</ul>'
1187 '</ul>'
1186
1188
1187 @project = Project.find(1)
1189 @project = Project.find(1)
1188 assert textilizable(raw).gsub("\n", "").include?(expected)
1190 assert textilizable(raw).gsub("\n", "").include?(expected)
1189 end
1191 end
1190
1192
1191 def test_toc_with_textile_formatting_should_be_parsed
1193 def test_toc_with_textile_formatting_should_be_parsed
1192 with_settings :text_formatting => 'textile' do
1194 with_settings :text_formatting => 'textile' do
1193 assert_select_in textilizable("{{toc}}\n\nh1. Heading"), 'ul.toc li', :text => 'Heading'
1195 assert_select_in textilizable("{{toc}}\n\nh1. Heading"), 'ul.toc li', :text => 'Heading'
1194 assert_select_in textilizable("{{<toc}}\n\nh1. Heading"), 'ul.toc.left li', :text => 'Heading'
1196 assert_select_in textilizable("{{<toc}}\n\nh1. Heading"), 'ul.toc.left li', :text => 'Heading'
1195 assert_select_in textilizable("{{>toc}}\n\nh1. Heading"), 'ul.toc.right li', :text => 'Heading'
1197 assert_select_in textilizable("{{>toc}}\n\nh1. Heading"), 'ul.toc.right li', :text => 'Heading'
1196 end
1198 end
1197 end
1199 end
1198
1200
1199 if Object.const_defined?(:Redcarpet)
1201 if Object.const_defined?(:Redcarpet)
1200 def test_toc_with_markdown_formatting_should_be_parsed
1202 def test_toc_with_markdown_formatting_should_be_parsed
1201 with_settings :text_formatting => 'markdown' do
1203 with_settings :text_formatting => 'markdown' do
1202 assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
1204 assert_select_in textilizable("{{toc}}\n\n# Heading"), 'ul.toc li', :text => 'Heading'
1203 assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
1205 assert_select_in textilizable("{{<toc}}\n\n# Heading"), 'ul.toc.left li', :text => 'Heading'
1204 assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
1206 assert_select_in textilizable("{{>toc}}\n\n# Heading"), 'ul.toc.right li', :text => 'Heading'
1205 end
1207 end
1206 end
1208 end
1207 end
1209 end
1208
1210
1209 def test_section_edit_links
1211 def test_section_edit_links
1210 raw = <<-RAW
1212 raw = <<-RAW
1211 h1. Title
1213 h1. Title
1212
1214
1213 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1215 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1214
1216
1215 h2. Subtitle with a [[Wiki]] link
1217 h2. Subtitle with a [[Wiki]] link
1216
1218
1217 h2. Subtitle with *some* _modifiers_
1219 h2. Subtitle with *some* _modifiers_
1218
1220
1219 h2. Subtitle with @inline code@
1221 h2. Subtitle with @inline code@
1220
1222
1221 <pre>
1223 <pre>
1222 some code
1224 some code
1223
1225
1224 h2. heading inside pre
1226 h2. heading inside pre
1225
1227
1226 <h2>html heading inside pre</h2>
1228 <h2>html heading inside pre</h2>
1227 </pre>
1229 </pre>
1228
1230
1229 h2. Subtitle after pre tag
1231 h2. Subtitle after pre tag
1230 RAW
1232 RAW
1231
1233
1232 @project = Project.find(1)
1234 @project = Project.find(1)
1233 set_language_if_valid 'en'
1235 set_language_if_valid 'en'
1234 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1236 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1235
1237
1236 # heading that contains inline code
1238 # heading that contains inline code
1237 assert_match Regexp.new('<div class="contextual" title="Edit this section" id="section-4">' +
1239 assert_match Regexp.new('<div class="contextual" title="Edit this section" id="section-4">' +
1238 '<a href="/projects/1/wiki/Test/edit\?section=4"><img src="/images/edit.png(\?\d+)?" alt="Edit" /></a></div>' +
1240 '<a href="/projects/1/wiki/Test/edit\?section=4"><img src="/images/edit.png(\?\d+)?" alt="Edit" /></a></div>' +
1239 '<a name="Subtitle-with-inline-code"></a>' +
1241 '<a name="Subtitle-with-inline-code"></a>' +
1240 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1242 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1241 result
1243 result
1242
1244
1243 # last heading
1245 # last heading
1244 assert_match Regexp.new('<div class="contextual" title="Edit this section" id="section-5">' +
1246 assert_match Regexp.new('<div class="contextual" title="Edit this section" id="section-5">' +
1245 '<a href="/projects/1/wiki/Test/edit\?section=5"><img src="/images/edit.png(\?\d+)?" alt="Edit" /></a></div>' +
1247 '<a href="/projects/1/wiki/Test/edit\?section=5"><img src="/images/edit.png(\?\d+)?" alt="Edit" /></a></div>' +
1246 '<a name="Subtitle-after-pre-tag"></a>' +
1248 '<a name="Subtitle-after-pre-tag"></a>' +
1247 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1249 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1248 result
1250 result
1249 end
1251 end
1250
1252
1251 def test_default_formatter
1253 def test_default_formatter
1252 with_settings :text_formatting => 'unknown' do
1254 with_settings :text_formatting => 'unknown' do
1253 text = 'a *link*: http://www.example.net/'
1255 text = 'a *link*: http://www.example.net/'
1254 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1256 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1255 end
1257 end
1256 end
1258 end
1257
1259
1258 def test_due_date_distance_in_words
1260 def test_due_date_distance_in_words
1259 to_test = { Date.today => 'Due in 0 days',
1261 to_test = { Date.today => 'Due in 0 days',
1260 Date.today + 1 => 'Due in 1 day',
1262 Date.today + 1 => 'Due in 1 day',
1261 Date.today + 100 => 'Due in about 3 months',
1263 Date.today + 100 => 'Due in about 3 months',
1262 Date.today + 20000 => 'Due in over 54 years',
1264 Date.today + 20000 => 'Due in over 54 years',
1263 Date.today - 1 => '1 day late',
1265 Date.today - 1 => '1 day late',
1264 Date.today - 100 => 'about 3 months late',
1266 Date.today - 100 => 'about 3 months late',
1265 Date.today - 20000 => 'over 54 years late',
1267 Date.today - 20000 => 'over 54 years late',
1266 }
1268 }
1267 ::I18n.locale = :en
1269 ::I18n.locale = :en
1268 to_test.each do |date, expected|
1270 to_test.each do |date, expected|
1269 assert_equal expected, due_date_distance_in_words(date)
1271 assert_equal expected, due_date_distance_in_words(date)
1270 end
1272 end
1271 end
1273 end
1272
1274
1273 def test_avatar_enabled
1275 def test_avatar_enabled
1274 with_settings :gravatar_enabled => '1' do
1276 with_settings :gravatar_enabled => '1' do
1275 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1277 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1276 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1278 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1277 # Default size is 50
1279 # Default size is 50
1278 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1280 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1279 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1281 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1280 # Non-avatar options should be considered html options
1282 # Non-avatar options should be considered html options
1281 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1283 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1282 # The default class of the img tag should be gravatar
1284 # The default class of the img tag should be gravatar
1283 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1285 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1284 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1286 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1285 assert_nil avatar('jsmith')
1287 assert_nil avatar('jsmith')
1286 assert_nil avatar(nil)
1288 assert_nil avatar(nil)
1287 end
1289 end
1288 end
1290 end
1289
1291
1290 def test_avatar_disabled
1292 def test_avatar_disabled
1291 with_settings :gravatar_enabled => '0' do
1293 with_settings :gravatar_enabled => '0' do
1292 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1294 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1293 end
1295 end
1294 end
1296 end
1295
1297
1296 def test_link_to_user
1298 def test_link_to_user
1297 user = User.find(2)
1299 user = User.find(2)
1298 result = link_to("John Smith", "/users/2", :class => "user active")
1300 result = link_to("John Smith", "/users/2", :class => "user active")
1299 assert_equal result, link_to_user(user)
1301 assert_equal result, link_to_user(user)
1300 end
1302 end
1301
1303
1302 def test_link_to_user_should_not_link_to_locked_user
1304 def test_link_to_user_should_not_link_to_locked_user
1303 with_current_user nil do
1305 with_current_user nil do
1304 user = User.find(5)
1306 user = User.find(5)
1305 assert user.locked?
1307 assert user.locked?
1306 assert_equal 'Dave2 Lopper2', link_to_user(user)
1308 assert_equal 'Dave2 Lopper2', link_to_user(user)
1307 end
1309 end
1308 end
1310 end
1309
1311
1310 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1312 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1311 with_current_user User.find(1) do
1313 with_current_user User.find(1) do
1312 user = User.find(5)
1314 user = User.find(5)
1313 assert user.locked?
1315 assert user.locked?
1314 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1316 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1315 assert_equal result, link_to_user(user)
1317 assert_equal result, link_to_user(user)
1316 end
1318 end
1317 end
1319 end
1318
1320
1319 def test_link_to_user_should_not_link_to_anonymous
1321 def test_link_to_user_should_not_link_to_anonymous
1320 user = User.anonymous
1322 user = User.anonymous
1321 assert user.anonymous?
1323 assert user.anonymous?
1322 t = link_to_user(user)
1324 t = link_to_user(user)
1323 assert_equal ::I18n.t(:label_user_anonymous), t
1325 assert_equal ::I18n.t(:label_user_anonymous), t
1324 end
1326 end
1325
1327
1326 def test_link_to_attachment
1328 def test_link_to_attachment
1327 a = Attachment.find(3)
1329 a = Attachment.find(3)
1328 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1330 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1329 link_to_attachment(a)
1331 link_to_attachment(a)
1330 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1332 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1331 link_to_attachment(a, :text => 'Text')
1333 link_to_attachment(a, :text => 'Text')
1332 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1334 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1333 assert_equal result,
1335 assert_equal result,
1334 link_to_attachment(a, :class => 'foo')
1336 link_to_attachment(a, :class => 'foo')
1335 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1337 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1336 link_to_attachment(a, :download => true)
1338 link_to_attachment(a, :download => true)
1337 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1339 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1338 link_to_attachment(a, :only_path => false)
1340 link_to_attachment(a, :only_path => false)
1339 end
1341 end
1340
1342
1341 def test_thumbnail_tag
1343 def test_thumbnail_tag
1342 a = Attachment.find(3)
1344 a = Attachment.find(3)
1343 assert_select_in thumbnail_tag(a),
1345 assert_select_in thumbnail_tag(a),
1344 'a[href=?][title=?] img[alt="3"][src=?]',
1346 'a[href=?][title=?] img[alt="3"][src=?]',
1345 "/attachments/3/logo.gif", "logo.gif", "/attachments/thumbnail/3"
1347 "/attachments/3/logo.gif", "logo.gif", "/attachments/thumbnail/3"
1346 end
1348 end
1347
1349
1348 def test_link_to_project
1350 def test_link_to_project
1349 project = Project.find(1)
1351 project = Project.find(1)
1350 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1352 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1351 link_to_project(project)
1353 link_to_project(project)
1352 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1354 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1353 link_to_project(project, {:only_path => false, :jump => 'blah'})
1355 link_to_project(project, {:only_path => false, :jump => 'blah'})
1354 end
1356 end
1355
1357
1356 def test_link_to_project_settings
1358 def test_link_to_project_settings
1357 project = Project.find(1)
1359 project = Project.find(1)
1358 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1360 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1359
1361
1360 project.status = Project::STATUS_CLOSED
1362 project.status = Project::STATUS_CLOSED
1361 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1363 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1362
1364
1363 project.status = Project::STATUS_ARCHIVED
1365 project.status = Project::STATUS_ARCHIVED
1364 assert_equal 'eCookbook', link_to_project_settings(project)
1366 assert_equal 'eCookbook', link_to_project_settings(project)
1365 end
1367 end
1366
1368
1367 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1369 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1368 # numeric identifier are no longer allowed
1370 # numeric identifier are no longer allowed
1369 Project.where(:id => 1).update_all(:identifier => 25)
1371 Project.where(:id => 1).update_all(:identifier => 25)
1370 assert_equal '<a href="/projects/1">eCookbook</a>',
1372 assert_equal '<a href="/projects/1">eCookbook</a>',
1371 link_to_project(Project.find(1))
1373 link_to_project(Project.find(1))
1372 end
1374 end
1373
1375
1374 def test_principals_options_for_select_with_users
1376 def test_principals_options_for_select_with_users
1375 User.current = nil
1377 User.current = nil
1376 users = [User.find(2), User.find(4)]
1378 users = [User.find(2), User.find(4)]
1377 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1379 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1378 principals_options_for_select(users)
1380 principals_options_for_select(users)
1379 end
1381 end
1380
1382
1381 def test_principals_options_for_select_with_selected
1383 def test_principals_options_for_select_with_selected
1382 User.current = nil
1384 User.current = nil
1383 users = [User.find(2), User.find(4)]
1385 users = [User.find(2), User.find(4)]
1384 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1386 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1385 principals_options_for_select(users, User.find(4))
1387 principals_options_for_select(users, User.find(4))
1386 end
1388 end
1387
1389
1388 def test_principals_options_for_select_with_users_and_groups
1390 def test_principals_options_for_select_with_users_and_groups
1389 User.current = nil
1391 User.current = nil
1390 set_language_if_valid 'en'
1392 set_language_if_valid 'en'
1391 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1393 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1392 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1394 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1393 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1395 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1394 principals_options_for_select(users)
1396 principals_options_for_select(users)
1395 end
1397 end
1396
1398
1397 def test_principals_options_for_select_with_empty_collection
1399 def test_principals_options_for_select_with_empty_collection
1398 assert_equal '', principals_options_for_select([])
1400 assert_equal '', principals_options_for_select([])
1399 end
1401 end
1400
1402
1401 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1403 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1402 set_language_if_valid 'en'
1404 set_language_if_valid 'en'
1403 users = [User.find(2), User.find(4)]
1405 users = [User.find(2), User.find(4)]
1404 User.current = User.find(4)
1406 User.current = User.find(4)
1405 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1407 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1406 end
1408 end
1407
1409
1408 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1410 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1409 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1411 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1410 end
1412 end
1411
1413
1412 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1414 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1413 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1415 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1414 end
1416 end
1415
1417
1416 def test_image_tag_should_pick_the_default_image
1418 def test_image_tag_should_pick_the_default_image
1417 assert_match 'src="/images/image.png"', image_tag("image.png")
1419 assert_match 'src="/images/image.png"', image_tag("image.png")
1418 end
1420 end
1419
1421
1420 def test_image_tag_should_pick_the_theme_image_if_it_exists
1422 def test_image_tag_should_pick_the_theme_image_if_it_exists
1421 theme = Redmine::Themes.themes.last
1423 theme = Redmine::Themes.themes.last
1422 theme.images << 'image.png'
1424 theme.images << 'image.png'
1423
1425
1424 with_settings :ui_theme => theme.id do
1426 with_settings :ui_theme => theme.id do
1425 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1427 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1426 assert_match %|src="/images/other.png"|, image_tag("other.png")
1428 assert_match %|src="/images/other.png"|, image_tag("other.png")
1427 end
1429 end
1428 ensure
1430 ensure
1429 theme.images.delete 'image.png'
1431 theme.images.delete 'image.png'
1430 end
1432 end
1431
1433
1432 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1434 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1433 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1435 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1434 end
1436 end
1435
1437
1436 def test_javascript_include_tag_should_pick_the_default_javascript
1438 def test_javascript_include_tag_should_pick_the_default_javascript
1437 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1439 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1438 end
1440 end
1439
1441
1440 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1442 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1441 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1443 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1442 end
1444 end
1443
1445
1444 def test_raw_json_should_escape_closing_tags
1446 def test_raw_json_should_escape_closing_tags
1445 s = raw_json(["<foo>bar</foo>"])
1447 s = raw_json(["<foo>bar</foo>"])
1446 assert_include '\/foo', s
1448 assert_include '\/foo', s
1447 end
1449 end
1448
1450
1449 def test_raw_json_should_be_html_safe
1451 def test_raw_json_should_be_html_safe
1450 s = raw_json(["foo"])
1452 s = raw_json(["foo"])
1451 assert s.html_safe?
1453 assert s.html_safe?
1452 end
1454 end
1453
1455
1454 def test_html_title_should_app_title_if_not_set
1456 def test_html_title_should_app_title_if_not_set
1455 assert_equal 'Redmine', html_title
1457 assert_equal 'Redmine', html_title
1456 end
1458 end
1457
1459
1458 def test_html_title_should_join_items
1460 def test_html_title_should_join_items
1459 html_title 'Foo', 'Bar'
1461 html_title 'Foo', 'Bar'
1460 assert_equal 'Foo - Bar - Redmine', html_title
1462 assert_equal 'Foo - Bar - Redmine', html_title
1461 end
1463 end
1462
1464
1463 def test_html_title_should_append_current_project_name
1465 def test_html_title_should_append_current_project_name
1464 @project = Project.find(1)
1466 @project = Project.find(1)
1465 html_title 'Foo', 'Bar'
1467 html_title 'Foo', 'Bar'
1466 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1468 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1467 end
1469 end
1468
1470
1469 def test_title_should_return_a_h2_tag
1471 def test_title_should_return_a_h2_tag
1470 assert_equal '<h2>Foo</h2>', title('Foo')
1472 assert_equal '<h2>Foo</h2>', title('Foo')
1471 end
1473 end
1472
1474
1473 def test_title_should_set_html_title
1475 def test_title_should_set_html_title
1474 title('Foo')
1476 title('Foo')
1475 assert_equal 'Foo - Redmine', html_title
1477 assert_equal 'Foo - Redmine', html_title
1476 end
1478 end
1477
1479
1478 def test_title_should_turn_arrays_into_links
1480 def test_title_should_turn_arrays_into_links
1479 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1481 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1480 assert_equal 'Foo - Redmine', html_title
1482 assert_equal 'Foo - Redmine', html_title
1481 end
1483 end
1482
1484
1483 def test_title_should_join_items
1485 def test_title_should_join_items
1484 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1486 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1485 assert_equal 'Bar - Foo - Redmine', html_title
1487 assert_equal 'Bar - Foo - Redmine', html_title
1486 end
1488 end
1487
1489
1488 def test_favicon_path
1490 def test_favicon_path
1489 assert_match %r{^/favicon\.ico}, favicon_path
1491 assert_match %r{^/favicon\.ico}, favicon_path
1490 end
1492 end
1491
1493
1492 def test_favicon_path_with_suburi
1494 def test_favicon_path_with_suburi
1493 Redmine::Utils.relative_url_root = '/foo'
1495 Redmine::Utils.relative_url_root = '/foo'
1494 assert_match %r{^/foo/favicon\.ico}, favicon_path
1496 assert_match %r{^/foo/favicon\.ico}, favicon_path
1495 ensure
1497 ensure
1496 Redmine::Utils.relative_url_root = ''
1498 Redmine::Utils.relative_url_root = ''
1497 end
1499 end
1498
1500
1499 def test_favicon_url
1501 def test_favicon_url
1500 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1502 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1501 end
1503 end
1502
1504
1503 def test_favicon_url_with_suburi
1505 def test_favicon_url_with_suburi
1504 Redmine::Utils.relative_url_root = '/foo'
1506 Redmine::Utils.relative_url_root = '/foo'
1505 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1507 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1506 ensure
1508 ensure
1507 Redmine::Utils.relative_url_root = ''
1509 Redmine::Utils.relative_url_root = ''
1508 end
1510 end
1509
1511
1510 def test_truncate_single_line
1512 def test_truncate_single_line
1511 str = "01234"
1513 str = "01234"
1512 result = truncate_single_line_raw("#{str}\n#{str}", 10)
1514 result = truncate_single_line_raw("#{str}\n#{str}", 10)
1513 assert_equal "01234 0...", result
1515 assert_equal "01234 0...", result
1514 assert !result.html_safe?
1516 assert !result.html_safe?
1515 result = truncate_single_line_raw("#{str}<&#>\n#{str}#{str}", 16)
1517 result = truncate_single_line_raw("#{str}<&#>\n#{str}#{str}", 16)
1516 assert_equal "01234<&#> 012...", result
1518 assert_equal "01234<&#> 012...", result
1517 assert !result.html_safe?
1519 assert !result.html_safe?
1518 end
1520 end
1519
1521
1520 def test_truncate_single_line_non_ascii
1522 def test_truncate_single_line_non_ascii
1521 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
1523 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e".force_encoding('UTF-8')
1522 result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10)
1524 result = truncate_single_line_raw("#{ja}\n#{ja}\n#{ja}", 10)
1523 assert_equal "#{ja} #{ja}...", result
1525 assert_equal "#{ja} #{ja}...", result
1524 assert !result.html_safe?
1526 assert !result.html_safe?
1525 end
1527 end
1526 end
1528 end
General Comments 0
You need to be logged in to leave comments. Login now