##// END OF EJS Templates
scm: add compatible "commit:xxx" link test for git and darcs....
Toshi MARUYAMA -
r4570:6a6b68d29515
parent child
Show More
@@ -1,663 +1,710
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
2 # Copyright (C) 2006-2010 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../../test_helper', __FILE__)
18 require File.expand_path('../../../test_helper', __FILE__)
19
19
20 class ApplicationHelperTest < ActionView::TestCase
20 class ApplicationHelperTest < ActionView::TestCase
21
21
22 fixtures :projects, :roles, :enabled_modules, :users,
22 fixtures :projects, :roles, :enabled_modules, :users,
23 :repositories, :changesets,
23 :repositories, :changesets,
24 :trackers, :issue_statuses, :issues, :versions, :documents,
24 :trackers, :issue_statuses, :issues, :versions, :documents,
25 :wikis, :wiki_pages, :wiki_contents,
25 :wikis, :wiki_pages, :wiki_contents,
26 :boards, :messages,
26 :boards, :messages,
27 :attachments,
27 :attachments,
28 :enumerations
28 :enumerations
29
29
30 def setup
30 def setup
31 super
31 super
32 end
32 end
33
33
34 context "#link_to_if_authorized" do
34 context "#link_to_if_authorized" do
35 context "authorized user" do
35 context "authorized user" do
36 should "be tested"
36 should "be tested"
37 end
37 end
38
38
39 context "unauthorized user" do
39 context "unauthorized user" do
40 should "be tested"
40 should "be tested"
41 end
41 end
42
42
43 should "allow using the :controller and :action for the target link" do
43 should "allow using the :controller and :action for the target link" do
44 User.current = User.find_by_login('admin')
44 User.current = User.find_by_login('admin')
45
45
46 @project = Issue.first.project # Used by helper
46 @project = Issue.first.project # Used by helper
47 response = link_to_if_authorized("By controller/action",
47 response = link_to_if_authorized("By controller/action",
48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
48 {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
49 assert_match /href/, response
49 assert_match /href/, response
50 end
50 end
51
51
52 end
52 end
53
53
54 def test_auto_links
54 def test_auto_links
55 to_test = {
55 to_test = {
56 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
56 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
57 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
57 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
58 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
58 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
59 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
59 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
60 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
60 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
61 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
61 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
62 '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>.',
62 '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>.',
63 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
63 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
64 '(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>)',
64 '(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>)',
65 '(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>)',
65 '(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>)',
66 '(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>).',
66 '(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>).',
67 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
67 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
68 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
68 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
69 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
69 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
70 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
70 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
71 '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>',
71 '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>',
72 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
72 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
73 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
73 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
74 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
74 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
75 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
75 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
76 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
76 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
77 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
77 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
78 # two exclamation marks
78 # two exclamation marks
79 '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>',
79 '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>',
80 # escaping
80 # escaping
81 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo"bar</a>',
81 'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo"bar</a>',
82 # wrap in angle brackets
82 # wrap in angle brackets
83 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
83 '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
84 }
84 }
85 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
85 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
86 end
86 end
87
87
88 def test_auto_mailto
88 def test_auto_mailto
89 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
89 assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
90 textilizable('test@foo.bar')
90 textilizable('test@foo.bar')
91 end
91 end
92
92
93 def test_inline_images
93 def test_inline_images
94 to_test = {
94 to_test = {
95 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
95 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
96 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
96 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
97 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
97 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
98 # inline styles should be stripped
98 # inline styles should be stripped
99 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" alt="" />',
99 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" alt="" />',
100 '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" />',
100 '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" />',
101 '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;" />',
101 '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;" />',
102 }
102 }
103 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
103 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
104 end
104 end
105
105
106 def test_inline_images_inside_tags
106 def test_inline_images_inside_tags
107 raw = <<-RAW
107 raw = <<-RAW
108 h1. !foo.png! Heading
108 h1. !foo.png! Heading
109
109
110 Centered image:
110 Centered image:
111
111
112 p=. !bar.gif!
112 p=. !bar.gif!
113 RAW
113 RAW
114
114
115 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
115 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
116 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
116 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
117 end
117 end
118
118
119 def test_attached_images
119 def test_attached_images
120 to_test = {
120 to_test = {
121 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
121 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
122 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
122 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
123 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
123 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
124 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
124 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
125 # link image
125 # link image
126 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3" title="This is a logo" alt="This is a logo" /></a>',
126 '!logo.gif!:http://foo.bar/' => '<a href="http://foo.bar/"><img src="/attachments/download/3" title="This is a logo" alt="This is a logo" /></a>',
127 }
127 }
128 attachments = Attachment.find(:all)
128 attachments = Attachment.find(:all)
129 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
129 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
130 end
130 end
131
131
132 def test_textile_external_links
132 def test_textile_external_links
133 to_test = {
133 to_test = {
134 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
134 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
135 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
135 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
136 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
136 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
137 '"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>',
137 '"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>',
138 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
138 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
139 # no multiline link text
139 # no multiline link text
140 "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",
140 "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",
141 # mailto link
141 # mailto link
142 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
142 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
143 # two exclamation marks
143 # two exclamation marks
144 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
144 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
145 # escaping
145 # escaping
146 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
146 '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
147 }
147 }
148 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
148 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
149 end
149 end
150
150
151 def test_redmine_links
151 def test_redmine_links
152 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
152 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
153 :class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)')
153 :class => 'issue status-1 priority-1 overdue', :title => 'Error 281 when updating a recipe (New)')
154
154
155 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
155 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
156 :class => 'changeset', :title => 'My very first commit')
156 :class => 'changeset', :title => 'My very first commit')
157 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
157 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
158 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
158 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
159
159
160 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
160 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
161 :class => 'document')
161 :class => 'document')
162
162
163 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
163 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
164 :class => 'version')
164 :class => 'version')
165
165
166 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
166 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
167
167
168 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
168 project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
169
169
170 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
170 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
171 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
171 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
172
172
173 to_test = {
173 to_test = {
174 # tickets
174 # tickets
175 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
175 '#3, [#3], (#3) and #3.' => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
176 # changesets
176 # changesets
177 'r1' => changeset_link,
177 'r1' => changeset_link,
178 'r1.' => "#{changeset_link}.",
178 'r1.' => "#{changeset_link}.",
179 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
179 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
180 'r1,r2' => "#{changeset_link},#{changeset_link2}",
180 'r1,r2' => "#{changeset_link},#{changeset_link2}",
181 # documents
181 # documents
182 'document#1' => document_link,
182 'document#1' => document_link,
183 'document:"Test document"' => document_link,
183 'document:"Test document"' => document_link,
184 # versions
184 # versions
185 'version#2' => version_link,
185 'version#2' => version_link,
186 'version:1.0' => version_link,
186 'version:1.0' => version_link,
187 'version:"1.0"' => version_link,
187 'version:"1.0"' => version_link,
188 # source
188 # source
189 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
189 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
190 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
190 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
191 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
191 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
192 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
192 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
193 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
193 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
194 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
194 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
195 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
195 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
196 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
196 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
197 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
197 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
198 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
198 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
199 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
199 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
200 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
200 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
201 # message
201 # message
202 'message#4' => link_to('Post 2', message_url, :class => 'message'),
202 'message#4' => link_to('Post 2', message_url, :class => 'message'),
203 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5'), :class => 'message'),
203 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5'), :class => 'message'),
204 # project
204 # project
205 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
205 'project#3' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
206 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
206 'project:subproject1' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
207 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
207 'project:"eCookbook subProject 1"' => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
208 # escaping
208 # escaping
209 '!#3.' => '#3.',
209 '!#3.' => '#3.',
210 '!r1' => 'r1',
210 '!r1' => 'r1',
211 '!document#1' => 'document#1',
211 '!document#1' => 'document#1',
212 '!document:"Test document"' => 'document:"Test document"',
212 '!document:"Test document"' => 'document:"Test document"',
213 '!version#2' => 'version#2',
213 '!version#2' => 'version#2',
214 '!version:1.0' => 'version:1.0',
214 '!version:1.0' => 'version:1.0',
215 '!version:"1.0"' => 'version:"1.0"',
215 '!version:"1.0"' => 'version:"1.0"',
216 '!source:/some/file' => 'source:/some/file',
216 '!source:/some/file' => 'source:/some/file',
217 # not found
217 # not found
218 '#0123456789' => '#0123456789',
218 '#0123456789' => '#0123456789',
219 # invalid expressions
219 # invalid expressions
220 'source:' => 'source:',
220 'source:' => 'source:',
221 # url hash
221 # url hash
222 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
222 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
223 }
223 }
224 @project = Project.find(1)
224 @project = Project.find(1)
225 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
225 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
226 end
226 end
227
227
228 def test_redmine_links_git_commit
229 changeset_link = link_to('abcd',
230 {
231 :controller => 'repositories',
232 :action => 'revision', :id => 'subproject1',
233 :rev => 'abcd'
234 },
235 :class => 'changeset', :title => 'test commit')
236 to_test = {
237 'commit:abcd' => changeset_link,
238 }
239 @project = Project.find(3)
240 r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
241 assert r
242 c = Changeset.new(:repository => r,
243 :committed_on => Time.now,
244 :revision => 'abcd',
245 :scmid => 'abcd',
246 :comments => 'test commit')
247 assert( c.save )
248 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
249 end
250
251 # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
252 def test_redmine_links_darcs_commit
253 changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
254 {
255 :controller => 'repositories',
256 :action => 'revision', :id => 'subproject1',
257 :rev => '123'
258 },
259 :class => 'changeset', :title => 'test commit')
260 to_test = {
261 'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
262 }
263 @project = Project.find(3)
264 r = Repository::Darcs.create!(:project => @project, :url => '/tmp/test/darcs')
265 assert r
266 c = Changeset.new(:repository => r,
267 :committed_on => Time.now,
268 :revision => '123',
269 :scmid => '20080308225258-98289-abcd456efg.gz',
270 :comments => 'test commit')
271 assert( c.save )
272 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
273 end
274
228 def test_attachment_links
275 def test_attachment_links
229 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment')
276 attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment')
230 to_test = {
277 to_test = {
231 'attachment:error281.txt' => attachment_link
278 'attachment:error281.txt' => attachment_link
232 }
279 }
233 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
280 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
234 end
281 end
235
282
236 def test_wiki_links
283 def test_wiki_links
237 to_test = {
284 to_test = {
238 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
285 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
239 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
286 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
240 # link with anchor
287 # link with anchor
241 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
288 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
242 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
289 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
243 # page that doesn't exist
290 # page that doesn't exist
244 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
291 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
245 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
292 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
246 # link to another project wiki
293 # link to another project wiki
247 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
294 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
248 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
295 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
249 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
296 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
250 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
297 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
251 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
298 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
252 # striked through link
299 # striked through link
253 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
300 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
254 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
301 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
255 # escaping
302 # escaping
256 '![[Another page|Page]]' => '[[Another page|Page]]',
303 '![[Another page|Page]]' => '[[Another page|Page]]',
257 # project does not exist
304 # project does not exist
258 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
305 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
259 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
306 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
260 }
307 }
261 @project = Project.find(1)
308 @project = Project.find(1)
262 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
309 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
263 end
310 end
264
311
265 def test_html_tags
312 def test_html_tags
266 to_test = {
313 to_test = {
267 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
314 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
268 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
315 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
269 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
316 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
270 # do not escape pre/code tags
317 # do not escape pre/code tags
271 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
318 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
272 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
319 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
273 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
320 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
274 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
321 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
275 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
322 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
276 # remove attributes except class
323 # remove attributes except class
277 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
324 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
278 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
325 '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
279 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
326 "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
280 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
327 '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
281 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
328 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
282 # xss
329 # xss
283 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
330 '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
284 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
331 '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
285 }
332 }
286 to_test.each { |text, result| assert_equal result, textilizable(text) }
333 to_test.each { |text, result| assert_equal result, textilizable(text) }
287 end
334 end
288
335
289 def test_allowed_html_tags
336 def test_allowed_html_tags
290 to_test = {
337 to_test = {
291 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
338 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
292 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
339 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
293 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
340 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
294 }
341 }
295 to_test.each { |text, result| assert_equal result, textilizable(text) }
342 to_test.each { |text, result| assert_equal result, textilizable(text) }
296 end
343 end
297
344
298 def test_pre_tags
345 def test_pre_tags
299 raw = <<-RAW
346 raw = <<-RAW
300 Before
347 Before
301
348
302 <pre>
349 <pre>
303 <prepared-statement-cache-size>32</prepared-statement-cache-size>
350 <prepared-statement-cache-size>32</prepared-statement-cache-size>
304 </pre>
351 </pre>
305
352
306 After
353 After
307 RAW
354 RAW
308
355
309 expected = <<-EXPECTED
356 expected = <<-EXPECTED
310 <p>Before</p>
357 <p>Before</p>
311 <pre>
358 <pre>
312 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
359 &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
313 </pre>
360 </pre>
314 <p>After</p>
361 <p>After</p>
315 EXPECTED
362 EXPECTED
316
363
317 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
364 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
318 end
365 end
319
366
320 def test_pre_content_should_not_parse_wiki_and_redmine_links
367 def test_pre_content_should_not_parse_wiki_and_redmine_links
321 raw = <<-RAW
368 raw = <<-RAW
322 [[CookBook documentation]]
369 [[CookBook documentation]]
323
370
324 #1
371 #1
325
372
326 <pre>
373 <pre>
327 [[CookBook documentation]]
374 [[CookBook documentation]]
328
375
329 #1
376 #1
330 </pre>
377 </pre>
331 RAW
378 RAW
332
379
333 expected = <<-EXPECTED
380 expected = <<-EXPECTED
334 <p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
381 <p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
335 <p><a href="/issues/1" class="issue status-1 priority-1" title="Can't print recipes (New)">#1</a></p>
382 <p><a href="/issues/1" class="issue status-1 priority-1" title="Can't print recipes (New)">#1</a></p>
336 <pre>
383 <pre>
337 [[CookBook documentation]]
384 [[CookBook documentation]]
338
385
339 #1
386 #1
340 </pre>
387 </pre>
341 EXPECTED
388 EXPECTED
342
389
343 @project = Project.find(1)
390 @project = Project.find(1)
344 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
391 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
345 end
392 end
346
393
347 def test_non_closing_pre_blocks_should_be_closed
394 def test_non_closing_pre_blocks_should_be_closed
348 raw = <<-RAW
395 raw = <<-RAW
349 <pre><code>
396 <pre><code>
350 RAW
397 RAW
351
398
352 expected = <<-EXPECTED
399 expected = <<-EXPECTED
353 <pre><code>
400 <pre><code>
354 </code></pre>
401 </code></pre>
355 EXPECTED
402 EXPECTED
356
403
357 @project = Project.find(1)
404 @project = Project.find(1)
358 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
405 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
359 end
406 end
360
407
361 def test_syntax_highlight
408 def test_syntax_highlight
362 raw = <<-RAW
409 raw = <<-RAW
363 <pre><code class="ruby">
410 <pre><code class="ruby">
364 # Some ruby code here
411 # Some ruby code here
365 </code></pre>
412 </code></pre>
366 RAW
413 RAW
367
414
368 expected = <<-EXPECTED
415 expected = <<-EXPECTED
369 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="no">1</span> <span class="c"># Some ruby code here</span></span>
416 <pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="no">1</span> <span class="c"># Some ruby code here</span></span>
370 </code></pre>
417 </code></pre>
371 EXPECTED
418 EXPECTED
372
419
373 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
420 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
374 end
421 end
375
422
376 def test_wiki_links_in_tables
423 def test_wiki_links_in_tables
377 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
424 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
378 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
425 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
379 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
426 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
380 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
427 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
381 }
428 }
382 @project = Project.find(1)
429 @project = Project.find(1)
383 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
430 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
384 end
431 end
385
432
386 def test_text_formatting
433 def test_text_formatting
387 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
434 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
388 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
435 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
389 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
436 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
390 '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>',
437 '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>',
391 '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',
438 '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',
392 }
439 }
393 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
440 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
394 end
441 end
395
442
396 def test_wiki_horizontal_rule
443 def test_wiki_horizontal_rule
397 assert_equal '<hr />', textilizable('---')
444 assert_equal '<hr />', textilizable('---')
398 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
445 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
399 end
446 end
400
447
401 def test_footnotes
448 def test_footnotes
402 raw = <<-RAW
449 raw = <<-RAW
403 This is some text[1].
450 This is some text[1].
404
451
405 fn1. This is the foot note
452 fn1. This is the foot note
406 RAW
453 RAW
407
454
408 expected = <<-EXPECTED
455 expected = <<-EXPECTED
409 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
456 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
410 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
457 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
411 EXPECTED
458 EXPECTED
412
459
413 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
460 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
414 end
461 end
415
462
416 def test_table_of_content
463 def test_table_of_content
417 raw = <<-RAW
464 raw = <<-RAW
418 {{toc}}
465 {{toc}}
419
466
420 h1. Title
467 h1. Title
421
468
422 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
469 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
423
470
424 h2. Subtitle with a [[Wiki]] link
471 h2. Subtitle with a [[Wiki]] link
425
472
426 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
473 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
427
474
428 h2. Subtitle with [[Wiki|another Wiki]] link
475 h2. Subtitle with [[Wiki|another Wiki]] link
429
476
430 h2. Subtitle with %{color:red}red text%
477 h2. Subtitle with %{color:red}red text%
431
478
432 <pre>
479 <pre>
433 some code
480 some code
434 </pre>
481 </pre>
435
482
436 h3. Subtitle with *some* _modifiers_
483 h3. Subtitle with *some* _modifiers_
437
484
438 h1. Another title
485 h1. Another title
439
486
440 h3. An "Internet link":http://www.redmine.org/ inside subtitle
487 h3. An "Internet link":http://www.redmine.org/ inside subtitle
441
488
442 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
489 h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
443
490
444 RAW
491 RAW
445
492
446 expected = '<ul class="toc">' +
493 expected = '<ul class="toc">' +
447 '<li><a href="#Title">Title</a>' +
494 '<li><a href="#Title">Title</a>' +
448 '<ul>' +
495 '<ul>' +
449 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
496 '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
450 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
497 '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
451 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
498 '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
452 '<ul>' +
499 '<ul>' +
453 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
500 '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
454 '</ul>' +
501 '</ul>' +
455 '</li>' +
502 '</li>' +
456 '</ul>' +
503 '</ul>' +
457 '</li>' +
504 '</li>' +
458 '<li><a href="#Another-title">Another title</a>' +
505 '<li><a href="#Another-title">Another title</a>' +
459 '<ul>' +
506 '<ul>' +
460 '<li>' +
507 '<li>' +
461 '<ul>' +
508 '<ul>' +
462 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
509 '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
463 '</ul>' +
510 '</ul>' +
464 '</li>' +
511 '</li>' +
465 '<li><a href="#Project-Name">Project Name</a></li>' +
512 '<li><a href="#Project-Name">Project Name</a></li>' +
466 '</ul>' +
513 '</ul>' +
467 '</li>' +
514 '</li>' +
468 '</ul>'
515 '</ul>'
469
516
470 @project = Project.find(1)
517 @project = Project.find(1)
471 assert textilizable(raw).gsub("\n", "").include?(expected), textilizable(raw)
518 assert textilizable(raw).gsub("\n", "").include?(expected), textilizable(raw)
472 end
519 end
473
520
474 def test_table_of_content_should_contain_included_page_headings
521 def test_table_of_content_should_contain_included_page_headings
475 raw = <<-RAW
522 raw = <<-RAW
476 {{toc}}
523 {{toc}}
477
524
478 h1. Included
525 h1. Included
479
526
480 {{include(Child_1)}}
527 {{include(Child_1)}}
481 RAW
528 RAW
482
529
483 expected = '<ul class="toc">' +
530 expected = '<ul class="toc">' +
484 '<li><a href="#Included">Included</a></li>' +
531 '<li><a href="#Included">Included</a></li>' +
485 '<li><a href="#Child-page-1">Child page 1</a></li>' +
532 '<li><a href="#Child-page-1">Child page 1</a></li>' +
486 '</ul>'
533 '</ul>'
487
534
488 @project = Project.find(1)
535 @project = Project.find(1)
489 assert textilizable(raw).gsub("\n", "").include?(expected)
536 assert textilizable(raw).gsub("\n", "").include?(expected)
490 end
537 end
491
538
492 def test_blockquote
539 def test_blockquote
493 # orig raw text
540 # orig raw text
494 raw = <<-RAW
541 raw = <<-RAW
495 John said:
542 John said:
496 > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
543 > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
497 > Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
544 > Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
498 > * Donec odio lorem,
545 > * Donec odio lorem,
499 > * sagittis ac,
546 > * sagittis ac,
500 > * malesuada in,
547 > * malesuada in,
501 > * adipiscing eu, dolor.
548 > * adipiscing eu, dolor.
502 >
549 >
503 > >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
550 > >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
504 > Proin a tellus. Nam vel neque.
551 > Proin a tellus. Nam vel neque.
505
552
506 He's right.
553 He's right.
507 RAW
554 RAW
508
555
509 # expected html
556 # expected html
510 expected = <<-EXPECTED
557 expected = <<-EXPECTED
511 <p>John said:</p>
558 <p>John said:</p>
512 <blockquote>
559 <blockquote>
513 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
560 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
514 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
561 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
515 <ul>
562 <ul>
516 <li>Donec odio lorem,</li>
563 <li>Donec odio lorem,</li>
517 <li>sagittis ac,</li>
564 <li>sagittis ac,</li>
518 <li>malesuada in,</li>
565 <li>malesuada in,</li>
519 <li>adipiscing eu, dolor.</li>
566 <li>adipiscing eu, dolor.</li>
520 </ul>
567 </ul>
521 <blockquote>
568 <blockquote>
522 <p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
569 <p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
523 </blockquote>
570 </blockquote>
524 <p>Proin a tellus. Nam vel neque.</p>
571 <p>Proin a tellus. Nam vel neque.</p>
525 </blockquote>
572 </blockquote>
526 <p>He's right.</p>
573 <p>He's right.</p>
527 EXPECTED
574 EXPECTED
528
575
529 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
576 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
530 end
577 end
531
578
532 def test_table
579 def test_table
533 raw = <<-RAW
580 raw = <<-RAW
534 This is a table with empty cells:
581 This is a table with empty cells:
535
582
536 |cell11|cell12||
583 |cell11|cell12||
537 |cell21||cell23|
584 |cell21||cell23|
538 |cell31|cell32|cell33|
585 |cell31|cell32|cell33|
539 RAW
586 RAW
540
587
541 expected = <<-EXPECTED
588 expected = <<-EXPECTED
542 <p>This is a table with empty cells:</p>
589 <p>This is a table with empty cells:</p>
543
590
544 <table>
591 <table>
545 <tr><td>cell11</td><td>cell12</td><td></td></tr>
592 <tr><td>cell11</td><td>cell12</td><td></td></tr>
546 <tr><td>cell21</td><td></td><td>cell23</td></tr>
593 <tr><td>cell21</td><td></td><td>cell23</td></tr>
547 <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
594 <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
548 </table>
595 </table>
549 EXPECTED
596 EXPECTED
550
597
551 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
598 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
552 end
599 end
553
600
554 def test_table_with_line_breaks
601 def test_table_with_line_breaks
555 raw = <<-RAW
602 raw = <<-RAW
556 This is a table with line breaks:
603 This is a table with line breaks:
557
604
558 |cell11
605 |cell11
559 continued|cell12||
606 continued|cell12||
560 |-cell21-||cell23
607 |-cell21-||cell23
561 cell23 line2
608 cell23 line2
562 cell23 *line3*|
609 cell23 *line3*|
563 |cell31|cell32
610 |cell31|cell32
564 cell32 line2|cell33|
611 cell32 line2|cell33|
565
612
566 RAW
613 RAW
567
614
568 expected = <<-EXPECTED
615 expected = <<-EXPECTED
569 <p>This is a table with line breaks:</p>
616 <p>This is a table with line breaks:</p>
570
617
571 <table>
618 <table>
572 <tr>
619 <tr>
573 <td>cell11<br />continued</td>
620 <td>cell11<br />continued</td>
574 <td>cell12</td>
621 <td>cell12</td>
575 <td></td>
622 <td></td>
576 </tr>
623 </tr>
577 <tr>
624 <tr>
578 <td><del>cell21</del></td>
625 <td><del>cell21</del></td>
579 <td></td>
626 <td></td>
580 <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
627 <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
581 </tr>
628 </tr>
582 <tr>
629 <tr>
583 <td>cell31</td>
630 <td>cell31</td>
584 <td>cell32<br/>cell32 line2</td>
631 <td>cell32<br/>cell32 line2</td>
585 <td>cell33</td>
632 <td>cell33</td>
586 </tr>
633 </tr>
587 </table>
634 </table>
588 EXPECTED
635 EXPECTED
589
636
590 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
637 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
591 end
638 end
592
639
593 def test_textile_should_not_mangle_brackets
640 def test_textile_should_not_mangle_brackets
594 assert_equal '<p>[msg1][msg2]</p>', textilizable('[msg1][msg2]')
641 assert_equal '<p>[msg1][msg2]</p>', textilizable('[msg1][msg2]')
595 end
642 end
596
643
597 def test_default_formatter
644 def test_default_formatter
598 Setting.text_formatting = 'unknown'
645 Setting.text_formatting = 'unknown'
599 text = 'a *link*: http://www.example.net/'
646 text = 'a *link*: http://www.example.net/'
600 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
647 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
601 Setting.text_formatting = 'textile'
648 Setting.text_formatting = 'textile'
602 end
649 end
603
650
604 def test_due_date_distance_in_words
651 def test_due_date_distance_in_words
605 to_test = { Date.today => 'Due in 0 days',
652 to_test = { Date.today => 'Due in 0 days',
606 Date.today + 1 => 'Due in 1 day',
653 Date.today + 1 => 'Due in 1 day',
607 Date.today + 100 => 'Due in about 3 months',
654 Date.today + 100 => 'Due in about 3 months',
608 Date.today + 20000 => 'Due in over 54 years',
655 Date.today + 20000 => 'Due in over 54 years',
609 Date.today - 1 => '1 day late',
656 Date.today - 1 => '1 day late',
610 Date.today - 100 => 'about 3 months late',
657 Date.today - 100 => 'about 3 months late',
611 Date.today - 20000 => 'over 54 years late',
658 Date.today - 20000 => 'over 54 years late',
612 }
659 }
613 ::I18n.locale = :en
660 ::I18n.locale = :en
614 to_test.each do |date, expected|
661 to_test.each do |date, expected|
615 assert_equal expected, due_date_distance_in_words(date)
662 assert_equal expected, due_date_distance_in_words(date)
616 end
663 end
617 end
664 end
618
665
619 def test_avatar
666 def test_avatar
620 # turn on avatars
667 # turn on avatars
621 Setting.gravatar_enabled = '1'
668 Setting.gravatar_enabled = '1'
622 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
669 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
623 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
670 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
624 assert_nil avatar('jsmith')
671 assert_nil avatar('jsmith')
625 assert_nil avatar(nil)
672 assert_nil avatar(nil)
626
673
627 # turn off avatars
674 # turn off avatars
628 Setting.gravatar_enabled = '0'
675 Setting.gravatar_enabled = '0'
629 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
676 assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
630 end
677 end
631
678
632 def test_link_to_user
679 def test_link_to_user
633 user = User.find(2)
680 user = User.find(2)
634 t = link_to_user(user)
681 t = link_to_user(user)
635 assert_equal "<a href=\"/users/2\">#{ user.name }</a>", t
682 assert_equal "<a href=\"/users/2\">#{ user.name }</a>", t
636 end
683 end
637
684
638 def test_link_to_user_should_not_link_to_locked_user
685 def test_link_to_user_should_not_link_to_locked_user
639 user = User.find(5)
686 user = User.find(5)
640 assert user.locked?
687 assert user.locked?
641 t = link_to_user(user)
688 t = link_to_user(user)
642 assert_equal user.name, t
689 assert_equal user.name, t
643 end
690 end
644
691
645 def test_link_to_user_should_not_link_to_anonymous
692 def test_link_to_user_should_not_link_to_anonymous
646 user = User.anonymous
693 user = User.anonymous
647 assert user.anonymous?
694 assert user.anonymous?
648 t = link_to_user(user)
695 t = link_to_user(user)
649 assert_equal ::I18n.t(:label_user_anonymous), t
696 assert_equal ::I18n.t(:label_user_anonymous), t
650 end
697 end
651
698
652 def test_link_to_project
699 def test_link_to_project
653 project = Project.find(1)
700 project = Project.find(1)
654 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
701 assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
655 link_to_project(project)
702 link_to_project(project)
656 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
703 assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
657 link_to_project(project, :action => 'settings')
704 link_to_project(project, :action => 'settings')
658 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
705 assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
659 link_to_project(project, {:only_path => false, :jump => 'blah'})
706 link_to_project(project, {:only_path => false, :jump => 'blah'})
660 assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
707 assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
661 link_to_project(project, {:action => 'settings'}, :class => "project")
708 link_to_project(project, {:action => 'settings'}, :class => "project")
662 end
709 end
663 end
710 end
General Comments 0
You need to be logged in to leave comments. Login now