comparison test/unit/.svn/text-base/mail_handler_test.rb.svn-base @ 0:513646585e45

* Import Redmine trunk SVN rev 3859
author Chris Cannam
date Fri, 23 Jul 2010 15:52:44 +0100
parents
children 94944d00e43c
comparison
equal deleted inserted replaced
-1:000000000000 0:513646585e45
1 # encoding: utf-8
2 #
3 # Redmine - project management software
4 # Copyright (C) 2006-2009 Jean-Philippe Lang
5 #
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
20 require File.dirname(__FILE__) + '/../test_helper'
21
22 class MailHandlerTest < ActiveSupport::TestCase
23 fixtures :users, :projects,
24 :enabled_modules,
25 :roles,
26 :members,
27 :member_roles,
28 :issues,
29 :issue_statuses,
30 :workflows,
31 :trackers,
32 :projects_trackers,
33 :enumerations,
34 :issue_categories,
35 :custom_fields,
36 :custom_fields_trackers,
37 :boards,
38 :messages
39
40 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
41
42 def setup
43 ActionMailer::Base.deliveries.clear
44 end
45
46 def test_add_issue
47 ActionMailer::Base.deliveries.clear
48 # This email contains: 'Project: onlinestore'
49 issue = submit_email('ticket_on_given_project.eml')
50 assert issue.is_a?(Issue)
51 assert !issue.new_record?
52 issue.reload
53 assert_equal 'New ticket on a given project', issue.subject
54 assert_equal User.find_by_login('jsmith'), issue.author
55 assert_equal Project.find(2), issue.project
56 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
57 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
58 assert_equal '2010-01-01', issue.start_date.to_s
59 assert_equal '2010-12-31', issue.due_date.to_s
60 assert_equal User.find_by_login('jsmith'), issue.assigned_to
61 # keywords should be removed from the email body
62 assert !issue.description.match(/^Project:/i)
63 assert !issue.description.match(/^Status:/i)
64 # Email notification should be sent
65 mail = ActionMailer::Base.deliveries.last
66 assert_not_nil mail
67 assert mail.subject.include?('New ticket on a given project')
68 end
69
70 def test_add_issue_with_status
71 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
72 issue = submit_email('ticket_on_given_project.eml')
73 assert issue.is_a?(Issue)
74 assert !issue.new_record?
75 issue.reload
76 assert_equal Project.find(2), issue.project
77 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
78 end
79
80 def test_add_issue_with_attributes_override
81 issue = submit_email('ticket_with_attributes.eml', :allow_override => 'tracker,category,priority')
82 assert issue.is_a?(Issue)
83 assert !issue.new_record?
84 issue.reload
85 assert_equal 'New ticket on a given project', issue.subject
86 assert_equal User.find_by_login('jsmith'), issue.author
87 assert_equal Project.find(2), issue.project
88 assert_equal 'Feature request', issue.tracker.to_s
89 assert_equal 'Stock management', issue.category.to_s
90 assert_equal 'Urgent', issue.priority.to_s
91 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
92 end
93
94 def test_add_issue_with_partial_attributes_override
95 issue = submit_email('ticket_with_attributes.eml', :issue => {:priority => 'High'}, :allow_override => ['tracker'])
96 assert issue.is_a?(Issue)
97 assert !issue.new_record?
98 issue.reload
99 assert_equal 'New ticket on a given project', issue.subject
100 assert_equal User.find_by_login('jsmith'), issue.author
101 assert_equal Project.find(2), issue.project
102 assert_equal 'Feature request', issue.tracker.to_s
103 assert_nil issue.category
104 assert_equal 'High', issue.priority.to_s
105 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
106 end
107
108 def test_add_issue_with_spaces_between_attribute_and_separator
109 issue = submit_email('ticket_with_spaces_between_attribute_and_separator.eml', :allow_override => 'tracker,category,priority')
110 assert issue.is_a?(Issue)
111 assert !issue.new_record?
112 issue.reload
113 assert_equal 'New ticket on a given project', issue.subject
114 assert_equal User.find_by_login('jsmith'), issue.author
115 assert_equal Project.find(2), issue.project
116 assert_equal 'Feature request', issue.tracker.to_s
117 assert_equal 'Stock management', issue.category.to_s
118 assert_equal 'Urgent', issue.priority.to_s
119 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
120 end
121
122
123 def test_add_issue_with_attachment_to_specific_project
124 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
125 assert issue.is_a?(Issue)
126 assert !issue.new_record?
127 issue.reload
128 assert_equal 'Ticket created by email with attachment', issue.subject
129 assert_equal User.find_by_login('jsmith'), issue.author
130 assert_equal Project.find(2), issue.project
131 assert_equal 'This is a new ticket with attachments', issue.description
132 # Attachment properties
133 assert_equal 1, issue.attachments.size
134 assert_equal 'Paella.jpg', issue.attachments.first.filename
135 assert_equal 'image/jpeg', issue.attachments.first.content_type
136 assert_equal 10790, issue.attachments.first.filesize
137 end
138
139 def test_add_issue_with_custom_fields
140 issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'})
141 assert issue.is_a?(Issue)
142 assert !issue.new_record?
143 issue.reload
144 assert_equal 'New ticket with custom field values', issue.subject
145 assert_equal 'Value for a custom field', issue.custom_value_for(CustomField.find_by_name('Searchable field')).value
146 assert !issue.description.match(/^searchable field:/i)
147 end
148
149 def test_add_issue_with_cc
150 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
151 assert issue.is_a?(Issue)
152 assert !issue.new_record?
153 issue.reload
154 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
155 assert_equal 1, issue.watchers.size
156 end
157
158 def test_add_issue_by_unknown_user
159 assert_no_difference 'User.count' do
160 assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'})
161 end
162 end
163
164 def test_add_issue_by_anonymous_user
165 Role.anonymous.add_permission!(:add_issues)
166 assert_no_difference 'User.count' do
167 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
168 assert issue.is_a?(Issue)
169 assert issue.author.anonymous?
170 end
171 end
172
173 def test_add_issue_by_anonymous_user_with_no_from_address
174 Role.anonymous.add_permission!(:add_issues)
175 assert_no_difference 'User.count' do
176 issue = submit_email('ticket_by_empty_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept')
177 assert issue.is_a?(Issue)
178 assert issue.author.anonymous?
179 end
180 end
181
182 def test_add_issue_by_anonymous_user_on_private_project
183 Role.anonymous.add_permission!(:add_issues)
184 assert_no_difference 'User.count' do
185 assert_no_difference 'Issue.count' do
186 assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :unknown_user => 'accept')
187 end
188 end
189 end
190
191 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
192 assert_no_difference 'User.count' do
193 assert_difference 'Issue.count' do
194 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :no_permission_check => '1', :unknown_user => 'accept')
195 assert issue.is_a?(Issue)
196 assert issue.author.anonymous?
197 assert !issue.project.is_public?
198 end
199 end
200 end
201
202 def test_add_issue_by_created_user
203 Setting.default_language = 'en'
204 assert_difference 'User.count' do
205 issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create')
206 assert issue.is_a?(Issue)
207 assert issue.author.active?
208 assert_equal 'john.doe@somenet.foo', issue.author.mail
209 assert_equal 'John', issue.author.firstname
210 assert_equal 'Doe', issue.author.lastname
211
212 # account information
213 email = ActionMailer::Base.deliveries.first
214 assert_not_nil email
215 assert email.subject.include?('account activation')
216 login = email.body.match(/\* Login: (.*)$/)[1]
217 password = email.body.match(/\* Password: (.*)$/)[1]
218 assert_equal issue.author, User.try_to_login(login, password)
219 end
220 end
221
222 def test_add_issue_without_from_header
223 Role.anonymous.add_permission!(:add_issues)
224 assert_equal false, submit_email('ticket_without_from_header.eml')
225 end
226
227 def test_add_issue_with_japanese_keywords
228 tracker = Tracker.create!(:name => '開発')
229 Project.find(1).trackers << tracker
230 issue = submit_email('japanese_keywords_iso_2022_jp.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'tracker')
231 assert_kind_of Issue, issue
232 assert_equal tracker, issue.tracker
233 end
234
235 def test_should_ignore_emails_from_emission_address
236 Role.anonymous.add_permission!(:add_issues)
237 assert_no_difference 'User.count' do
238 assert_equal false, submit_email('ticket_from_emission_address.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create')
239 end
240 end
241
242 def test_add_issue_should_send_email_notification
243 ActionMailer::Base.deliveries.clear
244 # This email contains: 'Project: onlinestore'
245 issue = submit_email('ticket_on_given_project.eml')
246 assert issue.is_a?(Issue)
247 assert_equal 1, ActionMailer::Base.deliveries.size
248 end
249
250 def test_add_issue_note
251 journal = submit_email('ticket_reply.eml')
252 assert journal.is_a?(Journal)
253 assert_equal User.find_by_login('jsmith'), journal.user
254 assert_equal Issue.find(2), journal.journalized
255 assert_match /This is reply/, journal.notes
256 end
257
258 def test_add_issue_note_with_attribute_changes
259 # This email contains: 'Status: Resolved'
260 journal = submit_email('ticket_reply_with_status.eml')
261 assert journal.is_a?(Journal)
262 issue = Issue.find(journal.issue.id)
263 assert_equal User.find_by_login('jsmith'), journal.user
264 assert_equal Issue.find(2), journal.journalized
265 assert_match /This is reply/, journal.notes
266 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
267 assert_equal '2010-01-01', issue.start_date.to_s
268 assert_equal '2010-12-31', issue.due_date.to_s
269 assert_equal User.find_by_login('jsmith'), issue.assigned_to
270 end
271
272 def test_add_issue_note_should_send_email_notification
273 ActionMailer::Base.deliveries.clear
274 journal = submit_email('ticket_reply.eml')
275 assert journal.is_a?(Journal)
276 assert_equal 1, ActionMailer::Base.deliveries.size
277 end
278
279 def test_reply_to_a_message
280 m = submit_email('message_reply.eml')
281 assert m.is_a?(Message)
282 assert !m.new_record?
283 m.reload
284 assert_equal 'Reply via email', m.subject
285 # The email replies to message #2 which is part of the thread of message #1
286 assert_equal Message.find(1), m.parent
287 end
288
289 def test_reply_to_a_message_by_subject
290 m = submit_email('message_reply_by_subject.eml')
291 assert m.is_a?(Message)
292 assert !m.new_record?
293 m.reload
294 assert_equal 'Reply to the first post', m.subject
295 assert_equal Message.find(1), m.parent
296 end
297
298 def test_should_strip_tags_of_html_only_emails
299 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
300 assert issue.is_a?(Issue)
301 assert !issue.new_record?
302 issue.reload
303 assert_equal 'HTML email', issue.subject
304 assert_equal 'This is a html-only email.', issue.description
305 end
306
307 context "truncate emails based on the Setting" do
308 context "with no setting" do
309 setup do
310 Setting.mail_handler_body_delimiters = ''
311 end
312
313 should "add the entire email into the issue" do
314 issue = submit_email('ticket_on_given_project.eml')
315 assert_issue_created(issue)
316 assert issue.description.include?('---')
317 assert issue.description.include?('This paragraph is after the delimiter')
318 end
319 end
320
321 context "with a single string" do
322 setup do
323 Setting.mail_handler_body_delimiters = '---'
324 end
325
326 should "truncate the email at the delimiter for the issue" do
327 issue = submit_email('ticket_on_given_project.eml')
328 assert_issue_created(issue)
329 assert issue.description.include?('This paragraph is before delimiters')
330 assert issue.description.include?('--- This line starts with a delimiter')
331 assert !issue.description.match(/^---$/)
332 assert !issue.description.include?('This paragraph is after the delimiter')
333 end
334 end
335
336 context "with multiple strings" do
337 setup do
338 Setting.mail_handler_body_delimiters = "---\nBREAK"
339 end
340
341 should "truncate the email at the first delimiter found (BREAK)" do
342 issue = submit_email('ticket_on_given_project.eml')
343 assert_issue_created(issue)
344 assert issue.description.include?('This paragraph is before delimiters')
345 assert !issue.description.include?('BREAK')
346 assert !issue.description.include?('This paragraph is between delimiters')
347 assert !issue.description.match(/^---$/)
348 assert !issue.description.include?('This paragraph is after the delimiter')
349 end
350 end
351 end
352
353 def test_email_with_long_subject_line
354 issue = submit_email('ticket_with_long_subject.eml')
355 assert issue.is_a?(Issue)
356 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]
357 end
358
359 private
360
361 def submit_email(filename, options={})
362 raw = IO.read(File.join(FIXTURES_PATH, filename))
363 MailHandler.receive(raw, options)
364 end
365
366 def assert_issue_created(issue)
367 assert issue.is_a?(Issue)
368 assert !issue.new_record?
369 issue.reload
370 end
371 end