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 / 00 / 002d478f30849d26745d0ec7b1c75e9c7796a254.svn-base @ 1298:4f746d8966dd

History | View | Annotate | Download (20.3 KB)

1 1295:622f24f53b42 Chris
# Redmine - project management software
2
# Copyright (C) 2006-2013  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 MailerTest < ActiveSupport::TestCase
21
  include Redmine::I18n
22
  include ActionDispatch::Assertions::SelectorAssertions
23
  fixtures :projects, :enabled_modules, :issues, :users, :members,
24
           :member_roles, :roles, :documents, :attachments, :news,
25
           :tokens, :journals, :journal_details, :changesets,
26
           :trackers, :projects_trackers,
27
           :issue_statuses, :enumerations, :messages, :boards, :repositories,
28
           :wikis, :wiki_pages, :wiki_contents, :wiki_content_versions,
29
           :versions,
30
           :comments
31
32
  def setup
33
    ActionMailer::Base.deliveries.clear
34
    Setting.host_name = 'mydomain.foo'
35
    Setting.protocol = 'http'
36
    Setting.plain_text_mail = '0'
37
  end
38
39
  def test_generated_links_in_emails
40
    Setting.default_language = 'en'
41
    Setting.host_name = 'mydomain.foo'
42
    Setting.protocol = 'https'
43
44
    journal = Journal.find(3)
45
    assert Mailer.issue_edit(journal).deliver
46
47
    mail = last_email
48
    assert_not_nil mail
49
50
    assert_select_email do
51
      # link to the main ticket
52
      assert_select 'a[href=?]',
53
                    'https://mydomain.foo/issues/2#change-3',
54
                    :text => 'Feature request #2: Add ingredients categories'
55
      # link to a referenced ticket
56
      assert_select 'a[href=?][title=?]',
57
                    'https://mydomain.foo/issues/1',
58
                    'Can&#x27;t print recipes (New)',
59
                    :text => '#1'
60
      # link to a changeset
61
      assert_select 'a[href=?][title=?]',
62
                    'https://mydomain.foo/projects/ecookbook/repository/revisions/2',
63
                    'This commit fixes #1, #2 and references #1 &amp; #3',
64
                    :text => 'r2'
65
      # link to a description diff
66
      assert_select 'a[href=?][title=?]',
67
                    'https://mydomain.foo/journals/diff/3?detail_id=4',
68
                    'View differences',
69
                    :text => 'diff'
70
      # link to an attachment
71
      assert_select 'a[href=?]',
72
                    'https://mydomain.foo/attachments/download/4/source.rb',
73
                    :text => 'source.rb'
74
    end
75
  end
76
77
  def test_generated_links_with_prefix
78
    Setting.default_language = 'en'
79
    relative_url_root = Redmine::Utils.relative_url_root
80
    Setting.host_name = 'mydomain.foo/rdm'
81
    Setting.protocol = 'http'
82
83
    journal = Journal.find(3)
84
    assert Mailer.issue_edit(journal).deliver
85
86
    mail = last_email
87
    assert_not_nil mail
88
89
    assert_select_email do
90
      # link to the main ticket
91
      assert_select 'a[href=?]',
92
                    'http://mydomain.foo/rdm/issues/2#change-3',
93
                    :text => 'Feature request #2: Add ingredients categories'
94
      # link to a referenced ticket
95
      assert_select 'a[href=?][title=?]',
96
                    'http://mydomain.foo/rdm/issues/1',
97
                    'Can&#x27;t print recipes (New)',
98
                    :text => '#1'
99
      # link to a changeset
100
      assert_select 'a[href=?][title=?]',
101
                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
102
                    'This commit fixes #1, #2 and references #1 &amp; #3',
103
                    :text => 'r2'
104
      # link to a description diff
105
      assert_select 'a[href=?][title=?]',
106
                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
107
                    'View differences',
108
                    :text => 'diff'
109
      # link to an attachment
110
      assert_select 'a[href=?]',
111
                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
112
                    :text => 'source.rb'
113
    end
114
  end
115
116
  def test_generated_links_with_prefix_and_no_relative_url_root
117
    Setting.default_language = 'en'
118
    relative_url_root = Redmine::Utils.relative_url_root
119
    Setting.host_name = 'mydomain.foo/rdm'
120
    Setting.protocol = 'http'
121
    Redmine::Utils.relative_url_root = nil
122
123
    journal = Journal.find(3)
124
    assert Mailer.issue_edit(journal).deliver
125
126
    mail = last_email
