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