annotate .svn/pristine/ee/ee02de8ba27a6ddd79e1d7dd4cd71cc7bb5bbdac.svn-base @ 1327:287f201c2802 redmine-2.2-integration

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