127
    assert_not_nil mail
128
129
    assert_select_email do
130
      # link to the main ticket
131
      assert_select 'a[href=?]',
132
                    'http://mydomain.foo/rdm/issues/2#change-3',
133
                    :text => 'Feature request #2: Add ingredients categories'
134
      # link to a referenced ticket
135
      assert_select 'a[href=?][title=?]',
136
                    'http://mydomain.foo/rdm/issues/1',
137
                    'Can&#x27;t print recipes (New)',
138
                    :text => '#1'
139
      # link to a changeset
140
      assert_select 'a[href=?][title=?]',
141
                    'http://mydomain.foo/rdm/projects/ecookbook/repository/revisions/2',
142
                    'This commit fixes #1, #2 and references #1 &amp; #3',
143
                    :text => 'r2'
144
      # link to a description diff
145
      assert_select 'a[href=?][title=?]',
146
                    'http://mydomain.foo/rdm/journals/diff/3?detail_id=4',
147
                    'View differences',
148
                    :text => 'diff'
149
      # link to an attachment
150
      assert_select 'a[href=?]',
151
                    'http://mydomain.foo/rdm/attachments/download/4/source.rb',
152
                    :text => 'source.rb'
153
    end
154
  ensure
155
    # restore it
156
    Redmine::Utils.relative_url_root = relative_url_root
157
  end
158
159
  def test_email_headers
160
    issue = Issue.find(1)
161
    Mailer.issue_add(issue).deliver
162
    mail = last_email
163
    assert_not_nil mail
164
    assert_equal 'OOF', mail.header['X-Auto-Response-Suppress'].to_s
165
    assert_equal 'auto-generated', mail.header['Auto-Submitted'].to_s
166
    assert_equal '<redmine.example.net>', mail.header['List-Id'].to_s
167
  end
168
169
  def test_email_headers_should_include_sender
170
    issue = Issue.find(1)
171
    Mailer.issue_add(issue).deliver
172
    mail = last_email
173
    assert_equal issue.author.login, mail.header['X-Redmine-Sender'].to_s
174
  end
175
176
  def test_plain_text_mail
177
    Setting.plain_text_mail = 1
178
    journal = Journal.find(2)
179
    Mailer.issue_edit(journal).deliver
180
    mail = last_email
181
    assert_equal "text/plain; charset=UTF-8", mail.content_type
182
    assert_equal 0, mail.parts.size
183
    assert !mail.encoded.include?('href')
184
  end
185
186
  def test_html_mail
187
    Setting.plain_text_mail = 0
188
    journal = Journal.find(2)
189
    Mailer.issue_edit(journal).deliver
190
    mail = last_email
191
    assert_equal 2, mail.parts.size
192
    assert mail.encoded.include?('href')
193
  end
194
195
  def test_from_header
196
    with_settings :mail_from => 'redmine@example.net' do
197
      Mailer.test_email(User.find(1)).deliver
198
    end
199
    mail = last_email
200
    assert_equal 'redmine@example.net', mail.from_addrs.first
201
  end
202
203
  def test_from_header_with_phrase
204
    with_settings :mail_from => 'Redmine app <redmine@example.net>' do
205
      Mailer.test_email(User.find(1)).deliver
206
    end
207
    mail = last_email
208
    assert_equal 'redmine@example.net', mail.from_addrs.first
209
    assert_equal 'Redmine app <redmine@example.net>', mail.header['From'].to_s
210
  end
211
212
  def test_should_not_send_email_without_recipient
213
    news = News.first
214
    user = news.author
215
    # Remove members except news author
216
    news.project.memberships.each {|m| m.destroy unless m.user == user}
217
218
    user.pref[:no_self_notified] = false
219
    user.pref.save
220
    User.current = user
221
    Mailer.news_added(news.reload).deliver
222
    assert_equal 1, last_email.bcc.size
223
224
    # nobody to notify
225
    user.pref[:no_self_notified] = true
226
    user.pref.save
227
    User.current = user
228
    ActionMailer::Base.deliveries.clear
229
    Mailer.news_added(news.reload).deliver
230
    assert ActionMailer::Base.deliveries.empty?
231
  end
232
233
  def test_issue_add_message_id
234
    issue = Issue.find(1)
235
    Mailer.issue_add(issue).deliver
236
    mail = last_email
237
    assert_equal Mailer.message_id_for(issue), mail.message_id
238
    assert_nil mail.references
239
  end
240
241
  def test_issue_edit_message_id
