To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 8e / 8e4c7afc7109386dd42e0a86c04a6247a9bd537e.svn-base @ 1297:0a574315af3e

History | View | Annotate | Download (10.5 KB)

1
# Redmine - project management software
2
# Copyright (C) 2006-2011  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
require 'digest/md5'
20

    
21
class Redmine::WikiFormatting::TextileFormatterTest < ActionView::TestCase
22

    
23
  def setup
24
    @formatter = Redmine::WikiFormatting::Textile::Formatter
25
  end
26

    
27
  MODIFIERS = {
28
    "*" => 'strong', # bold
29
    "_" => 'em',     # italic
30
    "+" => 'ins',    # underline
31
    "-" => 'del',    # deleted
32
    "^" => 'sup',    # superscript
33
    "~" => 'sub'     # subscript
34
  }
35

    
36
  def test_modifiers
37
    assert_html_output(
38
      '*bold*'                => '<strong>bold</strong>',
39
      'before *bold*'         => 'before <strong>bold</strong>',
40
      '*bold* after'          => '<strong>bold</strong> after',
41
      '*two words*'           => '<strong>two words</strong>',
42
      '*two*words*'           => '<strong>two*words</strong>',
43
      '*two * words*'         => '<strong>two * words</strong>',
44
      '*two* *words*'         => '<strong>two</strong> <strong>words</strong>',
45
      '*(two)* *(words)*'     => '<strong>(two)</strong> <strong>(words)</strong>',
46
      # with class
47
      '*(foo)two words*'      => '<strong class="foo">two words</strong>'
48
    )
49
  end
50

    
51
  def test_modifiers_combination
52
    MODIFIERS.each do |m1, tag1|
53
      MODIFIERS.each do |m2, tag2|
54
        next if m1 == m2
55
        text = "#{m2}#{m1}Phrase modifiers#{m1}#{m2}"
56
        html = "<#{tag2}><#{tag1}>Phrase modifiers</#{tag1}></#{tag2}>"
57
        assert_html_output text => html
58
      end
59
    end
60
  end
61

    
62
  def test_inline_code
63
    assert_html_output(
64
      'this is @some code@'      => 'this is <code>some code</code>',
65
      '@<Location /redmine>@'    => '<code>&lt;Location /redmine&gt;</code>'
66
    )
67
  end
68

    
69
  def test_escaping
70
    assert_html_output(
71
      'this is a <script>'      => 'this is a &lt;script&gt;'
72
    )
73
  end
74

    
75
  def test_use_of_backslashes_followed_by_numbers_in_headers
76
    assert_html_output({
77
      'h1. 2009\02\09'      => '<h1>2009\02\09</h1>'
78
    }, false)
79
  end
80

    
81
  def test_double_dashes_should_not_strikethrough
82
    assert_html_output(
83
      'double -- dashes -- test'  => 'double -- dashes -- test',
84
      'double -- *dashes* -- test'  => 'double -- <strong>dashes</strong> -- test'
85
    )
86
  end
87

    
88
  def test_acronyms
89
    assert_html_output(
90
      'this is an acronym: GPL(General Public License)' => 'this is an acronym: <acronym title="General Public License">GPL</acronym>',
91
      '2 letters JP(Jean-Philippe) acronym' => '2 letters <acronym title="Jean-Philippe">JP</acronym> acronym',
92
      'GPL(This is a double-quoted "title")' => '<acronym title="This is a double-quoted &quot;title&quot;">GPL</acronym>'
93
    )
94
  end
95

    
96
  def test_blockquote
97
    # orig raw text
98
    raw = <<-RAW
99
John said:
100
> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
101
> Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
102
> * Donec odio lorem,
103
> * sagittis ac,
104
> * malesuada in,
105
> * adipiscing eu, dolor.
106
>
107
> >Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.
108
> Proin a tellus. Nam vel neque.
109

    
110
He's right.
111
RAW
112

    
113
    # expected html
114
    expected = <<-EXPECTED
115
<p>John said:</p>
116
<blockquote>
117
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.<br />
118
Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
119
<ul>
120
  <li>Donec odio lorem,</li>
121
  <li>sagittis ac,</li>
122
  <li>malesuada in,</li>
123
  <li>adipiscing eu, dolor.</li>
