Revision 1297:0a574315af3e .svn/pristine/dc

View differences:

.svn/pristine/dc/dc6b5b76f3744d49697cec4f0525f325d4065393.svn-base
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 CustomValueTest < ActiveSupport::TestCase
21
  fixtures :custom_fields, :custom_values, :users
22

  
23
  def test_default_value
24
    field = CustomField.find_by_default_value('Default string')
25
    assert_not_nil field
26

  
27
    v = CustomValue.new(:custom_field => field)
28
    assert_equal 'Default string', v.value
29

  
30
    v = CustomValue.new(:custom_field => field, :value => 'Not empty')
31
    assert_equal 'Not empty', v.value
32
  end
33

  
34
  def test_sti_polymorphic_association
35
    # Rails uses top level sti class for polymorphic association. See #3978.
36
    assert !User.find(4).custom_values.empty?
37
    assert !CustomValue.find(2).customized.nil?
38
  end
39
end
.svn/pristine/dc/dc9b1cbad00145256a0e92e2088ee0a8b20dc51e.svn-base
1
# encoding: utf-8
2
#
3
# Redmine - project management software
4
# Copyright (C) 2006-2012  Jean-Philippe Lang
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License
8
# as published by the Free Software Foundation; either version 2
9
# of the License, or (at your option) any later version.
10
#
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
# GNU General Public License for more details.
15
#
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19

  
20
require File.expand_path('../../../test_helper', __FILE__)
21

  
22
class ApplicationHelperTest < ActionView::TestCase
23
  include ERB::Util
24

  
25
  fixtures :projects, :roles, :enabled_modules, :users,
26
           :repositories, :changesets,
27
           :trackers, :issue_statuses, :issues, :versions, :documents,
28
           :wikis, :wiki_pages, :wiki_contents,
29
           :boards, :messages, :news,
30
           :attachments, :enumerations
31

  
32
  def setup
33
    super
34
    set_tmp_attachments_directory
35
  end
36

  
37
  context "#link_to_if_authorized" do
38
    context "authorized user" do
39
      should "be tested"
40
    end
41

  
42
    context "unauthorized user" do
43
      should "be tested"
44
    end
45

  
46
    should "allow using the :controller and :action for the target link" do
47
      User.current = User.find_by_login('admin')
48

  
49
      @project = Issue.first.project # Used by helper
50
      response = link_to_if_authorized("By controller/action",
51
                                       {:controller => 'issues', :action => 'edit', :id => Issue.first.id})
52
      assert_match /href/, response
53
    end
54

  
55
  end
56

  
57
  def test_auto_links
58
    to_test = {
59
      'http://foo.bar' => '<a class="external" href="http://foo.bar">http://foo.bar</a>',
60
      'http://foo.bar/~user' => '<a class="external" href="http://foo.bar/~user">http://foo.bar/~user</a>',
61
      'http://foo.bar.' => '<a class="external" href="http://foo.bar">http://foo.bar</a>.',
62
      'https://foo.bar.' => '<a class="external" href="https://foo.bar">https://foo.bar</a>.',
63
      'This is a link: http://foo.bar.' => 'This is a link: <a class="external" href="http://foo.bar">http://foo.bar</a>.',
64
      'A link (eg. http://foo.bar).' => 'A link (eg. <a class="external" href="http://foo.bar">http://foo.bar</a>).',
65
      'http://foo.bar/foo.bar#foo.bar.' => '<a class="external" href="http://foo.bar/foo.bar#foo.bar">http://foo.bar/foo.bar#foo.bar</a>.',
66
      'http://www.foo.bar/Test_(foobar)' => '<a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>',
67
      '(see inline link : http://www.foo.bar/Test_(foobar))' => '(see inline link : <a class="external" href="http://www.foo.bar/Test_(foobar)">http://www.foo.bar/Test_(foobar)</a>)',
68
      '(see inline link : http://www.foo.bar/Test)' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>)',
69
      '(see inline link : http://www.foo.bar/Test).' => '(see inline link : <a class="external" href="http://www.foo.bar/Test">http://www.foo.bar/Test</a>).',
70
      '(see "inline link":http://www.foo.bar/Test_(foobar))' => '(see <a href="http://www.foo.bar/Test_(foobar)" class="external">inline link</a>)',
71
      '(see "inline link":http://www.foo.bar/Test)' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>)',
72
      '(see "inline link":http://www.foo.bar/Test).' => '(see <a href="http://www.foo.bar/Test" class="external">inline link</a>).',
73
      'www.foo.bar' => '<a class="external" href="http://www.foo.bar">www.foo.bar</a>',
74
      'http://foo.bar/page?p=1&t=z&s=' => '<a class="external" href="http://foo.bar/page?p=1&#38;t=z&#38;s=">http://foo.bar/page?p=1&#38;t=z&#38;s=</a>',
75
      'http://foo.bar/page#125' => '<a class="external" href="http://foo.bar/page#125">http://foo.bar/page#125</a>',
76
      'http://foo@www.bar.com' => '<a class="external" href="http://foo@www.bar.com">http://foo@www.bar.com</a>',
77
      'http://foo:bar@www.bar.com' => '<a class="external" href="http://foo:bar@www.bar.com">http://foo:bar@www.bar.com</a>',
78
      'ftp://foo.bar' => '<a class="external" href="ftp://foo.bar">ftp://foo.bar</a>',
79
      'ftps://foo.bar' => '<a class="external" href="ftps://foo.bar">ftps://foo.bar</a>',
80
      'sftp://foo.bar' => '<a class="external" href="sftp://foo.bar">sftp://foo.bar</a>',
81
      # two exclamation marks
82
      'http://example.net/path!602815048C7B5C20!302.html' => '<a class="external" href="http://example.net/path!602815048C7B5C20!302.html">http://example.net/path!602815048C7B5C20!302.html</a>',
83
      # escaping
84
      'http://foo"bar' => '<a class="external" href="http://foo&quot;bar">http://foo&quot;bar</a>',
85
      # wrap in angle brackets
86
      '<http://foo.bar>' => '&lt;<a class="external" href="http://foo.bar">http://foo.bar</a>&gt;'
87
    }
88
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
89
  end
90

  
91
  if 'ruby'.respond_to?(:encoding)
92
    def test_auto_links_with_non_ascii_characters
93
      to_test = {
94
        'http://foo.bar/тест' => '<a class="external" href="http://foo.bar/тест">http://foo.bar/тест</a>'
95
      }
96
      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
97
    end
98
  else
99
    puts 'Skipping test_auto_links_with_non_ascii_characters, unsupported ruby version'
100
  end
101

  
102
  def test_auto_mailto
103
    assert_equal '<p><a class="email" href="mailto:test@foo.bar">test@foo.bar</a></p>',
104
      textilizable('test@foo.bar')
105
  end
106

  
107
  def test_inline_images
108
    to_test = {
109
      '!http://foo.bar/image.jpg!' => '<img src="http://foo.bar/image.jpg" alt="" />',
110
      'floating !>http://foo.bar/image.jpg!' => 'floating <div style="float:right"><img src="http://foo.bar/image.jpg" alt="" /></div>',
111
      'with class !(some-class)http://foo.bar/image.jpg!' => 'with class <img src="http://foo.bar/image.jpg" class="some-class" alt="" />',
112
      '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="" />',
113
      '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" />',
114
      '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;" />',
115
    }
116
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
117
  end
118

  
119
  def test_inline_images_inside_tags
120
    raw = <<-RAW
121
h1. !foo.png! Heading
122

  
123
Centered image:
124

  
125
p=. !bar.gif!
126
RAW
127

  
128
    assert textilizable(raw).include?('<img src="foo.png" alt="" />')
129
    assert textilizable(raw).include?('<img src="bar.gif" alt="" />')
130
  end
131

  
132
  def test_attached_images
133
    to_test = {
134
      'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
135
      'Inline image: !logo.GIF!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />',
136
      'No match: !ogo.gif!' => 'No match: <img src="ogo.gif" alt="" />',
137
      'No match: !ogo.GIF!' => 'No match: <img src="ogo.GIF" alt="" />',
138
      # link image
139
      '!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>',
140
    }
141
    attachments = Attachment.find(:all)
142
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
143
  end
