##// END OF EJS Templates
code clean up MailHandlerTest unit test....
Toshi MARUYAMA -
r5439:d5b97d49c610
parent child
Show More
@@ -1,466 +1,457
1 1 # encoding: utf-8
2 2 #
3 3 # Redmine - project management software
4 4 # Copyright (C) 2006-2009 Jean-Philippe Lang
5 5 #
6 6 # This program is free software; you can redistribute it and/or
7 7 # modify it under the terms of the GNU General Public License
8 8 # as published by the Free Software Foundation; either version 2
9 9 # of the License, or (at your option) any later version.
10 10 #
11 11 # This program is distributed in the hope that it will be useful,
12 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 14 # GNU General Public License for more details.
15 15 #
16 16 # You should have received a copy of the GNU General Public License
17 17 # along with this program; if not, write to the Free Software
18 18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 19
20 20 require File.expand_path('../../test_helper', __FILE__)
21 21
22 22 class MailHandlerTest < ActiveSupport::TestCase
23 23 fixtures :users, :projects,
24 24 :enabled_modules,
25 25 :roles,
26 26 :members,
27 27 :member_roles,
28 28 :users,
29 29 :issues,
30 30 :issue_statuses,
31 31 :workflows,
32 32 :trackers,
33 33 :projects_trackers,
34 34 :versions,
35 35 :enumerations,
36 36 :issue_categories,
37 37 :custom_fields,
38 38 :custom_fields_trackers,
39 39 :custom_fields_projects,
40 40 :boards,
41 41 :messages
42 42
43 43 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
44 44
45 45 def setup
46 46 ActionMailer::Base.deliveries.clear
47 47 Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
48 48 end
49 49
50 50 def test_add_issue
51 51 ActionMailer::Base.deliveries.clear
52 52 # This email contains: 'Project: onlinestore'
53 53 issue = submit_email('ticket_on_given_project.eml')
54 54 assert issue.is_a?(Issue)
55 55 assert !issue.new_record?
56 56 issue.reload
57 57 assert_equal Project.find(2), issue.project
58 58 assert_equal issue.project.trackers.first, issue.tracker
59 59 assert_equal 'New ticket on a given project', issue.subject
60 60 assert_equal User.find_by_login('jsmith'), issue.author
61 61 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
62 62 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
63 63 assert_equal '2010-01-01', issue.start_date.to_s
64 64 assert_equal '2010-12-31', issue.due_date.to_s
65 65 assert_equal User.find_by_login('jsmith'), issue.assigned_to
66 66 assert_equal Version.find_by_name('alpha'), issue.fixed_version
67 67 assert_equal 2.5, issue.estimated_hours
68 68 assert_equal 30, issue.done_ratio
69 69 assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
70 70 # keywords should be removed from the email body
71 71 assert !issue.description.match(/^Project:/i)
72 72 assert !issue.description.match(/^Status:/i)
73 73 assert !issue.description.match(/^Start Date:/i)
74 74 # Email notification should be sent
75 75 mail = ActionMailer::Base.deliveries.last
76 76 assert_not_nil mail
77 77 assert mail.subject.include?('New ticket on a given project')
78 78 end
79 79
80 80 def test_add_issue_with_default_tracker
81 81 # This email contains: 'Project: onlinestore'
82 82 issue = submit_email('ticket_on_given_project.eml', :issue => {:tracker => 'Support request'})
83 83 assert issue.is_a?(Issue)
84 84 assert !issue.new_record?
85 85 issue.reload
86 86 assert_equal 'Support request', issue.tracker.name
87 87 end
88 88
89 89 def test_add_issue_with_status
90 90 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
91 91 issue = submit_email('ticket_on_given_project.eml')
92 92 assert issue.is_a?(Issue)
93 93 assert !issue.new_record?
94 94 issue.reload
95 95 assert_equal Project.find(2), issue.project
96 96 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
97 97 end
98 98
99 99 def test_add_issue_with_attributes_override
100 100 issue = submit_email('ticket_with_attributes.eml', :allow_override => 'tracker,category,priority')
101 101 assert issue.is_a?(Issue)
102 102 assert !issue.new_record?
103 103 issue.reload
104 104 assert_equal 'New ticket on a given project', issue.subject
105 105 assert_equal User.find_by_login('jsmith'), issue.author
106 106 assert_equal Project.find(2), issue.project
107 107 assert_equal 'Feature request', issue.tracker.to_s
108 108 assert_equal 'Stock management', issue.category.to_s
109 109 assert_equal 'Urgent', issue.priority.to_s
110 110 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
111 111 end
112 112
113 113 def test_add_issue_with_partial_attributes_override
114 114 issue = submit_email('ticket_with_attributes.eml', :issue => {:priority => 'High'}, :allow_override => ['tracker'])
115 115 assert issue.is_a?(Issue)
116 116 assert !issue.new_record?
117 117 issue.reload
118 118 assert_equal 'New ticket on a given project', issue.subject
119 119 assert_equal User.find_by_login('jsmith'), issue.author
120 120 assert_equal Project.find(2), issue.project
121 121 assert_equal 'Feature request', issue.tracker.to_s
122 122 assert_nil issue.category
123 123 assert_equal 'High', issue.priority.to_s
124 124 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
125 125 end
126 126
127 127 def test_add_issue_with_spaces_between_attribute_and_separator
128 128 issue = submit_email('ticket_with_spaces_between_attribute_and_separator.eml', :allow_override => 'tracker,category,priority')
129 129 assert issue.is_a?(Issue)
130 130 assert !issue.new_record?
131 131 issue.reload
132 132 assert_equal 'New ticket on a given project', issue.subject
133 133 assert_equal User.find_by_login('jsmith'), issue.author
134 134 assert_equal Project.find(2), issue.project
135 135 assert_equal 'Feature request', issue.tracker.to_s
136 136 assert_equal 'Stock management', issue.category.to_s
137 137 assert_equal 'Urgent', issue.priority.to_s
138 138 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
139 139 end
140 140
141
142 141 def test_add_issue_with_attachment_to_specific_project
143 142 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
144 143 assert issue.is_a?(Issue)
145 144 assert !issue.new_record?
146 145 issue.reload
147 146 assert_equal 'Ticket created by email with attachment', issue.subject
148 147 assert_equal User.find_by_login('jsmith'), issue.author
149 148 assert_equal Project.find(2), issue.project
150 149 assert_equal 'This is a new ticket with attachments', issue.description
151 150 # Attachment properties
152 151 assert_equal 1, issue.attachments.size
153 152 assert_equal 'Paella.jpg', issue.attachments.first.filename
154 153 assert_equal 'image/jpeg', issue.attachments.first.content_type
155 154 assert_equal 10790, issue.attachments.first.filesize
156 155 end
157 156
158 157 def test_add_issue_with_custom_fields
159 158 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'})
160 159 assert issue.is_a?(Issue)
161 160 assert !issue.new_record?
162 161 issue.reload
163 162 assert_equal 'New ticket with custom field values', issue.subject
164 163 assert_equal 'Value for a custom field', issue.custom_value_for(CustomField.find_by_name('Searchable field')).value
165 164 assert !issue.description.match(/^searchable field:/i)
166 165 end
167 166
168 167 def test_add_issue_with_cc
169 168 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
170 169 assert issue.is_a?(Issue)
171 170 assert !issue.new_record?
172 171 issue.reload
173 172 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
174 173 assert_equal 1, issue.watcher_user_ids.size
175 174 end
176 175
177 176 def test_add_issue_by_unknown_user
178 177 assert_no_difference 'User.count' do
179 178 assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'})
180 179 end
181 180 end
182 181
183 182 def test_add_issue_by_anonymous_user
184 183 Role.anonymous.add_permission!(:add_issues)
185 184 assert_no_difference 'User.count' do
186 185 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
187 186 assert issue.is_a?(Issue)
188 187 assert issue.author.anonymous?
189 188 end
190 189 end
191 190
192 191 def test_add_issue_by_anonymous_user_with_no_from_address
193 192 Role.anonymous.add_permission!(:add_issues)
194 193 assert_no_difference 'User.count' do
195 194 issue = submit_email('ticket_by_empty_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
196 195 assert issue.is_a?(Issue)
197 196 assert issue.author.anonymous?
198 197 end
199 198 end
200 199
201 200 def test_add_issue_by_anonymous_user_on_private_project
202 201 Role.anonymous.add_permission!(:add_issues)
203 202 assert_no_difference 'User.count' do
204 203 assert_no_difference 'Issue.count' do
205 204 assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :unknown_user => 'accept')
206 205 end
207 206 end
208 207 end
209 208
210 209 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
211 210 assert_no_difference 'User.count' do
212 211 assert_difference 'Issue.count' do
213 212 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :no_permission_check => '1', :unknown_user => 'accept')
214 213 assert issue.is_a?(Issue)
215 214 assert issue.author.anonymous?
216 215 assert !issue.project.is_public?
217 216 assert_equal [issue.id, 1, 2], [issue.root_id, issue.lft, issue.rgt]
218 217 end
219 218 end
220 219 end
221 220
222 221 def test_add_issue_by_created_user
223 222 Setting.default_language = 'en'
224 223 assert_difference 'User.count' do
225 224 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create')
226 225 assert issue.is_a?(Issue)
227 226 assert issue.author.active?
228 227 assert_equal 'john.doe@somenet.foo', issue.author.mail
229 228 assert_equal 'John', issue.author.firstname
230 229 assert_equal 'Doe', issue.author.lastname
231 230
232 231 # account information
233 232 email = ActionMailer::Base.deliveries.first
234 233 assert_not_nil email
235 234 assert email.subject.include?('account activation')
236 235 login = email.body.match(/\* Login: (.*)$/)[1]
237 236 password = email.body.match(/\* Password: (.*)$/)[1]
238 237 assert_equal issue.author, User.try_to_login(login, password)
239 238 end
240 239 end
241 240
242 241 def test_add_issue_without_from_header
243 242 Role.anonymous.add_permission!(:add_issues)
244 243 assert_equal false, submit_email('ticket_without_from_header.eml')
245 244 end
246 245
247 246 def test_add_issue_with_invalid_attributes
248 247 issue = submit_email('ticket_with_invalid_attributes.eml', :allow_override => 'tracker,category,priority')
249 248 assert issue.is_a?(Issue)
250 249 assert !issue.new_record?
251 250 issue.reload
252 251 assert_nil issue.assigned_to
253 252 assert_nil issue.start_date
254 253 assert_nil issue.due_date
255 254 assert_equal 0, issue.done_ratio
256 255 assert_equal 'Normal', issue.priority.to_s
257 256 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
258 257 end
259 258
260 259 def test_add_issue_with_localized_attributes
261 260 User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
262 261 issue = submit_email('ticket_with_localized_attributes.eml', :allow_override => 'tracker,category,priority')
263 262 assert issue.is_a?(Issue)
264 263 assert !issue.new_record?
265 264 issue.reload
266 265 assert_equal 'New ticket on a given project', issue.subject
267 266 assert_equal User.find_by_login('jsmith'), issue.author
268 267 assert_equal Project.find(2), issue.project
269 268 assert_equal 'Feature request', issue.tracker.to_s
270 269 assert_equal 'Stock management', issue.category.to_s
271 270 assert_equal 'Urgent', issue.priority.to_s
272 271 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
273 272 end
274 273
275 274 def test_add_issue_with_japanese_keywords
276 275 tracker = Tracker.create!(:name => 'ι–‹η™Ί')
277 276 Project.find(1).trackers << tracker
278 277 issue = submit_email('japanese_keywords_iso_2022_jp.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'tracker')
279 278 assert_kind_of Issue, issue
280 279 assert_equal tracker, issue.tracker
281 280 end
282 281
283 282 def test_should_ignore_emails_from_emission_address
284 283 Role.anonymous.add_permission!(:add_issues)
285 284 assert_no_difference 'User.count' do
286 285 assert_equal false, submit_email('ticket_from_emission_address.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create')
287 286 end
288 287 end
289 288
290 289 def test_add_issue_should_send_email_notification
291 290 Setting.notified_events = ['issue_added']
292 291 ActionMailer::Base.deliveries.clear
293 292 # This email contains: 'Project: onlinestore'
294 293 issue = submit_email('ticket_on_given_project.eml')
295 294 assert issue.is_a?(Issue)
296 295 assert_equal 1, ActionMailer::Base.deliveries.size
297 296 end
298 297
299 298 def test_add_issue_note
300 299 journal = submit_email('ticket_reply.eml')
301 300 assert journal.is_a?(Journal)
302 301 assert_equal User.find_by_login('jsmith'), journal.user
303 302 assert_equal Issue.find(2), journal.journalized
304 303 assert_match /This is reply/, journal.notes
305 304 assert_equal 'Feature request', journal.issue.tracker.name
306 305 end
307 306
308 307 def test_add_issue_note_with_attribute_changes
309 308 # This email contains: 'Status: Resolved'
310 309 journal = submit_email('ticket_reply_with_status.eml')
311 310 assert journal.is_a?(Journal)
312 311 issue = Issue.find(journal.issue.id)
313 312 assert_equal User.find_by_login('jsmith'), journal.user
314 313 assert_equal Issue.find(2), journal.journalized
315 314 assert_match /This is reply/, journal.notes
316 315 assert_equal 'Feature request', journal.issue.tracker.name
317 316 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
318 317 assert_equal '2010-01-01', issue.start_date.to_s
319 318 assert_equal '2010-12-31', issue.due_date.to_s
320 319 assert_equal User.find_by_login('jsmith'), issue.assigned_to
321 320 assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
322 321 # keywords should be removed from the email body
323 322 assert !journal.notes.match(/^Status:/i)
324 323 assert !journal.notes.match(/^Start Date:/i)
325 324 end
326 325
327 326 def test_add_issue_note_should_send_email_notification
328 327 ActionMailer::Base.deliveries.clear
329 328 journal = submit_email('ticket_reply.eml')
330 329 assert journal.is_a?(Journal)
331 330 assert_equal 1, ActionMailer::Base.deliveries.size
332 331 end
333 332
334 333 def test_add_issue_note_should_not_set_defaults
335 334 journal = submit_email('ticket_reply.eml', :issue => {:tracker => 'Support request', :priority => 'High'})
336 335 assert journal.is_a?(Journal)
337 336 assert_match /This is reply/, journal.notes
338 337 assert_equal 'Feature request', journal.issue.tracker.name
339 338 assert_equal 'Normal', journal.issue.priority.name
340 339 end
341 340
342 341 def test_reply_to_a_message
343 342 m = submit_email('message_reply.eml')
344 343 assert m.is_a?(Message)
345 344 assert !m.new_record?
346 345 m.reload
347 346 assert_equal 'Reply via email', m.subject
348 347 # The email replies to message #2 which is part of the thread of message #1
349 348 assert_equal Message.find(1), m.parent
350 349 end
351 350
352 351 def test_reply_to_a_message_by_subject
353 352 m = submit_email('message_reply_by_subject.eml')
354 353 assert m.is_a?(Message)
355 354 assert !m.new_record?
356 355 m.reload
357 356 assert_equal 'Reply to the first post', m.subject
358 357 assert_equal Message.find(1), m.parent
359 358 end
360 359
361 360 def test_should_strip_tags_of_html_only_emails
362 361 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
363 362 assert issue.is_a?(Issue)
364 363 assert !issue.new_record?
365 364 issue.reload
366 365 assert_equal 'HTML email', issue.subject
367 366 assert_equal 'This is a html-only email.', issue.description
368 367 end
369 368
370 369 context "truncate emails based on the Setting" do
371 370 context "with no setting" do
372 371 setup do
373 372 Setting.mail_handler_body_delimiters = ''
374 373 end
375 374
376 375 should "add the entire email into the issue" do
377 376 issue = submit_email('ticket_on_given_project.eml')
378 377 assert_issue_created(issue)
379 378 assert issue.description.include?('---')
380 379 assert issue.description.include?('This paragraph is after the delimiter')
381 380 end
382 381 end
383 382
384 383 context "with a single string" do
385 384 setup do
386 385 Setting.mail_handler_body_delimiters = '---'
387 386 end
388
389 387 should "truncate the email at the delimiter for the issue" do
390 388 issue = submit_email('ticket_on_given_project.eml')
391 389 assert_issue_created(issue)
392 390 assert issue.description.include?('This paragraph is before delimiters')
393 391 assert issue.description.include?('--- This line starts with a delimiter')
394 392 assert !issue.description.match(/^---$/)
395 393 assert !issue.description.include?('This paragraph is after the delimiter')
396 394 end
397 395 end
398 396
399 397 context "with a single quoted reply (e.g. reply to a Redmine email notification)" do
400 398 setup do
401 399 Setting.mail_handler_body_delimiters = '--- Reply above. Do not remove this line. ---'
402 400 end
403
404 401 should "truncate the email at the delimiter with the quoted reply symbols (>)" do
405 402 journal = submit_email('issue_update_with_quoted_reply_above.eml')
406 403 assert journal.is_a?(Journal)
407 404 assert journal.notes.include?('An update to the issue by the sender.')
408 405 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
409 406 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
410
411 407 end
412
413 408 end
414 409
415 410 context "with multiple quoted replies (e.g. reply to a reply of a Redmine email notification)" do
416 411 setup do
417 412 Setting.mail_handler_body_delimiters = '--- Reply above. Do not remove this line. ---'
418 413 end
419
420 414 should "truncate the email at the delimiter with the quoted reply symbols (>)" do
421 415 journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
422 416 assert journal.is_a?(Journal)
423 417 assert journal.notes.include?('An update to the issue by the sender.')
424 418 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
425 419 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
426
427 420 end
428
429 421 end
430 422
431 423 context "with multiple strings" do
432 424 setup do
433 425 Setting.mail_handler_body_delimiters = "---\nBREAK"
434 426 end
435
436 427 should "truncate the email at the first delimiter found (BREAK)" do
437 428 issue = submit_email('ticket_on_given_project.eml')
438 429 assert_issue_created(issue)
439 430 assert issue.description.include?('This paragraph is before delimiters')
440 431 assert !issue.description.include?('BREAK')
441 432 assert !issue.description.include?('This paragraph is between delimiters')
442 433 assert !issue.description.match(/^---$/)
443 434 assert !issue.description.include?('This paragraph is after the delimiter')
444 435 end
445 436 end
446 437 end
447 438
448 439 def test_email_with_long_subject_line
449 440 issue = submit_email('ticket_with_long_subject.eml')
450 441 assert issue.is_a?(Issue)
451 442 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]
452 443 end
453 444
454 445 private
455 446
456 447 def submit_email(filename, options={})
457 448 raw = IO.read(File.join(FIXTURES_PATH, filename))
458 449 MailHandler.receive(raw, options)
459 450 end
460 451
461 452 def assert_issue_created(issue)
462 453 assert issue.is_a?(Issue)
463 454 assert !issue.new_record?
464 455 issue.reload
465 456 end
466 457 end
General Comments 0
You need to be logged in to leave comments. Login now