annotate test/unit/mail_handler_test.rb @ 1298:4f746d8966dd redmine_2.3_integration

Merge from redmine-2.3 branch to create new branch redmine-2.3-integration
author Chris Cannam
date Fri, 14 Jun 2013 09:28:30 +0100
parents 622f24f53b42
children
rev   line source
Chris@0 1 # encoding: utf-8
Chris@0 2 #
Chris@0 3 # Redmine - project management software
Chris@1295 4 # Copyright (C) 2006-2013 Jean-Philippe Lang
Chris@0 5 #
Chris@0 6 # This program is free software; you can redistribute it and/or
Chris@0 7 # modify it under the terms of the GNU General Public License
Chris@0 8 # as published by the Free Software Foundation; either version 2
Chris@0 9 # of the License, or (at your option) any later version.
Chris@441 10 #
Chris@0 11 # This program is distributed in the hope that it will be useful,
Chris@0 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 14 # GNU General Public License for more details.
Chris@441 15 #
Chris@0 16 # You should have received a copy of the GNU General Public License
Chris@0 17 # along with this program; if not, write to the Free Software
Chris@0 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Chris@0 19
Chris@119 20 require File.expand_path('../../test_helper', __FILE__)
Chris@0 21
Chris@0 22 class MailHandlerTest < ActiveSupport::TestCase
Chris@1115 23 fixtures :users, :projects, :enabled_modules, :roles,
Chris@1115 24 :members, :member_roles, :users,
Chris@1115 25 :issues, :issue_statuses,
Chris@1115 26 :workflows, :trackers, :projects_trackers,
Chris@1115 27 :versions, :enumerations, :issue_categories,
Chris@1115 28 :custom_fields, :custom_fields_trackers, :custom_fields_projects,
Chris@1115 29 :boards, :messages
Chris@441 30
Chris@0 31 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
Chris@441 32
Chris@0 33 def setup
Chris@0 34 ActionMailer::Base.deliveries.clear
chris@37 35 Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
Chris@0 36 end
Chris@441 37
Chris@1115 38 def teardown
Chris@1115 39 Setting.clear_cache
Chris@1115 40 end
Chris@1115 41
Chris@0 42 def test_add_issue
Chris@0 43 ActionMailer::Base.deliveries.clear
Chris@0 44 # This email contains: 'Project: onlinestore'
Chris@0 45 issue = submit_email('ticket_on_given_project.eml')
Chris@0 46 assert issue.is_a?(Issue)
Chris@0 47 assert !issue.new_record?
Chris@0 48 issue.reload
Chris@119 49 assert_equal Project.find(2), issue.project
Chris@119 50 assert_equal issue.project.trackers.first, issue.tracker
Chris@0 51 assert_equal 'New ticket on a given project', issue.subject
Chris@0 52 assert_equal User.find_by_login('jsmith'), issue.author
Chris@0 53 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
Chris@0 54 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
Chris@0 55 assert_equal '2010-01-01', issue.start_date.to_s
Chris@0 56 assert_equal '2010-12-31', issue.due_date.to_s
Chris@0 57 assert_equal User.find_by_login('jsmith'), issue.assigned_to
Chris@507 58 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
chris@37 59 assert_equal 2.5, issue.estimated_hours
chris@37 60 assert_equal 30, issue.done_ratio
Chris@119 61 assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
Chris@0 62 # keywords should be removed from the email body
Chris@0 63 assert !issue.description.match(/^Project:/i)
Chris@0 64 assert !issue.description.match(/^Status:/i)
Chris@441 65 assert !issue.description.match(/^Start Date:/i)
Chris@0 66 # Email notification should be sent
Chris@0 67 mail = ActionMailer::Base.deliveries.last
Chris@0 68 assert_not_nil mail
Chris@0 69 assert mail.subject.include?('New ticket on a given project')
Chris@0 70 end
Chris@441 71
Chris@119 72 def test_add_issue_with_default_tracker
Chris@119 73 # This email contains: 'Project: onlinestore'
Chris@1115 74 issue = submit_email(
Chris@1115 75 'ticket_on_given_project.eml',
Chris@1115 76 :issue => {:tracker => 'Support request'}
Chris@1115 77 )
Chris@119 78 assert issue.is_a?(Issue)
Chris@119 79 assert !issue.new_record?
Chris@119 80 issue.reload
Chris@119 81 assert_equal 'Support request', issue.tracker.name
Chris@119 82 end
Chris@0 83
Chris@0 84 def test_add_issue_with_status
Chris@0 85 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
Chris@0 86 issue = submit_email('ticket_on_given_project.eml')
Chris@0 87 assert issue.is_a?(Issue)
Chris@0 88 assert !issue.new_record?
Chris@0 89 issue.reload
Chris@0 90 assert_equal Project.find(2), issue.project
Chris@0 91 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
Chris@0 92 end
Chris@441 93
Chris@0 94 def test_add_issue_with_attributes_override
Chris@1115 95 issue = submit_email(
Chris@1115 96 'ticket_with_attributes.eml',
Chris@1115 97 :allow_override => 'tracker,category,priority'
Chris@1115 98 )
Chris@0 99 assert issue.is_a?(Issue)
Chris@0 100 assert !issue.new_record?
Chris@0 101 issue.reload
Chris@0 102 assert_equal 'New ticket on a given project', issue.subject
Chris@0 103 assert_equal User.find_by_login('jsmith'), issue.author
Chris@0 104 assert_equal Project.find(2), issue.project
Chris@0 105 assert_equal 'Feature request', issue.tracker.to_s
Chris@0 106 assert_equal 'Stock management', issue.category.to_s
Chris@0 107 assert_equal 'Urgent', issue.priority.to_s
Chris@0 108 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
Chris@0 109 end
Chris@441 110
Chris@909 111 def test_add_issue_with_group_assignment
Chris@909 112 with_settings :issue_group_assignment => '1' do
Chris@909 113 issue = submit_email('ticket_on_given_project.eml') do |email|
Chris@909 114 email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
Chris@909 115 end
Chris@909 116 assert issue.is_a?(Issue)
Chris@909 117 assert !issue.new_record?
Chris@909 118 issue.reload
Chris@909 119 assert_equal Group.find(11), issue.assigned_to
Chris@909 120 end
Chris@909 121 end
Chris@909 122
Chris@0 123 def test_add_issue_with_partial_attributes_override
Chris@1115 124 issue = submit_email(
Chris@1115 125 'ticket_with_attributes.eml',
Chris@1115 126 :issue => {:priority => 'High'},
Chris@1115 127 :allow_override => ['tracker']
Chris@1115 128 )
Chris@0 129 assert issue.is_a?(Issue)
Chris@0 130 assert !issue.new_record?
Chris@0 131 issue.reload
Chris@0 132 assert_equal 'New ticket on a given project', issue.subject
Chris@0 133 assert_equal User.find_by_login('jsmith'), issue.author
Chris@0 134 assert_equal Project.find(2), issue.project
Chris@0 135 assert_equal 'Feature request', issue.tracker.to_s
Chris@0 136 assert_nil issue.category
Chris@0 137 assert_equal 'High', issue.priority.to_s
Chris@0 138 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
Chris@0 139 end
Chris@441 140
Chris@0 141 def test_add_issue_with_spaces_between_attribute_and_separator
Chris@1115 142 issue = submit_email(
Chris@1115 143 'ticket_with_spaces_between_attribute_and_separator.eml',
Chris@1115 144 :allow_override => 'tracker,category,priority'
Chris@1115 145 )
Chris@0 146 assert issue.is_a?(Issue)
Chris@0 147 assert !issue.new_record?
Chris@0 148 issue.reload
Chris@0 149 assert_equal 'New ticket on a given project', issue.subject
Chris@0 150 assert_equal User.find_by_login('jsmith'), issue.author
Chris@0 151 assert_equal Project.find(2), issue.project
Chris@0 152 assert_equal 'Feature request', issue.tracker.to_s
Chris@0 153 assert_equal 'Stock management', issue.category.to_s
Chris@0 154 assert_equal 'Urgent', issue.priority.to_s
Chris@0 155 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
Chris@0 156 end
Chris@0 157
Chris@0 158 def test_add_issue_with_attachment_to_specific_project
Chris@0 159 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
Chris@0 160 assert issue.is_a?(Issue)
Chris@0 161 assert !issue.new_record?
Chris@0 162 issue.reload
Chris@0 163 assert_equal 'Ticket created by email with attachment', issue.subject
Chris@0 164 assert_equal User.find_by_login('jsmith'), issue.author
Chris@0 165 assert_equal Project.find(2), issue.project
Chris@0 166 assert_equal 'This is a new ticket with attachments', issue.description
Chris@0 167 # Attachment properties
Chris@0 168 assert_equal 1, issue.attachments.size
Chris@0 169 assert_equal 'Paella.jpg', issue.attachments.first.filename
Chris@0 170 assert_equal 'image/jpeg', issue.attachments.first.content_type
Chris@0 171 assert_equal 10790, issue.attachments.first.filesize
Chris@0 172 end
Chris@441 173
Chris@0 174 def test_add_issue_with_custom_fields
Chris@0 175 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'})
Chris@0 176 assert issue.is_a?(Issue)
Chris@0 177 assert !issue.new_record?
Chris@0 178 issue.reload
Chris@0 179 assert_equal 'New ticket with custom field values', issue.subject
Chris@1115 180 assert_equal 'PostgreSQL', issue.custom_field_value(1)
Chris@1115 181 assert_equal 'Value for a custom field', issue.custom_field_value(2)
Chris@0 182 assert !issue.description.match(/^searchable field:/i)
Chris@0 183 end
Chris@441 184
Chris@1115 185 def test_add_issue_with_version_custom_fields
Chris@1115 186 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
Chris@1115 187
Chris@1115 188 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'ecookbook'}) do |email|
Chris@1115 189 email << "Affected version: 1.0\n"
Chris@1115 190 end
Chris@1115 191 assert issue.is_a?(Issue)
Chris@1115 192 assert !issue.new_record?
Chris@1115 193 issue.reload
Chris@1115 194 assert_equal '2', issue.custom_field_value(field)
Chris@1115 195 end
Chris@1115 196
Chris@1115 197 def test_add_issue_should_match_assignee_on_display_name
Chris@1115 198 user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
Chris@1115 199 User.add_to_project(user, Project.find(2))
Chris@1115 200 issue = submit_email('ticket_on_given_project.eml') do |email|
Chris@1115 201 email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
Chris@1115 202 end
Chris@1115 203 assert issue.is_a?(Issue)
Chris@1115 204 assert_equal user, issue.assigned_to
Chris@1115 205 end
Chris@1115 206
Chris@0 207 def test_add_issue_with_cc
Chris@0 208 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
Chris@0 209 assert issue.is_a?(Issue)
Chris@0 210 assert !issue.new_record?
Chris@0 211 issue.reload
Chris@0 212 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
chris@37 213 assert_equal 1, issue.watcher_user_ids.size
Chris@0 214 end
Chris@441 215
Chris@0 216 def test_add_issue_by_unknown_user
Chris@0 217 assert_no_difference 'User.count' do
Chris@1115 218 assert_equal false,
Chris@1115 219 submit_email(
Chris@1115 220 'ticket_by_unknown_user.eml',
Chris@1115 221 :issue => {:project => 'ecookbook'}
Chris@1115 222 )
Chris@0 223 end
Chris@0 224 end
Chris@441 225
Chris@0 226 def test_add_issue_by_anonymous_user
Chris@0 227 Role.anonymous.add_permission!(:add_issues)
Chris@0 228 assert_no_difference 'User.count' do
Chris@1115 229 issue = submit_email(
Chris@1115 230 'ticket_by_unknown_user.eml',
Chris@1115 231 :issue => {:project => 'ecookbook'},
Chris@1115 232 :unknown_user => 'accept'
Chris@1115 233 )
Chris@0 234 assert issue.is_a?(Issue)
Chris@0 235 assert issue.author.anonymous?
Chris@0 236 end
Chris@0 237 end
Chris@0 238
Chris@0 239 def test_add_issue_by_anonymous_user_with_no_from_address
Chris@0 240 Role.anonymous.add_permission!(:add_issues)
Chris@0 241 assert_no_difference 'User.count' do
Chris@1115 242 issue = submit_email(
Chris@1115 243 'ticket_by_empty_user.eml',
Chris@1115 244 :issue => {:project => 'ecookbook'},
Chris@1115 245 :unknown_user => 'accept'
Chris@1115 246 )
Chris@0 247 assert issue.is_a?(Issue)
Chris@0 248 assert issue.author.anonymous?
Chris@0 249 end
Chris@0 250 end
Chris@441 251
Chris@0 252 def test_add_issue_by_anonymous_user_on_private_project
Chris@0 253 Role.anonymous.add_permission!(:add_issues)
Chris@0 254 assert_no_difference 'User.count' do
Chris@0 255 assert_no_difference 'Issue.count' do
Chris@1115 256 assert_equal false,
Chris@1115 257 submit_email(
Chris@1115 258 'ticket_by_unknown_user.eml',
Chris@1115 259 :issue => {:project => 'onlinestore'},
Chris@1115 260 :unknown_user => 'accept'
Chris@1115 261 )
Chris@0 262 end
Chris@0 263 end
Chris@0 264 end
Chris@441 265
Chris@0 266 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
Chris@0 267 assert_no_difference 'User.count' do
Chris@0 268 assert_difference 'Issue.count' do
Chris@1115 269 issue = submit_email(
Chris@1115 270 'ticket_by_unknown_user.eml',
Chris@1115 271 :issue => {:project => 'onlinestore'},
Chris@1115 272 :no_permission_check => '1',
Chris@1115 273 :unknown_user => 'accept'
Chris@1115 274 )
Chris@0 275 assert issue.is_a?(Issue)
Chris@0 276 assert issue.author.anonymous?
Chris@0 277 assert !issue.project.is_public?
Chris@119 278 assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
Chris@0 279 end
Chris@0 280 end
Chris@0 281 end
Chris@441 282
Chris@0 283 def test_add_issue_by_created_user
Chris@0 284 Setting.default_language = 'en'
Chris@0 285 assert_difference 'User.count' do
Chris@1115 286 issue = submit_email(
Chris@1115 287 'ticket_by_unknown_user.eml',
Chris@1115 288 :issue => {:project => 'ecookbook'},
Chris@1115 289 :unknown_user => 'create'
Chris@1115 290 )
Chris@0 291 assert issue.is_a?(Issue)
Chris@0 292 assert issue.author.active?
Chris@0 293 assert_equal 'john.doe@somenet.foo', issue.author.mail
Chris@0 294 assert_equal 'John', issue.author.firstname
Chris@0 295 assert_equal 'Doe', issue.author.lastname
Chris@441 296
Chris@0 297 # account information
Chris@0 298 email = ActionMailer::Base.deliveries.first
Chris@0 299 assert_not_nil email
Chris@0 300 assert email.subject.include?('account activation')
Chris@1115 301 login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
Chris@1115 302 password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
Chris@0 303 assert_equal issue.author, User.try_to_login(login, password)
Chris@0 304 end
Chris@0 305 end
Chris@441 306
Chris@1295 307 def test_created_user_should_be_added_to_groups
Chris@1295 308 group1 = Group.generate!
Chris@1295 309 group2 = Group.generate!
Chris@1295 310
Chris@1295 311 assert_difference 'User.count' do
Chris@1295 312 submit_email(
Chris@1295 313 'ticket_by_unknown_user.eml',
Chris@1295 314 :issue => {:project => 'ecookbook'},
Chris@1295 315 :unknown_user => 'create',
Chris@1295 316 :default_group => "#{group1.name},#{group2.name}"
Chris@1295 317 )
Chris@1295 318 end
Chris@1295 319 user = User.order('id DESC').first
Chris@1295 320 assert_same_elements [group1, group2], user.groups
Chris@1295 321 end
Chris@1295 322
Chris@1295 323 def test_created_user_should_not_receive_account_information_with_no_account_info_option
Chris@1295 324 assert_difference 'User.count' do
Chris@1295 325 submit_email(
Chris@1295 326 'ticket_by_unknown_user.eml',
Chris@1295 327 :issue => {:project => 'ecookbook'},
Chris@1295 328 :unknown_user => 'create',
Chris@1295 329 :no_account_notice => '1'
Chris@1295 330 )
Chris@1295 331 end
Chris@1295 332
Chris@1295 333 # only 1 email for the new issue notification
Chris@1295 334 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@1295 335 email = ActionMailer::Base.deliveries.first
Chris@1295 336 assert_include 'Ticket by unknown user', email.subject
Chris@1295 337 end
Chris@1295 338
Chris@1295 339 def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
Chris@1295 340 assert_difference 'User.count' do
Chris@1295 341 submit_email(
Chris@1295 342 'ticket_by_unknown_user.eml',
Chris@1295 343 :issue => {:project => 'ecookbook'},
Chris@1295 344 :unknown_user => 'create',
Chris@1295 345 :no_notification => '1'
Chris@1295 346 )
Chris@1295 347 end
Chris@1295 348 user = User.order('id DESC').first
Chris@1295 349 assert_equal 'none', user.mail_notification
Chris@1295 350 end
Chris@1295 351
Chris@0 352 def test_add_issue_without_from_header
Chris@0 353 Role.anonymous.add_permission!(:add_issues)
Chris@0 354 assert_equal false, submit_email('ticket_without_from_header.eml')
Chris@0 355 end
chris@37 356
chris@37 357 def test_add_issue_with_invalid_attributes
Chris@1115 358 issue = submit_email(
Chris@1115 359 'ticket_with_invalid_attributes.eml',
Chris@1115 360 :allow_override => 'tracker,category,priority'
Chris@1115 361 )
chris@37 362 assert issue.is_a?(Issue)
chris@37 363 assert !issue.new_record?
chris@37 364 issue.reload
chris@37 365 assert_nil issue.assigned_to
chris@37 366 assert_nil issue.start_date
chris@37 367 assert_nil issue.due_date
chris@37 368 assert_equal 0, issue.done_ratio
chris@37 369 assert_equal 'Normal', issue.priority.to_s
chris@37 370 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
chris@37 371 end
chris@37 372
chris@37 373 def test_add_issue_with_localized_attributes
chris@37 374 User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
Chris@1115 375 issue = submit_email(
Chris@1115 376 'ticket_with_localized_attributes.eml',
Chris@1115 377 :allow_override => 'tracker,category,priority'
Chris@1115 378 )
chris@37 379 assert issue.is_a?(Issue)
chris@37 380 assert !issue.new_record?
chris@37 381 issue.reload
chris@37 382 assert_equal 'New ticket on a given project', issue.subject
chris@37 383 assert_equal User.find_by_login('jsmith'), issue.author
chris@37 384 assert_equal Project.find(2), issue.project
chris@37 385 assert_equal 'Feature request', issue.tracker.to_s
chris@37 386 assert_equal 'Stock management', issue.category.to_s
chris@37 387 assert_equal 'Urgent', issue.priority.to_s
chris@37 388 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
chris@37 389 end
Chris@441 390
Chris@0 391 def test_add_issue_with_japanese_keywords
Chris@1115 392 ja_dev = "\xe9\x96\x8b\xe7\x99\xba"
Chris@1115 393 ja_dev.force_encoding('UTF-8') if ja_dev.respond_to?(:force_encoding)
Chris@1115 394 tracker = Tracker.create!(:name => ja_dev)
Chris@0 395 Project.find(1).trackers << tracker
Chris@1115 396 issue = submit_email(
Chris@1115 397 'japanese_keywords_iso_2022_jp.eml',
Chris@1115 398 :issue => {:project => 'ecookbook'},
Chris@1115 399 :allow_override => 'tracker'
Chris@1115 400 )
Chris@0 401 assert_kind_of Issue, issue
Chris@0 402 assert_equal tracker, issue.tracker
Chris@0 403 end
Chris@0 404
Chris@909 405 def test_add_issue_from_apple_mail
Chris@1115 406 issue = submit_email(
Chris@1115 407 'apple_mail_with_attachment.eml',
Chris@1115 408 :issue => {:project => 'ecookbook'}
Chris@1115 409 )
Chris@909 410 assert_kind_of Issue, issue
Chris@909 411 assert_equal 1, issue.attachments.size
Chris@909 412
Chris@909 413 attachment = issue.attachments.first
Chris@909 414 assert_equal 'paella.jpg', attachment.filename
Chris@909 415 assert_equal 10790, attachment.filesize
Chris@1115 416 assert File.exist?(attachment.diskfile)
Chris@1115 417 assert_equal 10790, File.size(attachment.diskfile)
Chris@1115 418 assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
Chris@1115 419 end
Chris@1115 420
Chris@1115 421 def test_thunderbird_with_attachment_ja
Chris@1115 422 issue = submit_email(
Chris@1115 423 'thunderbird_with_attachment_ja.eml',
Chris@1115 424 :issue => {:project => 'ecookbook'}
Chris@1115 425 )
Chris@1115 426 assert_kind_of Issue, issue
Chris@1115 427 assert_equal 1, issue.attachments.size
Chris@1115 428 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
Chris@1115 429 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
Chris@1115 430 attachment = issue.attachments.first
Chris@1115 431 assert_equal ja, attachment.filename
Chris@1115 432 assert_equal 5, attachment.filesize
Chris@1115 433 assert File.exist?(attachment.diskfile)
Chris@1115 434 assert_equal 5, File.size(attachment.diskfile)
Chris@1115 435 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
Chris@1115 436 end
Chris@1115 437
Chris@1115 438 def test_gmail_with_attachment_ja
Chris@1115 439 issue = submit_email(
Chris@1115 440 'gmail_with_attachment_ja.eml',
Chris@1115 441 :issue => {:project => 'ecookbook'}
Chris@1115 442 )
Chris@1115 443 assert_kind_of Issue, issue
Chris@1115 444 assert_equal 1, issue.attachments.size
Chris@1115 445 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt"
Chris@1115 446 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
Chris@1115 447 attachment = issue.attachments.first
Chris@1115 448 assert_equal ja, attachment.filename
Chris@1115 449 assert_equal 5, attachment.filesize
Chris@1115 450 assert File.exist?(attachment.diskfile)
Chris@1115 451 assert_equal 5, File.size(attachment.diskfile)
Chris@1115 452 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
Chris@1115 453 end
Chris@1115 454
Chris@1115 455 def test_thunderbird_with_attachment_latin1
Chris@1115 456 issue = submit_email(
Chris@1115 457 'thunderbird_with_attachment_iso-8859-1.eml',
Chris@1115 458 :issue => {:project => 'ecookbook'}
Chris@1115 459 )
Chris@1115 460 assert_kind_of Issue, issue
Chris@1115 461 assert_equal 1, issue.attachments.size
Chris@1115 462 u = ""
Chris@1115 463 u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
Chris@1115 464 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
Chris@1115 465 u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
Chris@1115 466 11.times { u << u1 }
Chris@1115 467 attachment = issue.attachments.first
Chris@1115 468 assert_equal "#{u}.png", attachment.filename
Chris@1115 469 assert_equal 130, attachment.filesize
Chris@1115 470 assert File.exist?(attachment.diskfile)
Chris@1115 471 assert_equal 130, File.size(attachment.diskfile)
Chris@1115 472 assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
Chris@1115 473 end
Chris@1115 474
Chris@1115 475 def test_gmail_with_attachment_latin1
Chris@1115 476 issue = submit_email(
Chris@1115 477 'gmail_with_attachment_iso-8859-1.eml',
Chris@1115 478 :issue => {:project => 'ecookbook'}
Chris@1115 479 )
Chris@1115 480 assert_kind_of Issue, issue
Chris@1115 481 assert_equal 1, issue.attachments.size
Chris@1115 482 u = ""
Chris@1115 483 u.force_encoding('UTF-8') if u.respond_to?(:force_encoding)
Chris@1115 484 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc"
Chris@1115 485 u1.force_encoding('UTF-8') if u1.respond_to?(:force_encoding)
Chris@1115 486 11.times { u << u1 }
Chris@1115 487 attachment = issue.attachments.first
Chris@1115 488 assert_equal "#{u}.txt", attachment.filename
Chris@1115 489 assert_equal 5, attachment.filesize
Chris@1115 490 assert File.exist?(attachment.diskfile)
Chris@1115 491 assert_equal 5, File.size(attachment.diskfile)
Chris@1115 492 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
Chris@1115 493 end
Chris@1115 494
Chris@1115 495 def test_add_issue_with_iso_8859_1_subject
Chris@1115 496 issue = submit_email(
Chris@1115 497 'subject_as_iso-8859-1.eml',
Chris@1115 498 :issue => {:project => 'ecookbook'}
Chris@1115 499 )
Chris@1115 500 str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc..."
Chris@1115 501 str.force_encoding('UTF-8') if str.respond_to?(:force_encoding)
Chris@1115 502 assert_kind_of Issue, issue
Chris@1115 503 assert_equal str, issue.subject
Chris@1115 504 end
Chris@1115 505
Chris@1115 506 def test_add_issue_with_japanese_subject
Chris@1115 507 issue = submit_email(
Chris@1115 508 'subject_japanese_1.eml',
Chris@1115 509 :issue => {:project => 'ecookbook'}
Chris@1115 510 )
Chris@1115 511 assert_kind_of Issue, issue
Chris@1115 512 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
Chris@1115 513 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
Chris@1115 514 assert_equal ja, issue.subject
Chris@1115 515 end
Chris@1115 516
Chris@1115 517 def test_add_issue_with_no_subject_header
Chris@1115 518 issue = submit_email(
Chris@1115 519 'no_subject_header.eml',
Chris@1115 520 :issue => {:project => 'ecookbook'}
Chris@1115 521 )
Chris@1115 522 assert_kind_of Issue, issue
Chris@1115 523 assert_equal '(no subject)', issue.subject
Chris@1115 524 end
Chris@1115 525
Chris@1115 526 def test_add_issue_with_mixed_japanese_subject
Chris@1115 527 issue = submit_email(
Chris@1115 528 'subject_japanese_2.eml',
Chris@1115 529 :issue => {:project => 'ecookbook'}
Chris@1115 530 )
Chris@1115 531 assert_kind_of Issue, issue
Chris@1115 532 ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88"
Chris@1115 533 ja.force_encoding('UTF-8') if ja.respond_to?(:force_encoding)
Chris@1115 534 assert_equal ja, issue.subject
Chris@1115 535 end
Chris@1115 536
Chris@1115 537 def test_should_ignore_emails_from_locked_users
Chris@1115 538 User.find(2).lock!
Chris@1115 539
Chris@1115 540 MailHandler.any_instance.expects(:dispatch).never
Chris@1115 541 assert_no_difference 'Issue.count' do
Chris@1115 542 assert_equal false, submit_email('ticket_on_given_project.eml')
Chris@1115 543 end
Chris@909 544 end
Chris@909 545
Chris@0 546 def test_should_ignore_emails_from_emission_address
Chris@0 547 Role.anonymous.add_permission!(:add_issues)
Chris@0 548 assert_no_difference 'User.count' do
Chris@1115 549 assert_equal false,
Chris@1115 550 submit_email(
Chris@1115 551 'ticket_from_emission_address.eml',
Chris@1115 552 :issue => {:project => 'ecookbook'},
Chris@1115 553 :unknown_user => 'create'
Chris@1115 554 )
Chris@1115 555 end
Chris@1115 556 end
Chris@1115 557
Chris@1115 558 def test_should_ignore_auto_replied_emails
Chris@1115 559 MailHandler.any_instance.expects(:dispatch).never
Chris@1115 560 [
Chris@1115 561 "X-Auto-Response-Suppress: OOF",
Chris@1115 562 "Auto-Submitted: auto-replied",
Chris@1115 563 "Auto-Submitted: Auto-Replied",
Chris@1115 564 "Auto-Submitted: auto-generated"
Chris@1115 565 ].each do |header|
Chris@1115 566 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
Chris@1115 567 raw = header + "\n" + raw
Chris@1115 568
Chris@1115 569 assert_no_difference 'Issue.count' do
Chris@1115 570 assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
Chris@1115 571 end
Chris@0 572 end
Chris@0 573 end
Chris@0 574
Chris@0 575 def test_add_issue_should_send_email_notification
chris@37 576 Setting.notified_events = ['issue_added']
Chris@0 577 ActionMailer::Base.deliveries.clear
Chris@0 578 # This email contains: 'Project: onlinestore'
Chris@0 579 issue = submit_email('ticket_on_given_project.eml')
Chris@0 580 assert issue.is_a?(Issue)
Chris@0 581 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@0 582 end
Chris@441 583
Chris@909 584 def test_update_issue
Chris@0 585 journal = submit_email('ticket_reply.eml')
Chris@0 586 assert journal.is_a?(Journal)
Chris@0 587 assert_equal User.find_by_login('jsmith'), journal.user
Chris@0 588 assert_equal Issue.find(2), journal.journalized
Chris@0 589 assert_match /This is reply/, journal.notes
Chris@1115 590 assert_equal false, journal.private_notes
Chris@119 591 assert_equal 'Feature request', journal.issue.tracker.name
Chris@0 592 end
Chris@0 593
Chris@909 594 def test_update_issue_with_attribute_changes
Chris@0 595 # This email contains: 'Status: Resolved'
Chris@0 596 journal = submit_email('ticket_reply_with_status.eml')
Chris@0 597 assert journal.is_a?(Journal)
Chris@0 598 issue = Issue.find(journal.issue.id)
Chris@0 599 assert_equal User.find_by_login('jsmith'), journal.user
Chris@0 600 assert_equal Issue.find(2), journal.journalized
Chris@0 601 assert_match /This is reply/, journal.notes
Chris@119 602 assert_equal 'Feature request', journal.issue.tracker.name
Chris@0 603 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
Chris@0 604 assert_equal '2010-01-01', issue.start_date.to_s
Chris@0 605 assert_equal '2010-12-31', issue.due_date.to_s
Chris@0 606 assert_equal User.find_by_login('jsmith'), issue.assigned_to
Chris@119 607 assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
Chris@441 608 # keywords should be removed from the email body
Chris@441 609 assert !journal.notes.match(/^Status:/i)
Chris@441 610 assert !journal.notes.match(/^Start Date:/i)
Chris@0 611 end
Chris@0 612
Chris@909 613 def test_update_issue_with_attachment
Chris@909 614 assert_difference 'Journal.count' do
Chris@909 615 assert_difference 'JournalDetail.count' do
Chris@909 616 assert_difference 'Attachment.count' do
Chris@909 617 assert_no_difference 'Issue.count' do
Chris@909 618 journal = submit_email('ticket_with_attachment.eml') do |raw|
Chris@909 619 raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
Chris@909 620 end
Chris@909 621 end
Chris@909 622 end
Chris@909 623 end
Chris@909 624 end
Chris@909 625 journal = Journal.first(:order => 'id DESC')
Chris@909 626 assert_equal Issue.find(2), journal.journalized
Chris@909 627 assert_equal 1, journal.details.size
Chris@909 628
Chris@909 629 detail = journal.details.first
Chris@909 630 assert_equal 'attachment', detail.property
Chris@909 631 assert_equal 'Paella.jpg', detail.value
Chris@909 632 end
Chris@909 633
Chris@909 634 def test_update_issue_should_send_email_notification
Chris@0 635 ActionMailer::Base.deliveries.clear
Chris@0 636 journal = submit_email('ticket_reply.eml')
Chris@0 637 assert journal.is_a?(Journal)
Chris@0 638 assert_equal 1, ActionMailer::Base.deliveries.size
Chris@0 639 end
Chris@441 640
Chris@909 641 def test_update_issue_should_not_set_defaults
Chris@1115 642 journal = submit_email(
Chris@1115 643 'ticket_reply.eml',
Chris@1115 644 :issue => {:tracker => 'Support request', :priority => 'High'}
Chris@1115 645 )
Chris@119 646 assert journal.is_a?(Journal)
Chris@119 647 assert_match /This is reply/, journal.notes
Chris@119 648 assert_equal 'Feature request', journal.issue.tracker.name
Chris@119 649 assert_equal 'Normal', journal.issue.priority.name
Chris@119 650 end
Chris@441 651
Chris@1115 652 def test_replying_to_a_private_note_should_add_reply_as_private
Chris@1115 653 private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2)
Chris@1115 654
Chris@1115 655 assert_difference 'Journal.count' do
Chris@1115 656 journal = submit_email('ticket_reply.eml') do |email|
Chris@1115 657 email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
Chris@1115 658 end
Chris@1115 659
Chris@1115 660 assert_kind_of Journal, journal
Chris@1115 661 assert_match /This is reply/, journal.notes
Chris@1115 662 assert_equal true, journal.private_notes
Chris@1115 663 end
Chris@1115 664 end
Chris@1115 665
Chris@0 666 def test_reply_to_a_message
Chris@0 667 m = submit_email('message_reply.eml')
Chris@0 668 assert m.is_a?(Message)
Chris@0 669 assert !m.new_record?
Chris@0 670 m.reload
Chris@0 671 assert_equal 'Reply via email', m.subject
Chris@0 672 # The email replies to message #2 which is part of the thread of message #1
Chris@0 673 assert_equal Message.find(1), m.parent
Chris@0 674 end
Chris@441 675
Chris@0 676 def test_reply_to_a_message_by_subject
Chris@0 677 m = submit_email('message_reply_by_subject.eml')
Chris@0 678 assert m.is_a?(Message)
Chris@0 679 assert !m.new_record?
Chris@0 680 m.reload
Chris@0 681 assert_equal 'Reply to the first post', m.subject
Chris@0 682 assert_equal Message.find(1), m.parent
Chris@0 683 end
Chris@441 684
Chris@0 685 def test_should_strip_tags_of_html_only_emails
Chris@0 686 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
Chris@0 687 assert issue.is_a?(Issue)
Chris@0 688 assert !issue.new_record?
Chris@0 689 issue.reload
Chris@0 690 assert_equal 'HTML email', issue.subject
Chris@0 691 assert_equal 'This is a html-only email.', issue.description
Chris@0 692 end
Chris@0 693
Chris@1295 694 test "truncate emails with no setting should add the entire email into the issue" do
Chris@1295 695 with_settings :mail_handler_body_delimiters => '' do
Chris@1295 696 issue = submit_email('ticket_on_given_project.eml')
Chris@1295 697 assert_issue_created(issue)
Chris@1295 698 assert issue.description.include?('---')
Chris@1295 699 assert issue.description.include?('This paragraph is after the delimiter')
Chris@1295 700 end
Chris@1295 701 end
Chris@0 702
Chris@1295 703 test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
Chris@1295 704 with_settings :mail_handler_body_delimiters => '---' do
Chris@1295 705 issue = submit_email('ticket_on_given_project.eml')
Chris@1295 706 assert_issue_created(issue)
Chris@1295 707 assert issue.description.include?('This paragraph is before delimiters')
Chris@1295 708 assert issue.description.include?('--- This line starts with a delimiter')
Chris@1295 709 assert !issue.description.match(/^---$/)
Chris@1295 710 assert !issue.description.include?('This paragraph is after the delimiter')
Chris@0 711 end
Chris@1295 712 end
Chris@0 713
Chris@1295 714 test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
Chris@1295 715 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
Chris@1295 716 journal = submit_email('issue_update_with_quoted_reply_above.eml')
Chris@1295 717 assert journal.is_a?(Journal)
Chris@1295 718 assert journal.notes.include?('An update to the issue by the sender.')
Chris@1295 719 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
Chris@1295 720 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
Chris@0 721 end
Chris@1295 722 end
Chris@0 723
Chris@1295 724 test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
Chris@1295 725 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
Chris@1295 726 journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
Chris@1295 727 assert journal.is_a?(Journal)
Chris@1295 728 assert journal.notes.include?('An update to the issue by the sender.')
Chris@1295 729 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
Chris@1295 730 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
Chris@441 731 end
Chris@1295 732 end
chris@37 733
Chris@1295 734 test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
Chris@1295 735 with_settings :mail_handler_body_delimiters => "---\nBREAK" do
Chris@1295 736 issue = submit_email('ticket_on_given_project.eml')
Chris@1295 737 assert_issue_created(issue)
Chris@1295 738 assert issue.description.include?('This paragraph is before delimiters')
Chris@1295 739 assert !issue.description.include?('BREAK')
Chris@1295 740 assert !issue.description.include?('This paragraph is between delimiters')
Chris@1295 741 assert !issue.description.match(/^---$/)
Chris@1295 742 assert !issue.description.include?('This paragraph is after the delimiter')
Chris@0 743 end
Chris@0 744 end
Chris@441 745
Chris@0 746 def test_email_with_long_subject_line
Chris@0 747 issue = submit_email('ticket_with_long_subject.eml')
Chris@0 748 assert issue.is_a?(Issue)
Chris@0 749 assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255]
Chris@0 750 end
Chris@0 751
Chris@909 752 def test_new_user_from_attributes_should_return_valid_user
Chris@909 753 to_test = {
Chris@909 754 # [address, name] => [login, firstname, lastname]
Chris@909 755 ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
Chris@909 756 ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
Chris@909 757 ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
Chris@909 758 ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
Chris@909 759 ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
Chris@1115 760 ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
Chris@909 761 }
Chris@909 762
Chris@909 763 to_test.each do |attrs, expected|
Chris@909 764 user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
Chris@909 765
Chris@1115 766 assert user.valid?, user.errors.full_messages.to_s
Chris@909 767 assert_equal attrs.first, user.mail
Chris@909 768 assert_equal expected[0], user.login
Chris@909 769 assert_equal expected[1], user.firstname
Chris@909 770 assert_equal expected[2], user.lastname
Chris@1295 771 assert_equal 'only_my_events', user.mail_notification
Chris@909 772 end
Chris@909 773 end
Chris@909 774
Chris@909 775 def test_new_user_from_attributes_should_respect_minimum_password_length
Chris@909 776 with_settings :password_min_length => 15 do
Chris@909 777 user = MailHandler.new_user_from_attributes('jsmith@example.net')
Chris@909 778 assert user.valid?
Chris@909 779 assert user.password.length >= 15
Chris@909 780 end
Chris@909 781 end
Chris@1115 782
Chris@909 783 def test_new_user_from_attributes_should_use_default_login_if_invalid
Chris@1115 784 user = MailHandler.new_user_from_attributes('foo+bar@example.net')
Chris@909 785 assert user.valid?
Chris@909 786 assert user.login =~ /^user[a-f0-9]+$/
Chris@1115 787 assert_equal 'foo+bar@example.net', user.mail
Chris@1115 788 end
Chris@1115 789
Chris@1115 790 def test_new_user_with_utf8_encoded_fullname_should_be_decoded
Chris@1115 791 assert_difference 'User.count' do
Chris@1115 792 issue = submit_email(
Chris@1115 793 'fullname_of_sender_as_utf8_encoded.eml',
Chris@1115 794 :issue => {:project => 'ecookbook'},
Chris@1115 795 :unknown_user => 'create'
Chris@1115 796 )
Chris@1115 797 end
Chris@1115 798
Chris@1115 799 user = User.first(:order => 'id DESC')
Chris@1115 800 assert_equal "foo@example.org", user.mail
Chris@1115 801 str1 = "\xc3\x84\xc3\xa4"
Chris@1115 802 str2 = "\xc3\x96\xc3\xb6"
Chris@1115 803 str1.force_encoding('UTF-8') if str1.respond_to?(:force_encoding)
Chris@1115 804 str2.force_encoding('UTF-8') if str2.respond_to?(:force_encoding)
Chris@1115 805 assert_equal str1, user.firstname
Chris@1115 806 assert_equal str2, user.lastname
Chris@909 807 end
Chris@909 808
Chris@0 809 private
Chris@441 810
Chris@0 811 def submit_email(filename, options={})
Chris@0 812 raw = IO.read(File.join(FIXTURES_PATH, filename))
Chris@909 813 yield raw if block_given?
Chris@0 814 MailHandler.receive(raw, options)
Chris@0 815 end
Chris@0 816
Chris@0 817 def assert_issue_created(issue)
Chris@0 818 assert issue.is_a?(Issue)
Chris@0 819 assert !issue.new_record?
Chris@0 820 issue.reload
Chris@0 821 end
Chris@0 822 end