144

  
145
  def test_attached_images_filename_extension
146
    set_tmp_attachments_directory
147
    a1 = Attachment.new(
148
            :container => Issue.find(1),
149
            :file => mock_file_with_options({:original_filename => "testtest.JPG"}),
150
            :author => User.find(1))
151
    assert a1.save
152
    assert_equal "testtest.JPG", a1.filename
153
    assert_equal "image/jpeg", a1.content_type
154
    assert a1.image?
155

  
156
    a2 = Attachment.new(
157
            :container => Issue.find(1),
158
            :file => mock_file_with_options({:original_filename => "testtest.jpeg"}),
159
            :author => User.find(1))
160
    assert a2.save
161
    assert_equal "testtest.jpeg", a2.filename
162
    assert_equal "image/jpeg", a2.content_type
163
    assert a2.image?
164

  
165
    a3 = Attachment.new(
166
            :container => Issue.find(1),
167
            :file => mock_file_with_options({:original_filename => "testtest.JPE"}),
168
            :author => User.find(1))
169
    assert a3.save
170
    assert_equal "testtest.JPE", a3.filename
171
    assert_equal "image/jpeg", a3.content_type
172
    assert a3.image?
173

  
174
    a4 = Attachment.new(
175
            :container => Issue.find(1),
176
            :file => mock_file_with_options({:original_filename => "Testtest.BMP"}),
177
            :author => User.find(1))
178
    assert a4.save
179
    assert_equal "Testtest.BMP", a4.filename
180
    assert_equal "image/x-ms-bmp", a4.content_type
181
    assert a4.image?
182

  
183
    to_test = {
184
      'Inline image: !testtest.jpg!' =>
185
        'Inline image: <img src="/attachments/download/' + a1.id.to_s + '" alt="" />',
186
      'Inline image: !testtest.jpeg!' =>
187
        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />',
188
      'Inline image: !testtest.jpe!' =>
189
        'Inline image: <img src="/attachments/download/' + a3.id.to_s + '" alt="" />',
190
      'Inline image: !testtest.bmp!' =>
191
        'Inline image: <img src="/attachments/download/' + a4.id.to_s + '" alt="" />',
192
    }
193

  
194
    attachments = [a1, a2, a3, a4]
195
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
196
  end
197

  
198
  def test_attached_images_should_read_later
199
    set_fixtures_attachments_directory
200
    a1 = Attachment.find(16)
201
    assert_equal "testfile.png", a1.filename
202
    assert a1.readable?
203
    assert (! a1.visible?(User.anonymous))
204
    assert a1.visible?(User.find(2))
205
    a2 = Attachment.find(17)
206
    assert_equal "testfile.PNG", a2.filename
207
    assert a2.readable?
208
    assert (! a2.visible?(User.anonymous))
209
    assert a2.visible?(User.find(2))
210
    assert a1.created_on < a2.created_on
211

  
212
    to_test = {
213
      'Inline image: !testfile.png!' =>
214
        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />',
215
      'Inline image: !Testfile.PNG!' =>
216
        'Inline image: <img src="/attachments/download/' + a2.id.to_s + '" alt="" />',
217
    }
218
    attachments = [a1, a2]
219
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => attachments) }
220
    set_tmp_attachments_directory
221
  end
222

  
223
  def test_textile_external_links
224
    to_test = {
225
      'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>',
226
      'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>',
227
      '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>',
228
      '"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>',
229
      "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph",
230
      # no multiline link text
231
      "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",
232
      # mailto link
233
      "\"system administrator\":mailto:sysadmin@example.com?subject=redmine%20permissions" => "<a href=\"mailto:sysadmin@example.com?subject=redmine%20permissions\">system administrator</a>",
234
      # two exclamation marks
235
      '"a link":http://example.net/path!602815048C7B5C20!302.html' => '<a href="http://example.net/path!602815048C7B5C20!302.html" class="external">a link</a>',
236
      # escaping
237
      '"test":http://foo"bar' => '<a href="http://foo&quot;bar" class="external">test</a>',
238
    }
239
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
240
  end
241

  
242
  if 'ruby'.respond_to?(:encoding)
243
    def test_textile_external_links_with_non_ascii_characters
244
      to_test = {
245
        'This is a "link":http://foo.bar/тест' => 'This is a <a href="http://foo.bar/тест" class="external">link</a>'
246
      }
247
      to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
248
    end
249
  else
250
    puts 'Skipping test_textile_external_links_with_non_ascii_characters, unsupported ruby version'
251
  end
252

  
253
  def test_redmine_links
254
    issue_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3},
255
                               :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)')
256
    note_link = link_to('#3', {:controller => 'issues', :action => 'show', :id => 3, :anchor => 'note-14'},
257
                               :class => 'issue status-1 priority-4 priority-lowest overdue', :title => 'Error 281 when updating a recipe (New)')
258

  
259
    changeset_link = link_to('r1', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 1},
260
                                   :class => 'changeset', :title => 'My very first commit')
261
    changeset_link2 = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
262
                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
263

  
264
    document_link = link_to('Test document', {:controller => 'documents', :action => 'show', :id => 1},
265
                                             :class => 'document')
266

  
267
    version_link = link_to('1.0', {:controller => 'versions', :action => 'show', :id => 2},
268
                                  :class => 'version')
269

  
270
    board_url = {:controller => 'boards', :action => 'show', :id => 2, :project_id => 'ecookbook'}
271

  
272
    message_url = {:controller => 'messages', :action => 'show', :board_id => 1, :id => 4}
273
    
274
    news_url = {:controller => 'news', :action => 'show', :id => 1}
275

  
276
    project_url = {:controller => 'projects', :action => 'show', :id => 'subproject1'}
277

  
278
    source_url = '/projects/ecookbook/repository/entry/some/file'
279
    source_url_with_rev = '/projects/ecookbook/repository/revisions/52/entry/some/file'
280
    source_url_with_ext = '/projects/ecookbook/repository/entry/some/file.ext'
281
    source_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/entry/some/file.ext'
282

  
283
    export_url = '/projects/ecookbook/repository/raw/some/file'
284
    export_url_with_rev = '/projects/ecookbook/repository/revisions/52/raw/some/file'
285
    export_url_with_ext = '/projects/ecookbook/repository/raw/some/file.ext'
286
    export_url_with_rev_and_ext = '/projects/ecookbook/repository/revisions/52/raw/some/file.ext'