242
    journal = Journal.find(1)
243
    Mailer.issue_edit(journal).deliver
244
    mail = last_email
245
    assert_equal Mailer.message_id_for(journal), mail.message_id
246
    assert_include Mailer.message_id_for(journal.issue), mail.references
247
    assert_select_email do
248
      # link to the update
249
      assert_select "a[href=?]",
250
                    "http://mydomain.foo/issues/#{journal.journalized_id}#change-#{journal.id}"
251
    end
252
  end
253
254
  def test_message_posted_message_id
255
    message = Message.find(1)
256
    Mailer.message_posted(message).deliver
257
    mail = last_email
258
    assert_equal Mailer.message_id_for(message), mail.message_id
259
    assert_nil mail.references
260
    assert_select_email do
261
      # link to the message
262
      assert_select "a[href=?]",
263
                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.id}",
264
                    :text => message.subject
265
    end
266
  end
267
268
  def test_reply_posted_message_id
269
    message = Message.find(3)
270
    Mailer.message_posted(message).deliver
271
    mail = last_email
272
    assert_equal Mailer.message_id_for(message), mail.message_id
273
    assert_include Mailer.message_id_for(message.parent), mail.references
274
    assert_select_email do
275
      # link to the reply
276
      assert_select "a[href=?]",
277
                    "http://mydomain.foo/boards/#{message.board.id}/topics/#{message.root.id}?r=#{message.id}#message-#{message.id}",
278
                    :text => message.subject
279
    end
280
  end
281
282
  test "#issue_add should notify project members" do
283
    issue = Issue.find(1)
284
    assert Mailer.issue_add(issue).deliver
285
    assert last_email.bcc.include?('dlopper@somenet.foo')
286
  end
287
288
  test "#issue_add should not notify project members that are not allow to view the issue" do
289
    issue = Issue.find(1)
290
    Role.find(2).remove_permission!(:view_issues)
291
    assert Mailer.issue_add(issue).deliver
292
    assert !last_email.bcc.include?('dlopper@somenet.foo')
293
  end
294
295
  test "#issue_add should notify issue watchers" do
296
    issue = Issue.find(1)
297
    user = User.find(9)
298
    # minimal email notification options
299
    user.pref[:no_self_notified] = '1'
300
    user.pref.save
301
    user.mail_notification = false
302
    user.save
303
304
    Watcher.create!(:watchable => issue, :user => user)
305
    assert Mailer.issue_add(issue).deliver
306
    assert last_email.bcc.include?(user.mail)
307
  end
308
309
  test "#issue_add should not notify watchers not allowed to view the issue" do
310
    issue = Issue.find(1)
311
    user = User.find(9)
312
    Watcher.create!(:watchable => issue, :user => user)
313
    Role.non_member.remove_permission!(:view_issues)
314
    assert Mailer.issue_add(issue).deliver
315
    assert !last_email.bcc.include?(user.mail)
316
  end
317
318
  # test mailer methods for each language
319
  def test_issue_add
320
    issue = Issue.find(1)
321
    valid_languages.each do |lang|
322
      Setting.default_language = lang.to_s
323
      assert Mailer.issue_add(issue).deliver
324
    end
325
  end
326
327
  def test_issue_edit
328
    journal = Journal.find(1)
329
    valid_languages.each do |lang|
330
      Setting.default_language = lang.to_s
331
      assert Mailer.issue_edit(journal).deliver
332
    end
333
  end
334
335
  def test_issue_edit_should_send_private_notes_to_users_with_permission_only
336
    journal = Journal.find(1)
337
    journal.private_notes = true
338
    journal.save!
339
340
    Role.find(2).add_permission! :view_private_notes
341
    Mailer.issue_edit(journal).deliver
342
    assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
343
344
    Role.find(2).remove_permission! :view_private_notes
345
    Mailer.issue_edit(journal).deliver
346
    assert_equal %w(jsmith@somenet.foo), ActionMailer::Base.deliveries.last.bcc.sort
347
  end
348
349
  def test_issue_edit_should_send_private_notes_to_watchers_with_permission_only
350
    Issue.find(1).set_watcher(User.find_by_login('someone'))
351
    journal = Journal.find(1)
352
    journal.private_notes = true
353
    journal.save!
354
355
    Role.non_member.add_permission! :view_private_notes
356
    Mailer.issue_edit(journal).deliver
357
    assert_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
358
359
    Role.non_member.remove_permission! :view_private_notes
360
    Mailer.issue_edit(journal).deliver
