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