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