361
    assert_not_include 'someone@foo.bar', ActionMailer::Base.deliveries.last.bcc.sort
362
  end
363
364
  def test_document_added
365
    document = Document.find(1)
366
    valid_languages.each do |lang|
367
      Setting.default_language = lang.to_s
368
      assert Mailer.document_added(document).deliver
369
    end
370
  end
371
372
  def test_attachments_added
373
    attachements = [ Attachment.find_by_container_type('Document') ]
374
    valid_languages.each do |lang|
375
      Setting.default_language = lang.to_s
376
      assert Mailer.attachments_added(attachements).deliver
377
    end
378
  end
379
380
  def test_version_file_added
381
    attachements = [ Attachment.find_by_container_type('Version') ]
382
    assert Mailer.attachments_added(attachements).deliver
383
    assert_not_nil last_email.bcc
384
    assert last_email.bcc.any?
385
    assert_select_email do
386
      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
387
    end
388
  end
389
390
  def test_project_file_added
391
    attachements = [ Attachment.find_by_container_type('Project') ]
392
    assert Mailer.attachments_added(attachements).deliver
393
    assert_not_nil last_email.bcc
394
    assert last_email.bcc.any?
395
    assert_select_email do
396
      assert_select "a[href=?]", "http://mydomain.foo/projects/ecookbook/files"
397
    end
398
  end
399
400
  def test_news_added
401
    news = News.first
402
    valid_languages.each do |lang|
403
      Setting.default_language = lang.to_s
404
      assert Mailer.news_added(news).deliver
405
    end
406
  end
407
408
  def test_news_comment_added
409
    comment = Comment.find(2)
410
    valid_languages.each do |lang|
411
      Setting.default_language = lang.to_s
412
      assert Mailer.news_comment_added(comment).deliver
413
    end
414
  end
415
416
  def test_message_posted
417
    message = Message.first
418
    recipients = ([message.root] + message.root.children).collect {|m| m.author.mail if m.author}
419
    recipients = recipients.compact.uniq
420
    valid_languages.each do |lang|
421
      Setting.default_language = lang.to_s
422
      assert Mailer.message_posted(message).deliver
423
    end
424
  end
425
426
  def test_wiki_content_added
427
    content = WikiContent.find(1)
428
    valid_languages.each do |lang|
429
      Setting.default_language = lang.to_s
430
      assert_difference 'ActionMailer::Base.deliveries.size' do
431
        assert Mailer.wiki_content_added(content).deliver
432
        assert_select_email do
433
          assert_select 'a[href=?]',
434
            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
435
            :text => 'CookBook documentation'
436
        end
437
      end
438
    end
439
  end
440
441
  def test_wiki_content_updated
442
    content = WikiContent.find(1)
443
    valid_languages.each do |lang|
444
      Setting.default_language = lang.to_s
445
      assert_difference 'ActionMailer::Base.deliveries.size' do
446
        assert Mailer.wiki_content_updated(content).deliver
447
        assert_select_email do
448
          assert_select 'a[href=?]',
449
            'http://mydomain.foo/projects/ecookbook/wiki/CookBook_documentation',
450
            :text => 'CookBook documentation'
451
        end
452
      end
453
    end
454
  end
455
456
  def test_account_information
457
    user = User.find(2)
458
    valid_languages.each do |lang|
459
      user.update_attribute :language, lang.to_s
460
      user.reload
461
      assert Mailer.account_information(user, 'pAsswORd').deliver
462
    end
463
  end
464
465
  def test_lost_password
466
    token = Token.find(2)
467
    valid_languages.each do |lang|
468
      token.user.update_attribute :language, lang.to_s
469
      token.reload
470
      assert Mailer.lost_password(token).deliver
471
    end
472
  end
473
474
  def test_register
475
    token = Token.find(1)
476
    Setting.host_name = 'redmine.foo'
477
    Setting.protocol = 'https'
478
479
    valid_languages.each do |lang|
480
      token.user.update_attribute :language, lang.to_s
481
      token.reload
482
      ActionMailer::Base.deliveries.clear
483
      assert Mailer.register(token).deliver
484
      mail = last_email
485
      assert_select_email do
486
        assert_select "a[href=?]",
487
                      "https://redmine.foo/account/activate?token=#{token.value}",
488
                      :text => "https://redmine.foo/account/activate?token=#{token.value}"
489
      end
490
    end
491
  end
492
493
  def test_test
494
    user = User.find(1)
495
    valid_languages.each do |lang|
496
      user.update_attribute :language, lang.to_s
