##// END OF EJS Templates
add tests of ApplicationHelper#link_to_issue subject and title...
Toshi MARUYAMA -
r12554:e4d152e84a0f
parent child
Show More
@@ -1,1371 +1,1406
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_link_to_issue_subject
440 issue = Issue.generate!(:subject => "01234567890123456789")
441 str = link_to_issue(issue, :truncate => 10)
442 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
443 assert_equal "#{result}: 0123456...", str
444
445 issue = Issue.generate!(:subject => "<&>")
446 str = link_to_issue(issue)
447 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
448 assert_equal "#{result}: &lt;&amp;&gt;", str
449
450 issue = Issue.generate!(:subject => "<&>0123456789012345")
451 str = link_to_issue(issue, :truncate => 10)
452 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}", :class => issue.css_classes)
453 assert_equal "#{result}: &lt;&amp;&gt;0123...", str
454 end
455
456 def test_link_to_issue_title
457 long_str = "0123456789" * 5
458
459 issue = Issue.generate!(:subject => "#{long_str}01234567890123456789")
460 str = link_to_issue(issue, :subject => false)
461 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
462 :class => issue.css_classes,
463 :title => "#{long_str}0123456...")
464 assert_equal result, str
465
466 issue = Issue.generate!(:subject => "<&>#{long_str}01234567890123456789")
467 str = link_to_issue(issue, :subject => false)
468 result = link_to("Bug ##{issue.id}", "/issues/#{issue.id}",
469 :class => issue.css_classes,
470 :title => "<&>#{long_str}0123...")
471 assert_equal result, str
472 end
473
439 def test_multiple_repositories_redmine_links
474 def test_multiple_repositories_redmine_links
440 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
475 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')
476 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
442 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
477 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')
478 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
444
479
445 changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
480 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')
481 :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},
482 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 => '')
483 :class => 'changeset', :title => '')
449 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
484 hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
450 :class => 'changeset', :title => '')
485 :class => 'changeset', :title => '')
451
486
452 source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
487 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')
488 hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
454
489
455 to_test = {
490 to_test = {
456 'r2' => changeset_link,
491 'r2' => changeset_link,
457 'svn_repo-1|r123' => svn_changeset_link,
492 'svn_repo-1|r123' => svn_changeset_link,
458 'invalid|r123' => 'invalid|r123',
493 'invalid|r123' => 'invalid|r123',
459 'commit:hg1|abcd' => hg_changeset_link,
494 'commit:hg1|abcd' => hg_changeset_link,
460 'commit:invalid|abcd' => 'commit:invalid|abcd',
495 'commit:invalid|abcd' => 'commit:invalid|abcd',
461 # source
496 # source
462 'source:some/file' => source_link,
497 'source:some/file' => source_link,
463 'source:hg1|some/file' => hg_source_link,
498 'source:hg1|some/file' => hg_source_link,
464 'source:invalid|some/file' => 'source:invalid|some/file',
499 'source:invalid|some/file' => 'source:invalid|some/file',
465 }
500 }
466
501
467 @project = Project.find(1)
502 @project = Project.find(1)
468 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
503 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
469 end
504 end
470
505
471 def test_cross_project_multiple_repositories_redmine_links
506 def test_cross_project_multiple_repositories_redmine_links
472 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
507 svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
473 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
508 Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
474 hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
509 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')
510 Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
476
511
477 changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
512 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')
513 :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},
514 svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
480 :class => 'changeset', :title => '')
515 :class => 'changeset', :title => '')
481 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
516 hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
482 :class => 'changeset', :title => '')
517 :class => 'changeset', :title => '')
483
518
484 source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
519 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')
520 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
521
487 to_test = {
522 to_test = {
488 'ecookbook:r2' => changeset_link,
523 'ecookbook:r2' => changeset_link,
489 'ecookbook:svn1|r123' => svn_changeset_link,
524 'ecookbook:svn1|r123' => svn_changeset_link,
490 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
525 'ecookbook:invalid|r123' => 'ecookbook:invalid|r123',
491 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
526 'ecookbook:commit:hg1|abcd' => hg_changeset_link,
492 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
527 'ecookbook:commit:invalid|abcd' => 'ecookbook:commit:invalid|abcd',
493 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
528 'invalid:commit:invalid|abcd' => 'invalid:commit:invalid|abcd',
494 # source
529 # source
495 'ecookbook:source:some/file' => source_link,
530 'ecookbook:source:some/file' => source_link,
496 'ecookbook:source:hg1|some/file' => hg_source_link,
531 'ecookbook:source:hg1|some/file' => hg_source_link,
497 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
532 'ecookbook:source:invalid|some/file' => 'ecookbook:source:invalid|some/file',
498 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
533 'invalid:source:invalid|some/file' => 'invalid:source:invalid|some/file',
499 }
534 }
500
535
501 @project = Project.find(3)
536 @project = Project.find(3)
502 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
537 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
503 end
538 end
504
539
505 def test_redmine_links_git_commit
540 def test_redmine_links_git_commit
506 changeset_link = link_to('abcd',
541 changeset_link = link_to('abcd',
507 {
542 {
508 :controller => 'repositories',
543 :controller => 'repositories',
509 :action => 'revision',
544 :action => 'revision',
510 :id => 'subproject1',
545 :id => 'subproject1',
511 :rev => 'abcd',
546 :rev => 'abcd',
512 },
547 },
513 :class => 'changeset', :title => 'test commit')
548 :class => 'changeset', :title => 'test commit')
514 to_test = {
549 to_test = {
515 'commit:abcd' => changeset_link,
550 'commit:abcd' => changeset_link,
516 }
551 }
517 @project = Project.find(3)
552 @project = Project.find(3)
518 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
553 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
519 assert r
554 assert r
520 c = Changeset.new(:repository => r,
555 c = Changeset.new(:repository => r,
521 :committed_on => Time.now,
556 :committed_on => Time.now,
522 :revision => 'abcd',
557 :revision => 'abcd',
523 :scmid => 'abcd',
558 :scmid => 'abcd',
524 :comments => 'test commit')
559 :comments => 'test commit')
525 assert( c.save )
560 assert( c.save )
526 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
561 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
527 end
562 end
528
563
529 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
564 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
530 def test_redmine_links_darcs_commit
565 def test_redmine_links_darcs_commit
531 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
566 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
532 {
567 {
533 :controller => 'repositories',
568 :controller => 'repositories',
534 :action => 'revision',
569 :action => 'revision',
535 :id => 'subproject1',
570 :id => 'subproject1',
536 :rev => '123',
571 :rev => '123',
537 },
572 },
538 :class => 'changeset', :title => 'test commit')
573 :class => 'changeset', :title => 'test commit')
539 to_test = {
574 to_test = {
540 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
575 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
541 }
576 }
542 @project = Project.find(3)
577 @project = Project.find(3)
543 r = Repository::Darcs.create!(
578 r = Repository::Darcs.create!(
544 :project => @project, :url => '/tmp/test/darcs',
579 :project => @project, :url => '/tmp/test/darcs',
545 :log_encoding => 'UTF-8')
580 :log_encoding => 'UTF-8')
546 assert r
581 assert r
547 c = Changeset.new(:repository => r,
582 c = Changeset.new(:repository => r,
548 :committed_on => Time.now,
583 :committed_on => Time.now,
549 :revision => '123',
584 :revision => '123',
550 :scmid => '20080308225258-98289-abcd456efg.gz',
585 :scmid => '20080308225258-98289-abcd456efg.gz',
551 :comments => 'test commit')
586 :comments => 'test commit')
552 assert( c.save )
587 assert( c.save )
553 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
588 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
554 end
589 end
555
590
556 def test_redmine_links_mercurial_commit
591 def test_redmine_links_mercurial_commit
557 changeset_link_rev = link_to('r123',
592 changeset_link_rev = link_to('r123',
558 {
593 {
559 :controller => 'repositories',
594 :controller => 'repositories',
560 :action => 'revision',
595 :action => 'revision',
561 :id => 'subproject1',
596 :id => 'subproject1',
562 :rev => '123' ,
597 :rev => '123' ,
563 },
598 },
564 :class => 'changeset', :title => 'test commit')
599 :class => 'changeset', :title => 'test commit')
565 changeset_link_commit = link_to('abcd',
600 changeset_link_commit = link_to('abcd',
566 {
601 {
567 :controller => 'repositories',
602 :controller => 'repositories',
568 :action => 'revision',
603 :action => 'revision',
569 :id => 'subproject1',
604 :id => 'subproject1',
570 :rev => 'abcd' ,
605 :rev => 'abcd' ,
571 },
606 },
572 :class => 'changeset', :title => 'test commit')
607 :class => 'changeset', :title => 'test commit')
573 to_test = {
608 to_test = {
574 'r123' => changeset_link_rev,
609 'r123' => changeset_link_rev,
575 'commit:abcd' => changeset_link_commit,
610 'commit:abcd' => changeset_link_commit,
576 }
611 }
577 @project = Project.find(3)
612 @project = Project.find(3)
578 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
613 r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
579 assert r
614 assert r
580 c = Changeset.new(:repository => r,
615 c = Changeset.new(:repository => r,
581 :committed_on => Time.now,
616 :committed_on => Time.now,
582 :revision => '123',
617 :revision => '123',
583 :scmid => 'abcd',
618 :scmid => 'abcd',
584 :comments => 'test commit')
619 :comments => 'test commit')
585 assert( c.save )
620 assert( c.save )
586 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
621 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
587 end
622 end
588
623
589 def test_attachment_links
624 def test_attachment_links
590 text = 'attachment:error281.txt'
625 text = 'attachment:error281.txt'
591 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
626 result = link_to("error281.txt", "/attachments/download/1/error281.txt",
592 :class => "attachment")
627 :class => "attachment")
593 assert_equal "<p>#{result}</p>",
628 assert_equal "<p>#{result}</p>",
594 textilizable(text,
629 textilizable(text,
595 :attachments => Issue.find(3).attachments),
630 :attachments => Issue.find(3).attachments),
596 "#{text} failed"
631 "#{text} failed"
597 end
632 end
598
633
599 def test_attachment_link_should_link_to_latest_attachment
634 def test_attachment_link_should_link_to_latest_attachment
600 set_tmp_attachments_directory
635 set_tmp_attachments_directory
601 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
636 a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
602 a2 = Attachment.generate!(:filename => "test.txt")
637 a2 = Attachment.generate!(:filename => "test.txt")
603 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
638 result = link_to("test.txt", "/attachments/download/#{a2.id}/test.txt",
604 :class => "attachment")
639 :class => "attachment")
605 assert_equal "<p>#{result}</p>",
640 assert_equal "<p>#{result}</p>",
606 textilizable('attachment:test.txt', :attachments => [a1, a2])
641 textilizable('attachment:test.txt', :attachments => [a1, a2])
607 end
642 end
608
643
609 def test_wiki_links
644 def test_wiki_links
610 russian_eacape = CGI.escape(@russian_test)
645 russian_eacape = CGI.escape(@russian_test)
611 to_test = {
646 to_test = {
612 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
647 '[[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>',
648 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
614 # title content should be formatted
649 # 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>',
650 '[[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>',
651 '[[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
652 # link with anchor
618 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
653 '[[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>',
654 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
620 # UTF8 anchor
655 # UTF8 anchor
621 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
656 "[[Another_page##{@russian_test}|#{@russian_test}]]" =>
622 %|<a href="/projects/ecookbook/wiki/Another_page##{russian_eacape}" class="wiki-page">#{@russian_test}</a>|,
657 %|<a href="/projects/ecookbook/wiki/Another_page##{russian_eacape}" class="wiki-page">#{@russian_test}</a>|,
623 # page that doesn't exist
658 # page that doesn't exist
624 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
659 '[[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>',
660 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
626 # link to another project wiki
661 # link to another project wiki
627 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
662 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
628 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
663 '[[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>',
664 '[[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>',
665 '[[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>',
666 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
632 # striked through link
667 # striked through link
633 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
668 '-[[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>',
669 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
635 # escaping
670 # escaping
636 '![[Another page|Page]]' => '[[Another page|Page]]',
671 '![[Another page|Page]]' => '[[Another page|Page]]',
637 # project does not exist
672 # project does not exist
638 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
673 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
639 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
674 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
640 }
675 }
641
676
642 @project = Project.find(1)
677 @project = Project.find(1)
643 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
678 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
644 end
679 end
645
680
646 def test_wiki_links_within_local_file_generation_context
681 def test_wiki_links_within_local_file_generation_context
647 to_test = {
682 to_test = {
648 # link to a page
683 # link to a page
649 '[[CookBook documentation]]' =>
684 '[[CookBook documentation]]' =>
650 link_to("CookBook documentation", "CookBook_documentation.html",
685 link_to("CookBook documentation", "CookBook_documentation.html",
651 :class => "wiki-page"),
686 :class => "wiki-page"),
652 '[[CookBook documentation|documentation]]' =>
687 '[[CookBook documentation|documentation]]' =>
653 link_to("documentation", "CookBook_documentation.html",
688 link_to("documentation", "CookBook_documentation.html",
654 :class => "wiki-page"),
689 :class => "wiki-page"),
655 '[[CookBook documentation#One-section]]' =>
690 '[[CookBook documentation#One-section]]' =>
656 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
691 link_to("CookBook documentation", "CookBook_documentation.html#One-section",
657 :class => "wiki-page"),
692 :class => "wiki-page"),
658 '[[CookBook documentation#One-section|documentation]]' =>
693 '[[CookBook documentation#One-section|documentation]]' =>
659 link_to("documentation", "CookBook_documentation.html#One-section",
694 link_to("documentation", "CookBook_documentation.html#One-section",
660 :class => "wiki-page"),
695 :class => "wiki-page"),
661 # page that doesn't exist
696 # page that doesn't exist
662 '[[Unknown page]]' =>
697 '[[Unknown page]]' =>
663 link_to("Unknown page", "Unknown_page.html",
698 link_to("Unknown page", "Unknown_page.html",
664 :class => "wiki-page new"),
699 :class => "wiki-page new"),
665 '[[Unknown page|404]]' =>
700 '[[Unknown page|404]]' =>
666 link_to("404", "Unknown_page.html",
701 link_to("404", "Unknown_page.html",
667 :class => "wiki-page new"),
702 :class => "wiki-page new"),
668 '[[Unknown page#anchor]]' =>
703 '[[Unknown page#anchor]]' =>
669 link_to("Unknown page", "Unknown_page.html#anchor",
704 link_to("Unknown page", "Unknown_page.html#anchor",
670 :class => "wiki-page new"),
705 :class => "wiki-page new"),
671 '[[Unknown page#anchor|404]]' =>
706 '[[Unknown page#anchor|404]]' =>
672 link_to("404", "Unknown_page.html#anchor",
707 link_to("404", "Unknown_page.html#anchor",
673 :class => "wiki-page new"),
708 :class => "wiki-page new"),
674 }
709 }
675 @project = Project.find(1)
710 @project = Project.find(1)
676 to_test.each do |text, result|
711 to_test.each do |text, result|
677 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
712 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local)
678 end
713 end
679 end
714 end
680
715
681 def test_wiki_links_within_wiki_page_context
716 def test_wiki_links_within_wiki_page_context
682
717
683 page = WikiPage.find_by_title('Another_page' )
718 page = WikiPage.find_by_title('Another_page' )
684
719
685 to_test = {
720 to_test = {
686 # link to another page
721 # link to another page
687 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
722 '[[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>',
723 '[[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>',
724 '[[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>',
725 '[[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
726 # link to the current page
692 '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>',
727 '[[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>',
728 '[[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>',
729 '[[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>',
730 '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>',
696 # page that doesn't exist
731 # 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>',
732 '[[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>',
733 '[[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>',
734 '[[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>',
735 '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">404</a>',
701 }
736 }
702
737
703 @project = Project.find(1)
738 @project = Project.find(1)
704
739
705 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
740 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
706 end
741 end
707
742
708 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
743 def test_wiki_links_anchor_option_should_prepend_page_title_to_href
709 to_test = {
744 to_test = {
710 # link to a page
745 # link to a page
711 '[[CookBook documentation]]' =>
746 '[[CookBook documentation]]' =>
712 link_to("CookBook documentation",
747 link_to("CookBook documentation",
713 "#CookBook_documentation",
748 "#CookBook_documentation",
714 :class => "wiki-page"),
749 :class => "wiki-page"),
715 '[[CookBook documentation|documentation]]' =>
750 '[[CookBook documentation|documentation]]' =>
716 link_to("documentation",
751 link_to("documentation",
717 "#CookBook_documentation",
752 "#CookBook_documentation",
718 :class => "wiki-page"),
753 :class => "wiki-page"),
719 '[[CookBook documentation#One-section]]' =>
754 '[[CookBook documentation#One-section]]' =>
720 link_to("CookBook documentation",
755 link_to("CookBook documentation",
721 "#CookBook_documentation_One-section",
756 "#CookBook_documentation_One-section",
722 :class => "wiki-page"),
757 :class => "wiki-page"),
723 '[[CookBook documentation#One-section|documentation]]' =>
758 '[[CookBook documentation#One-section|documentation]]' =>
724 link_to("documentation",
759 link_to("documentation",
725 "#CookBook_documentation_One-section",
760 "#CookBook_documentation_One-section",
726 :class => "wiki-page"),
761 :class => "wiki-page"),
727 # page that doesn't exist
762 # page that doesn't exist
728 '[[Unknown page]]' =>
763 '[[Unknown page]]' =>
729 link_to("Unknown page",
764 link_to("Unknown page",
730 "#Unknown_page",
765 "#Unknown_page",
731 :class => "wiki-page new"),
766 :class => "wiki-page new"),
732 '[[Unknown page|404]]' =>
767 '[[Unknown page|404]]' =>
733 link_to("404",
768 link_to("404",
734 "#Unknown_page",
769 "#Unknown_page",
735 :class => "wiki-page new"),
770 :class => "wiki-page new"),
736 '[[Unknown page#anchor]]' =>
771 '[[Unknown page#anchor]]' =>
737 link_to("Unknown page",
772 link_to("Unknown page",
738 "#Unknown_page_anchor",
773 "#Unknown_page_anchor",
739 :class => "wiki-page new"),
774 :class => "wiki-page new"),
740 '[[Unknown page#anchor|404]]' =>
775 '[[Unknown page#anchor|404]]' =>
741 link_to("404",
776 link_to("404",
742 "#Unknown_page_anchor",
777 "#Unknown_page_anchor",
743 :class => "wiki-page new"),
778 :class => "wiki-page new"),
744 }
779 }
745 @project = Project.find(1)
780 @project = Project.find(1)
746 to_test.each do |text, result|
781 to_test.each do |text, result|
747 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
782 assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor)
748 end
783 end
749 end
784 end
750
785
751 def test_html_tags
786 def test_html_tags
752 to_test = {
787 to_test = {
753 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
788 "<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>",
789 "<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>",
790 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
756 # do not escape pre/code tags
791 # do not escape pre/code tags
757 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
792 "<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>",
793 "<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>",
794 "<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>",
795 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
761 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
796 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
762 # remove attributes except class
797 # remove attributes except class
763 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
798 "<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>',
799 '<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>",
800 "<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>',
801 '<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>",
802 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
768 # xss
803 # xss
769 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
804 '<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>',
805 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
771 }
806 }
772 to_test.each { |text, result| assert_equal result, textilizable(text) }
807 to_test.each { |text, result| assert_equal result, textilizable(text) }
773 end
808 end
774
809
775 def test_allowed_html_tags
810 def test_allowed_html_tags
776 to_test = {
811 to_test = {
777 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
812 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
778 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
813 "<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;"
814 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
780 }
815 }
781 to_test.each { |text, result| assert_equal result, textilizable(text) }
816 to_test.each { |text, result| assert_equal result, textilizable(text) }
782 end
817 end
783
818
784 def test_pre_tags
819 def test_pre_tags
785 raw = <<-RAW
820 raw = <<-RAW
786 Before
821 Before
787
822
788 <pre>
823 <pre>
789 <prepared-statement-cache-size>32</prepared-statement-cache-size>
824 <prepared-statement-cache-size>32</prepared-statement-cache-size>
790 </pre>
825 </pre>
791
826
792 After
827 After
793 RAW
828 RAW
794
829
795 expected = <<-EXPECTED
830 expected = <<-EXPECTED
796 <p>Before</p>
831 <p>Before</p>
797 <pre>
832 <pre>
798 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
833 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
799 </pre>
834 </pre>
800 <p>After</p>
835 <p>After</p>
801 EXPECTED
836 EXPECTED
802
837
803 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
838 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
804 end
839 end
805
840
806 def test_pre_content_should_not_parse_wiki_and_redmine_links
841 def test_pre_content_should_not_parse_wiki_and_redmine_links
807 raw = <<-RAW
842 raw = <<-RAW
808 [[CookBook documentation]]
843 [[CookBook documentation]]
809
844
810 #1
845 #1
811
846
812 <pre>
847 <pre>
813 [[CookBook documentation]]
848 [[CookBook documentation]]
814
849
815 #1
850 #1
816 </pre>
851 </pre>
817 RAW
852 RAW
818
853
819 result1 = link_to("CookBook documentation",
854 result1 = link_to("CookBook documentation",
820 "/projects/ecookbook/wiki/CookBook_documentation",
855 "/projects/ecookbook/wiki/CookBook_documentation",
821 :class => "wiki-page")
856 :class => "wiki-page")
822 result2 = link_to('#1',
857 result2 = link_to('#1',
823 "/issues/1",
858 "/issues/1",
824 :class => Issue.find(1).css_classes,
859 :class => Issue.find(1).css_classes,
825 :title => "Can't print recipes (New)")
860 :title => "Can't print recipes (New)")
826
861
827 expected = <<-EXPECTED
862 expected = <<-EXPECTED
828 <p>#{result1}</p>
863 <p>#{result1}</p>
829 <p>#{result2}</p>
864 <p>#{result2}</p>
830 <pre>
865 <pre>
831 [[CookBook documentation]]
866 [[CookBook documentation]]
832
867
833 #1
868 #1
834 </pre>
869 </pre>
835 EXPECTED
870 EXPECTED
836
871
837 @project = Project.find(1)
872 @project = Project.find(1)
838 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
873 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
839 end
874 end
840
875
841 def test_non_closing_pre_blocks_should_be_closed
876 def test_non_closing_pre_blocks_should_be_closed
842 raw = <<-RAW
877 raw = <<-RAW
843 <pre><code>
878 <pre><code>
844 RAW
879 RAW
845
880
846 expected = <<-EXPECTED
881 expected = <<-EXPECTED
847 <pre><code>
882 <pre><code>
848 </code></pre>
883 </code></pre>
849 EXPECTED
884 EXPECTED
850
885
851 @project = Project.find(1)
886 @project = Project.find(1)
852 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
887 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
853 end
888 end
854
889
855 def test_syntax_highlight
890 def test_syntax_highlight
856 raw = <<-RAW
891 raw = <<-RAW
857 <pre><code class="ruby">
892 <pre><code class="ruby">
858 # Some ruby code here
893 # Some ruby code here
859 </code></pre>
894 </code></pre>
860 RAW
895 RAW
861
896
862 expected = <<-EXPECTED
897 expected = <<-EXPECTED
863 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
898 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
864 </code></pre>
899 </code></pre>
865 EXPECTED
900 EXPECTED
866
901
867 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
902 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
868 end
903 end
869
904
870 def test_to_path_param
905 def test_to_path_param
871 assert_equal 'test1/test2', to_path_param('test1/test2')
906 assert_equal 'test1/test2', to_path_param('test1/test2')
872 assert_equal 'test1/test2', to_path_param('/test1/test2/')
907 assert_equal 'test1/test2', to_path_param('/test1/test2/')
873 assert_equal 'test1/test2', to_path_param('//test1/test2/')
908 assert_equal 'test1/test2', to_path_param('//test1/test2/')
874 assert_equal nil, to_path_param('/')
909 assert_equal nil, to_path_param('/')
875 end
910 end
876
911
877 def test_wiki_links_in_tables
912 def test_wiki_links_in_tables
878 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
913 text = "|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|"
879 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
914 link1 = link_to("Link title", "/projects/ecookbook/wiki/Page", :class => "wiki-page new")
880 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
915 link2 = link_to("Other title", "/projects/ecookbook/wiki/Other_Page", :class => "wiki-page new")
881 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
916 link3 = link_to("Last page", "/projects/ecookbook/wiki/Last_page", :class => "wiki-page new")
882 result = "<tr><td>#{link1}</td>" +
917 result = "<tr><td>#{link1}</td>" +
883 "<td>#{link2}</td>" +
918 "<td>#{link2}</td>" +
884 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
919 "</tr><tr><td>Cell 21</td><td>#{link3}</td></tr>"
885 @project = Project.find(1)
920 @project = Project.find(1)
886 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
921 assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '')
887 end
922 end
888
923
889 def test_text_formatting
924 def test_text_formatting
890 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
925 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
891 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
926 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
892 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
927 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
893 '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>',
928 '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>',
894 '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',
929 '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',
895 }
930 }
896 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
931 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
897 end
932 end
898
933
899 def test_wiki_horizontal_rule
934 def test_wiki_horizontal_rule
900 assert_equal '<hr />', textilizable('---')
935 assert_equal '<hr />', textilizable('---')
901 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
936 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
902 end
937 end
903
938
904 def test_footnotes
939 def test_footnotes
905 raw = <<-RAW
940 raw = <<-RAW
906 This is some text[1].
941 This is some text[1].
907
942
908 fn1. This is the foot note
943 fn1. This is the foot note
909 RAW
944 RAW
910
945
911 expected = <<-EXPECTED
946 expected = <<-EXPECTED
912 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
947 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
913 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
948 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
914 EXPECTED
949 EXPECTED
915
950
916 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
951 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
917 end
952 end
918
953
919 def test_headings
954 def test_headings
920 raw = 'h1. Some heading'
955 raw = 'h1. Some heading'
921 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
956 expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
922
957
923 assert_equal expected, textilizable(raw)
958 assert_equal expected, textilizable(raw)
924 end
959 end
925
960
926 def test_headings_with_special_chars
961 def test_headings_with_special_chars
927 # This test makes sure that the generated anchor names match the expected
962 # This test makes sure that the generated anchor names match the expected
928 # ones even if the heading text contains unconventional characters
963 # ones even if the heading text contains unconventional characters
929 raw = 'h1. Some heading related to version 0.5'
964 raw = 'h1. Some heading related to version 0.5'
930 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
965 anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
931 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
966 expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
932
967
933 assert_equal expected, textilizable(raw)
968 assert_equal expected, textilizable(raw)
934 end
969 end
935
970
936 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
971 def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
937 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
972 page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
938 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
973 content = WikiContent.new( :text => 'h1. Some heading', :page => page )
939
974
940 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
975 expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
941
976
942 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
977 assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
943 end
978 end
944
979
945 def test_table_of_content
980 def test_table_of_content
946 raw = <<-RAW
981 raw = <<-RAW
947 {{toc}}
982 {{toc}}
948
983
949 h1. Title
984 h1. Title
950
985
951 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
986 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
952
987
953 h2. Subtitle with a [[Wiki]] link
988 h2. Subtitle with a [[Wiki]] link
954
989
955 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
990 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
956
991
957 h2. Subtitle with [[Wiki|another Wiki]] link
992 h2. Subtitle with [[Wiki|another Wiki]] link
958
993
959 h2. Subtitle with %{color:red}red text%
994 h2. Subtitle with %{color:red}red text%
960
995
961 <pre>
996 <pre>
962 some code
997 some code
963 </pre>
998 </pre>
964
999
965 h3. Subtitle with *some* _modifiers_
1000 h3. Subtitle with *some* _modifiers_
966
1001
967 h3. Subtitle with @inline code@
1002 h3. Subtitle with @inline code@
968
1003
969 h1. Another title
1004 h1. Another title
970
1005
971 h3. An "Internet link":http://www.redmine.org/ inside subtitle
1006 h3. An "Internet link":http://www.redmine.org/ inside subtitle
972
1007
973 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
1008 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
974
1009
975 RAW
1010 RAW
976
1011
977 expected = '<ul class="toc">' +
1012 expected = '<ul class="toc">' +
978 '<li><a href="#Title">Title</a>' +
1013 '<li><a href="#Title">Title</a>' +
979 '<ul>' +
1014 '<ul>' +
980 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
1015 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
981 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
1016 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
982 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
1017 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
983 '<ul>' +
1018 '<ul>' +
984 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
1019 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
985 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
1020 '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
986 '</ul>' +
1021 '</ul>' +
987 '</li>' +
1022 '</li>' +
988 '</ul>' +
1023 '</ul>' +
989 '</li>' +
1024 '</li>' +
990 '<li><a href="#Another-title">Another title</a>' +
1025 '<li><a href="#Another-title">Another title</a>' +
991 '<ul>' +
1026 '<ul>' +
992 '<li>' +
1027 '<li>' +
993 '<ul>' +
1028 '<ul>' +
994 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
1029 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
995 '</ul>' +
1030 '</ul>' +
996 '</li>' +
1031 '</li>' +
997 '<li><a href="#Project-Name">Project Name</a></li>' +
1032 '<li><a href="#Project-Name">Project Name</a></li>' +
998 '</ul>' +
1033 '</ul>' +
999 '</li>' +
1034 '</li>' +
1000 '</ul>'
1035 '</ul>'
1001
1036
1002 @project = Project.find(1)
1037 @project = Project.find(1)
1003 assert textilizable(raw).gsub("\n", "").include?(expected)
1038 assert textilizable(raw).gsub("\n", "").include?(expected)
1004 end
1039 end
1005
1040
1006 def test_table_of_content_should_generate_unique_anchors
1041 def test_table_of_content_should_generate_unique_anchors
1007 raw = <<-RAW
1042 raw = <<-RAW
1008 {{toc}}
1043 {{toc}}
1009
1044
1010 h1. Title
1045 h1. Title
1011
1046
1012 h2. Subtitle
1047 h2. Subtitle
1013
1048
1014 h2. Subtitle
1049 h2. Subtitle
1015 RAW
1050 RAW
1016
1051
1017 expected = '<ul class="toc">' +
1052 expected = '<ul class="toc">' +
1018 '<li><a href="#Title">Title</a>' +
1053 '<li><a href="#Title">Title</a>' +
1019 '<ul>' +
1054 '<ul>' +
1020 '<li><a href="#Subtitle">Subtitle</a></li>' +
1055 '<li><a href="#Subtitle">Subtitle</a></li>' +
1021 '<li><a href="#Subtitle-2">Subtitle</a></li>'
1056 '<li><a href="#Subtitle-2">Subtitle</a></li>'
1022 '</ul>'
1057 '</ul>'
1023 '</li>' +
1058 '</li>' +
1024 '</ul>'
1059 '</ul>'
1025
1060
1026 @project = Project.find(1)
1061 @project = Project.find(1)
1027 result = textilizable(raw).gsub("\n", "")
1062 result = textilizable(raw).gsub("\n", "")
1028 assert_include expected, result
1063 assert_include expected, result
1029 assert_include '<a name="Subtitle">', result
1064 assert_include '<a name="Subtitle">', result
1030 assert_include '<a name="Subtitle-2">', result
1065 assert_include '<a name="Subtitle-2">', result
1031 end
1066 end
1032
1067
1033 def test_table_of_content_should_contain_included_page_headings
1068 def test_table_of_content_should_contain_included_page_headings
1034 raw = <<-RAW
1069 raw = <<-RAW
1035 {{toc}}
1070 {{toc}}
1036
1071
1037 h1. Included
1072 h1. Included
1038
1073
1039 {{include(Child_1)}}
1074 {{include(Child_1)}}
1040 RAW
1075 RAW
1041
1076
1042 expected = '<ul class="toc">' +
1077 expected = '<ul class="toc">' +
1043 '<li><a href="#Included">Included</a></li>' +
1078 '<li><a href="#Included">Included</a></li>' +
1044 '<li><a href="#Child-page-1">Child page 1</a></li>' +
1079 '<li><a href="#Child-page-1">Child page 1</a></li>' +
1045 '</ul>'
1080 '</ul>'
1046
1081
1047 @project = Project.find(1)
1082 @project = Project.find(1)
1048 assert textilizable(raw).gsub("\n", "").include?(expected)
1083 assert textilizable(raw).gsub("\n", "").include?(expected)
1049 end
1084 end
1050
1085
1051 def test_section_edit_links
1086 def test_section_edit_links
1052 raw = <<-RAW
1087 raw = <<-RAW
1053 h1. Title
1088 h1. Title
1054
1089
1055 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1090 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
1056
1091
1057 h2. Subtitle with a [[Wiki]] link
1092 h2. Subtitle with a [[Wiki]] link
1058
1093
1059 h2. Subtitle with *some* _modifiers_
1094 h2. Subtitle with *some* _modifiers_
1060
1095
1061 h2. Subtitle with @inline code@
1096 h2. Subtitle with @inline code@
1062
1097
1063 <pre>
1098 <pre>
1064 some code
1099 some code
1065
1100
1066 h2. heading inside pre
1101 h2. heading inside pre
1067
1102
1068 <h2>html heading inside pre</h2>
1103 <h2>html heading inside pre</h2>
1069 </pre>
1104 </pre>
1070
1105
1071 h2. Subtitle after pre tag
1106 h2. Subtitle after pre tag
1072 RAW
1107 RAW
1073
1108
1074 @project = Project.find(1)
1109 @project = Project.find(1)
1075 set_language_if_valid 'en'
1110 set_language_if_valid 'en'
1076 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1111 result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
1077
1112
1078 # heading that contains inline code
1113 # heading that contains inline code
1079 assert_match Regexp.new('<div class="contextual" id="section-4" title="Edit this section">' +
1114 assert_match Regexp.new('<div class="contextual" id="section-4" title="Edit this section">' +
1080 '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1115 '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1081 '<a name="Subtitle-with-inline-code"></a>' +
1116 '<a name="Subtitle-with-inline-code"></a>' +
1082 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1117 '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
1083 result
1118 result
1084
1119
1085 # last heading
1120 # last heading
1086 assert_match Regexp.new('<div class="contextual" id="section-5" title="Edit this section">' +
1121 assert_match Regexp.new('<div class="contextual" id="section-5" title="Edit this section">' +
1087 '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1122 '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1088 '<a name="Subtitle-after-pre-tag"></a>' +
1123 '<a name="Subtitle-after-pre-tag"></a>' +
1089 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1124 '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1090 result
1125 result
1091 end
1126 end
1092
1127
1093 def test_default_formatter
1128 def test_default_formatter
1094 with_settings :text_formatting => 'unknown' do
1129 with_settings :text_formatting => 'unknown' do
1095 text = 'a *link*: http://www.example.net/'
1130 text = 'a *link*: http://www.example.net/'
1096 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1131 assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1097 end
1132 end
1098 end
1133 end
1099
1134
1100 def test_due_date_distance_in_words
1135 def test_due_date_distance_in_words
1101 to_test = { Date.today => 'Due in 0 days',
1136 to_test = { Date.today => 'Due in 0 days',
1102 Date.today + 1 => 'Due in 1 day',
1137 Date.today + 1 => 'Due in 1 day',
1103 Date.today + 100 => 'Due in about 3 months',
1138 Date.today + 100 => 'Due in about 3 months',
1104 Date.today + 20000 => 'Due in over 54 years',
1139 Date.today + 20000 => 'Due in over 54 years',
1105 Date.today - 1 => '1 day late',
1140 Date.today - 1 => '1 day late',
1106 Date.today - 100 => 'about 3 months late',
1141 Date.today - 100 => 'about 3 months late',
1107 Date.today - 20000 => 'over 54 years late',
1142 Date.today - 20000 => 'over 54 years late',
1108 }
1143 }
1109 ::I18n.locale = :en
1144 ::I18n.locale = :en
1110 to_test.each do |date, expected|
1145 to_test.each do |date, expected|
1111 assert_equal expected, due_date_distance_in_words(date)
1146 assert_equal expected, due_date_distance_in_words(date)
1112 end
1147 end
1113 end
1148 end
1114
1149
1115 def test_avatar_enabled
1150 def test_avatar_enabled
1116 with_settings :gravatar_enabled => '1' do
1151 with_settings :gravatar_enabled => '1' do
1117 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1152 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1118 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1153 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1119 # Default size is 50
1154 # Default size is 50
1120 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1155 assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1121 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1156 assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1122 # Non-avatar options should be considered html options
1157 # Non-avatar options should be considered html options
1123 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1158 assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1124 # The default class of the img tag should be gravatar
1159 # The default class of the img tag should be gravatar
1125 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1160 assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1126 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1161 assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1127 assert_nil avatar('jsmith')
1162 assert_nil avatar('jsmith')
1128 assert_nil avatar(nil)
1163 assert_nil avatar(nil)
1129 end
1164 end
1130 end
1165 end
1131
1166
1132 def test_avatar_disabled
1167 def test_avatar_disabled
1133 with_settings :gravatar_enabled => '0' do
1168 with_settings :gravatar_enabled => '0' do
1134 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1169 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1135 end
1170 end
1136 end
1171 end
1137
1172
1138 def test_link_to_user
1173 def test_link_to_user
1139 user = User.find(2)
1174 user = User.find(2)
1140 result = link_to("John Smith", "/users/2", :class => "user active")
1175 result = link_to("John Smith", "/users/2", :class => "user active")
1141 assert_equal result, link_to_user(user)
1176 assert_equal result, link_to_user(user)
1142 end
1177 end
1143
1178
1144 def test_link_to_user_should_not_link_to_locked_user
1179 def test_link_to_user_should_not_link_to_locked_user
1145 with_current_user nil do
1180 with_current_user nil do
1146 user = User.find(5)
1181 user = User.find(5)
1147 assert user.locked?
1182 assert user.locked?
1148 assert_equal 'Dave2 Lopper2', link_to_user(user)
1183 assert_equal 'Dave2 Lopper2', link_to_user(user)
1149 end
1184 end
1150 end
1185 end
1151
1186
1152 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1187 def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1153 with_current_user User.find(1) do
1188 with_current_user User.find(1) do
1154 user = User.find(5)
1189 user = User.find(5)
1155 assert user.locked?
1190 assert user.locked?
1156 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1191 result = link_to("Dave2 Lopper2", "/users/5", :class => "user locked")
1157 assert_equal result, link_to_user(user)
1192 assert_equal result, link_to_user(user)
1158 end
1193 end
1159 end
1194 end
1160
1195
1161 def test_link_to_user_should_not_link_to_anonymous
1196 def test_link_to_user_should_not_link_to_anonymous
1162 user = User.anonymous
1197 user = User.anonymous
1163 assert user.anonymous?
1198 assert user.anonymous?
1164 t = link_to_user(user)
1199 t = link_to_user(user)
1165 assert_equal ::I18n.t(:label_user_anonymous), t
1200 assert_equal ::I18n.t(:label_user_anonymous), t
1166 end
1201 end
1167
1202
1168 def test_link_to_attachment
1203 def test_link_to_attachment
1169 a = Attachment.find(3)
1204 a = Attachment.find(3)
1170 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1205 assert_equal '<a href="/attachments/3/logo.gif">logo.gif</a>',
1171 link_to_attachment(a)
1206 link_to_attachment(a)
1172 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1207 assert_equal '<a href="/attachments/3/logo.gif">Text</a>',
1173 link_to_attachment(a, :text => 'Text')
1208 link_to_attachment(a, :text => 'Text')
1174 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1209 result = link_to("logo.gif", "/attachments/3/logo.gif", :class => "foo")
1175 assert_equal result,
1210 assert_equal result,
1176 link_to_attachment(a, :class => 'foo')
1211 link_to_attachment(a, :class => 'foo')
1177 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1212 assert_equal '<a href="/attachments/download/3/logo.gif">logo.gif</a>',
1178 link_to_attachment(a, :download => true)
1213 link_to_attachment(a, :download => true)
1179 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1214 assert_equal '<a href="http://test.host/attachments/3/logo.gif">logo.gif</a>',
1180 link_to_attachment(a, :only_path => false)
1215 link_to_attachment(a, :only_path => false)
1181 end
1216 end
1182
1217
1183 def test_thumbnail_tag
1218 def test_thumbnail_tag
1184 a = Attachment.find(3)
1219 a = Attachment.find(3)
1185 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1220 assert_equal '<a href="/attachments/3/logo.gif" title="logo.gif"><img alt="3" src="/attachments/thumbnail/3" /></a>',
1186 thumbnail_tag(a)
1221 thumbnail_tag(a)
1187 end
1222 end
1188
1223
1189 def test_link_to_project
1224 def test_link_to_project
1190 project = Project.find(1)
1225 project = Project.find(1)
1191 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1226 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1192 link_to_project(project)
1227 link_to_project(project)
1193 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1228 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1194 link_to_project(project, :action => 'settings')
1229 link_to_project(project, :action => 'settings')
1195 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1230 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1196 link_to_project(project, {:only_path => false, :jump => 'blah'})
1231 link_to_project(project, {:only_path => false, :jump => 'blah'})
1197 result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
1232 result = link_to("eCookbook", "/projects/ecookbook/settings", :class => "project")
1198 assert_equal result,
1233 assert_equal result,
1199 link_to_project(project, {:action => 'settings'}, :class => "project")
1234 link_to_project(project, {:action => 'settings'}, :class => "project")
1200 end
1235 end
1201
1236
1202 def test_link_to_project_settings
1237 def test_link_to_project_settings
1203 project = Project.find(1)
1238 project = Project.find(1)
1204 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1239 assert_equal '<a href="/projects/ecookbook/settings">eCookbook</a>', link_to_project_settings(project)
1205
1240
1206 project.status = Project::STATUS_CLOSED
1241 project.status = Project::STATUS_CLOSED
1207 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1242 assert_equal '<a href="/projects/ecookbook">eCookbook</a>', link_to_project_settings(project)
1208
1243
1209 project.status = Project::STATUS_ARCHIVED
1244 project.status = Project::STATUS_ARCHIVED
1210 assert_equal 'eCookbook', link_to_project_settings(project)
1245 assert_equal 'eCookbook', link_to_project_settings(project)
1211 end
1246 end
1212
1247
1213 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1248 def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1214 # numeric identifier are no longer allowed
1249 # numeric identifier are no longer allowed
1215 Project.where(:id => 1).update_all(:identifier => 25)
1250 Project.where(:id => 1).update_all(:identifier => 25)
1216 assert_equal '<a href="/projects/1">eCookbook</a>',
1251 assert_equal '<a href="/projects/1">eCookbook</a>',
1217 link_to_project(Project.find(1))
1252 link_to_project(Project.find(1))
1218 end
1253 end
1219
1254
1220 def test_principals_options_for_select_with_users
1255 def test_principals_options_for_select_with_users
1221 User.current = nil
1256 User.current = nil
1222 users = [User.find(2), User.find(4)]
1257 users = [User.find(2), User.find(4)]
1223 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1258 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1224 principals_options_for_select(users)
1259 principals_options_for_select(users)
1225 end
1260 end
1226
1261
1227 def test_principals_options_for_select_with_selected
1262 def test_principals_options_for_select_with_selected
1228 User.current = nil
1263 User.current = nil
1229 users = [User.find(2), User.find(4)]
1264 users = [User.find(2), User.find(4)]
1230 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1265 assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1231 principals_options_for_select(users, User.find(4))
1266 principals_options_for_select(users, User.find(4))
1232 end
1267 end
1233
1268
1234 def test_principals_options_for_select_with_users_and_groups
1269 def test_principals_options_for_select_with_users_and_groups
1235 User.current = nil
1270 User.current = nil
1236 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1271 users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1237 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1272 assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1238 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1273 %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1239 principals_options_for_select(users)
1274 principals_options_for_select(users)
1240 end
1275 end
1241
1276
1242 def test_principals_options_for_select_with_empty_collection
1277 def test_principals_options_for_select_with_empty_collection
1243 assert_equal '', principals_options_for_select([])
1278 assert_equal '', principals_options_for_select([])
1244 end
1279 end
1245
1280
1246 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1281 def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1247 users = [User.find(2), User.find(4)]
1282 users = [User.find(2), User.find(4)]
1248 User.current = User.find(4)
1283 User.current = User.find(4)
1249 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1284 assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1250 end
1285 end
1251
1286
1252 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1287 def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1253 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1288 assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1254 end
1289 end
1255
1290
1256 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1291 def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1257 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1292 assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1258 end
1293 end
1259
1294
1260 def test_image_tag_should_pick_the_default_image
1295 def test_image_tag_should_pick_the_default_image
1261 assert_match 'src="/images/image.png"', image_tag("image.png")
1296 assert_match 'src="/images/image.png"', image_tag("image.png")
1262 end
1297 end
1263
1298
1264 def test_image_tag_should_pick_the_theme_image_if_it_exists
1299 def test_image_tag_should_pick_the_theme_image_if_it_exists
1265 theme = Redmine::Themes.themes.last
1300 theme = Redmine::Themes.themes.last
1266 theme.images << 'image.png'
1301 theme.images << 'image.png'
1267
1302
1268 with_settings :ui_theme => theme.id do
1303 with_settings :ui_theme => theme.id do
1269 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1304 assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1270 assert_match %|src="/images/other.png"|, image_tag("other.png")
1305 assert_match %|src="/images/other.png"|, image_tag("other.png")
1271 end
1306 end
1272 ensure
1307 ensure
1273 theme.images.delete 'image.png'
1308 theme.images.delete 'image.png'
1274 end
1309 end
1275
1310
1276 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1311 def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1277 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1312 assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1278 end
1313 end
1279
1314
1280 def test_javascript_include_tag_should_pick_the_default_javascript
1315 def test_javascript_include_tag_should_pick_the_default_javascript
1281 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1316 assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1282 end
1317 end
1283
1318
1284 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1319 def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1285 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1320 assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1286 end
1321 end
1287
1322
1288 def test_raw_json_should_escape_closing_tags
1323 def test_raw_json_should_escape_closing_tags
1289 s = raw_json(["<foo>bar</foo>"])
1324 s = raw_json(["<foo>bar</foo>"])
1290 assert_equal '["<foo>bar<\/foo>"]', s
1325 assert_equal '["<foo>bar<\/foo>"]', s
1291 end
1326 end
1292
1327
1293 def test_raw_json_should_be_html_safe
1328 def test_raw_json_should_be_html_safe
1294 s = raw_json(["foo"])
1329 s = raw_json(["foo"])
1295 assert s.html_safe?
1330 assert s.html_safe?
1296 end
1331 end
1297
1332
1298 def test_html_title_should_app_title_if_not_set
1333 def test_html_title_should_app_title_if_not_set
1299 assert_equal 'Redmine', html_title
1334 assert_equal 'Redmine', html_title
1300 end
1335 end
1301
1336
1302 def test_html_title_should_join_items
1337 def test_html_title_should_join_items
1303 html_title 'Foo', 'Bar'
1338 html_title 'Foo', 'Bar'
1304 assert_equal 'Foo - Bar - Redmine', html_title
1339 assert_equal 'Foo - Bar - Redmine', html_title
1305 end
1340 end
1306
1341
1307 def test_html_title_should_append_current_project_name
1342 def test_html_title_should_append_current_project_name
1308 @project = Project.find(1)
1343 @project = Project.find(1)
1309 html_title 'Foo', 'Bar'
1344 html_title 'Foo', 'Bar'
1310 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1345 assert_equal 'Foo - Bar - eCookbook - Redmine', html_title
1311 end
1346 end
1312
1347
1313 def test_title_should_return_a_h2_tag
1348 def test_title_should_return_a_h2_tag
1314 assert_equal '<h2>Foo</h2>', title('Foo')
1349 assert_equal '<h2>Foo</h2>', title('Foo')
1315 end
1350 end
1316
1351
1317 def test_title_should_set_html_title
1352 def test_title_should_set_html_title
1318 title('Foo')
1353 title('Foo')
1319 assert_equal 'Foo - Redmine', html_title
1354 assert_equal 'Foo - Redmine', html_title
1320 end
1355 end
1321
1356
1322 def test_title_should_turn_arrays_into_links
1357 def test_title_should_turn_arrays_into_links
1323 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1358 assert_equal '<h2><a href="/foo">Foo</a></h2>', title(['Foo', '/foo'])
1324 assert_equal 'Foo - Redmine', html_title
1359 assert_equal 'Foo - Redmine', html_title
1325 end
1360 end
1326
1361
1327 def test_title_should_join_items
1362 def test_title_should_join_items
1328 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1363 assert_equal '<h2>Foo &#187; Bar</h2>', title('Foo', 'Bar')
1329 assert_equal 'Bar - Foo - Redmine', html_title
1364 assert_equal 'Bar - Foo - Redmine', html_title
1330 end
1365 end
1331
1366
1332 def test_favicon_path
1367 def test_favicon_path
1333 assert_match %r{^/favicon\.ico}, favicon_path
1368 assert_match %r{^/favicon\.ico}, favicon_path
1334 end
1369 end
1335
1370
1336 def test_favicon_path_with_suburi
1371 def test_favicon_path_with_suburi
1337 Redmine::Utils.relative_url_root = '/foo'
1372 Redmine::Utils.relative_url_root = '/foo'
1338 assert_match %r{^/foo/favicon\.ico}, favicon_path
1373 assert_match %r{^/foo/favicon\.ico}, favicon_path
1339 ensure
1374 ensure
1340 Redmine::Utils.relative_url_root = ''
1375 Redmine::Utils.relative_url_root = ''
1341 end
1376 end
1342
1377
1343 def test_favicon_url
1378 def test_favicon_url
1344 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1379 assert_match %r{^http://test\.host/favicon\.ico}, favicon_url
1345 end
1380 end
1346
1381
1347 def test_favicon_url_with_suburi
1382 def test_favicon_url_with_suburi
1348 Redmine::Utils.relative_url_root = '/foo'
1383 Redmine::Utils.relative_url_root = '/foo'
1349 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1384 assert_match %r{^http://test\.host/foo/favicon\.ico}, favicon_url
1350 ensure
1385 ensure
1351 Redmine::Utils.relative_url_root = ''
1386 Redmine::Utils.relative_url_root = ''
1352 end
1387 end
1353
1388
1354 def test_truncate_single_line
1389 def test_truncate_single_line
1355 str = "01234"
1390 str = "01234"
1356 result = truncate_single_line("#{str}\n#{str}", :length => 10)
1391 result = truncate_single_line("#{str}\n#{str}", :length => 10)
1357 assert_equal "01234 0...", result
1392 assert_equal "01234 0...", result
1358 assert !result.html_safe?
1393 assert !result.html_safe?
1359 result = truncate_single_line("#{str}<&#>\n#{str}#{str}", :length => 16)
1394 result = truncate_single_line("#{str}<&#>\n#{str}#{str}", :length => 16)
1360 assert_equal "01234<&#> 012...", result
1395 assert_equal "01234<&#> 012...", result
1361 assert !result.html_safe?
1396 assert !result.html_safe?
1362 end
1397 end
1363
1398
1364 def test_truncate_single_line_non_ascii
1399 def test_truncate_single_line_non_ascii
1365 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
1400 ja = "\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"
1366 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
1401 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
1367 result = truncate_single_line("#{ja}\n#{ja}\n#{ja}", :length => 10)
1402 result = truncate_single_line("#{ja}\n#{ja}\n#{ja}", :length => 10)
1368 assert_equal "#{ja} #{ja}...", result
1403 assert_equal "#{ja} #{ja}...", result
1369 assert !result.html_safe?
1404 assert !result.html_safe?
1370 end
1405 end
1371 end
1406 end
General Comments 0
You need to be logged in to leave comments. Login now