124
</ul>
125
<blockquote>
126
<p>Nulla varius pulvinar diam. Proin id arcu id lorem scelerisque condimentum. Proin vehicula turpis vitae lacus.</p>
127
</blockquote>
128
<p>Proin a tellus. Nam vel neque.</p>
129
</blockquote>
130
<p>He's right.</p>
131
EXPECTED
132

    
133
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
134
  end
135

    
136
  def test_table
137
    raw = <<-RAW
138
This is a table with empty cells:
139

    
140
|cell11|cell12||
141
|cell21||cell23|
142
|cell31|cell32|cell33|
143
RAW
144

    
145
    expected = <<-EXPECTED
146
<p>This is a table with empty cells:</p>
147

    
148
<table>
149
  <tr><td>cell11</td><td>cell12</td><td></td></tr>
150
  <tr><td>cell21</td><td></td><td>cell23</td></tr>
151
  <tr><td>cell31</td><td>cell32</td><td>cell33</td></tr>
152
</table>
153
EXPECTED
154

    
155
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
156
  end
157

    
158
  def test_table_with_line_breaks
159
    raw = <<-RAW
160
This is a table with line breaks:
161

    
162
|cell11
163
continued|cell12||
164
|-cell21-||cell23
165
cell23 line2
166
cell23 *line3*|
167
|cell31|cell32
168
cell32 line2|cell33|
169

    
170
RAW
171

    
172
    expected = <<-EXPECTED
173
<p>This is a table with line breaks:</p>
174

    
175
<table>
176
  <tr>
177
    <td>cell11<br />continued</td>
178
    <td>cell12</td>
179
    <td></td>
180
  </tr>
181
  <tr>
182
    <td><del>cell21</del></td>
183
    <td></td>
184
    <td>cell23<br/>cell23 line2<br/>cell23 <strong>line3</strong></td>
185
  </tr>
186
  <tr>
187
    <td>cell31</td>
188
    <td>cell32<br/>cell32 line2</td>
189
    <td>cell33</td>
190
  </tr>
191
</table>
192
EXPECTED
193

    
194
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
195
  end
196

    
197
  def test_textile_should_not_mangle_brackets
198
    assert_equal '<p>[msg1][msg2]</p>', to_html('[msg1][msg2]')
199
  end
200

    
201
  def test_textile_should_escape_image_urls
202
    # this is onclick="alert('XSS');" in encoded form
203
    raw = '!/images/comment.png"onclick=&#x61;&#x6c;&#x65;&#x72;&#x74;&#x28;&#x27;&#x58;&#x53;&#x53;&#x27;&#x29;;&#x22;!'
204
    expected = '<p><img src="/images/comment.png&quot;onclick=&amp;#x61;&amp;#x6c;&amp;#x65;&amp;#x72;&amp;#x74;&amp;#x28;&amp;#x27;&amp;#x58;&amp;#x53;&amp;#x53;&amp;#x27;&amp;#x29;;&amp;#x22;" alt="" /></p>'
205
    assert_equal expected.gsub(%r{\s+}, ''), to_html(raw).gsub(%r{\s+}, '')
206
  end
207
  
208
  
