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