287

  
288
    to_test = {
289
      # tickets
290
      '#3, [#3], (#3) and #3.'      => "#{issue_link}, [#{issue_link}], (#{issue_link}) and #{issue_link}.",
291
      # ticket notes
292
      '#3-14'                       => note_link,
293
      '#3#note-14'                  => note_link,
294
      # should not ignore leading zero
295
      '#03'                         => '#03',
296
      # changesets
297
      'r1'                          => changeset_link,
298
      'r1.'                         => "#{changeset_link}.",
299
      'r1, r2'                      => "#{changeset_link}, #{changeset_link2}",
300
      'r1,r2'                       => "#{changeset_link},#{changeset_link2}",
301
      # documents
302
      'document#1'                  => document_link,
303
      'document:"Test document"'    => document_link,
304
      # versions
305
      'version#2'                   => version_link,
306
      'version:1.0'                 => version_link,
307
      'version:"1.0"'               => version_link,
308
      # source
309
      'source:some/file'            => link_to('source:some/file', source_url, :class => 'source'),
310
      'source:/some/file'           => link_to('source:/some/file', source_url, :class => 'source'),
311
      'source:/some/file.'          => link_to('source:/some/file', source_url, :class => 'source') + ".",
312
      'source:/some/file.ext.'      => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
313
      'source:/some/file. '         => link_to('source:/some/file', source_url, :class => 'source') + ".",
314
      'source:/some/file.ext. '     => link_to('source:/some/file.ext', source_url_with_ext, :class => 'source') + ".",
315
      'source:/some/file, '         => link_to('source:/some/file', source_url, :class => 'source') + ",",
316
      'source:/some/file@52'        => link_to('source:/some/file@52', source_url_with_rev, :class => 'source'),
317
      'source:/some/file.ext@52'    => link_to('source:/some/file.ext@52', source_url_with_rev_and_ext, :class => 'source'),
318
      'source:/some/file#L110'      => link_to('source:/some/file#L110', source_url + "#L110", :class => 'source'),
319
      'source:/some/file.ext#L110'  => link_to('source:/some/file.ext#L110', source_url_with_ext + "#L110", :class => 'source'),
320
      'source:/some/file@52#L110'   => link_to('source:/some/file@52#L110', source_url_with_rev + "#L110", :class => 'source'),
321
      # export
322
      'export:/some/file'           => link_to('export:/some/file', export_url, :class => 'source download'),
323
      'export:/some/file.ext'       => link_to('export:/some/file.ext', export_url_with_ext, :class => 'source download'),
324
      'export:/some/file@52'        => link_to('export:/some/file@52', export_url_with_rev, :class => 'source download'),
325
      'export:/some/file.ext@52'    => link_to('export:/some/file.ext@52', export_url_with_rev_and_ext, :class => 'source download'),
326
      # forum
327
      'forum#2'                     => link_to('Discussion', board_url, :class => 'board'),
328
      'forum:Discussion'            => link_to('Discussion', board_url, :class => 'board'),
329
      # message
330
      'message#4'                   => link_to('Post 2', message_url, :class => 'message'),
331
      'message#5'                   => link_to('RE: post 2', message_url.merge(:anchor => 'message-5', :r => 5), :class => 'message'),
332
      # news
333
      'news#1'                      => link_to('eCookbook first release !', news_url, :class => 'news'),
334
      'news:"eCookbook first release !"'        => link_to('eCookbook first release !', news_url, :class => 'news'),
335
      # project
336
      'project#3'                   => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
337
      'project:subproject1'         => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
338
      'project:"eCookbook subProject 1"'        => link_to('eCookbook Subproject 1', project_url, :class => 'project'),
339
      # not found
340
      '#0123456789'                 => '#0123456789',
341
      # invalid expressions
342
      'source:'                     => 'source:',
343
      # url hash
344
      "http://foo.bar/FAQ#3"       => '<a class="external" href="http://foo.bar/FAQ#3">http://foo.bar/FAQ#3</a>',
345
    }
346
    @project = Project.find(1)
347
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
348
  end
349

  
350
  def test_redmine_links_with_a_different_project_before_current_project
351
    vp1 = Version.generate!(:project_id => 1, :name => '1.4.4')
352
    vp3 = Version.generate!(:project_id => 3, :name => '1.4.4')
353

  
354
    @project = Project.find(3)
355
    assert_equal %(<p><a href="/versions/#{vp1.id}" class="version">1.4.4</a> <a href="/versions/#{vp3.id}" class="version">1.4.4</a></p>),
356
      textilizable("ecookbook:version:1.4.4 version:1.4.4")
357
  end
358

  
359
  def test_escaped_redmine_links_should_not_be_parsed
360
    to_test = [
361
      '#3.',
362
      '#3-14.',
363
      '#3#-note14.',
364
      'r1',
365
      'document#1',
366
      'document:"Test document"',
367
      'version#2',
368
      'version:1.0',
369
      'version:"1.0"',
370
      'source:/some/file'
371
    ]
372
    @project = Project.find(1)
373
    to_test.each { |text| assert_equal "<p>#{text}</p>", textilizable("!" + text), "#{text} failed" }
374
  end
375

  
376
  def test_cross_project_redmine_links
377
    source_link = link_to('ecookbook:source:/some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']},
378
      :class => 'source')
379

  
380
    changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
381
      :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
382

  
383
    to_test = {
384
      # documents
385
      'document:"Test document"'              => 'document:"Test document"',
386
      'ecookbook:document:"Test document"'    => '<a href="/documents/1" class="document">Test document</a>',
387
      'invalid:document:"Test document"'      => 'invalid:document:"Test document"',
388
      # versions
389
      'version:"1.0"'                         => 'version:"1.0"',
390
      'ecookbook:version:"1.0"'               => '<a href="/versions/2" class="version">1.0</a>',
391
      'invalid:version:"1.0"'                 => 'invalid:version:"1.0"',
392
      # changeset
393
      'r2'                                    => 'r2',
394
      'ecookbook:r2'                          => changeset_link,
395
      'invalid:r2'                            => 'invalid:r2',
396
      # source
397
      'source:/some/file'                     => 'source:/some/file',
398
      'ecookbook:source:/some/file'           => source_link,
399
      'invalid:source:/some/file'             => 'invalid:source:/some/file',
400
    }
401
    @project = Project.find(3)
402
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
403
  end
404

  
405
  def test_multiple_repositories_redmine_links
406
    svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn_repo-1', :url => 'file:///foo/hg')
407
    Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
408
    hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
409
    Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
410

  
411
    changeset_link = link_to('r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
412
                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
413
    svn_changeset_link = link_to('svn_repo-1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn_repo-1', :rev => 123},
414
                                    :class => 'changeset', :title => '')
415
    hg_changeset_link = link_to('hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
416
                                    :class => 'changeset', :title => '')
417

  
418
    source_link = link_to('source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
419
    hg_source_link = link_to('source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
420

  
421
    to_test = {
422
      'r2'                          => changeset_link,
423
      'svn_repo-1|r123'             => svn_changeset_link,
424
      'invalid|r123'                => 'invalid|r123',
425
      'commit:hg1|abcd'             => hg_changeset_link,
426
      'commit:invalid|abcd'         => 'commit:invalid|abcd',
427
      # source
428
      'source:some/file'            => source_link,
429
      'source:hg1|some/file'        => hg_source_link,
430
      'source:invalid|some/file'    => 'source:invalid|some/file',
431
    }
432

  
433
    @project = Project.find(1)
434
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
435
  end
436

  
437
  def test_cross_project_multiple_repositories_redmine_links
438
    svn = Repository::Subversion.create!(:project_id => 1, :identifier => 'svn1', :url => 'file:///foo/hg')
439
    Changeset.create!(:repository => svn, :committed_on => Time.now, :revision => '123')
440
    hg = Repository::Mercurial.create!(:project_id => 1, :identifier => 'hg1', :url => '/foo/hg')
441
    Changeset.create!(:repository => hg, :committed_on => Time.now, :revision => '123', :scmid => 'abcd')
442

  
443
    changeset_link = link_to('ecookbook:r2', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :rev => 2},
444
                                    :class => 'changeset', :title => 'This commit fixes #1, #2 and references #1 & #3')
445
    svn_changeset_link = link_to('ecookbook:svn1|r123', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'svn1', :rev => 123},
446
                                    :class => 'changeset', :title => '')
447
    hg_changeset_link = link_to('ecookbook:hg1|abcd', {:controller => 'repositories', :action => 'revision', :id => 'ecookbook', :repository_id => 'hg1', :rev => 'abcd'},
448
                                    :class => 'changeset', :title => '')
449

  
450
    source_link = link_to('ecookbook:source:some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :path => ['some', 'file']}, :class => 'source')
451
    hg_source_link = link_to('ecookbook:source:hg1|some/file', {:controller => 'repositories', :action => 'entry', :id => 'ecookbook', :repository_id => 'hg1', :path => ['some', 'file']}, :class => 'source')
452

  
453
    to_test = {
454
      'ecookbook:r2'                           => changeset_link,
455
      'ecookbook:svn1|r123'                    => svn_changeset_link,
456
      'ecookbook:invalid|r123'                 => 'ecookbook:invalid|r123',
457
      'ecookbook:commit:hg1|abcd'              => hg_changeset_link,
458
      'ecookbook:commit:invalid|abcd'          => 'ecookbook:commit:invalid|abcd',
459
      'invalid:commit:invalid|abcd'            => 'invalid:commit:invalid|abcd',
460
      # source
461
      'ecookbook:source:some/file'             => source_link,
462
      'ecookbook:source:hg1|some/file'         => hg_source_link,
463
      'ecookbook:source:invalid|some/file'     => 'ecookbook:source:invalid|some/file',
464
      'invalid:source:invalid|some/file'       => 'invalid:source:invalid|some/file',
465
    }
466

  
467
    @project = Project.find(3)
468
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text), "#{text} failed" }
469
  end
470

  
471
  def test_redmine_links_git_commit
