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