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