472
    changeset_link = link_to('abcd',
473
                               {
474
                                 :controller => 'repositories',
475
                                 :action     => 'revision',
476
                                 :id         => 'subproject1',
477
                                 :rev        => 'abcd',
478
                                },
479
                              :class => 'changeset', :title => 'test commit')
480
    to_test = {
481
      'commit:abcd' => changeset_link,
482
     }
483
    @project = Project.find(3)
484
    r = Repository::Git.create!(:project => @project, :url => '/tmp/test/git')
485
    assert r
486
    c = Changeset.new(:repository => r,
487
                      :committed_on => Time.now,
488
                      :revision => 'abcd',
489
                      :scmid => 'abcd',
490
                      :comments => 'test commit')
491
    assert( c.save )
492
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
493
  end
494

  
495
  # TODO: Bazaar commit id contains mail address, so it contains '@' and '_'.
496
  def test_redmine_links_darcs_commit
497
    changeset_link = link_to('20080308225258-98289-abcd456efg.gz',
498
                               {
499
                                 :controller => 'repositories',
500
                                 :action     => 'revision',
501
                                 :id         => 'subproject1',
502
                                 :rev        => '123',
503
                                },
504
                              :class => 'changeset', :title => 'test commit')
505
    to_test = {
506
      'commit:20080308225258-98289-abcd456efg.gz' => changeset_link,
507
     }
508
    @project = Project.find(3)
509
    r = Repository::Darcs.create!(
510
            :project => @project, :url => '/tmp/test/darcs',
511
            :log_encoding => 'UTF-8')
512
    assert r
513
    c = Changeset.new(:repository => r,
514
                      :committed_on => Time.now,
515
                      :revision => '123',
516
                      :scmid => '20080308225258-98289-abcd456efg.gz',
517
                      :comments => 'test commit')
518
    assert( c.save )
519
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
520
  end
521

  
522
  def test_redmine_links_mercurial_commit
523
    changeset_link_rev = link_to('r123',
524
                                  {
525
                                     :controller => 'repositories',
526
                                     :action     => 'revision',
527
                                     :id         => 'subproject1',
528
                                     :rev        => '123' ,
529
                                  },
530
                              :class => 'changeset', :title => 'test commit')
531
    changeset_link_commit = link_to('abcd',
532
                                  {
533
                                        :controller => 'repositories',
534
                                        :action     => 'revision',
535
                                        :id         => 'subproject1',
536
                                        :rev        => 'abcd' ,
537
                                  },
538
                              :class => 'changeset', :title => 'test commit')
539
    to_test = {
540
      'r123' => changeset_link_rev,
541
      'commit:abcd' => changeset_link_commit,
542
     }
543
    @project = Project.find(3)
544
    r = Repository::Mercurial.create!(:project => @project, :url => '/tmp/test')
545
    assert r
546
    c = Changeset.new(:repository => r,
547
                      :committed_on => Time.now,
548
                      :revision => '123',
549
                      :scmid => 'abcd',
550
                      :comments => 'test commit')
551
    assert( c.save )
552
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
553
  end
554

  
555
  def test_attachment_links
556
    attachment_link = link_to('error281.txt', {:controller => 'attachments', :action => 'download', :id => '1'}, :class => 'attachment')
557
    to_test = {
558
      'attachment:error281.txt'      => attachment_link
559
    }
560
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :attachments => Issue.find(3).attachments), "#{text} failed" }
561
  end
562

  
563
  def test_attachment_link_should_link_to_latest_attachment
564
    set_tmp_attachments_directory
565
    a1 = Attachment.generate!(:filename => "test.txt", :created_on => 1.hour.ago)
566
    a2 = Attachment.generate!(:filename => "test.txt")
567

  
568
    assert_equal %(<p><a href="/attachments/download/#{a2.id}" class="attachment">test.txt</a></p>),
569
      textilizable('attachment:test.txt', :attachments => [a1, a2])
570
  end
571

  
572
  def test_wiki_links
573
    to_test = {
574
      '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
575
      '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
576
      # title content should be formatted
577
      '[[Another page|With _styled_ *title*]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">With <em>styled</em> <strong>title</strong></a>',
578
      '[[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>',
579
      # link with anchor
580
      '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
581
      '[[Another page#anchor|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page#anchor" class="wiki-page">Page</a>',
582
      # UTF8 anchor
583
      '[[Another_page#Тест|Тест]]' => %|<a href="/projects/ecookbook/wiki/Another_page##{CGI.escape 'Тест'}" class="wiki-page">Тест</a>|,
584
      # page that doesn't exist
585
      '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
586
      '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page" class="wiki-page new">404</a>',
587
      # link to another project wiki
588
      '[[onlinestore:]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">onlinestore</a>',
589
      '[[onlinestore:|Wiki]]' => '<a href="/projects/onlinestore/wiki" class="wiki-page">Wiki</a>',
590
      '[[onlinestore:Start page]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Start page</a>',
591
      '[[onlinestore:Start page|Text]]' => '<a href="/projects/onlinestore/wiki/Start_page" class="wiki-page">Text</a>',
592
      '[[onlinestore:Unknown page]]' => '<a href="/projects/onlinestore/wiki/Unknown_page" class="wiki-page new">Unknown page</a>',
593
      # striked through link
594
      '-[[Another page|Page]]-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a></del>',
595
      '-[[Another page|Page]] link-' => '<del><a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a> link</del>',
596
      # escaping
597
      '![[Another page|Page]]' => '[[Another page|Page]]',
598
      # project does not exist
599
      '[[unknowproject:Start]]' => '[[unknowproject:Start]]',
600
      '[[unknowproject:Start|Page title]]' => '[[unknowproject:Start|Page title]]',
601
    }
602

  
603
    @project = Project.find(1)
604
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
605
  end
606

  
607
  def test_wiki_links_within_local_file_generation_context
608

  
609
    to_test = {
610
      # link to a page
611
      '[[CookBook documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">CookBook documentation</a>',
612
      '[[CookBook documentation|documentation]]' => '<a href="CookBook_documentation.html" class="wiki-page">documentation</a>',
613
      '[[CookBook documentation#One-section]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">CookBook documentation</a>',
614
      '[[CookBook documentation#One-section|documentation]]' => '<a href="CookBook_documentation.html#One-section" class="wiki-page">documentation</a>',
615
      # page that doesn't exist
616
      '[[Unknown page]]' => '<a href="Unknown_page.html" class="wiki-page new">Unknown page</a>',
617
      '[[Unknown page|404]]' => '<a href="Unknown_page.html" class="wiki-page new">404</a>',
618
      '[[Unknown page#anchor]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">Unknown page</a>',
619
      '[[Unknown page#anchor|404]]' => '<a href="Unknown_page.html#anchor" class="wiki-page new">404</a>',
620
    }
621

  
622
    @project = Project.find(1)
623

  
624
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :local) }
625
  end
626

  
627
  def test_wiki_links_within_wiki_page_context
628

  
629
    page = WikiPage.find_by_title('Another_page' )
630

  
631
    to_test = {
632
      # link to another page
633
      '[[CookBook documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a>',
634
      '[[CookBook documentation|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">documentation</a>',
635
      '[[CookBook documentation#One-section]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">CookBook documentation</a>',
636
      '[[CookBook documentation#One-section|documentation]]' => '<a href="/projects/ecookbook/wiki/CookBook_documentation#One-section" class="wiki-page">documentation</a>',
637
      # link to the current page
638
      '[[Another page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Another page</a>',
639
      '[[Another page|Page]]' => '<a href="/projects/ecookbook/wiki/Another_page" class="wiki-page">Page</a>',
640
      '[[Another page#anchor]]' => '<a href="#anchor" class="wiki-page">Another page</a>',
641
      '[[Another page#anchor|Page]]' => '<a href="#anchor" class="wiki-page">Page</a>',
642
      # page that doesn't exist
643
      '[[Unknown page]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">Unknown page</a>',
644
      '[[Unknown page|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page" class="wiki-page new">404</a>',
645
      '[[Unknown page#anchor]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">Unknown page</a>',
646
      '[[Unknown page#anchor|404]]' => '<a href="/projects/ecookbook/wiki/Unknown_page?parent=Another_page#anchor" class="wiki-page new">404</a>',
647
    }
648

  
649
    @project = Project.find(1)
