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