209
  STR_WITHOUT_PRE = [
210
  # 0
211
"h1. Title
212

    
213
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
214
  # 1
215
"h2. Heading 2
216

    
217
Maecenas sed elit sit amet mi accumsan vestibulum non nec velit. Proin porta tincidunt lorem, consequat rhoncus dolor fermentum in.
218

    
219
Cras ipsum felis, ultrices at porttitor vel, faucibus eu nunc.",
220
  # 2
221
"h2. Heading 2
222

    
223
Morbi facilisis accumsan orci non pharetra.
224

    
225
h3. Heading 3
226

    
227
Nulla nunc nisi, egestas in ornare vel, posuere ac libero.",
228
  # 3
229
"h3. Heading 3
230

    
231
Praesent eget turpis nibh, a lacinia nulla.",
232
  # 4
233
"h2. Heading 2
234

    
235
Ut rhoncus elementum adipiscing."]
236

    
237
  TEXT_WITHOUT_PRE = STR_WITHOUT_PRE.join("\n\n").freeze
238
  
239
  def test_get_section_should_return_the_requested_section_and_its_hash
240
    assert_section_with_hash STR_WITHOUT_PRE[1], TEXT_WITHOUT_PRE, 2
241
    assert_section_with_hash STR_WITHOUT_PRE[2..3].join("\n\n"), TEXT_WITHOUT_PRE, 3
242
    assert_section_with_hash STR_WITHOUT_PRE[3], TEXT_WITHOUT_PRE, 5
243
    assert_section_with_hash STR_WITHOUT_PRE[4], TEXT_WITHOUT_PRE, 6
244
    
245
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 0
246
    assert_section_with_hash '', TEXT_WITHOUT_PRE, 10
247
  end
248
  
249
  def test_update_section_should_update_the_requested_section
250
    replacement = "New text"
251
    
252
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement)
253
    assert_equal [STR_WITHOUT_PRE[0..1], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(3, replacement)
254
    assert_equal [STR_WITHOUT_PRE[0..2], replacement, STR_WITHOUT_PRE[4]].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(5, replacement)
255
    assert_equal [STR_WITHOUT_PRE[0..3], replacement].flatten.join("\n\n"), @formatter.new(TEXT_WITHOUT_PRE).update_section(6, replacement)
256
    
257
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(0, replacement)
258
    assert_equal TEXT_WITHOUT_PRE, @formatter.new(TEXT_WITHOUT_PRE).update_section(10, replacement)
259
  end
260
  
261
  def test_update_section_with_hash_should_update_the_requested_section
262
    replacement = "New text"
263
    
264
    assert_equal [STR_WITHOUT_PRE[0], replacement, STR_WITHOUT_PRE[2..4]].flatten.join("\n\n"),
265
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, replacement, Digest::MD5.hexdigest(STR_WITHOUT_PRE[1]))
266
  end
267
  
268
  def test_update_section_with_wrong_hash_should_raise_an_error
269
    assert_raise Redmine::WikiFormatting::StaleSectionError do
270
      @formatter.new(TEXT_WITHOUT_PRE).update_section(2, "New text", Digest::MD5.hexdigest("Old text"))
271
    end
272
  end
273

    
274
  STR_WITH_PRE = [
275
  # 0
276
"h1. Title
277

    
278
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.",
279
  # 1
280
"h2. Heading 2
281

    
282
<pre><code class=\"ruby\">
283
  def foo
284
  end
285
</code></pre>
286

    
287
<pre><code><pre><code class=\"ruby\">
288
  Place your code here.
289
</code></pre>
290
</code></pre>
291

    
292
Morbi facilisis accumsan orci non pharetra.
293

    
294
<pre>
295
Pre Content:
296

    
297
h2. Inside pre
298

    
299
<tag> inside pre block
300

    
301
Morbi facilisis accumsan orci non pharetra.
302
</pre>",
303
  # 2
304
"h3. Heading 3
305

    
306
Nulla nunc nisi, egestas in ornare vel, posuere ac libero."]
307

    
308
  def test_get_section_should_ignore_pre_content
309
    text = STR_WITH_PRE.join("\n\n")
310

    
311
    assert_section_with_hash STR_WITH_PRE[1..2].join("\n\n"), text, 2
312
    assert_section_with_hash STR_WITH_PRE[2], text, 3
313
  end
314

    
315
  def test_update_section_should_not_escape_pre_content_outside_section
316
    text = STR_WITH_PRE.join("\n\n")
317
    replacement = "New text"
318
    
319
    assert_equal [STR_WITH_PRE[0..1], "New text"].flatten.join("\n\n"),
320
      @formatter.new(text).update_section(3, replacement)
321
  end
322

    
323
  private
324

    
325
  def assert_html_output(to_test, expect_paragraph = true)
326
    to_test.each do |text, expected|
327
      assert_equal(( expect_paragraph ? "<p>#{expected}</p>" : expected ), @formatter.new(text).to_html, "Formatting the following text failed:\n===\n#{text}\n===\n")
328
    end
329
  end
330

    
331
  def to_html(text)
332
    @formatter.new(text).to_html
333
  end
334
  
335
  def assert_section_with_hash(expected, text, index)
336
    result = @formatter.new(text).get_section(index)
337
    
338
    assert_kind_of Array, result
339
    assert_equal 2, result.size
340
    assert_equal expected, result.first, "section content did not match"
341
    assert_equal Digest::MD5.hexdigest(expected), result.last, "section hash did not match"
342
  end
343
end