##// END OF EJS Templates
Fixes distance of date in words calculation....
Jean-Philippe Lang -
r2902:86a9d90f07d6
parent child
Show More
@@ -1,80 +1,80
1
1
2 require 'activerecord'
2 require 'activerecord'
3
3
4 module ActiveRecord
4 module ActiveRecord
5 class Base
5 class Base
6 include Redmine::I18n
6 include Redmine::I18n
7
7
8 # Translate attribute names for validation errors display
8 # Translate attribute names for validation errors display
9 def self.human_attribute_name(attr)
9 def self.human_attribute_name(attr)
10 l("field_#{attr.to_s.gsub(/_id$/, '')}")
10 l("field_#{attr.to_s.gsub(/_id$/, '')}")
11 end
11 end
12 end
12 end
13 end
13 end
14
14
15 module ActiveRecord
15 module ActiveRecord
16 class Errors
16 class Errors
17 def full_messages(options = {})
17 def full_messages(options = {})
18 full_messages = []
18 full_messages = []
19
19
20 @errors.each_key do |attr|
20 @errors.each_key do |attr|
21 @errors[attr].each do |message|
21 @errors[attr].each do |message|
22 next unless message
22 next unless message
23
23
24 if attr == "base"
24 if attr == "base"
25 full_messages << message
25 full_messages << message
26 elsif attr == "custom_values"
26 elsif attr == "custom_values"
27 # Replace the generic "custom values is invalid"
27 # Replace the generic "custom values is invalid"
28 # with the errors on custom values
28 # with the errors on custom values
29 @base.custom_values.each do |value|
29 @base.custom_values.each do |value|
30 value.errors.each do |attr, msg|
30 value.errors.each do |attr, msg|
31 full_messages << value.custom_field.name + ' ' + msg
31 full_messages << value.custom_field.name + ' ' + msg
32 end
32 end
33 end
33 end
34 else
34 else
35 attr_name = @base.class.human_attribute_name(attr)
35 attr_name = @base.class.human_attribute_name(attr)
36 full_messages << attr_name + ' ' + message.to_s
36 full_messages << attr_name + ' ' + message.to_s
37 end
37 end
38 end
38 end
39 end
39 end
40 full_messages
40 full_messages
41 end
41 end
42 end
42 end
43 end
43 end
44
44
45 module ActionView
45 module ActionView
46 module Helpers
46 module Helpers
47 module DateHelper
47 module DateHelper
48 # distance_of_time_in_words breaks when difference is greater than 30 years
48 # distance_of_time_in_words breaks when difference is greater than 30 years
49 def distance_of_date_in_words(from_date, to_date = 0, options = {})
49 def distance_of_date_in_words(from_date, to_date = 0, options = {})
50 from_date = from_date.to_date if from_date.respond_to?(:to_date)
50 from_date = from_date.to_date if from_date.respond_to?(:to_date)
51 to_date = to_date.to_date if to_date.respond_to?(:to_date)
51 to_date = to_date.to_date if to_date.respond_to?(:to_date)
52 distance_in_days = (to_date - from_date).abs
52 distance_in_days = (to_date - from_date).abs
53
53
54 I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
54 I18n.with_options :locale => options[:locale], :scope => :'datetime.distance_in_words' do |locale|
55 case distance_in_days
55 case distance_in_days
56 when 0..60 then locale.t :x_days, :count => distance_in_days
56 when 0..60 then locale.t :x_days, :count => distance_in_days.round
57 when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
57 when 61..720 then locale.t :about_x_months, :count => (distance_in_days / 30).round
58 else locale.t :over_x_years, :count => (distance_in_days / 365).round
58 else locale.t :over_x_years, :count => (distance_in_days / 365).floor
59 end
59 end
60 end
60 end
61 end
61 end
62 end
62 end
63 end
63 end
64 end
64 end
65
65
66 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
66 ActionView::Base.field_error_proc = Proc.new{ |html_tag, instance| "#{html_tag}" }
67
67
68 # Adds :async_smtp and :async_sendmail delivery methods
68 # Adds :async_smtp and :async_sendmail delivery methods
69 # to perform email deliveries asynchronously
69 # to perform email deliveries asynchronously
70 module AsynchronousMailer
70 module AsynchronousMailer
71 %w(smtp sendmail).each do |type|
71 %w(smtp sendmail).each do |type|
72 define_method("perform_delivery_async_#{type}") do |mail|
72 define_method("perform_delivery_async_#{type}") do |mail|
73 Thread.start do
73 Thread.start do
74 send "perform_delivery_#{type}", mail
74 send "perform_delivery_#{type}", mail
75 end
75 end
76 end
76 end
77 end
77 end
78 end
78 end
79
79
80 ActionMailer::Base.send :include, AsynchronousMailer
80 ActionMailer::Base.send :include, AsynchronousMailer
@@ -1,486 +1,486
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2009 Jean-Philippe Lang
2 # Copyright (C) 2006-2009 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.dirname(__FILE__) + '/../../test_helper'
18 require File.dirname(__FILE__) + '/../../test_helper'
19
19
20 class ApplicationHelperTest < HelperTestCase
20 class ApplicationHelperTest < HelperTestCase
21 include ApplicationHelper
21 include ApplicationHelper
22 include ActionView::Helpers::TextHelper
22 include ActionView::Helpers::TextHelper
23 include ActionView::Helpers::DateHelper
23 include ActionView::Helpers::DateHelper
24
24
25 fixtures :projects, :roles, :enabled_modules, :users,
25 fixtures :projects, :roles, :enabled_modules, :users,
26 :repositories, :changesets,
26 :repositories, :changesets,
27 :trackers, :issue_statuses, :issues, :versions, :documents,
27 :trackers, :issue_statuses, :issues, :versions, :documents,
28 :wikis, :wiki_pages, :wiki_contents,
28 :wikis, :wiki_pages, :wiki_contents,
29 :boards, :messages,
29 :boards, :messages,
30 :attachments
30 :attachments
31
31
32 def setup
32 def setup
33 super
33 super
34 end
34 end
35
35
36 def test_auto_links
36 def test_auto_links
37 to_test = {
37 to_test = {
38 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
38 'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
39 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
39 'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
40 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
40 'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
41 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
41 'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
42 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
42 'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
43 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
43 'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
44 '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>.',
44 '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>.',
45 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
45 'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
46 '(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>)',
46 '(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>)',
47 '(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>)',
47 '(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>)',
48 '(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>).',
48 '(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>).',
49 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
49 '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
50 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
50 '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
51 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
51 '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
52 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
52 'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
53 '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>',
53 '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>',
54 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
54 'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
55 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
55 'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
56 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
56 'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
57 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
57 'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
58 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
58 'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
59 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
59 'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
60 # two exclamation marks
60 # two exclamation marks
61 '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>',
61 '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>',
62 }
62 }
63 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
63 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
64 end
64 end
65
65
66 def test_auto_mailto
66 def test_auto_mailto
67 assert_equal '<p><a href="mailto:test@foo.bar" class="email">test@foo.bar</a></p>',
67 assert_equal '<p><a href="mailto:test@foo.bar" class="email">test@foo.bar</a></p>',
68 textilizable('test@foo.bar')
68 textilizable('test@foo.bar')
69 end
69 end
70
70
71 def test_inline_images
71 def test_inline_images
72 to_test = {
72 to_test = {
73 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
73 '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
74 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
74 'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
75 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
75 'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
76 # inline styles should be stripped
76 # inline styles should be stripped
77 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" alt="" />',
77 'with style !{width:100px;height100px}http://foo.bar/image.jpg!' => 'with style <img src="http://foo.bar/image.jpg" alt="" />',
78 '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" />',
78 '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" />',
79 '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;" />',
79 '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;" />',
80 }
80 }
81 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
81 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
82 end
82 end
83
83
84 def test_inline_images_inside_tags
84 def test_inline_images_inside_tags
85 raw = <<-RAW
85 raw = <<-RAW
86 h1. !foo.png! Heading
86 h1. !foo.png! Heading
87
87
88 Centered image:
88 Centered image:
89
89
90 p=. !bar.gif!
90 p=. !bar.gif!
91 RAW
91 RAW
92
92
93 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
93 assert textilizable(raw).include?('<img src="foo.png" alt="" />')
94 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
94 assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
95 end
95 end
96
96
97 def test_acronyms
97 def test_acronyms
98 to_test = {
98 to_test = {
99 'this is an acronym: GPL(General Public License)' => 'this is an acronym: <acronym title="General Public License">GPL</acronym>',
99 'this is an acronym: GPL(General Public License)' => 'this is an acronym: <acronym title="General Public License">GPL</acronym>',
100 'GPL(This is a double-quoted "title")' => '<acronym title="This is a double-quoted &quot;title&quot;">GPL</acronym>',
100 'GPL(This is a double-quoted "title")' => '<acronym title="This is a double-quoted &quot;title&quot;">GPL</acronym>',
101 }
101 }
102 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
102 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
103
103
104 end
104 end
105
105
106 def test_attached_images
106 def test_attached_images
107 to_test = {
107 to_test = {
108 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
108 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
109 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
109 'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
110 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
110 'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
111 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
111 'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
112 # link image
112 # link image
113 '!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>',
113 '!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>',
114 }
114 }
115 attachments = Attachment.find(:all)
115 attachments = Attachment.find(:all)
116 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
116 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
117 end
117 end
118
118
119 def test_textile_external_links
119 def test_textile_external_links
120 to_test = {
120 to_test = {
121 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
121 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
122 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
122 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
123 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
123 '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
124 '"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>',
124 '"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>',
125 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
125 "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
126 # no multiline link text
126 # no multiline link text
127 "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",
127 "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",
128 # mailto link
128 # mailto link
129 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
129 "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
130 # two exclamation marks
130 # two exclamation marks
131 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
131 '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
132 }
132 }
133 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
133 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
134 end
134 end
135
135
136 def test_redmine_links
136 def test_redmine_links
137 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
137 issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
138 :class => 'issue', :title => 'Error 281 when updating a recipe (New)')
138 :class => 'issue', :title => 'Error 281 when updating a recipe (New)')
139
139
140 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
140 changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
141 :class => 'changeset', :title => 'My very first commit')
141 :class => 'changeset', :title => 'My very first commit')
142 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
142 changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
143 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
143 :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
144
144
145 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
145 document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
146 :class => 'document')
146 :class => 'document')
147
147
148 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
148 version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
149 :class => 'version')
149 :class => 'version')
150
150
151 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
151 message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
152
152
153 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
153 source_url = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}
154 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
154 source_url_with_ext = {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file.ext']}
155
155
156 to_test = {
156 to_test = {
157 # tickets
157 # tickets
158 '#3, #3 and #3.' => "#{issue_link}, #{issue_link} and #{issue_link}.",
158 '#3, #3 and #3.' => "#{issue_link}, #{issue_link} and #{issue_link}.",
159 # changesets
159 # changesets
160 'r1' => changeset_link,
160 'r1' => changeset_link,
161 'r1.' => "#{changeset_link}.",
161 'r1.' => "#{changeset_link}.",
162 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
162 'r1, r2' => "#{changeset_link}, #{changeset_link2}",
163 'r1,r2' => "#{changeset_link},#{changeset_link2}",
163 'r1,r2' => "#{changeset_link},#{changeset_link2}",
164 # documents
164 # documents
165 'document#1' => document_link,
165 'document#1' => document_link,
166 'document:"Test document"' => document_link,
166 'document:"Test document"' => document_link,
167 # versions
167 # versions
168 'version#2' => version_link,
168 'version#2' => version_link,
169 'version:1.0' => version_link,
169 'version:1.0' => version_link,
170 'version:"1.0"' => version_link,
170 'version:"1.0"' => version_link,
171 # source
171 # source
172 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
172 'source:/some/file' => link_to('source:/some/file', source_url, :class => 'source'),
173 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
173 'source:/some/file.' => link_to('source:/some/file', source_url, :class => 'source') + ".",
174 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
174 'source:/some/file.ext.' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
175 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
175 'source:/some/file. ' => link_to('source:/some/file', source_url, :class => 'source') + ".",
176 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
176 'source:/some/file.ext. ' => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
177 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
177 'source:/some/file, ' => link_to('source:/some/file', source_url, :class => 'source') + ",",
178 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
178 'source:/some/file@52' => link_to('source:/some/file@52', source_url.merge(:rev => 52), :class => 'source'),
179 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
179 'source:/some/file.ext@52' => link_to('source:/some/file.ext@52', source_url_with_ext.merge(:rev => 52), :class => 'source'),
180 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
180 'source:/some/file#L110' => link_to('source:/some/file#L110', source_url.merge(:anchor => 'L110'), :class => 'source'),
181 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
181 'source:/some/file.ext#L110' => link_to('source:/some/file.ext#L110', source_url_with_ext.merge(:anchor => 'L110'), :class => 'source'),
182 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
182 'source:/some/file@52#L110' => link_to('source:/some/file@52#L110', source_url.merge(:rev => 52, :anchor => 'L110'), :class => 'source'),
183 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
183 'export:/some/file' => link_to('export:/some/file', source_url.merge(:format => 'raw'), :class => 'source download'),
184 # message
184 # message
185 'message#4' => link_to('Post 2', message_url, :class => 'message'),
185 'message#4' => link_to('Post 2', message_url, :class => 'message'),
186 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5'), :class => 'message'),
186 'message#5' => link_to('RE: post 2', message_url.merge(:anchor => 'message-5'), :class => 'message'),
187 # escaping
187 # escaping
188 '!#3.' => '#3.',
188 '!#3.' => '#3.',
189 '!r1' => 'r1',
189 '!r1' => 'r1',
190 '!document#1' => 'document#1',
190 '!document#1' => 'document#1',
191 '!document:"Test document"' => 'document:"Test document"',
191 '!document:"Test document"' => 'document:"Test document"',
192 '!version#2' => 'version#2',
192 '!version#2' => 'version#2',
193 '!version:1.0' => 'version:1.0',
193 '!version:1.0' => 'version:1.0',
194 '!version:"1.0"' => 'version:"1.0"',
194 '!version:"1.0"' => 'version:"1.0"',
195 '!source:/some/file' => 'source:/some/file',
195 '!source:/some/file' => 'source:/some/file',
196 # invalid expressions
196 # invalid expressions
197 'source:' => 'source:',
197 'source:' => 'source:',
198 # url hash
198 # url hash
199 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
199 "http://foo.bar/FAQ#3" => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
200 }
200 }
201 @project = Project.find(1)
201 @project = Project.find(1)
202 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
202 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
203 end
203 end
204
204
205 def test_wiki_links
205 def test_wiki_links
206 to_test = {
206 to_test = {
207 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
207 '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
208 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
208 '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
209 # link with anchor
209 # link with anchor
210 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
210 '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
211 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
211 '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
212 # page that doesn't exist
212 # page that doesn't exist
213 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
213 '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
214 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
214 '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
215 # link to another project wiki
215 # link to another project wiki
216 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki/" class="wiki-page">onlinestore</a>',
216 '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki/" class="wiki-page">onlinestore</a>',
217 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki/" class="wiki-page">Wiki</a>',
217 '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki/" class="wiki-page">Wiki</a>',
218 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
218 '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
219 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
219 '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
220 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
220 '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
221 # striked through link
221 # striked through link
222 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
222 '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
223 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
223 '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
224 # escaping
224 # escaping
225 '![[Another page|Page]]' => '[[Another page|Page]]',
225 '![[Another page|Page]]' => '[[Another page|Page]]',
226 # project does not exist
226 # project does not exist
227 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
227 '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
228 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
228 '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
229 }
229 }
230 @project = Project.find(1)
230 @project = Project.find(1)
231 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
231 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
232 end
232 end
233
233
234 def test_html_tags
234 def test_html_tags
235 to_test = {
235 to_test = {
236 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
236 "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
237 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
237 "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
238 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
238 "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
239 # do not escape pre/code tags
239 # do not escape pre/code tags
240 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
240 "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
241 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
241 "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
242 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
242 "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
243 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
243 "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
244 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
244 "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
245 # remove attributes except class
245 # remove attributes except class
246 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
246 "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
247 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
247 "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
248 }
248 }
249 to_test.each { |text, result| assert_equal result, textilizable(text) }
249 to_test.each { |text, result| assert_equal result, textilizable(text) }
250 end
250 end
251
251
252 def test_allowed_html_tags
252 def test_allowed_html_tags
253 to_test = {
253 to_test = {
254 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
254 "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
255 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
255 "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
256 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
256 "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
257 }
257 }
258 to_test.each { |text, result| assert_equal result, textilizable(text) }
258 to_test.each { |text, result| assert_equal result, textilizable(text) }
259 end
259 end
260
260
261 def test_syntax_highlight
261 def test_syntax_highlight
262 raw = <<-RAW
262 raw = <<-RAW
263 <pre><code class="ruby">
263 <pre><code class="ruby">
264 # Some ruby code here
264 # Some ruby code here
265 </pre></code>
265 </pre></code>
266 RAW
266 RAW
267
267
268 expected = <<-EXPECTED
268 expected = <<-EXPECTED
269 <pre><code class="ruby CodeRay"><span class="no">1</span> <span class="c"># Some ruby code here</span>
269 <pre><code class="ruby CodeRay"><span class="no">1</span> <span class="c"># Some ruby code here</span>
270 </pre></code>
270 </pre></code>
271 EXPECTED
271 EXPECTED
272
272
273 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
273 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
274 end
274 end
275
275
276 def test_wiki_links_in_tables
276 def test_wiki_links_in_tables
277 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
277 to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
278 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
278 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
279 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
279 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
280 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
280 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
281 }
281 }
282 @project = Project.find(1)
282 @project = Project.find(1)
283 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
283 to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
284 end
284 end
285
285
286 def test_text_formatting
286 def test_text_formatting
287 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
287 to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
288 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
288 '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
289 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
289 'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
290 '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>',
290 '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>',
291 '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',
291 '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',
292 }
292 }
293 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
293 to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
294 end
294 end
295
295
296 def test_wiki_horizontal_rule
296 def test_wiki_horizontal_rule
297 assert_equal '<hr />', textilizable('---')
297 assert_equal '<hr />', textilizable('---')
298 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
298 assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
299 end
299 end
300
300
301 def test_acronym
301 def test_acronym
302 assert_equal '<p>This is an acronym: <acronym title="American Civil Liberties Union">ACLU</acronym>.</p>',
302 assert_equal '<p>This is an acronym: <acronym title="American Civil Liberties Union">ACLU</acronym>.</p>',
303 textilizable('This is an acronym: ACLU(American Civil Liberties Union).')
303 textilizable('This is an acronym: ACLU(American Civil Liberties Union).')
304 end
304 end
305
305
306 def test_footnotes
306 def test_footnotes
307 raw = <<-RAW
307 raw = <<-RAW
308 This is some text[1].
308 This is some text[1].
309
309
310 fn1. This is the foot note
310 fn1. This is the foot note
311 RAW
311 RAW
312
312
313 expected = <<-EXPECTED
313 expected = <<-EXPECTED
314 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
314 <p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
315 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
315 <p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
316 EXPECTED
316 EXPECTED
317
317
318 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
318 assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
319 end
319 end
320
320
321 def test_table_of_content
321 def test_table_of_content
322 raw = <<-RAW
322 raw = <<-RAW
323 {{toc}}
323 {{toc}}
324
324
325 h1. Title
325 h1. Title
326
326
327 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
327 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
328
328
329 h2. Subtitle with a [[Wiki]] link
329 h2. Subtitle with a [[Wiki]] link
330
330
331 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
331 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
332
332
333 h2. Subtitle with [[Wiki|another Wiki]] link
333 h2. Subtitle with [[Wiki|another Wiki]] link
334
334
335 h2. Subtitle with %{color:red}red text%
335 h2. Subtitle with %{color:red}red text%
336
336
337 h1. Another title
337 h1. Another title
338
338
339 RAW
339 RAW
340
340
341 expected = '<ul class="toc">' +
341 expected = '<ul class="toc">' +
342 '<li class="heading1"><a href="#Title">Title</a></li>' +
342 '<li class="heading1"><a href="#Title">Title</a></li>' +
343 '<li class="heading2"><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
343 '<li class="heading2"><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
344 '<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
344 '<li class="heading2"><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
345 '<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
345 '<li class="heading2"><a href="#Subtitle-with-red-text">Subtitle with red text</a></li>' +
346 '<li class="heading1"><a href="#Another-title">Another title</a></li>' +
346 '<li class="heading1"><a href="#Another-title">Another title</a></li>' +
347 '</ul>'
347 '</ul>'
348
348
349 assert textilizable(raw).gsub("\n", "").include?(expected)
349 assert textilizable(raw).gsub("\n", "").include?(expected)
350 end
350 end
351
351
352 def test_blockquote
352 def test_blockquote
353 # orig raw text
353 # orig raw text
354 raw = <<-RAW
354 raw = <<-RAW
355 John said:
355 John said:
356 > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
356 > Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
357 > Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
357 > Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
358 > * Donec odio lorem,
358 > * Donec odio lorem,
359 > * sagittis ac,
359 > * sagittis ac,
360 > * malesuada in,
360 > * malesuada in,
361 > * adipiscing eu, dolor.
361 > * adipiscing eu, dolor.
362 >
362 >
363 > >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
363 > >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
364 > Proin a tellus. Nam vel neque.
364 > Proin a tellus. Nam vel neque.
365
365
366 He's right.
366 He's right.
367 RAW
367 RAW
368
368
369 # expected html
369 # expected html
370 expected = <<-EXPECTED
370 expected = <<-EXPECTED
371 <p>John said:</p>
371 <p>John said:</p>
372 <blockquote>
372 <blockquote>
373 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
373 Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
374 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
374 Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
375 <ul>
375 <ul>
376 <li>Donec odio lorem,</li>
376 <li>Donec odio lorem,</li>
377 <li>sagittis ac,</li>
377 <li>sagittis ac,</li>
378 <li>malesuada in,</li>
378 <li>malesuada in,</li>
379 <li>adipiscing eu, dolor.</li>
379 <li>adipiscing eu, dolor.</li>
380 </ul>
380 </ul>
381 <blockquote>
381 <blockquote>
382 <p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
382 <p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
383 </blockquote>
383 </blockquote>
384 <p>Proin a tellus. Nam vel neque.</p>
384 <p>Proin a tellus. Nam vel neque.</p>
385 </blockquote>
385 </blockquote>
386 <p>He's right.</p>
386 <p>He's right.</p>
387 EXPECTED
387 EXPECTED
388
388
389 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
389 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
390 end
390 end
391
391
392 def test_table
392 def test_table
393 raw = <<-RAW
393 raw = <<-RAW
394 This is a table with empty cells:
394 This is a table with empty cells:
395
395
396 |cell11|cell12||
396 |cell11|cell12||
397 |cell21||cell23|
397 |cell21||cell23|
398 |cell31|cell32|cell33|
398 |cell31|cell32|cell33|
399 RAW
399 RAW
400
400
401 expected = <<-EXPECTED
401 expected = <<-EXPECTED
402 <p>This is a table with empty cells:</p>
402 <p>This is a table with empty cells:</p>
403
403
404 <table>
404 <table>
405 <tr><td>cell11</td><td>cell12</td><td></td></tr>
405 <tr><td>cell11</td><td>cell12</td><td></td></tr>
406 <tr><td>cell21</td><td></td><td>cell23</td></tr>
406 <tr><td>cell21</td><td></td><td>cell23</td></tr>
407 <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
407 <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
408 </table>
408 </table>
409 EXPECTED
409 EXPECTED
410
410
411 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
411 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
412 end
412 end
413
413
414 def test_table_with_line_breaks
414 def test_table_with_line_breaks
415 raw = <<-RAW
415 raw = <<-RAW
416 This is a table with line breaks:
416 This is a table with line breaks:
417
417
418 |cell11
418 |cell11
419 continued|cell12||
419 continued|cell12||
420 |-cell21-||cell23
420 |-cell21-||cell23
421 cell23 line2
421 cell23 line2
422 cell23 *line3*|
422 cell23 *line3*|
423 |cell31|cell32
423 |cell31|cell32
424 cell32 line2|cell33|
424 cell32 line2|cell33|
425
425
426 RAW
426 RAW
427
427
428 expected = <<-EXPECTED
428 expected = <<-EXPECTED
429 <p>This is a table with line breaks:</p>
429 <p>This is a table with line breaks:</p>
430
430
431 <table>
431 <table>
432 <tr>
432 <tr>
433 <td>cell11<br />continued</td>
433 <td>cell11<br />continued</td>
434 <td>cell12</td>
434 <td>cell12</td>
435 <td></td>
435 <td></td>
436 </tr>
436 </tr>
437 <tr>
437 <tr>
438 <td><del>cell21</del></td>
438 <td><del>cell21</del></td>
439 <td></td>
439 <td></td>
440 <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
440 <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
441 </tr>
441 </tr>
442 <tr>
442 <tr>
443 <td>cell31</td>
443 <td>cell31</td>
444 <td>cell32<br/>cell32 line2</td>
444 <td>cell32<br/>cell32 line2</td>
445 <td>cell33</td>
445 <td>cell33</td>
446 </tr>
446 </tr>
447 </table>
447 </table>
448 EXPECTED
448 EXPECTED
449
449
450 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
450 assert_equal expected.gsub(%r{\s+}, ''), textilizable(raw).gsub(%r{\s+}, '')
451 end
451 end
452
452
453 def test_default_formatter
453 def test_default_formatter
454 Setting.text_formatting = 'unknown'
454 Setting.text_formatting = 'unknown'
455 text = 'a *link*: http://www.example.net/'
455 text = 'a *link*: http://www.example.net/'
456 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
456 assert_equal '<p>a *link*: <a href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
457 Setting.text_formatting = 'textile'
457 Setting.text_formatting = 'textile'
458 end
458 end
459
459
460 def test_due_date_distance_in_words
460 def test_due_date_distance_in_words
461 to_test = { Date.today => 'Due in 0 days',
461 to_test = { Date.today => 'Due in 0 days',
462 Date.today + 1 => 'Due in 1 day',
462 Date.today + 1 => 'Due in 1 day',
463 Date.today + 100 => 'Due in about 3 months',
463 Date.today + 100 => 'Due in about 3 months',
464 Date.today + 20000 => 'Due in over 55 years',
464 Date.today + 20000 => 'Due in over 54 years',
465 Date.today - 1 => '1 day late',
465 Date.today - 1 => '1 day late',
466 Date.today - 100 => 'about 3 months late',
466 Date.today - 100 => 'about 3 months late',
467 Date.today - 20000 => 'over 55 years late',
467 Date.today - 20000 => 'over 54 years late',
468 }
468 }
469 to_test.each do |date, expected|
469 to_test.each do |date, expected|
470 assert_equal expected, due_date_distance_in_words(date)
470 assert_equal expected, due_date_distance_in_words(date)
471 end
471 end
472 end
472 end
473
473
474 def test_avatar
474 def test_avatar
475 # turn on avatars
475 # turn on avatars
476 Setting.gravatar_enabled = '1'
476 Setting.gravatar_enabled = '1'
477 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
477 assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
478 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
478 assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
479 assert_nil avatar('jsmith')
479 assert_nil avatar('jsmith')
480 assert_nil avatar(nil)
480 assert_nil avatar(nil)
481
481
482 # turn off avatars
482 # turn off avatars
483 Setting.gravatar_enabled = '0'
483 Setting.gravatar_enabled = '0'
484 assert_nil avatar(User.find_by_mail('jsmith@somenet.foo'))
484 assert_nil avatar(User.find_by_mail('jsmith@somenet.foo'))
485 end
485 end
486 end
486 end
General Comments 0
You need to be logged in to leave comments. Login now