497
      assert Mailer.test_email(user).deliver
498
    end
499
  end
500
501
  def test_reminders
502
    Mailer.reminders(:days => 42)
503
    assert_equal 1, ActionMailer::Base.deliveries.size
504
    mail = last_email
505
    assert mail.bcc.include?('dlopper@somenet.foo')
506
    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
507
    assert_equal '1 issue(s) due in the next 42 days', mail.subject
508
  end
509
510
  def test_reminders_should_not_include_closed_issues
511
    with_settings :default_language => 'en' do
512
      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 5,
513
                      :subject => 'Closed issue', :assigned_to_id => 3,
514
                      :due_date => 5.days.from_now,
515
                      :author_id => 2)
516
      ActionMailer::Base.deliveries.clear
517
518
      Mailer.reminders(:days => 42)
519
      assert_equal 1, ActionMailer::Base.deliveries.size
520
      mail = last_email
521
      assert mail.bcc.include?('dlopper@somenet.foo')
522
      assert_mail_body_no_match 'Closed issue', mail
523
    end
524
  end
525
526
  def test_reminders_for_users
527
    Mailer.reminders(:days => 42, :users => ['5'])
528
    assert_equal 0, ActionMailer::Base.deliveries.size # No mail for dlopper
529
    Mailer.reminders(:days => 42, :users => ['3'])
530
    assert_equal 1, ActionMailer::Base.deliveries.size # No mail for dlopper
531
    mail = last_email
532
    assert mail.bcc.include?('dlopper@somenet.foo')
533
    assert_mail_body_match 'Bug #3: Error 281 when updating a recipe', mail
534
  end
535
536
  def test_reminder_should_include_issues_assigned_to_groups
537
    with_settings :default_language => 'en' do
538
      group = Group.generate!
539
      group.users << User.find(2)
540
      group.users << User.find(3)
541
542
      Issue.create!(:project_id => 1, :tracker_id => 1, :status_id => 1,
543
                      :subject => 'Assigned to group', :assigned_to => group,
544
                      :due_date => 5.days.from_now,
545
                      :author_id => 2)
546
      ActionMailer::Base.deliveries.clear
547
548
      Mailer.reminders(:days => 7)
549
      assert_equal 2, ActionMailer::Base.deliveries.size
550
      assert_equal %w(dlopper@somenet.foo jsmith@somenet.foo), ActionMailer::Base.deliveries.map(&:bcc).flatten.sort
551
      ActionMailer::Base.deliveries.each do |mail|
552
        assert_mail_body_match 'Assigned to group', mail
553
      end
554
    end
555
  end
556
557
  def test_mailer_should_not_change_locale
558
    Setting.default_language = 'en'
559
    # Set current language to italian
560
    set_language_if_valid 'it'
561
    # Send an email to a french user
562
    user = User.find(1)
563
    user.language = 'fr'
564
    Mailer.account_activated(user).deliver
565
    mail = last_email
566
    assert_mail_body_match 'Votre compte', mail
567
568
    assert_equal :it, current_language
569
  end
570
571
  def test_with_deliveries_off
572
    Mailer.with_deliveries false do
573
      Mailer.test_email(User.find(1)).deliver
574
    end
575
    assert ActionMailer::Base.deliveries.empty?
576
    # should restore perform_deliveries
577
    assert ActionMailer::Base.perform_deliveries
578
  end
579
580
  def test_layout_should_include_the_emails_header
581
    with_settings :emails_header => "*Header content*" do
582
      assert Mailer.test_email(User.find(1)).deliver
583
      assert_select_email do
584
        assert_select ".header" do
585
          assert_select "strong", :text => "Header content"
586
        end
587
      end
588
    end
589
  end
590
591
  def test_should_escape_html_templates_only
592
    Issue.generate!(:project_id => 1, :tracker_id => 1, :subject => 'Subject with a <tag>')
593
    mail = last_email
594
    assert_equal 2, mail.parts.size
595
    assert_include '<tag>', text_part.body.encoded
596
    assert_include '&lt;tag&gt;', html_part.body.encoded
597
  end
598
599
  private
600
601
  def last_email
602
    mail = ActionMailer::Base.deliveries.last
603
    assert_not_nil mail
604
    mail
605
  end
606
607
  def text_part
608
    last_email.parts.detect {|part| part.content_type.include?('text/plain')}
609
  end
610
611
  def html_part
612
    last_email.parts.detect {|part| part.content_type.include?('text/html')}
613
  end
614
end