650

  
651
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(WikiContent.new( :text => text, :page => page ), :text) }
652
  end
653

  
654
  def test_wiki_links_anchor_option_should_prepend_page_title_to_href
655

  
656
    to_test = {
657
      # link to a page
658
      '[[CookBook documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">CookBook documentation</a>',
659
      '[[CookBook documentation|documentation]]' => '<a href="#CookBook_documentation" class="wiki-page">documentation</a>',
660
      '[[CookBook documentation#One-section]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">CookBook documentation</a>',
661
      '[[CookBook documentation#One-section|documentation]]' => '<a href="#CookBook_documentation_One-section" class="wiki-page">documentation</a>',
662
      # page that doesn't exist
663
      '[[Unknown page]]' => '<a href="#Unknown_page" class="wiki-page new">Unknown page</a>',
664
      '[[Unknown page|404]]' => '<a href="#Unknown_page" class="wiki-page new">404</a>',
665
      '[[Unknown page#anchor]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">Unknown page</a>',
666
      '[[Unknown page#anchor|404]]' => '<a href="#Unknown_page_anchor" class="wiki-page new">404</a>',
667
    }
668

  
669
    @project = Project.find(1)
670

  
671
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text, :wiki_links => :anchor) }
672
  end
673

  
674
  def test_html_tags
675
    to_test = {
676
      "<div>content</div>" => "<p>&lt;div&gt;content&lt;/div&gt;</p>",
677
      "<div class=\"bold\">content</div>" => "<p>&lt;div class=\"bold\"&gt;content&lt;/div&gt;</p>",
678
      "<script>some script;</script>" => "<p>&lt;script&gt;some script;&lt;/script&gt;</p>",
679
      # do not escape pre/code tags
680
      "<pre>\nline 1\nline2</pre>" => "<pre>\nline 1\nline2</pre>",
681
      "<pre><code>\nline 1\nline2</code></pre>" => "<pre><code>\nline 1\nline2</code></pre>",
682
      "<pre><div>content</div></pre>" => "<pre>&lt;div&gt;content&lt;/div&gt;</pre>",
683
      "HTML comment: <!-- no comments -->" => "<p>HTML comment: &lt;!-- no comments --&gt;</p>",
684
      "<!-- opening comment" => "<p>&lt;!-- opening comment</p>",
685
      # remove attributes except class
686
      "<pre class='foo'>some text</pre>" => "<pre class='foo'>some text</pre>",
687
      '<pre class="foo">some text</pre>' => '<pre class="foo">some text</pre>',
688
      "<pre class='foo bar'>some text</pre>" => "<pre class='foo bar'>some text</pre>",
689
      '<pre class="foo bar">some text</pre>' => '<pre class="foo bar">some text</pre>',
690
      "<pre onmouseover='alert(1)'>some text</pre>" => "<pre>some text</pre>",
691
      # xss
692
      '<pre><code class=""onmouseover="alert(1)">text</code></pre>' => '<pre><code>text</code></pre>',
693
      '<pre class=""onmouseover="alert(1)">text</pre>' => '<pre>text</pre>',
694
    }
695
    to_test.each { |text, result| assert_equal result, textilizable(text) }
696
  end
697

  
698
  def test_allowed_html_tags
699
    to_test = {
700
      "<pre>preformatted text</pre>" => "<pre>preformatted text</pre>",
701
      "<notextile>no *textile* formatting</notextile>" => "no *textile* formatting",
702
      "<notextile>this is <tag>a tag</tag></notextile>" => "this is &lt;tag&gt;a tag&lt;/tag&gt;"
703
    }
704
    to_test.each { |text, result| assert_equal result, textilizable(text) }
705
  end
706

  
707
  def test_pre_tags
708
    raw = <<-RAW
709
Before
710

  
711
<pre>
712
<prepared-statement-cache-size>32</prepared-statement-cache-size>
713
</pre>
714

  
715
After
716
RAW
717

  
718
    expected = <<-EXPECTED
719
<p>Before</p>
720
<pre>
721
&lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
722
</pre>
723
<p>After</p>
724
EXPECTED
725

  
726
    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
727
  end
728

  
729
  def test_pre_content_should_not_parse_wiki_and_redmine_links
730
    raw = <<-RAW
731
[[CookBook documentation]]
732
  
733
#1
734

  
735
<pre>
736
[[CookBook documentation]]
737
  
738
#1
739
</pre>
740
RAW
741

  
742
    expected = <<-EXPECTED
743
<p><a href="/projects/ecookbook/wiki/CookBook_documentation" class="wiki-page">CookBook documentation</a></p>
744
<p><a href="/issues/1" class="issue status-1 priority-4 priority-lowest" title="Can&#x27;t print recipes (New)">#1</a></p>
745
<pre>
746
[[CookBook documentation]]
747

  
748
#1
749
</pre>
750
EXPECTED
751

  
752
    @project = Project.find(1)
753
    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
754
  end
755

  
756
  def test_non_closing_pre_blocks_should_be_closed
757
    raw = <<-RAW
758
<pre><code>
759
RAW
760

  
761
    expected = <<-EXPECTED
762
<pre><code>
763
</code></pre>
764
EXPECTED
765

  
766
    @project = Project.find(1)
767
    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
768
  end
769

  
770
  def test_syntax_highlight
771
    raw = <<-RAW
772
<pre><code class="ruby">
773
# Some ruby code here
774
</code></pre>
775
RAW
776

  
777
    expected = <<-EXPECTED
778
<pre><code class="ruby syntaxhl"><span class=\"CodeRay\"><span class="comment"># Some ruby code here</span></span>
779
</code></pre>
780
EXPECTED
781

  
782
    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
783
  end
784

  
785
  def test_to_path_param
786
    assert_equal 'test1/test2', to_path_param('test1/test2')
787
    assert_equal 'test1/test2', to_path_param('/test1/test2/')
788
    assert_equal 'test1/test2', to_path_param('//test1/test2/')
789
    assert_equal nil, to_path_param('/')
790
  end
791

  
792
  def test_wiki_links_in_tables
793
    to_test = {"|[[Page|Link title]]|[[Other Page|Other title]]|\n|Cell 21|[[Last page]]|" =>
794
                 '<tr><td><a href="/projects/ecookbook/wiki/Page" class="wiki-page new">Link title</a></td>' +
795
                 '<td><a href="/projects/ecookbook/wiki/Other_Page" class="wiki-page new">Other title</a></td>' +
796
                 '</tr><tr><td>Cell 21</td><td><a href="/projects/ecookbook/wiki/Last_page" class="wiki-page new">Last page</a></td></tr>'
797
    }
798
    @project = Project.find(1)
799
    to_test.each { |text, result| assert_equal "<table>#{result}</table>", textilizable(text).gsub(/[\t\n]/, '') }
800
  end
801

  
802
  def test_text_formatting
803
    to_test = {'*_+bold, italic and underline+_*' => '<strong><em><ins>bold, italic and underline</ins></em></strong>',
804
               '(_text within parentheses_)' => '(<em>text within parentheses</em>)',
805
               'a *Humane Web* Text Generator' => 'a <strong>Humane Web</strong> Text Generator',
806
               '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>',
807
               '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',
808
              }
809
    to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) }
810
  end
811

  
812
  def test_wiki_horizontal_rule
813
    assert_equal '<hr />', textilizable('---')
814
    assert_equal '<p>Dashes: ---</p>', textilizable('Dashes: ---')
815
  end
816

  
817
  def test_footnotes
818
    raw = <<-RAW
819
This is some text[1].
820

  
821
fn1. This is the foot note
822
RAW
823

  
824
    expected = <<-EXPECTED
825
<p>This is some text<sup><a href=\"#fn1\">1</a></sup>.</p>
826
<p id="fn1" class="footnote"><sup>1</sup> This is the foot note</p>
827
EXPECTED
828

  
829
    assert_equal expected.gsub(%r{[\r\n\t]}, ''), textilizable(raw).gsub(%r{[\r\n\t]}, '')
830
  end
831

  
832
  def test_headings
833
    raw = 'h1. Some heading'
834
    expected = %|<a name="Some-heading"></a>\n<h1 >Some heading<a href="#Some-heading" class="wiki-anchor">&para;</a></h1>|
