##// END OF EJS Templates
Rails4: replace hard-coded html with class at ApplicationHelperTest#test_link_to_user_should_link_to_locked_user_if_current_user_is_admin...
Toshi MARUYAMA -
r12552:fab81930f786
parent child
Show More
@@ -1,1362 +1,1363
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 result = link_to("John Smith", "/users/2", :class => "user active")
1132 result = link_to("John Smith", "/users/2", :class => "user active")
1133 assert_equal result, link_to_user(user)
1133 assert_equal result, link_to_user(user)
1134 end
1134 end
1135
1135
1136 def test_link_to_user_should_not_link_to_locked_user
1136 def test_link_to_user_should_not_link_to_locked_user
1137 with_current_user nil do
1137 with_current_user nil do
1138 user = User.find(5)
1138 user = User.find(5)
1139 assert user.locked?
1139 assert user.locked?
1140 assert_equal 'Dave2 Lopper2', link_to_user(user)
1140 assert_equal 'Dave2 Lopper2', link_to_user(user)
1141 end
1141 end
1142 end
1142 end
1143
1143
1144 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1144 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1145 with_current_user User.find(1) do
1145 with_current_user User.find(1) do
1146 user = User.find(5)
1146 user = User.find(5)
1147 assert user.locked?
1147 assert user.locked?
1148 assert_equal '<a href="/users/5" class="user locked">Dave2 Lopper2</a>', link_to_user(user)
1148 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1149 assert_equal result, link_to_user(user)
1149 end
1150 end
1150 end
1151 end
1151
1152
1152 def test_link_to_user_should_not_link_to_anonymous
1153 def test_link_to_user_should_not_link_to_anonymous
1153 user = User.anonymous
1154 user = User.anonymous
1154 assert user.anonymous?
1155 assert user.anonymous?
1155 t = link_to_user(user)
1156 t = link_to_user(user)
1156 assert_equal ::I18n.t(:label_user_anonymous), t
1157 assert_equal ::I18n.t(:label_user_anonymous), t
1157 end
1158 end
1158
1159
1159 def test_link_to_attachment
1160 def test_link_to_attachment
1160 a = Attachment.find(3)
1161 a = Attachment.find(3)
1161 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1162 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1162 link_to_attachment(a)
1163 link_to_attachment(a)
1163 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1164 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1164 link_to_attachment(a, :text => 'Text')
1165 link_to_attachment(a, :text => 'Text')
1165 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1166 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1166 assert_equal result,
1167 assert_equal result,
1167 link_to_attachment(a, :class => 'foo')
1168 link_to_attachment(a, :class => 'foo')
1168 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1169 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1169 link_to_attachment(a, :download => true)
1170 link_to_attachment(a, :download => true)
1170 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1171 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1171 link_to_attachment(a, :only_path => false)
1172 link_to_attachment(a, :only_path => false)
1172 end
1173 end
1173
1174
1174 def test_thumbnail_tag
1175 def test_thumbnail_tag
1175 a = Attachment.find(3)
1176 a = Attachment.find(3)
1176 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1177 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1177 thumbnail_tag(a)
1178 thumbnail_tag(a)
1178 end
1179 end
1179
1180
1180 def test_link_to_project
1181 def test_link_to_project
1181 project = Project.find(1)
1182 project = Project.find(1)
1182 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1183 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1183 link_to_project(project)
1184 link_to_project(project)
1184 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1185 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1185 link_to_project(project, :action => 'settings')
1186 link_to_project(project, :action => 'settings')
1186 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1187 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1187 link_to_project(project, {:only_path => false, :jump => 'blah'})
1188 link_to_project(project, {:only_path => false, :jump => 'blah'})
1188 result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
1189 result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
1189 assert_equal result,
1190 assert_equal result,
1190 link_to_project(project, {:action => 'settings'}, :class => "project")
1191 link_to_project(project, {:action => 'settings'}, :class => "project")
1191 end
1192 end
1192
1193
1193 def test_link_to_project_settings
1194 def test_link_to_project_settings
1194 project = Project.find(1)
1195 project = Project.find(1)
1195 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1196 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1196
1197
1197 project.status = Project::STATUS_CLOSED
1198 project.status = Project::STATUS_CLOSED
1198 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1199 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1199
1200
1200 project.status = Project::STATUS_ARCHIVED
1201 project.status = Project::STATUS_ARCHIVED
1201 assert_equal 'eCookbook', link_to_project_settings(project)
1202 assert_equal 'eCookbook', link_to_project_settings(project)
1202 end
1203 end
1203
1204
1204 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1205 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1205 # numeric identifier are no longer allowed
1206 # numeric identifier are no longer allowed
1206 Project.where(:id => 1).update_all(:identifier => 25)
1207 Project.where(:id => 1).update_all(:identifier => 25)
1207 assert_equal '<a href="/projects/1">eCookbook</a>',
1208 assert_equal '<a href="/projects/1">eCookbook</a>',
1208 link_to_project(Project.find(1))
1209 link_to_project(Project.find(1))
1209 end
1210 end
1210
1211
1211 def test_principals_options_for_select_with_users
1212 def test_principals_options_for_select_with_users
1212 User.current = nil
1213 User.current = nil
1213 users = [User.find(2), User.find(4)]
1214 users = [User.find(2), User.find(4)]
1214 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1215 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1215 principals_options_for_select(users)
1216 principals_options_for_select(users)
1216 end
1217 end
1217
1218
1218 def test_principals_options_for_select_with_selected
1219 def test_principals_options_for_select_with_selected
1219 User.current = nil
1220 User.current = nil
1220 users = [User.find(2), User.find(4)]
1221 users = [User.find(2), User.find(4)]
1221 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1222 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1222 principals_options_for_select(users, User.find(4))
1223 principals_options_for_select(users, User.find(4))
1223 end
1224 end
1224
1225
1225 def test_principals_options_for_select_with_users_and_groups
1226 def test_principals_options_for_select_with_users_and_groups
1226 User.current = nil
1227 User.current = nil
1227 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1228 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1228 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1229 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1229 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1230 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1230 principals_options_for_select(users)
1231 principals_options_for_select(users)
1231 end
1232 end
1232
1233
1233 def test_principals_options_for_select_with_empty_collection
1234 def test_principals_options_for_select_with_empty_collection
1234 assert_equal '', principals_options_for_select([])
1235 assert_equal '', principals_options_for_select([])
1235 end
1236 end
1236
1237
1237 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1238 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1238 users = [User.find(2), User.find(4)]
1239 users = [User.find(2), User.find(4)]
1239 User.current = User.find(4)
1240 User.current = User.find(4)
1240 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1241 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1241 end
1242 end
1242
1243
1243 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1244 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1244 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1245 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1245 end
1246 end
1246
1247
1247 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1248 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1248 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1249 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1249 end
1250 end
1250
1251
1251 def test_image_tag_should_pick_the_default_image
1252 def test_image_tag_should_pick_the_default_image
1252 assert_match 'src="/images/image.png"', image_tag("image.png")
1253 assert_match 'src="/images/image.png"', image_tag("image.png")
1253 end
1254 end
1254
1255
1255 def test_image_tag_should_pick_the_theme_image_if_it_exists
1256 def test_image_tag_should_pick_the_theme_image_if_it_exists
1256 theme = Redmine::Themes.themes.last
1257 theme = Redmine::Themes.themes.last
1257 theme.images << 'image.png'
1258 theme.images << 'image.png'
1258
1259
1259 with_settings :ui_theme => theme.id do
1260 with_settings :ui_theme => theme.id do
1260 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1261 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1261 assert_match %|src="/images/other.png"|, image_tag("other.png")
1262 assert_match %|src="/images/other.png"|, image_tag("other.png")
1262 end
1263 end
1263 ensure
1264 ensure
1264 theme.images.delete 'image.png'
1265 theme.images.delete 'image.png'
1265 end
1266 end
1266
1267
1267 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1268 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1268 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1269 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1269 end
1270 end
1270
1271
1271 def test_javascript_include_tag_should_pick_the_default_javascript
1272 def test_javascript_include_tag_should_pick_the_default_javascript
1272 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1273 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1273 end
1274 end
1274
1275
1275 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1276 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1276 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1277 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1277 end
1278 end
1278
1279
1279 def test_raw_json_should_escape_closing_tags
1280 def test_raw_json_should_escape_closing_tags
1280 s = raw_json(["<foo>bar</foo>"])
1281 s = raw_json(["<foo>bar</foo>"])
1281 assert_equal '["<foo>bar<\/foo>"]', s
1282 assert_equal '["<foo>bar<\/foo>"]', s
1282 end
1283 end
1283
1284
1284 def test_raw_json_should_be_html_safe
1285 def test_raw_json_should_be_html_safe
1285 s = raw_json(["foo"])
1286 s = raw_json(["foo"])
1286 assert s.html_safe?
1287 assert s.html_safe?
1287 end
1288 end
1288
1289
1289 def test_html_title_should_app_title_if_not_set
1290 def test_html_title_should_app_title_if_not_set
1290 assert_equal 'Redmine', html_title
1291 assert_equal 'Redmine', html_title
1291 end
1292 end
1292
1293
1293 def test_html_title_should_join_items
1294 def test_html_title_should_join_items
1294 html_title 'Foo', 'Bar'
1295 html_title 'Foo', 'Bar'
1295 assert_equal 'Foo - Bar - Redmine', html_title
1296 assert_equal 'Foo - Bar - Redmine', html_title
1296 end
1297 end
1297
1298
1298 def test_html_title_should_append_current_project_name
1299 def test_html_title_should_append_current_project_name
1299 @project = Project.find(1)
1300 @project = Project.find(1)
1300 html_title 'Foo', 'Bar'
1301 html_title 'Foo', 'Bar'
1301 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1302 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1302 end
1303 end
1303
1304
1304 def test_title_should_return_a_h2_tag
1305 def test_title_should_return_a_h2_tag
1305 assert_equal '<h2>Foo</h2>', title('Foo')
1306 assert_equal '<h2>Foo</h2>', title('Foo')
1306 end
1307 end
1307
1308
1308 def test_title_should_set_html_title
1309 def test_title_should_set_html_title
1309 title('Foo')
1310 title('Foo')
1310 assert_equal 'Foo - Redmine', html_title
1311 assert_equal 'Foo - Redmine', html_title
1311 end
1312 end
1312
1313
1313 def test_title_should_turn_arrays_into_links
1314 def test_title_should_turn_arrays_into_links
1314 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1315 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1315 assert_equal 'Foo - Redmine', html_title
1316 assert_equal 'Foo - Redmine', html_title
1316 end
1317 end
1317
1318
1318 def test_title_should_join_items
1319 def test_title_should_join_items
1319 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1320 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1320 assert_equal 'Bar - Foo - Redmine', html_title
1321 assert_equal 'Bar - Foo - Redmine', html_title
1321 end
1322 end
1322
1323
1323 def test_favicon_path
1324 def test_favicon_path
1324 assert_match %r{^/favicon\.ico}, favicon_path
1325 assert_match %r{^/favicon\.ico}, favicon_path
1325 end
1326 end
1326
1327
1327 def test_favicon_path_with_suburi
1328 def test_favicon_path_with_suburi
1328 Redmine::Utils.relative_url_root = '/foo'
1329 Redmine::Utils.relative_url_root = '/foo'
1329 assert_match %r{^/foo/favicon\.ico}, favicon_path
1330 assert_match %r{^/foo/favicon\.ico}, favicon_path
1330 ensure
1331 ensure
1331 Redmine::Utils.relative_url_root = ''
1332 Redmine::Utils.relative_url_root = ''
1332 end
1333 end
1333
1334
1334 def test_favicon_url
1335 def test_favicon_url
1335 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1336 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1336 end
1337 end
1337
1338
1338 def test_favicon_url_with_suburi
1339 def test_favicon_url_with_suburi
1339 Redmine::Utils.relative_url_root = '/foo'
1340 Redmine::Utils.relative_url_root = '/foo'
1340 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1341 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1341 ensure
1342 ensure
1342 Redmine::Utils.relative_url_root = ''
1343 Redmine::Utils.relative_url_root = ''
1343 end
1344 end
1344
1345
1345 def test_truncate_single_line
1346 def test_truncate_single_line
1346 str = "01234"
1347 str = "01234"
1347 result = truncate_single_line("#{str}\n#{str}", :length => 10)
1348 result = truncate_single_line("#{str}\n#{str}", :length => 10)
1348 assert_equal "01234 0...", result
1349 assert_equal "01234 0...", result
1349 assert !result.html_safe?
1350 assert !result.html_safe?
1350 result = truncate_single_line("#{str}<&#>\n#{str}#{str}", :length => 16)
1351 result = truncate_single_line("#{str}<&#>\n#{str}#{str}", :length => 16)
1351 assert_equal "01234<&#> 012...", result
1352 assert_equal "01234<&#> 012...", result
1352 assert !result.html_safe?
1353 assert !result.html_safe?
1353 end
1354 end
1354
1355
1355 def test_truncate_single_line_non_ascii
1356 def test_truncate_single_line_non_ascii
1356 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
1357 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
1357 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
1358 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
1358 result = truncate_single_line("#{ja}\n#{ja}\n#{ja}", :length => 10)
1359 result = truncate_single_line("#{ja}\n#{ja}\n#{ja}", :length => 10)
1359 assert_equal "#{ja} #{ja}...", result
1360 assert_equal "#{ja} #{ja}...", result
1360 assert !result.html_safe?
1361 assert !result.html_safe?
1361 end
1362 end
1362 end
1363 end
General Comments 0
You need to be logged in to leave comments. Login now