835

  
836
    assert_equal expected, textilizable(raw)
837
  end
838

  
839
  def test_headings_with_special_chars
840
    # This test makes sure that the generated anchor names match the expected
841
    # ones even if the heading text contains unconventional characters
842
    raw = 'h1. Some heading related to version 0.5'
843
    anchor = sanitize_anchor_name("Some-heading-related-to-version-0.5")
844
    expected = %|<a name="#{anchor}"></a>\n<h1 >Some heading related to version 0.5<a href="##{anchor}" class="wiki-anchor">&para;</a></h1>|
845

  
846
    assert_equal expected, textilizable(raw)
847
  end
848

  
849
  def test_headings_in_wiki_single_page_export_should_be_prepended_with_page_title
850
    page = WikiPage.new( :title => 'Page Title', :wiki_id => 1 )
851
    content = WikiContent.new( :text => 'h1. Some heading', :page => page )
852

  
853
    expected = %|<a name="Page_Title_Some-heading"></a>\n<h1 >Some heading<a href="#Page_Title_Some-heading" class="wiki-anchor">&para;</a></h1>|
854

  
855
    assert_equal expected, textilizable(content, :text, :wiki_links => :anchor )
856
  end
857

  
858
  def test_table_of_content
859
    raw = <<-RAW
860
{{toc}}
861

  
862
h1. Title
863

  
864
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
865

  
866
h2. Subtitle with a [[Wiki]] link
867

  
868
Nullam commodo metus accumsan nulla. Curabitur lobortis dui id dolor.
869

  
870
h2. Subtitle with [[Wiki|another Wiki]] link
871

  
872
h2. Subtitle with %{color:red}red text%
873

  
874
<pre>
875
some code
876
</pre>
877

  
878
h3. Subtitle with *some* _modifiers_
879

  
880
h3. Subtitle with @inline code@
881

  
882
h1. Another title
883

  
884
h3. An "Internet link":http://www.redmine.org/ inside subtitle
885

  
886
h2. "Project Name !/attachments/1234/logo_small.gif! !/attachments/5678/logo_2.png!":/projects/projectname/issues
887

  
888
RAW
889

  
890
    expected =  '<ul class="toc">' +
891
                  '<li><a href="#Title">Title</a>' +
892
                    '<ul>' +
893
                      '<li><a href="#Subtitle-with-a-Wiki-link">Subtitle with a Wiki link</a></li>' +
894
                      '<li><a href="#Subtitle-with-another-Wiki-link">Subtitle with another Wiki link</a></li>' +
895
                      '<li><a href="#Subtitle-with-red-text">Subtitle with red text</a>' +
896
                        '<ul>' +
897
                          '<li><a href="#Subtitle-with-some-modifiers">Subtitle with some modifiers</a></li>' +
898
                          '<li><a href="#Subtitle-with-inline-code">Subtitle with inline code</a></li>' +
899
                        '</ul>' +
900
                      '</li>' +
901
                    '</ul>' +
902
                  '</li>' +
903
                  '<li><a href="#Another-title">Another title</a>' +
904
                    '<ul>' +
905
                      '<li>' +
906
                        '<ul>' +
907
                          '<li><a href="#An-Internet-link-inside-subtitle">An Internet link inside subtitle</a></li>' +
908
                        '</ul>' +
909
                      '</li>' +
910
                      '<li><a href="#Project-Name">Project Name</a></li>' +
911
                    '</ul>' +
912
                  '</li>' +
913
               '</ul>'
914

  
915
    @project = Project.find(1)
916
    assert textilizable(raw).gsub("\n", "").include?(expected)
917
  end
918

  
919
  def test_table_of_content_should_generate_unique_anchors
920
    raw = <<-RAW
921
{{toc}}
922

  
923
h1. Title
924

  
925
h2. Subtitle
926

  
927
h2. Subtitle
928
RAW
929

  
930
    expected =  '<ul class="toc">' +
931
                  '<li><a href="#Title">Title</a>' +
932
                    '<ul>' +
933
                      '<li><a href="#Subtitle">Subtitle</a></li>' +
934
                      '<li><a href="#Subtitle-2">Subtitle</a></li>'
935
                    '</ul>'
936
                  '</li>' +
937
               '</ul>'
938

  
939
    @project = Project.find(1)
940
    result = textilizable(raw).gsub("\n", "")
941
    assert_include expected, result
942
    assert_include '<a name="Subtitle">', result
943
    assert_include '<a name="Subtitle-2">', result
944
  end
945

  
946
  def test_table_of_content_should_contain_included_page_headings
947
    raw = <<-RAW
948
{{toc}}
949

  
950
h1. Included
951

  
952
{{include(Child_1)}}
953
RAW
954

  
955
    expected = '<ul class="toc">' +
956
               '<li><a href="#Included">Included</a></li>' +
957
               '<li><a href="#Child-page-1">Child page 1</a></li>' +
958
               '</ul>'
959

  
960
    @project = Project.find(1)
961
    assert textilizable(raw).gsub("\n", "").include?(expected)
962
  end
963

  
964
  def test_section_edit_links
965
    raw = <<-RAW
966
h1. Title
967

  
968
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas sed libero.
969

  
970
h2. Subtitle with a [[Wiki]] link
971

  
972
h2. Subtitle with *some* _modifiers_
973

  
974
h2. Subtitle with @inline code@
975

  
976
<pre>
977
some code
978

  
979
h2. heading inside pre
980

  
981
<h2>html heading inside pre</h2>
982
</pre>
983

  
984
h2. Subtitle after pre tag
985
RAW
986

  
987
    @project = Project.find(1)
988
    set_language_if_valid 'en'
989
    result = textilizable(raw, :edit_section_links => {:controller => 'wiki', :action => 'edit', :project_id => '1', :id => 'Test'}).gsub("\n", "")
990

  
991
    # heading that contains inline code
992
    assert_match Regexp.new('<div class="contextual" title="Edit this section">' +
993
      '<a href="/projects/1/wiki/Test/edit\?section=4"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
994
      '<a name="Subtitle-with-inline-code"></a>' +
995
      '<h2 >Subtitle with <code>inline code</code><a href="#Subtitle-with-inline-code" class="wiki-anchor">&para;</a></h2>'),
996
      result
997

  
998
    # last heading
999
    assert_match Regexp.new('<div class="contextual" title="Edit this section">' +
1000
      '<a href="/projects/1/wiki/Test/edit\?section=5"><img alt="Edit" src="/images/edit.png(\?\d+)?" /></a></div>' +
1001
      '<a name="Subtitle-after-pre-tag"></a>' +
1002
      '<h2 >Subtitle after pre tag<a href="#Subtitle-after-pre-tag" class="wiki-anchor">&para;</a></h2>'),
1003
      result
1004
  end
1005

  
1006
  def test_default_formatter
1007
    with_settings :text_formatting => 'unknown' do
1008
      text = 'a *link*: http://www.example.net/'
1009
      assert_equal '<p>a *link*: <a class="external" href="http://www.example.net/">http://www.example.net/</a></p>', textilizable(text)
1010
    end
1011
  end
1012

  
1013
  def test_due_date_distance_in_words
1014
    to_test = { Date.today => 'Due in 0 days',
1015
                Date.today + 1 => 'Due in 1 day',
1016
                Date.today + 100 => 'Due in about 3 months',
1017
                Date.today + 20000 => 'Due in over 54 years',
1018
                Date.today - 1 => '1 day late',
1019
                Date.today - 100 => 'about 3 months late',
1020
                Date.today - 20000 => 'over 54 years late',
1021
               }
1022
    ::I18n.locale = :en
1023
    to_test.each do |date, expected|
1024
      assert_equal expected, due_date_distance_in_words(date)
1025
    end
1026
  end
1027

  
1028
  def test_avatar_enabled
1029
    with_settings :gravatar_enabled => '1' do
1030
      assert avatar(User.find_by_mail('jsmith@somenet.foo')).include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1031
      assert avatar('jsmith <jsmith@somenet.foo>').include?(Digest::MD5.hexdigest('jsmith@somenet.foo'))
1032
      # Default size is 50
1033
      assert avatar('jsmith <jsmith@somenet.foo>').include?('size=50')
1034
      assert avatar('jsmith <jsmith@somenet.foo>', :size => 24).include?('size=24')
1035
      # Non-avatar options should be considered html options
1036
      assert avatar('jsmith <jsmith@somenet.foo>', :title => 'John Smith').include?('title="John Smith"')
1037
      # The default class of the img tag should be gravatar
1038
      assert avatar('jsmith <jsmith@somenet.foo>').include?('class="gravatar"')
1039
      assert !avatar('jsmith <jsmith@somenet.foo>', :class => 'picture').include?('class="gravatar"')
1040
      assert_nil avatar('jsmith')
1041
      assert_nil avatar(nil)
1042
    end
1043
  end
1044

  
1045
  def test_avatar_disabled
1046
    with_settings :gravatar_enabled => '0' do
1047
      assert_equal '', avatar(User.find_by_mail('jsmith@somenet.foo'))
1048
    end
1049
  end
1050

  
1051
  def test_link_to_user
1052
    user = User.find(2)
1053
    assert_equal '<a href="/users/2" class="user active">John Smith</a>', link_to_user(user)
1054
  end
1055

  
1056
  def test_link_to_user_should_not_link_to_locked_user
1057
    with_current_user nil do
1058
      user = User.find(5)
1059
      assert user.locked?
1060
      assert_equal 'Dave2 Lopper2', link_to_user(user)
1061
    end
1062
  end
1063

  
1064
  def test_link_to_user_should_link_to_locked_user_if_current_user_is_admin
1065
    with_current_user User.find(1) do
1066
      user = User.find(5)
1067
      assert user.locked?
1068
      assert_equal '<a href="/users/5" class="user locked">Dave2 Lopper2</a>', link_to_user(user)
1069
    end
1070
  end
1071

  
1072
  def test_link_to_user_should_not_link_to_anonymous
1073
    user = User.anonymous
1074
    assert user.anonymous?
1075
    t = link_to_user(user)
1076
    assert_equal ::I18n.t(:label_user_anonymous), t
1077
  end
1078

  
1079
  def test_link_to_project
1080
    project = Project.find(1)
1081
    assert_equal %(<a href="/projects/ecookbook">eCookbook</a>),
1082
                 link_to_project(project)
1083
    assert_equal %(<a href="/projects/ecookbook/settings">eCookbook</a>),
1084
                 link_to_project(project, :action => 'settings')
1085
    assert_equal %(<a href="http://test.host/projects/ecookbook?jump=blah">eCookbook</a>),
1086
                 link_to_project(project, {:only_path => false, :jump => 'blah'})
1087
    assert_equal %(<a href="/projects/ecookbook/settings" class="project">eCookbook</a>),
1088
                 link_to_project(project, {:action => 'settings'}, :class => "project")
1089
  end
1090

  
1091
  def test_link_to_legacy_project_with_numerical_identifier_should_use_id
1092
    # numeric identifier are no longer allowed
1093
    Project.update_all "identifier=25", "id=1"
1094

  
1095
    assert_equal '<a href="/projects/1">eCookbook</a>',
1096
                 link_to_project(Project.find(1))
1097
  end
1098

  
1099
  def test_principals_options_for_select_with_users
1100
    User.current = nil
1101
    users = [User.find(2), User.find(4)]
1102
    assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>),
1103
      principals_options_for_select(users)
1104
  end
1105

  
1106
  def test_principals_options_for_select_with_selected
1107
    User.current = nil
1108
    users = [User.find(2), User.find(4)]
1109
    assert_equal %(<option value="2">John Smith</option><option value="4" selected="selected">Robert Hill</option>),
1110
      principals_options_for_select(users, User.find(4))
1111
  end
1112

  
1113
  def test_principals_options_for_select_with_users_and_groups
1114
    User.current = nil
1115
    users = [User.find(2), Group.find(11), User.find(4), Group.find(10)]
1116
    assert_equal %(<option value="2">John Smith</option><option value="4">Robert Hill</option>) +
1117
      %(<optgroup label="Groups"><option value="10">A Team</option><option value="11">B Team</option></optgroup>),
1118
      principals_options_for_select(users)
1119
  end
1120

  
1121
  def test_principals_options_for_select_with_empty_collection
1122
    assert_equal '', principals_options_for_select([])
1123
  end
1124

  
1125
  def test_principals_options_for_select_should_include_me_option_when_current_user_is_in_collection
1126
    users = [User.find(2), User.find(4)]
1127
    User.current = User.find(4)
1128
    assert_include '<option value="4">&lt;&lt; me &gt;&gt;</option>', principals_options_for_select(users)
1129
  end
1130

  
1131
  def test_stylesheet_link_tag_should_pick_the_default_stylesheet
1132
    assert_match 'href="/stylesheets/styles.css"', stylesheet_link_tag("styles")
1133
  end
1134

  
1135
  def test_stylesheet_link_tag_for_plugin_should_pick_the_plugin_stylesheet
1136
    assert_match 'href="/plugin_assets/foo/stylesheets/styles.css"', stylesheet_link_tag("styles", :plugin => :foo)
1137
  end
1138

  
1139
  def test_image_tag_should_pick_the_default_image
1140
    assert_match 'src="/images/image.png"', image_tag("image.png")
1141
  end
1142

  
1143
  def test_image_tag_should_pick_the_theme_image_if_it_exists
1144
    theme = Redmine::Themes.themes.last
1145
    theme.images << 'image.png'
1146

  
1147
    with_settings :ui_theme => theme.id do
1148
      assert_match %|src="/themes/#{theme.dir}/images/image.png"|, image_tag("image.png")
1149
      assert_match %|src="/images/other.png"|, image_tag("other.png")
1150
    end
1151
  ensure
1152
    theme.images.delete 'image.png'
1153
  end
1154

  
1155
  def test_image_tag_sfor_plugin_should_pick_the_plugin_image
1156
    assert_match 'src="/plugin_assets/foo/images/image.png"', image_tag("image.png", :plugin => :foo)
1157
  end
1158

  
1159
  def test_javascript_include_tag_should_pick_the_default_javascript
1160
    assert_match 'src="/javascripts/scripts.js"', javascript_include_tag("scripts")
1161
  end
1162

  
1163
  def test_javascript_include_tag_for_plugin_should_pick_the_plugin_javascript
1164
    assert_match 'src="/plugin_assets/foo/javascripts/scripts.js"', javascript_include_tag("scripts", :plugin => :foo)
1165
  end
1166

  
1167
  def test_per_page_links_should_show_usefull_values
1168
    set_language_if_valid 'en'
1169
    stubs(:link_to).returns("[link]")
1170

  
1171
    with_settings :per_page_options => '10, 25, 50, 100' do
1172
      assert_nil per_page_links(10, 3)
1173
      assert_nil per_page_links(25, 3)
1174
      assert_equal "Per page: 10, [link]", per_page_links(10, 22)
1175
      assert_equal "Per page: [link], 25", per_page_links(25, 22)
1176
      assert_equal "Per page: [link], [link], 50", per_page_links(50, 22)
1177
      assert_equal "Per page: [link], 25, [link]", per_page_links(25, 26)
1178
      assert_equal "Per page: [link], 25, [link], [link]", per_page_links(25, 120)
1179
    end
1180
  end
1181
end
.svn/pristine/dc/dce158397cf543f178989488879d39aee998d33c.svn-base
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 UserTest < ActiveSupport::TestCase
21
  fixtures :users, :members, :projects, :roles, :member_roles, :auth_sources,
22
            :trackers, :issue_statuses,
23
            :projects_trackers,
24
            :watchers,
25
            :issue_categories, :enumerations, :issues,
26
            :journals, :journal_details,
27
            :groups_users,
28
            :enabled_modules,
29
            :workflows
30

  
31
  def setup
32
    @admin = User.find(1)
33
    @jsmith = User.find(2)
34
    @dlopper = User.find(3)
35
  end
36

  
37
  def test_generate
38
    User.generate!(:firstname => 'Testing connection')
39
    User.generate!(:firstname => 'Testing connection')
40
    assert_equal 2, User.count(:all, :conditions => {:firstname => 'Testing connection'})
41
  end
42

  
43
  def test_truth
44
    assert_kind_of User, @jsmith
45
  end
46

  
47
  def test_mail_should_be_stripped
48
    u = User.new
49
    u.mail = " foo@bar.com  "
50
    assert_equal "foo@bar.com", u.mail
51
  end
52

  
53
  def test_mail_validation
54
    u = User.new
55
    u.mail = ''
56
    assert !u.valid?
57
    assert_include I18n.translate('activerecord.errors.messages.blank'), u.errors[:mail]
58
  end
59

  
60
  def test_login_length_validation
61
    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
62
    user.login = "x" * (User::LOGIN_LENGTH_LIMIT+1)
63
    assert !user.valid?
64

  
65
    user.login = "x" * (User::LOGIN_LENGTH_LIMIT)
66
    assert user.valid?
67
    assert user.save
68
  end
69

  
70
  def test_create
71
    user = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
72

  
73
    user.login = "jsmith"
74
    user.password, user.password_confirmation = "password", "password"
75
    # login uniqueness
76
    assert !user.save
77
    assert_equal 1, user.errors.count
78

  
79
    user.login = "newuser"
80
    user.password, user.password_confirmation = "password", "pass"
81
    # password confirmation
82
    assert !user.save
83
    assert_equal 1, user.errors.count
84

  
85
    user.password, user.password_confirmation = "password", "password"
86
    assert user.save
87
  end
88

  
89
  def test_user_before_create_should_set_the_mail_notification_to_the_default_setting
90
    @user1 = User.generate!
91
    assert_equal 'only_my_events', @user1.mail_notification
92
    with_settings :default_notification_option => 'all' do
93
      @user2 = User.generate!
94
      assert_equal 'all', @user2.mail_notification
95
    end
96
  end
97

  
98
  def test_user_login_should_be_case_insensitive
99
    u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
100
    u.login = 'newuser'
101
    u.password, u.password_confirmation = "password", "password"
102
    assert u.save
103
    u = User.new(:firstname => "Similar", :lastname => "User", :mail => "similaruser@somenet.foo")
104
    u.login = 'NewUser'
105
    u.password, u.password_confirmation = "password", "password"
106
    assert !u.save
107
    assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:login]
108
  end
109

  
110
  def test_mail_uniqueness_should_not_be_case_sensitive
111
    u = User.new(:firstname => "new", :lastname => "user", :mail => "newuser@somenet.foo")
112
    u.login = 'newuser1'
113
    u.password, u.password_confirmation = "password", "password"
114
    assert u.save
115

  
116
    u = User.new(:firstname => "new", :lastname => "user", :mail => "newUser@Somenet.foo")
117
    u.login = 'newuser2'
118
    u.password, u.password_confirmation = "password", "password"
119
    assert !u.save
120
    assert_include I18n.translate('activerecord.errors.messages.taken'), u.errors[:mail]
121
  end
122

  
123
  def test_update
124
    assert_equal "admin", @admin.login
125
    @admin.login = "john"
126
    assert @admin.save, @admin.errors.full_messages.join("; ")
127
    @admin.reload
128
    assert_equal "john", @admin.login
129
  end
130

  
131
  def test_update_should_not_fail_for_legacy_user_with_different_case_logins
132
    u1 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser1@somenet.foo")
133
    u1.login = 'newuser1'
134
    assert u1.save
135

  
136
    u2 = User.new(:firstname => "new", :lastname => "user", :mail => "newuser2@somenet.foo")
137
    u2.login = 'newuser1'
138
    assert u2.save(:validate => false)
139

  
140
    user = User.find(u2.id)
141
    user.firstname = "firstname"
142
    assert user.save, "Save failed"
143
  end
144

  
145
  def test_destroy_should_delete_members_and_roles
146
    members = Member.find_all_by_user_id(2)
147
    ms = members.size
148
    rs = members.collect(&:roles).flatten.size
149

  
150
    assert_difference 'Member.count', - ms do
151
      assert_difference 'MemberRole.count', - rs do
152
        User.find(2).destroy
153
      end
154
    end
155

  
156
    assert_nil User.find_by_id(2)
157
    assert Member.find_all_by_user_id(2).empty?
158
  end
159

  
160
  def test_destroy_should_update_attachments
161
    attachment = Attachment.create!(:container => Project.find(1),
162
      :file => uploaded_test_file("testfile.txt", "text/plain"),
163
      :author_id => 2)
164

  
165
    User.find(2).destroy
166
    assert_nil User.find_by_id(2)
167
    assert_equal User.anonymous, attachment.reload.author
168
  end
169

  
170
  def test_destroy_should_update_comments
171
    comment = Comment.create!(
172
      :commented => News.create!(:project_id => 1, :author_id => 1, :title => 'foo', :description => 'foo'),
173
      :author => User.find(2),
174
      :comments => 'foo'
175
    )
176

  
177
    User.find(2).destroy
178
    assert_nil User.find_by_id(2)
179
    assert_equal User.anonymous, comment.reload.author
180
  end
181

  
182
  def test_destroy_should_update_issues
183
    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
184

  
185
    User.find(2).destroy
186
    assert_nil User.find_by_id(2)
187
    assert_equal User.anonymous, issue.reload.author
188
  end
189

  
190
  def test_destroy_should_unassign_issues
191
    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
192

  
193
    User.find(2).destroy
194
    assert_nil User.find_by_id(2)
195
    assert_nil issue.reload.assigned_to
196
  end
197

  
198
  def test_destroy_should_update_journals
199
    issue = Issue.create!(:project_id => 1, :author_id => 2, :tracker_id => 1, :subject => 'foo')
200
    issue.init_journal(User.find(2), "update")
201
    issue.save!
202

  
203
    User.find(2).destroy
204
    assert_nil User.find_by_id(2)
205
    assert_equal User.anonymous, issue.journals.first.reload.user
206
  end
207

  
208
  def test_destroy_should_update_journal_details_old_value
209
    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo', :assigned_to_id => 2)
210
    issue.init_journal(User.find(1), "update")
211
    issue.assigned_to_id = nil
212
    assert_difference 'JournalDetail.count' do
213
      issue.save!
214
    end
215
    journal_detail = JournalDetail.first(:order => 'id DESC')
216
    assert_equal '2', journal_detail.old_value
217

  
218
    User.find(2).destroy
219
    assert_nil User.find_by_id(2)
220
    assert_equal User.anonymous.id.to_s, journal_detail.reload.old_value
221
  end
222

  
223
  def test_destroy_should_update_journal_details_value
224
    issue = Issue.create!(:project_id => 1, :author_id => 1, :tracker_id => 1, :subject => 'foo')
225
    issue.init_journal(User.find(1), "update")
226
    issue.assigned_to_id = 2
227
    assert_difference 'JournalDetail.count' do
228
      issue.save!
229
    end
230
    journal_detail = JournalDetail.first(:order => 'id DESC')
231
    assert_equal '2', journal_detail.value
232

  
233
    User.find(2).destroy
234
    assert_nil User.find_by_id(2)
235
    assert_equal User.anonymous.id.to_s, journal_detail.reload.value
236
  end
237

  
238
  def test_destroy_should_update_messages
239
    board = Board.create!(:project_id => 1, :name => 'Board', :description => 'Board')
240
    message = Message.create!(:board_id => board.id, :author_id => 2, :subject => 'foo', :content => 'foo')
241

  
242
    User.find(2).destroy
243
    assert_nil User.find_by_id(2)
244
    assert_equal User.anonymous, message.reload.author
245
  end
246

  
247
  def test_destroy_should_update_news
248
    news = News.create!(:project_id => 1, :author_id => 2, :title => 'foo', :description => 'foo')
249

  
250
    User.find(2).destroy
251
    assert_nil User.find_by_id(2)
252
    assert_equal User.anonymous, news.reload.author
253
  end
254

  
255
  def test_destroy_should_delete_private_queries
256
    query = Query.new(:name => 'foo', :is_public => false)
257
    query.project_id = 1
258
    query.user_id = 2
259
    query.save!
260

  
261
    User.find(2).destroy
262
    assert_nil User.find_by_id(2)
263
    assert_nil Query.find_by_id(query.id)
264
  end
265

  
266
  def test_destroy_should_update_public_queries
267
    query = Query.new(:name => 'foo', :is_public => true)
268
    query.project_id = 1
269
    query.user_id = 2
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff