##// END OF EJS Templates
Merged r15609 (#23278)....
Jean-Philippe Lang -
r15255:f2317792524b
parent child
Show More
@@ -1,88 +1,92
1 # ActsAsWatchable
1 # ActsAsWatchable
2 module Redmine
2 module Redmine
3 module Acts
3 module Acts
4 module Watchable
4 module Watchable
5 def self.included(base)
5 def self.included(base)
6 base.extend ClassMethods
6 base.extend ClassMethods
7 end
7 end
8
8
9 module ClassMethods
9 module ClassMethods
10 def acts_as_watchable(options = {})
10 def acts_as_watchable(options = {})
11 return if self.included_modules.include?(Redmine::Acts::Watchable::InstanceMethods)
11 return if self.included_modules.include?(Redmine::Acts::Watchable::InstanceMethods)
12 class_eval do
12 class_eval do
13 has_many :watchers, :as => :watchable, :dependent => :delete_all
13 has_many :watchers, :as => :watchable, :dependent => :delete_all
14 has_many :watcher_users, :through => :watchers, :source => :user, :validate => false
14 has_many :watcher_users, :through => :watchers, :source => :user, :validate => false
15
15
16 scope :watched_by, lambda { |user_id|
16 scope :watched_by, lambda { |user_id|
17 joins(:watchers).
17 joins(:watchers).
18 where("#{Watcher.table_name}.user_id = ?", user_id)
18 where("#{Watcher.table_name}.user_id = ?", user_id)
19 }
19 }
20 attr_protected :watcher_ids, :watcher_user_ids
20 attr_protected :watcher_ids, :watcher_user_ids
21 end
21 end
22 send :include, Redmine::Acts::Watchable::InstanceMethods
22 send :include, Redmine::Acts::Watchable::InstanceMethods
23 alias_method_chain :watcher_user_ids=, :uniq_ids
23 alias_method_chain :watcher_user_ids=, :uniq_ids
24 end
24 end
25 end
25 end
26
26
27 module InstanceMethods
27 module InstanceMethods
28 def self.included(base)
28 def self.included(base)
29 base.extend ClassMethods
29 base.extend ClassMethods
30 end
30 end
31
31
32 # Returns an array of users that are proposed as watchers
32 # Returns an array of users that are proposed as watchers
33 def addable_watcher_users
33 def addable_watcher_users
34 users = self.project.users.sort - self.watcher_users
34 users = self.project.users.sort - self.watcher_users
35 if respond_to?(:visible?)
35 if respond_to?(:visible?)
36 users.reject! {|user| !visible?(user)}
36 users.reject! {|user| !visible?(user)}
37 end
37 end
38 users
38 users
39 end
39 end
40
40
41 # Adds user as a watcher
41 # Adds user as a watcher
42 def add_watcher(user)
42 def add_watcher(user)
43 # Rails does not reset the has_many :through association
44 watcher_users.reset
43 self.watchers << Watcher.new(:user => user)
45 self.watchers << Watcher.new(:user => user)
44 end
46 end
45
47
46 # Removes user from the watchers list
48 # Removes user from the watchers list
47 def remove_watcher(user)
49 def remove_watcher(user)
48 return nil unless user && user.is_a?(User)
50 return nil unless user && user.is_a?(User)
51 # Rails does not reset the has_many :through association
52 watcher_users.reset
49 watchers.where(:user_id => user.id).delete_all
53 watchers.where(:user_id => user.id).delete_all
50 end
54 end
51
55
52 # Adds/removes watcher
56 # Adds/removes watcher
53 def set_watcher(user, watching=true)
57 def set_watcher(user, watching=true)
54 watching ? add_watcher(user) : remove_watcher(user)
58 watching ? add_watcher(user) : remove_watcher(user)
55 end
59 end
56
60
57 # Overrides watcher_user_ids= to make user_ids uniq
61 # Overrides watcher_user_ids= to make user_ids uniq
58 def watcher_user_ids_with_uniq_ids=(user_ids)
62 def watcher_user_ids_with_uniq_ids=(user_ids)
59 if user_ids.is_a?(Array)
63 if user_ids.is_a?(Array)
60 user_ids = user_ids.uniq
64 user_ids = user_ids.uniq
61 end
65 end
62 send :watcher_user_ids_without_uniq_ids=, user_ids
66 send :watcher_user_ids_without_uniq_ids=, user_ids
63 end
67 end
64
68
65 # Returns true if object is watched by +user+
69 # Returns true if object is watched by +user+
66 def watched_by?(user)
70 def watched_by?(user)
67 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
71 !!(user && self.watcher_user_ids.detect {|uid| uid == user.id })
68 end
72 end
69
73
70 def notified_watchers
74 def notified_watchers
71 notified = watcher_users.active.to_a
75 notified = watcher_users.active.to_a
72 notified.reject! {|user| user.mail.blank? || user.mail_notification == 'none'}
76 notified.reject! {|user| user.mail.blank? || user.mail_notification == 'none'}
73 if respond_to?(:visible?)
77 if respond_to?(:visible?)
74 notified.reject! {|user| !visible?(user)}
78 notified.reject! {|user| !visible?(user)}
75 end
79 end
76 notified
80 notified
77 end
81 end
78
82
79 # Returns an array of watchers' email addresses
83 # Returns an array of watchers' email addresses
80 def watcher_recipients
84 def watcher_recipients
81 notified_watchers.collect(&:mail)
85 notified_watchers.collect(&:mail)
82 end
86 end
83
87
84 module ClassMethods; end
88 module ClassMethods; end
85 end
89 end
86 end
90 end
87 end
91 end
88 end
92 end
@@ -1,1095 +1,1096
1 # encoding: utf-8
1 # encoding: utf-8
2 #
2 #
3 # Redmine - project management software
3 # Redmine - project management software
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
4 # Copyright (C) 2006-2016 Jean-Philippe Lang
5 #
5 #
6 # This program is free software; you can redistribute it and/or
6 # This program is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU General Public License
7 # modify it under the terms of the GNU General Public License
8 # as published by the Free Software Foundation; either version 2
8 # as published by the Free Software Foundation; either version 2
9 # of the License, or (at your option) any later version.
9 # of the License, or (at your option) any later version.
10 #
10 #
11 # This program is distributed in the hope that it will be useful,
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
14 # GNU General Public License for more details.
15 #
15 #
16 # You should have received a copy of the GNU General Public License
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
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.
18 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
19
20 require File.expand_path('../../test_helper', __FILE__)
20 require File.expand_path('../../test_helper', __FILE__)
21
21
22 class MailHandlerTest < ActiveSupport::TestCase
22 class MailHandlerTest < ActiveSupport::TestCase
23 fixtures :users, :projects, :enabled_modules, :roles,
23 fixtures :users, :projects, :enabled_modules, :roles,
24 :members, :member_roles, :users,
24 :members, :member_roles, :users,
25 :email_addresses, :user_preferences,
25 :email_addresses, :user_preferences,
26 :issues, :issue_statuses,
26 :issues, :issue_statuses,
27 :workflows, :trackers, :projects_trackers,
27 :workflows, :trackers, :projects_trackers,
28 :versions, :enumerations, :issue_categories,
28 :versions, :enumerations, :issue_categories,
29 :custom_fields, :custom_fields_trackers, :custom_fields_projects,
29 :custom_fields, :custom_fields_trackers, :custom_fields_projects,
30 :boards, :messages
30 :boards, :messages
31
31
32 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
32 FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler'
33
33
34 def setup
34 def setup
35 ActionMailer::Base.deliveries.clear
35 ActionMailer::Base.deliveries.clear
36 Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
36 Setting.notified_events = Redmine::Notifiable.all.collect(&:name)
37 end
37 end
38
38
39 def teardown
39 def teardown
40 Setting.clear_cache
40 Setting.clear_cache
41 end
41 end
42
42
43 def test_add_issue_with_specific_overrides
43 def test_add_issue_with_specific_overrides
44 issue = submit_email('ticket_on_given_project.eml',
44 issue = submit_email('ticket_on_given_project.eml',
45 :allow_override => ['status', 'start_date', 'due_date', 'assigned_to', 'fixed_version', 'estimated_hours', 'done_ratio']
45 :allow_override => ['status', 'start_date', 'due_date', 'assigned_to', 'fixed_version', 'estimated_hours', 'done_ratio']
46 )
46 )
47 assert issue.is_a?(Issue)
47 assert issue.is_a?(Issue)
48 assert !issue.new_record?
48 assert !issue.new_record?
49 issue.reload
49 issue.reload
50 assert_equal Project.find(2), issue.project
50 assert_equal Project.find(2), issue.project
51 assert_equal issue.project.trackers.first, issue.tracker
51 assert_equal issue.project.trackers.first, issue.tracker
52 assert_equal 'New ticket on a given project', issue.subject
52 assert_equal 'New ticket on a given project', issue.subject
53 assert_equal User.find_by_login('jsmith'), issue.author
53 assert_equal User.find_by_login('jsmith'), issue.author
54 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
54 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
55 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
55 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
56 assert_equal '2010-01-01', issue.start_date.to_s
56 assert_equal '2010-01-01', issue.start_date.to_s
57 assert_equal '2010-12-31', issue.due_date.to_s
57 assert_equal '2010-12-31', issue.due_date.to_s
58 assert_equal User.find_by_login('jsmith'), issue.assigned_to
58 assert_equal User.find_by_login('jsmith'), issue.assigned_to
59 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
59 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
60 assert_equal 2.5, issue.estimated_hours
60 assert_equal 2.5, issue.estimated_hours
61 assert_equal 30, issue.done_ratio
61 assert_equal 30, issue.done_ratio
62 # keywords should be removed from the email body
62 # keywords should be removed from the email body
63 assert !issue.description.match(/^Project:/i)
63 assert !issue.description.match(/^Project:/i)
64 assert !issue.description.match(/^Status:/i)
64 assert !issue.description.match(/^Status:/i)
65 assert !issue.description.match(/^Start Date:/i)
65 assert !issue.description.match(/^Start Date:/i)
66 end
66 end
67
67
68 def test_add_issue_with_all_overrides
68 def test_add_issue_with_all_overrides
69 issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
69 issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
70 assert issue.is_a?(Issue)
70 assert issue.is_a?(Issue)
71 assert !issue.new_record?
71 assert !issue.new_record?
72 issue.reload
72 issue.reload
73 assert_equal Project.find(2), issue.project
73 assert_equal Project.find(2), issue.project
74 assert_equal issue.project.trackers.first, issue.tracker
74 assert_equal issue.project.trackers.first, issue.tracker
75 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
75 assert_equal IssueStatus.find_by_name('Resolved'), issue.status
76 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
76 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
77 assert_equal '2010-01-01', issue.start_date.to_s
77 assert_equal '2010-01-01', issue.start_date.to_s
78 assert_equal '2010-12-31', issue.due_date.to_s
78 assert_equal '2010-12-31', issue.due_date.to_s
79 assert_equal User.find_by_login('jsmith'), issue.assigned_to
79 assert_equal User.find_by_login('jsmith'), issue.assigned_to
80 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
80 assert_equal Version.find_by_name('Alpha'), issue.fixed_version
81 assert_equal 2.5, issue.estimated_hours
81 assert_equal 2.5, issue.estimated_hours
82 assert_equal 30, issue.done_ratio
82 assert_equal 30, issue.done_ratio
83 end
83 end
84
84
85 def test_add_issue_without_overrides_should_ignore_attributes
85 def test_add_issue_without_overrides_should_ignore_attributes
86 WorkflowRule.delete_all
86 WorkflowRule.delete_all
87 issue = submit_email('ticket_on_given_project.eml')
87 issue = submit_email('ticket_on_given_project.eml')
88 assert issue.is_a?(Issue)
88 assert issue.is_a?(Issue)
89 assert !issue.new_record?
89 assert !issue.new_record?
90 issue.reload
90 issue.reload
91 assert_equal Project.find(2), issue.project
91 assert_equal Project.find(2), issue.project
92 assert_equal 'New ticket on a given project', issue.subject
92 assert_equal 'New ticket on a given project', issue.subject
93 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
93 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
94 assert_equal User.find_by_login('jsmith'), issue.author
94 assert_equal User.find_by_login('jsmith'), issue.author
95
95
96 assert_equal issue.project.trackers.first, issue.tracker
96 assert_equal issue.project.trackers.first, issue.tracker
97 assert_equal 'New', issue.status.name
97 assert_equal 'New', issue.status.name
98 assert_not_equal '2010-01-01', issue.start_date.to_s
98 assert_not_equal '2010-01-01', issue.start_date.to_s
99 assert_nil issue.due_date
99 assert_nil issue.due_date
100 assert_nil issue.assigned_to
100 assert_nil issue.assigned_to
101 assert_nil issue.fixed_version
101 assert_nil issue.fixed_version
102 assert_nil issue.estimated_hours
102 assert_nil issue.estimated_hours
103 assert_equal 0, issue.done_ratio
103 assert_equal 0, issue.done_ratio
104 end
104 end
105
105
106 def test_add_issue_to_project_specified_by_subaddress
106 def test_add_issue_to_project_specified_by_subaddress
107 # This email has redmine+onlinestore@somenet.foo as 'To' header
107 # This email has redmine+onlinestore@somenet.foo as 'To' header
108 issue = submit_email(
108 issue = submit_email(
109 'ticket_on_project_given_by_to_header.eml',
109 'ticket_on_project_given_by_to_header.eml',
110 :issue => {:tracker => 'Support request'},
110 :issue => {:tracker => 'Support request'},
111 :project_from_subaddress => 'redmine@somenet.foo'
111 :project_from_subaddress => 'redmine@somenet.foo'
112 )
112 )
113 assert issue.is_a?(Issue)
113 assert issue.is_a?(Issue)
114 assert !issue.new_record?
114 assert !issue.new_record?
115 issue.reload
115 issue.reload
116 assert_equal 'onlinestore', issue.project.identifier
116 assert_equal 'onlinestore', issue.project.identifier
117 assert_equal 'Support request', issue.tracker.name
117 assert_equal 'Support request', issue.tracker.name
118 end
118 end
119
119
120 def test_add_issue_with_default_tracker
120 def test_add_issue_with_default_tracker
121 # This email contains: 'Project: onlinestore'
121 # This email contains: 'Project: onlinestore'
122 issue = submit_email(
122 issue = submit_email(
123 'ticket_on_given_project.eml',
123 'ticket_on_given_project.eml',
124 :issue => {:tracker => 'Support request'}
124 :issue => {:tracker => 'Support request'}
125 )
125 )
126 assert issue.is_a?(Issue)
126 assert issue.is_a?(Issue)
127 assert !issue.new_record?
127 assert !issue.new_record?
128 issue.reload
128 issue.reload
129 assert_equal 'Support request', issue.tracker.name
129 assert_equal 'Support request', issue.tracker.name
130 end
130 end
131
131
132 def test_add_issue_with_default_version
132 def test_add_issue_with_default_version
133 # This email contains: 'Project: onlinestore'
133 # This email contains: 'Project: onlinestore'
134 issue = submit_email(
134 issue = submit_email(
135 'ticket_on_given_project.eml',
135 'ticket_on_given_project.eml',
136 :issue => {:fixed_version => 'Alpha'}
136 :issue => {:fixed_version => 'Alpha'}
137 )
137 )
138 assert issue.is_a?(Issue)
138 assert issue.is_a?(Issue)
139 assert !issue.new_record?
139 assert !issue.new_record?
140 assert_equal 'Alpha', issue.reload.fixed_version.name
140 assert_equal 'Alpha', issue.reload.fixed_version.name
141 end
141 end
142
142
143 def test_add_issue_with_default_assigned_to
143 def test_add_issue_with_default_assigned_to
144 # This email contains: 'Project: onlinestore'
144 # This email contains: 'Project: onlinestore'
145 issue = submit_email(
145 issue = submit_email(
146 'ticket_on_given_project.eml',
146 'ticket_on_given_project.eml',
147 :issue => {:assigned_to => 'jsmith'}
147 :issue => {:assigned_to => 'jsmith'}
148 )
148 )
149 assert issue.is_a?(Issue)
149 assert issue.is_a?(Issue)
150 assert !issue.new_record?
150 assert !issue.new_record?
151 assert_equal 'jsmith', issue.reload.assigned_to.login
151 assert_equal 'jsmith', issue.reload.assigned_to.login
152 end
152 end
153
153
154 def test_add_issue_with_status_override
154 def test_add_issue_with_status_override
155 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
155 # This email contains: 'Project: onlinestore' and 'Status: Resolved'
156 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['status'])
156 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['status'])
157 assert issue.is_a?(Issue)
157 assert issue.is_a?(Issue)
158 assert !issue.new_record?
158 assert !issue.new_record?
159 issue.reload
159 issue.reload
160 assert_equal Project.find(2), issue.project
160 assert_equal Project.find(2), issue.project
161 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
161 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
162 end
162 end
163
163
164 def test_add_issue_should_accept_is_private_attribute
164 def test_add_issue_should_accept_is_private_attribute
165 issue = submit_email('ticket_on_given_project.eml', :issue => {:is_private => '1'})
165 issue = submit_email('ticket_on_given_project.eml', :issue => {:is_private => '1'})
166 assert issue.is_a?(Issue)
166 assert issue.is_a?(Issue)
167 assert !issue.new_record?
167 assert !issue.new_record?
168 assert_equal true, issue.reload.is_private
168 assert_equal true, issue.reload.is_private
169 end
169 end
170
170
171 def test_add_issue_with_group_assignment
171 def test_add_issue_with_group_assignment
172 with_settings :issue_group_assignment => '1' do
172 with_settings :issue_group_assignment => '1' do
173 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
173 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
174 email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
174 email.gsub!('Assigned to: John Smith', 'Assigned to: B Team')
175 end
175 end
176 assert issue.is_a?(Issue)
176 assert issue.is_a?(Issue)
177 assert !issue.new_record?
177 assert !issue.new_record?
178 issue.reload
178 issue.reload
179 assert_equal Group.find(11), issue.assigned_to
179 assert_equal Group.find(11), issue.assigned_to
180 end
180 end
181 end
181 end
182
182
183 def test_add_issue_with_partial_attributes_override
183 def test_add_issue_with_partial_attributes_override
184 issue = submit_email(
184 issue = submit_email(
185 'ticket_with_attributes.eml',
185 'ticket_with_attributes.eml',
186 :issue => {:priority => 'High'},
186 :issue => {:priority => 'High'},
187 :allow_override => ['tracker']
187 :allow_override => ['tracker']
188 )
188 )
189 assert issue.is_a?(Issue)
189 assert issue.is_a?(Issue)
190 assert !issue.new_record?
190 assert !issue.new_record?
191 issue.reload
191 issue.reload
192 assert_equal 'New ticket on a given project', issue.subject
192 assert_equal 'New ticket on a given project', issue.subject
193 assert_equal User.find_by_login('jsmith'), issue.author
193 assert_equal User.find_by_login('jsmith'), issue.author
194 assert_equal Project.find(2), issue.project
194 assert_equal Project.find(2), issue.project
195 assert_equal 'Feature request', issue.tracker.to_s
195 assert_equal 'Feature request', issue.tracker.to_s
196 assert_nil issue.category
196 assert_nil issue.category
197 assert_equal 'High', issue.priority.to_s
197 assert_equal 'High', issue.priority.to_s
198 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
198 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
199 end
199 end
200
200
201 def test_add_issue_with_spaces_between_attribute_and_separator
201 def test_add_issue_with_spaces_between_attribute_and_separator
202 issue = submit_email(
202 issue = submit_email(
203 'ticket_with_spaces_between_attribute_and_separator.eml',
203 'ticket_with_spaces_between_attribute_and_separator.eml',
204 :allow_override => 'tracker,category,priority'
204 :allow_override => 'tracker,category,priority'
205 )
205 )
206 assert issue.is_a?(Issue)
206 assert issue.is_a?(Issue)
207 assert !issue.new_record?
207 assert !issue.new_record?
208 issue.reload
208 issue.reload
209 assert_equal 'New ticket on a given project', issue.subject
209 assert_equal 'New ticket on a given project', issue.subject
210 assert_equal User.find_by_login('jsmith'), issue.author
210 assert_equal User.find_by_login('jsmith'), issue.author
211 assert_equal Project.find(2), issue.project
211 assert_equal Project.find(2), issue.project
212 assert_equal 'Feature request', issue.tracker.to_s
212 assert_equal 'Feature request', issue.tracker.to_s
213 assert_equal 'Stock management', issue.category.to_s
213 assert_equal 'Stock management', issue.category.to_s
214 assert_equal 'Urgent', issue.priority.to_s
214 assert_equal 'Urgent', issue.priority.to_s
215 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
215 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
216 end
216 end
217
217
218 def test_add_issue_with_attachment_to_specific_project
218 def test_add_issue_with_attachment_to_specific_project
219 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
219 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
220 assert issue.is_a?(Issue)
220 assert issue.is_a?(Issue)
221 assert !issue.new_record?
221 assert !issue.new_record?
222 issue.reload
222 issue.reload
223 assert_equal 'Ticket created by email with attachment', issue.subject
223 assert_equal 'Ticket created by email with attachment', issue.subject
224 assert_equal User.find_by_login('jsmith'), issue.author
224 assert_equal User.find_by_login('jsmith'), issue.author
225 assert_equal Project.find(2), issue.project
225 assert_equal Project.find(2), issue.project
226 assert_equal 'This is a new ticket with attachments', issue.description
226 assert_equal 'This is a new ticket with attachments', issue.description
227 # Attachment properties
227 # Attachment properties
228 assert_equal 1, issue.attachments.size
228 assert_equal 1, issue.attachments.size
229 assert_equal 'Paella.jpg', issue.attachments.first.filename
229 assert_equal 'Paella.jpg', issue.attachments.first.filename
230 assert_equal 'image/jpeg', issue.attachments.first.content_type
230 assert_equal 'image/jpeg', issue.attachments.first.content_type
231 assert_equal 10790, issue.attachments.first.filesize
231 assert_equal 10790, issue.attachments.first.filesize
232 end
232 end
233
233
234 def test_add_issue_with_custom_fields
234 def test_add_issue_with_custom_fields
235 issue = submit_email('ticket_with_custom_fields.eml',
235 issue = submit_email('ticket_with_custom_fields.eml',
236 :issue => {:project => 'onlinestore'}, :allow_override => ['database', 'Searchable_field']
236 :issue => {:project => 'onlinestore'}, :allow_override => ['database', 'Searchable_field']
237 )
237 )
238 assert issue.is_a?(Issue)
238 assert issue.is_a?(Issue)
239 assert !issue.new_record?
239 assert !issue.new_record?
240 issue.reload
240 issue.reload
241 assert_equal 'New ticket with custom field values', issue.subject
241 assert_equal 'New ticket with custom field values', issue.subject
242 assert_equal 'PostgreSQL', issue.custom_field_value(1)
242 assert_equal 'PostgreSQL', issue.custom_field_value(1)
243 assert_equal 'Value for a custom field', issue.custom_field_value(2)
243 assert_equal 'Value for a custom field', issue.custom_field_value(2)
244 assert !issue.description.match(/^searchable field:/i)
244 assert !issue.description.match(/^searchable field:/i)
245 end
245 end
246
246
247 def test_add_issue_with_version_custom_fields
247 def test_add_issue_with_version_custom_fields
248 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
248 field = IssueCustomField.create!(:name => 'Affected version', :field_format => 'version', :is_for_all => true, :tracker_ids => [1,2,3])
249
249
250 issue = submit_email('ticket_with_custom_fields.eml',
250 issue = submit_email('ticket_with_custom_fields.eml',
251 :issue => {:project => 'ecookbook'}, :allow_override => ['affected version']
251 :issue => {:project => 'ecookbook'}, :allow_override => ['affected version']
252 ) do |email|
252 ) do |email|
253 email << "Affected version: 1.0\n"
253 email << "Affected version: 1.0\n"
254 end
254 end
255 assert issue.is_a?(Issue)
255 assert issue.is_a?(Issue)
256 assert !issue.new_record?
256 assert !issue.new_record?
257 issue.reload
257 issue.reload
258 assert_equal '2', issue.custom_field_value(field)
258 assert_equal '2', issue.custom_field_value(field)
259 end
259 end
260
260
261 def test_add_issue_should_match_assignee_on_display_name
261 def test_add_issue_should_match_assignee_on_display_name
262 user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
262 user = User.generate!(:firstname => 'Foo Bar', :lastname => 'Foo Baz')
263 User.add_to_project(user, Project.find(2))
263 User.add_to_project(user, Project.find(2))
264 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
264 issue = submit_email('ticket_on_given_project.eml', :allow_override => ['assigned_to']) do |email|
265 email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
265 email.sub!(/^Assigned to.*$/, 'Assigned to: Foo Bar Foo baz')
266 end
266 end
267 assert issue.is_a?(Issue)
267 assert issue.is_a?(Issue)
268 assert_equal user, issue.assigned_to
268 assert_equal user, issue.assigned_to
269 end
269 end
270
270
271 def test_add_issue_should_set_default_start_date
271 def test_add_issue_should_set_default_start_date
272 with_settings :default_issue_start_date_to_creation_date => '1' do
272 with_settings :default_issue_start_date_to_creation_date => '1' do
273 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
273 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
274 assert issue.is_a?(Issue)
274 assert issue.is_a?(Issue)
275 assert_equal Date.today, issue.start_date
275 assert_equal Date.today, issue.start_date
276 end
276 end
277 end
277 end
278
278
279 def test_add_issue_should_add_cc_as_watchers
279 def test_add_issue_should_add_cc_as_watchers
280 user = User.find_by_mail('dlopper@somenet.foo')
280 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
281 issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'})
281 assert issue.is_a?(Issue)
282 assert issue.is_a?(Issue)
282 assert !issue.new_record?
283 assert !issue.new_record?
283 issue.reload
284 assert issue.watched_by?(user)
284 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
285 assert_equal 1, issue.watcher_user_ids.size
285 assert_equal 1, issue.watcher_user_ids.size
286 assert_include user, issue.watcher_users.to_a
286 end
287 end
287
288
288 def test_add_issue_from_additional_email_address
289 def test_add_issue_from_additional_email_address
289 user = User.find(2)
290 user = User.find(2)
290 user.mail = 'mainaddress@somenet.foo'
291 user.mail = 'mainaddress@somenet.foo'
291 user.save!
292 user.save!
292 EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo')
293 EmailAddress.create!(:user => user, :address => 'jsmith@somenet.foo')
293
294
294 issue = submit_email('ticket_on_given_project.eml')
295 issue = submit_email('ticket_on_given_project.eml')
295 assert issue
296 assert issue
296 assert_equal user, issue.author
297 assert_equal user, issue.author
297 end
298 end
298
299
299 def test_add_issue_by_unknown_user
300 def test_add_issue_by_unknown_user
300 assert_no_difference 'User.count' do
301 assert_no_difference 'User.count' do
301 assert_equal false,
302 assert_equal false,
302 submit_email(
303 submit_email(
303 'ticket_by_unknown_user.eml',
304 'ticket_by_unknown_user.eml',
304 :issue => {:project => 'ecookbook'}
305 :issue => {:project => 'ecookbook'}
305 )
306 )
306 end
307 end
307 end
308 end
308
309
309 def test_add_issue_by_anonymous_user
310 def test_add_issue_by_anonymous_user
310 Role.anonymous.add_permission!(:add_issues)
311 Role.anonymous.add_permission!(:add_issues)
311 assert_no_difference 'User.count' do
312 assert_no_difference 'User.count' do
312 issue = submit_email(
313 issue = submit_email(
313 'ticket_by_unknown_user.eml',
314 'ticket_by_unknown_user.eml',
314 :issue => {:project => 'ecookbook'},
315 :issue => {:project => 'ecookbook'},
315 :unknown_user => 'accept'
316 :unknown_user => 'accept'
316 )
317 )
317 assert issue.is_a?(Issue)
318 assert issue.is_a?(Issue)
318 assert issue.author.anonymous?
319 assert issue.author.anonymous?
319 end
320 end
320 end
321 end
321
322
322 def test_add_issue_by_anonymous_user_with_no_from_address
323 def test_add_issue_by_anonymous_user_with_no_from_address
323 Role.anonymous.add_permission!(:add_issues)
324 Role.anonymous.add_permission!(:add_issues)
324 assert_no_difference 'User.count' do
325 assert_no_difference 'User.count' do
325 issue = submit_email(
326 issue = submit_email(
326 'ticket_by_empty_user.eml',
327 'ticket_by_empty_user.eml',
327 :issue => {:project => 'ecookbook'},
328 :issue => {:project => 'ecookbook'},
328 :unknown_user => 'accept'
329 :unknown_user => 'accept'
329 )
330 )
330 assert issue.is_a?(Issue)
331 assert issue.is_a?(Issue)
331 assert issue.author.anonymous?
332 assert issue.author.anonymous?
332 end
333 end
333 end
334 end
334
335
335 def test_add_issue_by_anonymous_user_on_private_project
336 def test_add_issue_by_anonymous_user_on_private_project
336 Role.anonymous.add_permission!(:add_issues)
337 Role.anonymous.add_permission!(:add_issues)
337 assert_no_difference 'User.count' do
338 assert_no_difference 'User.count' do
338 assert_no_difference 'Issue.count' do
339 assert_no_difference 'Issue.count' do
339 assert_equal false,
340 assert_equal false,
340 submit_email(
341 submit_email(
341 'ticket_by_unknown_user.eml',
342 'ticket_by_unknown_user.eml',
342 :issue => {:project => 'onlinestore'},
343 :issue => {:project => 'onlinestore'},
343 :unknown_user => 'accept'
344 :unknown_user => 'accept'
344 )
345 )
345 end
346 end
346 end
347 end
347 end
348 end
348
349
349 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
350 def test_add_issue_by_anonymous_user_on_private_project_without_permission_check
350 assert_no_difference 'User.count' do
351 assert_no_difference 'User.count' do
351 assert_difference 'Issue.count' do
352 assert_difference 'Issue.count' do
352 issue = submit_email(
353 issue = submit_email(
353 'ticket_by_unknown_user.eml',
354 'ticket_by_unknown_user.eml',
354 :issue => {:project => 'onlinestore'},
355 :issue => {:project => 'onlinestore'},
355 :no_permission_check => '1',
356 :no_permission_check => '1',
356 :unknown_user => 'accept'
357 :unknown_user => 'accept'
357 )
358 )
358 assert issue.is_a?(Issue)
359 assert issue.is_a?(Issue)
359 assert issue.author.anonymous?
360 assert issue.author.anonymous?
360 assert !issue.project.is_public?
361 assert !issue.project.is_public?
361 end
362 end
362 end
363 end
363 end
364 end
364
365
365 def test_add_issue_by_created_user
366 def test_add_issue_by_created_user
366 Setting.default_language = 'en'
367 Setting.default_language = 'en'
367 assert_difference 'User.count' do
368 assert_difference 'User.count' do
368 issue = submit_email(
369 issue = submit_email(
369 'ticket_by_unknown_user.eml',
370 'ticket_by_unknown_user.eml',
370 :issue => {:project => 'ecookbook'},
371 :issue => {:project => 'ecookbook'},
371 :unknown_user => 'create'
372 :unknown_user => 'create'
372 )
373 )
373 assert issue.is_a?(Issue)
374 assert issue.is_a?(Issue)
374 assert issue.author.active?
375 assert issue.author.active?
375 assert_equal 'john.doe@somenet.foo', issue.author.mail
376 assert_equal 'john.doe@somenet.foo', issue.author.mail
376 assert_equal 'John', issue.author.firstname
377 assert_equal 'John', issue.author.firstname
377 assert_equal 'Doe', issue.author.lastname
378 assert_equal 'Doe', issue.author.lastname
378
379
379 # account information
380 # account information
380 email = ActionMailer::Base.deliveries.first
381 email = ActionMailer::Base.deliveries.first
381 assert_not_nil email
382 assert_not_nil email
382 assert email.subject.include?('account activation')
383 assert email.subject.include?('account activation')
383 login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
384 login = mail_body(email).match(/\* Login: (.*)$/)[1].strip
384 password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
385 password = mail_body(email).match(/\* Password: (.*)$/)[1].strip
385 assert_equal issue.author, User.try_to_login(login, password)
386 assert_equal issue.author, User.try_to_login(login, password)
386 end
387 end
387 end
388 end
388
389
389 def test_add_issue_should_send_notification
390 def test_add_issue_should_send_notification
390 issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
391 issue = submit_email('ticket_on_given_project.eml', :allow_override => 'all')
391 assert issue.is_a?(Issue)
392 assert issue.is_a?(Issue)
392 assert !issue.new_record?
393 assert !issue.new_record?
393
394
394 mail = ActionMailer::Base.deliveries.last
395 mail = ActionMailer::Base.deliveries.last
395 assert_not_nil mail
396 assert_not_nil mail
396 assert mail.subject.include?("##{issue.id}")
397 assert mail.subject.include?("##{issue.id}")
397 assert mail.subject.include?('New ticket on a given project')
398 assert mail.subject.include?('New ticket on a given project')
398 end
399 end
399
400
400 def test_created_user_should_be_added_to_groups
401 def test_created_user_should_be_added_to_groups
401 group1 = Group.generate!
402 group1 = Group.generate!
402 group2 = Group.generate!
403 group2 = Group.generate!
403
404
404 assert_difference 'User.count' do
405 assert_difference 'User.count' do
405 submit_email(
406 submit_email(
406 'ticket_by_unknown_user.eml',
407 'ticket_by_unknown_user.eml',
407 :issue => {:project => 'ecookbook'},
408 :issue => {:project => 'ecookbook'},
408 :unknown_user => 'create',
409 :unknown_user => 'create',
409 :default_group => "#{group1.name},#{group2.name}"
410 :default_group => "#{group1.name},#{group2.name}"
410 )
411 )
411 end
412 end
412 user = User.order('id DESC').first
413 user = User.order('id DESC').first
413 assert_equal [group1, group2].sort, user.groups.sort
414 assert_equal [group1, group2].sort, user.groups.sort
414 end
415 end
415
416
416 def test_created_user_should_not_receive_account_information_with_no_account_info_option
417 def test_created_user_should_not_receive_account_information_with_no_account_info_option
417 assert_difference 'User.count' do
418 assert_difference 'User.count' do
418 submit_email(
419 submit_email(
419 'ticket_by_unknown_user.eml',
420 'ticket_by_unknown_user.eml',
420 :issue => {:project => 'ecookbook'},
421 :issue => {:project => 'ecookbook'},
421 :unknown_user => 'create',
422 :unknown_user => 'create',
422 :no_account_notice => '1'
423 :no_account_notice => '1'
423 )
424 )
424 end
425 end
425
426
426 # only 1 email for the new issue notification
427 # only 1 email for the new issue notification
427 assert_equal 1, ActionMailer::Base.deliveries.size
428 assert_equal 1, ActionMailer::Base.deliveries.size
428 email = ActionMailer::Base.deliveries.first
429 email = ActionMailer::Base.deliveries.first
429 assert_include 'Ticket by unknown user', email.subject
430 assert_include 'Ticket by unknown user', email.subject
430 end
431 end
431
432
432 def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
433 def test_created_user_should_have_mail_notification_to_none_with_no_notification_option
433 assert_difference 'User.count' do
434 assert_difference 'User.count' do
434 submit_email(
435 submit_email(
435 'ticket_by_unknown_user.eml',
436 'ticket_by_unknown_user.eml',
436 :issue => {:project => 'ecookbook'},
437 :issue => {:project => 'ecookbook'},
437 :unknown_user => 'create',
438 :unknown_user => 'create',
438 :no_notification => '1'
439 :no_notification => '1'
439 )
440 )
440 end
441 end
441 user = User.order('id DESC').first
442 user = User.order('id DESC').first
442 assert_equal 'none', user.mail_notification
443 assert_equal 'none', user.mail_notification
443 end
444 end
444
445
445 def test_add_issue_without_from_header
446 def test_add_issue_without_from_header
446 Role.anonymous.add_permission!(:add_issues)
447 Role.anonymous.add_permission!(:add_issues)
447 assert_equal false, submit_email('ticket_without_from_header.eml')
448 assert_equal false, submit_email('ticket_without_from_header.eml')
448 end
449 end
449
450
450 def test_add_issue_with_invalid_attributes
451 def test_add_issue_with_invalid_attributes
451 with_settings :default_issue_start_date_to_creation_date => '0' do
452 with_settings :default_issue_start_date_to_creation_date => '0' do
452 issue = submit_email(
453 issue = submit_email(
453 'ticket_with_invalid_attributes.eml',
454 'ticket_with_invalid_attributes.eml',
454 :allow_override => 'tracker,category,priority'
455 :allow_override => 'tracker,category,priority'
455 )
456 )
456 assert issue.is_a?(Issue)
457 assert issue.is_a?(Issue)
457 assert !issue.new_record?
458 assert !issue.new_record?
458 issue.reload
459 issue.reload
459 assert_nil issue.assigned_to
460 assert_nil issue.assigned_to
460 assert_nil issue.start_date
461 assert_nil issue.start_date
461 assert_nil issue.due_date
462 assert_nil issue.due_date
462 assert_equal 0, issue.done_ratio
463 assert_equal 0, issue.done_ratio
463 assert_equal 'Normal', issue.priority.to_s
464 assert_equal 'Normal', issue.priority.to_s
464 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
465 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
465 end
466 end
466 end
467 end
467
468
468 def test_add_issue_with_invalid_project_should_be_assigned_to_default_project
469 def test_add_issue_with_invalid_project_should_be_assigned_to_default_project
469 issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email|
470 issue = submit_email('ticket_on_given_project.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'project') do |email|
470 email.gsub!(/^Project:.+$/, 'Project: invalid')
471 email.gsub!(/^Project:.+$/, 'Project: invalid')
471 end
472 end
472 assert issue.is_a?(Issue)
473 assert issue.is_a?(Issue)
473 assert !issue.new_record?
474 assert !issue.new_record?
474 assert_equal 'ecookbook', issue.project.identifier
475 assert_equal 'ecookbook', issue.project.identifier
475 end
476 end
476
477
477 def test_add_issue_with_localized_attributes
478 def test_add_issue_with_localized_attributes
478 User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
479 User.find_by_mail('jsmith@somenet.foo').update_attribute 'language', 'fr'
479 issue = submit_email(
480 issue = submit_email(
480 'ticket_with_localized_attributes.eml',
481 'ticket_with_localized_attributes.eml',
481 :allow_override => 'tracker,category,priority'
482 :allow_override => 'tracker,category,priority'
482 )
483 )
483 assert issue.is_a?(Issue)
484 assert issue.is_a?(Issue)
484 assert !issue.new_record?
485 assert !issue.new_record?
485 issue.reload
486 issue.reload
486 assert_equal 'New ticket on a given project', issue.subject
487 assert_equal 'New ticket on a given project', issue.subject
487 assert_equal User.find_by_login('jsmith'), issue.author
488 assert_equal User.find_by_login('jsmith'), issue.author
488 assert_equal Project.find(2), issue.project
489 assert_equal Project.find(2), issue.project
489 assert_equal 'Feature request', issue.tracker.to_s
490 assert_equal 'Feature request', issue.tracker.to_s
490 assert_equal 'Stock management', issue.category.to_s
491 assert_equal 'Stock management', issue.category.to_s
491 assert_equal 'Urgent', issue.priority.to_s
492 assert_equal 'Urgent', issue.priority.to_s
492 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
493 assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.')
493 end
494 end
494
495
495 def test_add_issue_with_japanese_keywords
496 def test_add_issue_with_japanese_keywords
496 ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8')
497 ja_dev = "\xe9\x96\x8b\xe7\x99\xba".force_encoding('UTF-8')
497 tracker = Tracker.generate!(:name => ja_dev)
498 tracker = Tracker.generate!(:name => ja_dev)
498 Project.find(1).trackers << tracker
499 Project.find(1).trackers << tracker
499 issue = submit_email(
500 issue = submit_email(
500 'japanese_keywords_iso_2022_jp.eml',
501 'japanese_keywords_iso_2022_jp.eml',
501 :issue => {:project => 'ecookbook'},
502 :issue => {:project => 'ecookbook'},
502 :allow_override => 'tracker'
503 :allow_override => 'tracker'
503 )
504 )
504 assert_kind_of Issue, issue
505 assert_kind_of Issue, issue
505 assert_equal tracker, issue.tracker
506 assert_equal tracker, issue.tracker
506 end
507 end
507
508
508 def test_add_issue_from_apple_mail
509 def test_add_issue_from_apple_mail
509 issue = submit_email(
510 issue = submit_email(
510 'apple_mail_with_attachment.eml',
511 'apple_mail_with_attachment.eml',
511 :issue => {:project => 'ecookbook'}
512 :issue => {:project => 'ecookbook'}
512 )
513 )
513 assert_kind_of Issue, issue
514 assert_kind_of Issue, issue
514 assert_equal 1, issue.attachments.size
515 assert_equal 1, issue.attachments.size
515
516
516 attachment = issue.attachments.first
517 attachment = issue.attachments.first
517 assert_equal 'paella.jpg', attachment.filename
518 assert_equal 'paella.jpg', attachment.filename
518 assert_equal 10790, attachment.filesize
519 assert_equal 10790, attachment.filesize
519 assert File.exist?(attachment.diskfile)
520 assert File.exist?(attachment.diskfile)
520 assert_equal 10790, File.size(attachment.diskfile)
521 assert_equal 10790, File.size(attachment.diskfile)
521 assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
522 assert_equal 'caaf384198bcbc9563ab5c058acd73cd', attachment.digest
522 end
523 end
523
524
524 def test_thunderbird_with_attachment_ja
525 def test_thunderbird_with_attachment_ja
525 issue = submit_email(
526 issue = submit_email(
526 'thunderbird_with_attachment_ja.eml',
527 'thunderbird_with_attachment_ja.eml',
527 :issue => {:project => 'ecookbook'}
528 :issue => {:project => 'ecookbook'}
528 )
529 )
529 assert_kind_of Issue, issue
530 assert_kind_of Issue, issue
530 assert_equal 1, issue.attachments.size
531 assert_equal 1, issue.attachments.size
531 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
532 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
532 attachment = issue.attachments.first
533 attachment = issue.attachments.first
533 assert_equal ja, attachment.filename
534 assert_equal ja, attachment.filename
534 assert_equal 5, attachment.filesize
535 assert_equal 5, attachment.filesize
535 assert File.exist?(attachment.diskfile)
536 assert File.exist?(attachment.diskfile)
536 assert_equal 5, File.size(attachment.diskfile)
537 assert_equal 5, File.size(attachment.diskfile)
537 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
538 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
538 end
539 end
539
540
540 def test_gmail_with_attachment_ja
541 def test_gmail_with_attachment_ja
541 issue = submit_email(
542 issue = submit_email(
542 'gmail_with_attachment_ja.eml',
543 'gmail_with_attachment_ja.eml',
543 :issue => {:project => 'ecookbook'}
544 :issue => {:project => 'ecookbook'}
544 )
545 )
545 assert_kind_of Issue, issue
546 assert_kind_of Issue, issue
546 assert_equal 1, issue.attachments.size
547 assert_equal 1, issue.attachments.size
547 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
548 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88.txt".force_encoding('UTF-8')
548 attachment = issue.attachments.first
549 attachment = issue.attachments.first
549 assert_equal ja, attachment.filename
550 assert_equal ja, attachment.filename
550 assert_equal 5, attachment.filesize
551 assert_equal 5, attachment.filesize
551 assert File.exist?(attachment.diskfile)
552 assert File.exist?(attachment.diskfile)
552 assert_equal 5, File.size(attachment.diskfile)
553 assert_equal 5, File.size(attachment.diskfile)
553 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
554 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
554 end
555 end
555
556
556 def test_thunderbird_with_attachment_latin1
557 def test_thunderbird_with_attachment_latin1
557 issue = submit_email(
558 issue = submit_email(
558 'thunderbird_with_attachment_iso-8859-1.eml',
559 'thunderbird_with_attachment_iso-8859-1.eml',
559 :issue => {:project => 'ecookbook'}
560 :issue => {:project => 'ecookbook'}
560 )
561 )
561 assert_kind_of Issue, issue
562 assert_kind_of Issue, issue
562 assert_equal 1, issue.attachments.size
563 assert_equal 1, issue.attachments.size
563 u = "".force_encoding('UTF-8')
564 u = "".force_encoding('UTF-8')
564 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
565 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
565 11.times { u << u1 }
566 11.times { u << u1 }
566 attachment = issue.attachments.first
567 attachment = issue.attachments.first
567 assert_equal "#{u}.png", attachment.filename
568 assert_equal "#{u}.png", attachment.filename
568 assert_equal 130, attachment.filesize
569 assert_equal 130, attachment.filesize
569 assert File.exist?(attachment.diskfile)
570 assert File.exist?(attachment.diskfile)
570 assert_equal 130, File.size(attachment.diskfile)
571 assert_equal 130, File.size(attachment.diskfile)
571 assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
572 assert_equal '4d80e667ac37dddfe05502530f152abb', attachment.digest
572 end
573 end
573
574
574 def test_gmail_with_attachment_latin1
575 def test_gmail_with_attachment_latin1
575 issue = submit_email(
576 issue = submit_email(
576 'gmail_with_attachment_iso-8859-1.eml',
577 'gmail_with_attachment_iso-8859-1.eml',
577 :issue => {:project => 'ecookbook'}
578 :issue => {:project => 'ecookbook'}
578 )
579 )
579 assert_kind_of Issue, issue
580 assert_kind_of Issue, issue
580 assert_equal 1, issue.attachments.size
581 assert_equal 1, issue.attachments.size
581 u = "".force_encoding('UTF-8')
582 u = "".force_encoding('UTF-8')
582 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
583 u1 = "\xc3\x84\xc3\xa4\xc3\x96\xc3\xb6\xc3\x9c\xc3\xbc".force_encoding('UTF-8')
583 11.times { u << u1 }
584 11.times { u << u1 }
584 attachment = issue.attachments.first
585 attachment = issue.attachments.first
585 assert_equal "#{u}.txt", attachment.filename
586 assert_equal "#{u}.txt", attachment.filename
586 assert_equal 5, attachment.filesize
587 assert_equal 5, attachment.filesize
587 assert File.exist?(attachment.diskfile)
588 assert File.exist?(attachment.diskfile)
588 assert_equal 5, File.size(attachment.diskfile)
589 assert_equal 5, File.size(attachment.diskfile)
589 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
590 assert_equal 'd8e8fca2dc0f896fd7cb4cb0031ba249', attachment.digest
590 end
591 end
591
592
592 def test_mail_with_attachment_latin2
593 def test_mail_with_attachment_latin2
593 issue = submit_email(
594 issue = submit_email(
594 'ticket_with_text_attachment_iso-8859-2.eml',
595 'ticket_with_text_attachment_iso-8859-2.eml',
595 :issue => {:project => 'ecookbook'}
596 :issue => {:project => 'ecookbook'}
596 )
597 )
597 assert_kind_of Issue, issue
598 assert_kind_of Issue, issue
598 assert_equal 1, issue.attachments.size
599 assert_equal 1, issue.attachments.size
599 attachment = issue.attachments.first
600 attachment = issue.attachments.first
600 assert_equal 'latin2.txt', attachment.filename
601 assert_equal 'latin2.txt', attachment.filename
601 assert_equal 19, attachment.filesize
602 assert_equal 19, attachment.filesize
602 assert File.exist?(attachment.diskfile)
603 assert File.exist?(attachment.diskfile)
603 assert_equal 19, File.size(attachment.diskfile)
604 assert_equal 19, File.size(attachment.diskfile)
604 content = "p\xF8\xEDli\xB9 \xBEluou\xE8k\xFD k\xF9n".force_encoding('CP852')
605 content = "p\xF8\xEDli\xB9 \xBEluou\xE8k\xFD k\xF9n".force_encoding('CP852')
605 assert_equal content, File.read(attachment.diskfile).force_encoding('CP852')
606 assert_equal content, File.read(attachment.diskfile).force_encoding('CP852')
606 end
607 end
607
608
608 def test_multiple_inline_text_parts_should_be_appended_to_issue_description
609 def test_multiple_inline_text_parts_should_be_appended_to_issue_description
609 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
610 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
610 assert_include 'first', issue.description
611 assert_include 'first', issue.description
611 assert_include 'second', issue.description
612 assert_include 'second', issue.description
612 assert_include 'third', issue.description
613 assert_include 'third', issue.description
613 end
614 end
614
615
615 def test_attachment_text_part_should_be_added_as_issue_attachment
616 def test_attachment_text_part_should_be_added_as_issue_attachment
616 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
617 issue = submit_email('multiple_text_parts.eml', :issue => {:project => 'ecookbook'})
617 assert_not_include 'Plain text attachment', issue.description
618 assert_not_include 'Plain text attachment', issue.description
618 attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'}
619 attachment = issue.attachments.detect {|a| a.filename == 'textfile.txt'}
619 assert_not_nil attachment
620 assert_not_nil attachment
620 assert_include 'Plain text attachment', File.read(attachment.diskfile)
621 assert_include 'Plain text attachment', File.read(attachment.diskfile)
621 end
622 end
622
623
623 def test_add_issue_with_iso_8859_1_subject
624 def test_add_issue_with_iso_8859_1_subject
624 issue = submit_email(
625 issue = submit_email(
625 'subject_as_iso-8859-1.eml',
626 'subject_as_iso-8859-1.eml',
626 :issue => {:project => 'ecookbook'}
627 :issue => {:project => 'ecookbook'}
627 )
628 )
628 str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc...".force_encoding('UTF-8')
629 str = "Testmail from Webmail: \xc3\xa4 \xc3\xb6 \xc3\xbc...".force_encoding('UTF-8')
629 assert_kind_of Issue, issue
630 assert_kind_of Issue, issue
630 assert_equal str, issue.subject
631 assert_equal str, issue.subject
631 end
632 end
632
633
633 def test_quoted_printable_utf8
634 def test_quoted_printable_utf8
634 issue = submit_email(
635 issue = submit_email(
635 'quoted_printable_utf8.eml',
636 'quoted_printable_utf8.eml',
636 :issue => {:project => 'ecookbook'}
637 :issue => {:project => 'ecookbook'}
637 )
638 )
638 assert_kind_of Issue, issue
639 assert_kind_of Issue, issue
639 str = "Freundliche Gr\xc3\xbcsse".force_encoding('UTF-8')
640 str = "Freundliche Gr\xc3\xbcsse".force_encoding('UTF-8')
640 assert_equal str, issue.description
641 assert_equal str, issue.description
641 end
642 end
642
643
643 def test_gmail_iso8859_2
644 def test_gmail_iso8859_2
644 issue = submit_email(
645 issue = submit_email(
645 'gmail-iso8859-2.eml',
646 'gmail-iso8859-2.eml',
646 :issue => {:project => 'ecookbook'}
647 :issue => {:project => 'ecookbook'}
647 )
648 )
648 assert_kind_of Issue, issue
649 assert_kind_of Issue, issue
649 str = "Na \xc5\xa1triku se su\xc5\xa1i \xc5\xa1osi\xc4\x87.".force_encoding('UTF-8')
650 str = "Na \xc5\xa1triku se su\xc5\xa1i \xc5\xa1osi\xc4\x87.".force_encoding('UTF-8')
650 assert issue.description.include?(str)
651 assert issue.description.include?(str)
651 end
652 end
652
653
653 def test_add_issue_with_japanese_subject
654 def test_add_issue_with_japanese_subject
654 issue = submit_email(
655 issue = submit_email(
655 'subject_japanese_1.eml',
656 'subject_japanese_1.eml',
656 :issue => {:project => 'ecookbook'}
657 :issue => {:project => 'ecookbook'}
657 )
658 )
658 assert_kind_of Issue, issue
659 assert_kind_of Issue, issue
659 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
660 ja = "\xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
660 assert_equal ja, issue.subject
661 assert_equal ja, issue.subject
661 end
662 end
662
663
663 def test_add_issue_with_korean_body
664 def test_add_issue_with_korean_body
664 # Make sure mail bodies with a charset unknown to Ruby
665 # Make sure mail bodies with a charset unknown to Ruby
665 # but known to the Mail gem 2.5.4 are handled correctly
666 # but known to the Mail gem 2.5.4 are handled correctly
666 kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4.".force_encoding('UTF-8')
667 kr = "\xEA\xB3\xA0\xEB\xA7\x99\xEC\x8A\xB5\xEB\x8B\x88\xEB\x8B\xA4.".force_encoding('UTF-8')
667 issue = submit_email(
668 issue = submit_email(
668 'body_ks_c_5601-1987.eml',
669 'body_ks_c_5601-1987.eml',
669 :issue => {:project => 'ecookbook'}
670 :issue => {:project => 'ecookbook'}
670 )
671 )
671 assert_kind_of Issue, issue
672 assert_kind_of Issue, issue
672 assert_equal kr, issue.description
673 assert_equal kr, issue.description
673 end
674 end
674
675
675 def test_add_issue_with_no_subject_header
676 def test_add_issue_with_no_subject_header
676 issue = submit_email(
677 issue = submit_email(
677 'no_subject_header.eml',
678 'no_subject_header.eml',
678 :issue => {:project => 'ecookbook'}
679 :issue => {:project => 'ecookbook'}
679 )
680 )
680 assert_kind_of Issue, issue
681 assert_kind_of Issue, issue
681 assert_equal '(no subject)', issue.subject
682 assert_equal '(no subject)', issue.subject
682 end
683 end
683
684
684 def test_add_issue_with_mixed_japanese_subject
685 def test_add_issue_with_mixed_japanese_subject
685 issue = submit_email(
686 issue = submit_email(
686 'subject_japanese_2.eml',
687 'subject_japanese_2.eml',
687 :issue => {:project => 'ecookbook'}
688 :issue => {:project => 'ecookbook'}
688 )
689 )
689 assert_kind_of Issue, issue
690 assert_kind_of Issue, issue
690 ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
691 ja = "Re: \xe3\x83\x86\xe3\x82\xb9\xe3\x83\x88".force_encoding('UTF-8')
691 assert_equal ja, issue.subject
692 assert_equal ja, issue.subject
692 end
693 end
693
694
694 def test_should_ignore_emails_from_locked_users
695 def test_should_ignore_emails_from_locked_users
695 User.find(2).lock!
696 User.find(2).lock!
696
697
697 MailHandler.any_instance.expects(:dispatch).never
698 MailHandler.any_instance.expects(:dispatch).never
698 assert_no_difference 'Issue.count' do
699 assert_no_difference 'Issue.count' do
699 assert_equal false, submit_email('ticket_on_given_project.eml')
700 assert_equal false, submit_email('ticket_on_given_project.eml')
700 end
701 end
701 end
702 end
702
703
703 def test_should_ignore_emails_from_emission_address
704 def test_should_ignore_emails_from_emission_address
704 Role.anonymous.add_permission!(:add_issues)
705 Role.anonymous.add_permission!(:add_issues)
705 assert_no_difference 'User.count' do
706 assert_no_difference 'User.count' do
706 assert_equal false,
707 assert_equal false,
707 submit_email(
708 submit_email(
708 'ticket_from_emission_address.eml',
709 'ticket_from_emission_address.eml',
709 :issue => {:project => 'ecookbook'},
710 :issue => {:project => 'ecookbook'},
710 :unknown_user => 'create'
711 :unknown_user => 'create'
711 )
712 )
712 end
713 end
713 end
714 end
714
715
715 def test_should_ignore_auto_replied_emails
716 def test_should_ignore_auto_replied_emails
716 MailHandler.any_instance.expects(:dispatch).never
717 MailHandler.any_instance.expects(:dispatch).never
717 [
718 [
718 "Auto-Submitted: auto-replied",
719 "Auto-Submitted: auto-replied",
719 "Auto-Submitted: Auto-Replied",
720 "Auto-Submitted: Auto-Replied",
720 "Auto-Submitted: auto-generated",
721 "Auto-Submitted: auto-generated",
721 'X-Autoreply: yes'
722 'X-Autoreply: yes'
722 ].each do |header|
723 ].each do |header|
723 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
724 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
724 raw = header + "\n" + raw
725 raw = header + "\n" + raw
725
726
726 assert_no_difference 'Issue.count' do
727 assert_no_difference 'Issue.count' do
727 assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
728 assert_equal false, MailHandler.receive(raw), "email with #{header} header was not ignored"
728 end
729 end
729 end
730 end
730 end
731 end
731
732
732 test "should not ignore Auto-Submitted headers not defined in RFC3834" do
733 test "should not ignore Auto-Submitted headers not defined in RFC3834" do
733 [
734 [
734 "Auto-Submitted: auto-forwarded"
735 "Auto-Submitted: auto-forwarded"
735 ].each do |header|
736 ].each do |header|
736 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
737 raw = IO.read(File.join(FIXTURES_PATH, 'ticket_on_given_project.eml'))
737 raw = header + "\n" + raw
738 raw = header + "\n" + raw
738
739
739 assert_difference 'Issue.count', 1 do
740 assert_difference 'Issue.count', 1 do
740 assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored"
741 assert_not_nil MailHandler.receive(raw), "email with #{header} header was ignored"
741 end
742 end
742 end
743 end
743 end
744 end
744
745
745 def test_add_issue_should_send_email_notification
746 def test_add_issue_should_send_email_notification
746 Setting.notified_events = ['issue_added']
747 Setting.notified_events = ['issue_added']
747 # This email contains: 'Project: onlinestore'
748 # This email contains: 'Project: onlinestore'
748 issue = submit_email('ticket_on_given_project.eml')
749 issue = submit_email('ticket_on_given_project.eml')
749 assert issue.is_a?(Issue)
750 assert issue.is_a?(Issue)
750 assert_equal 1, ActionMailer::Base.deliveries.size
751 assert_equal 1, ActionMailer::Base.deliveries.size
751 end
752 end
752
753
753 def test_update_issue
754 def test_update_issue
754 journal = submit_email('ticket_reply.eml')
755 journal = submit_email('ticket_reply.eml')
755 assert journal.is_a?(Journal)
756 assert journal.is_a?(Journal)
756 assert_equal User.find_by_login('jsmith'), journal.user
757 assert_equal User.find_by_login('jsmith'), journal.user
757 assert_equal Issue.find(2), journal.journalized
758 assert_equal Issue.find(2), journal.journalized
758 assert_match /This is reply/, journal.notes
759 assert_match /This is reply/, journal.notes
759 assert_equal false, journal.private_notes
760 assert_equal false, journal.private_notes
760 assert_equal 'Feature request', journal.issue.tracker.name
761 assert_equal 'Feature request', journal.issue.tracker.name
761 end
762 end
762
763
763 def test_update_issue_should_accept_issue_id_after_space_inside_brackets
764 def test_update_issue_should_accept_issue_id_after_space_inside_brackets
764 journal = submit_email('ticket_reply_with_status.eml') do |email|
765 journal = submit_email('ticket_reply_with_status.eml') do |email|
765 assert email.sub!(/^Subject:.*$/, "Subject: Re: [Feature request #2] Add ingredients categories")
766 assert email.sub!(/^Subject:.*$/, "Subject: Re: [Feature request #2] Add ingredients categories")
766 end
767 end
767 assert journal.is_a?(Journal)
768 assert journal.is_a?(Journal)
768 assert_equal Issue.find(2), journal.journalized
769 assert_equal Issue.find(2), journal.journalized
769 end
770 end
770
771
771 def test_update_issue_should_accept_issue_id_inside_brackets
772 def test_update_issue_should_accept_issue_id_inside_brackets
772 journal = submit_email('ticket_reply_with_status.eml') do |email|
773 journal = submit_email('ticket_reply_with_status.eml') do |email|
773 assert email.sub!(/^Subject:.*$/, "Subject: Re: [#2] Add ingredients categories")
774 assert email.sub!(/^Subject:.*$/, "Subject: Re: [#2] Add ingredients categories")
774 end
775 end
775 assert journal.is_a?(Journal)
776 assert journal.is_a?(Journal)
776 assert_equal Issue.find(2), journal.journalized
777 assert_equal Issue.find(2), journal.journalized
777 end
778 end
778
779
779 def test_update_issue_should_ignore_bogus_issue_ids_in_subject
780 def test_update_issue_should_ignore_bogus_issue_ids_in_subject
780 journal = submit_email('ticket_reply_with_status.eml') do |email|
781 journal = submit_email('ticket_reply_with_status.eml') do |email|
781 assert email.sub!(/^Subject:.*$/, "Subject: Re: [12345#1][bogus#1][Feature request #2] Add ingredients categories")
782 assert email.sub!(/^Subject:.*$/, "Subject: Re: [12345#1][bogus#1][Feature request #2] Add ingredients categories")
782 end
783 end
783 assert journal.is_a?(Journal)
784 assert journal.is_a?(Journal)
784 assert_equal Issue.find(2), journal.journalized
785 assert_equal Issue.find(2), journal.journalized
785 end
786 end
786
787
787 def test_update_issue_with_attribute_changes
788 def test_update_issue_with_attribute_changes
788 journal = submit_email('ticket_reply_with_status.eml', :allow_override => ['status','assigned_to','start_date','due_date', 'float field'])
789 journal = submit_email('ticket_reply_with_status.eml', :allow_override => ['status','assigned_to','start_date','due_date', 'float field'])
789 assert journal.is_a?(Journal)
790 assert journal.is_a?(Journal)
790 issue = Issue.find(journal.issue.id)
791 issue = Issue.find(journal.issue.id)
791 assert_equal User.find_by_login('jsmith'), journal.user
792 assert_equal User.find_by_login('jsmith'), journal.user
792 assert_equal Issue.find(2), journal.journalized
793 assert_equal Issue.find(2), journal.journalized
793 assert_match /This is reply/, journal.notes
794 assert_match /This is reply/, journal.notes
794 assert_equal 'Feature request', journal.issue.tracker.name
795 assert_equal 'Feature request', journal.issue.tracker.name
795 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
796 assert_equal IssueStatus.find_by_name("Resolved"), issue.status
796 assert_equal '2010-01-01', issue.start_date.to_s
797 assert_equal '2010-01-01', issue.start_date.to_s
797 assert_equal '2010-12-31', issue.due_date.to_s
798 assert_equal '2010-12-31', issue.due_date.to_s
798 assert_equal User.find_by_login('jsmith'), issue.assigned_to
799 assert_equal User.find_by_login('jsmith'), issue.assigned_to
799 assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
800 assert_equal "52.6", issue.custom_value_for(CustomField.find_by_name('Float field')).value
800 # keywords should be removed from the email body
801 # keywords should be removed from the email body
801 assert !journal.notes.match(/^Status:/i)
802 assert !journal.notes.match(/^Status:/i)
802 assert !journal.notes.match(/^Start Date:/i)
803 assert !journal.notes.match(/^Start Date:/i)
803 end
804 end
804
805
805 def test_update_issue_with_attachment
806 def test_update_issue_with_attachment
806 assert_difference 'Journal.count' do
807 assert_difference 'Journal.count' do
807 assert_difference 'JournalDetail.count' do
808 assert_difference 'JournalDetail.count' do
808 assert_difference 'Attachment.count' do
809 assert_difference 'Attachment.count' do
809 assert_no_difference 'Issue.count' do
810 assert_no_difference 'Issue.count' do
810 journal = submit_email('ticket_with_attachment.eml') do |raw|
811 journal = submit_email('ticket_with_attachment.eml') do |raw|
811 raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
812 raw.gsub! /^Subject: .*$/, 'Subject: Re: [Cookbook - Feature #2] (New) Add ingredients categories'
812 end
813 end
813 end
814 end
814 end
815 end
815 end
816 end
816 end
817 end
817 journal = Journal.order('id DESC').first
818 journal = Journal.order('id DESC').first
818 assert_equal Issue.find(2), journal.journalized
819 assert_equal Issue.find(2), journal.journalized
819 assert_equal 1, journal.details.size
820 assert_equal 1, journal.details.size
820
821
821 detail = journal.details.first
822 detail = journal.details.first
822 assert_equal 'attachment', detail.property
823 assert_equal 'attachment', detail.property
823 assert_equal 'Paella.jpg', detail.value
824 assert_equal 'Paella.jpg', detail.value
824 end
825 end
825
826
826 def test_update_issue_should_send_email_notification
827 def test_update_issue_should_send_email_notification
827 journal = submit_email('ticket_reply.eml')
828 journal = submit_email('ticket_reply.eml')
828 assert journal.is_a?(Journal)
829 assert journal.is_a?(Journal)
829 assert_equal 1, ActionMailer::Base.deliveries.size
830 assert_equal 1, ActionMailer::Base.deliveries.size
830 end
831 end
831
832
832 def test_update_issue_should_not_set_defaults
833 def test_update_issue_should_not_set_defaults
833 journal = submit_email(
834 journal = submit_email(
834 'ticket_reply.eml',
835 'ticket_reply.eml',
835 :issue => {:tracker => 'Support request', :priority => 'High'}
836 :issue => {:tracker => 'Support request', :priority => 'High'}
836 )
837 )
837 assert journal.is_a?(Journal)
838 assert journal.is_a?(Journal)
838 assert_match /This is reply/, journal.notes
839 assert_match /This is reply/, journal.notes
839 assert_equal 'Feature request', journal.issue.tracker.name
840 assert_equal 'Feature request', journal.issue.tracker.name
840 assert_equal 'Normal', journal.issue.priority.name
841 assert_equal 'Normal', journal.issue.priority.name
841 end
842 end
842
843
843 def test_update_issue_should_add_cc_as_watchers
844 def test_update_issue_should_add_cc_as_watchers
844 Watcher.delete_all
845 Watcher.delete_all
845 issue = Issue.find(2)
846 issue = Issue.find(2)
846
847
847 assert_difference 'Watcher.count' do
848 assert_difference 'Watcher.count' do
848 assert submit_email('issue_update_with_cc.eml')
849 assert submit_email('issue_update_with_cc.eml')
849 end
850 end
850 issue.reload
851 issue.reload
851 assert_equal 1, issue.watcher_user_ids.size
852 assert_equal 1, issue.watcher_user_ids.size
852 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
853 assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo'))
853 end
854 end
854
855
855 def test_update_issue_should_not_add_cc_as_watchers_if_already_watching
856 def test_update_issue_should_not_add_cc_as_watchers_if_already_watching
856 Watcher.delete_all
857 Watcher.delete_all
857 issue = Issue.find(2)
858 issue = Issue.find(2)
858 Watcher.create!(:watchable => issue, :user => User.find_by_mail('dlopper@somenet.foo'))
859 Watcher.create!(:watchable => issue, :user => User.find_by_mail('dlopper@somenet.foo'))
859
860
860 assert_no_difference 'Watcher.count' do
861 assert_no_difference 'Watcher.count' do
861 assert submit_email('issue_update_with_cc.eml')
862 assert submit_email('issue_update_with_cc.eml')
862 end
863 end
863 end
864 end
864
865
865 def test_replying_to_a_private_note_should_add_reply_as_private
866 def test_replying_to_a_private_note_should_add_reply_as_private
866 private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2)
867 private_journal = Journal.create!(:notes => 'Private notes', :journalized => Issue.find(1), :private_notes => true, :user_id => 2)
867
868
868 assert_difference 'Journal.count' do
869 assert_difference 'Journal.count' do
869 journal = submit_email('ticket_reply.eml') do |email|
870 journal = submit_email('ticket_reply.eml') do |email|
870 email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
871 email.sub! %r{^In-Reply-To:.*$}, "In-Reply-To: <redmine.journal-#{private_journal.id}.20060719210421@osiris>"
871 end
872 end
872
873
873 assert_kind_of Journal, journal
874 assert_kind_of Journal, journal
874 assert_match /This is reply/, journal.notes
875 assert_match /This is reply/, journal.notes
875 assert_equal true, journal.private_notes
876 assert_equal true, journal.private_notes
876 end
877 end
877 end
878 end
878
879
879 def test_reply_to_a_message
880 def test_reply_to_a_message
880 m = submit_email('message_reply.eml')
881 m = submit_email('message_reply.eml')
881 assert m.is_a?(Message)
882 assert m.is_a?(Message)
882 assert !m.new_record?
883 assert !m.new_record?
883 m.reload
884 m.reload
884 assert_equal 'Reply via email', m.subject
885 assert_equal 'Reply via email', m.subject
885 # The email replies to message #2 which is part of the thread of message #1
886 # The email replies to message #2 which is part of the thread of message #1
886 assert_equal Message.find(1), m.parent
887 assert_equal Message.find(1), m.parent
887 end
888 end
888
889
889 def test_reply_to_a_message_by_subject
890 def test_reply_to_a_message_by_subject
890 m = submit_email('message_reply_by_subject.eml')
891 m = submit_email('message_reply_by_subject.eml')
891 assert m.is_a?(Message)
892 assert m.is_a?(Message)
892 assert !m.new_record?
893 assert !m.new_record?
893 m.reload
894 m.reload
894 assert_equal 'Reply to the first post', m.subject
895 assert_equal 'Reply to the first post', m.subject
895 assert_equal Message.find(1), m.parent
896 assert_equal Message.find(1), m.parent
896 end
897 end
897
898
898 def test_should_convert_tags_of_html_only_emails
899 def test_should_convert_tags_of_html_only_emails
899 with_settings :text_formatting => 'textile' do
900 with_settings :text_formatting => 'textile' do
900 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
901 issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'})
901 assert issue.is_a?(Issue)
902 assert issue.is_a?(Issue)
902 assert !issue.new_record?
903 assert !issue.new_record?
903 issue.reload
904 issue.reload
904 assert_equal 'HTML email', issue.subject
905 assert_equal 'HTML email', issue.subject
905 assert_equal "This is a *html-only* email.\r\n\r\nh1. With a title\r\n\r\nand a paragraph.", issue.description
906 assert_equal "This is a *html-only* email.\r\n\r\nh1. With a title\r\n\r\nand a paragraph.", issue.description
906 end
907 end
907 end
908 end
908
909
909 def test_should_handle_outlook_web_access_2010_html_only
910 def test_should_handle_outlook_web_access_2010_html_only
910 issue = submit_email('outlook_web_access_2010_html_only.eml', :issue => {:project => 'ecookbook'})
911 issue = submit_email('outlook_web_access_2010_html_only.eml', :issue => {:project => 'ecookbook'})
911 assert issue.is_a?(Issue)
912 assert issue.is_a?(Issue)
912 issue.reload
913 issue.reload
913 assert_equal 'Upgrade Redmine to 3.0.x', issue.subject
914 assert_equal 'Upgrade Redmine to 3.0.x', issue.subject
914 assert_equal "A mess.\r\n\r\n--Geoff Maciolek\r\nMYCOMPANYNAME, LLC", issue.description
915 assert_equal "A mess.\r\n\r\n--Geoff Maciolek\r\nMYCOMPANYNAME, LLC", issue.description
915 end
916 end
916
917
917 def test_should_handle_outlook_2010_html_only
918 def test_should_handle_outlook_2010_html_only
918 issue = submit_email('outlook_2010_html_only.eml', :issue => {:project => 'ecookbook'})
919 issue = submit_email('outlook_2010_html_only.eml', :issue => {:project => 'ecookbook'})
919 assert issue.is_a?(Issue)
920 assert issue.is_a?(Issue)
920 issue.reload
921 issue.reload
921 assert_equal 'Test email', issue.subject
922 assert_equal 'Test email', issue.subject
922 assert_equal "Simple, unadorned test email generated by Outlook 2010. It is in HTML format, but" +
923 assert_equal "Simple, unadorned test email generated by Outlook 2010. It is in HTML format, but" +
923 " no special formatting has been chosen. I’m going to save this as a draft and then manually" +
924 " no special formatting has been chosen. I’m going to save this as a draft and then manually" +
924 " drop it into the Inbox for scraping by Redmine 3.0.2.", issue.description
925 " drop it into the Inbox for scraping by Redmine 3.0.2.", issue.description
925 end
926 end
926
927
927 test "truncate emails with no setting should add the entire email into the issue" do
928 test "truncate emails with no setting should add the entire email into the issue" do
928 with_settings :mail_handler_body_delimiters => '' do
929 with_settings :mail_handler_body_delimiters => '' do
929 issue = submit_email('ticket_on_given_project.eml')
930 issue = submit_email('ticket_on_given_project.eml')
930 assert_issue_created(issue)
931 assert_issue_created(issue)
931 assert issue.description.include?('---')
932 assert issue.description.include?('---')
932 assert issue.description.include?('This paragraph is after the delimiter')
933 assert issue.description.include?('This paragraph is after the delimiter')
933 end
934 end
934 end
935 end
935
936
936 test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
937 test "truncate emails with a single string should truncate the email at the delimiter for the issue" do
937 with_settings :mail_handler_body_delimiters => '---' do
938 with_settings :mail_handler_body_delimiters => '---' do
938 issue = submit_email('ticket_on_given_project.eml')
939 issue = submit_email('ticket_on_given_project.eml')
939 assert_issue_created(issue)
940 assert_issue_created(issue)
940 assert issue.description.include?('This paragraph is before delimiters')
941 assert issue.description.include?('This paragraph is before delimiters')
941 assert issue.description.include?('--- This line starts with a delimiter')
942 assert issue.description.include?('--- This line starts with a delimiter')
942 assert !issue.description.match(/^---$/)
943 assert !issue.description.match(/^---$/)
943 assert !issue.description.include?('This paragraph is after the delimiter')
944 assert !issue.description.include?('This paragraph is after the delimiter')
944 end
945 end
945 end
946 end
946
947
947 test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
948 test "truncate emails with a single quoted reply should truncate the email at the delimiter with the quoted reply symbols (>)" do
948 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
949 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
949 journal = submit_email('issue_update_with_quoted_reply_above.eml')
950 journal = submit_email('issue_update_with_quoted_reply_above.eml')
950 assert journal.is_a?(Journal)
951 assert journal.is_a?(Journal)
951 assert journal.notes.include?('An update to the issue by the sender.')
952 assert journal.notes.include?('An update to the issue by the sender.')
952 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
953 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
953 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
954 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
954 end
955 end
955 end
956 end
956
957
957 test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
958 test "truncate emails with multiple quoted replies should truncate the email at the delimiter with the quoted reply symbols (>)" do
958 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
959 with_settings :mail_handler_body_delimiters => '--- Reply above. Do not remove this line. ---' do
959 journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
960 journal = submit_email('issue_update_with_multiple_quoted_reply_above.eml')
960 assert journal.is_a?(Journal)
961 assert journal.is_a?(Journal)
961 assert journal.notes.include?('An update to the issue by the sender.')
962 assert journal.notes.include?('An update to the issue by the sender.')
962 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
963 assert !journal.notes.match(Regexp.escape("--- Reply above. Do not remove this line. ---"))
963 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
964 assert !journal.notes.include?('Looks like the JSON api for projects was missed.')
964 end
965 end
965 end
966 end
966
967
967 test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
968 test "truncate emails with multiple strings should truncate the email at the first delimiter found (BREAK)" do
968 with_settings :mail_handler_body_delimiters => "---\nBREAK" do
969 with_settings :mail_handler_body_delimiters => "---\nBREAK" do
969 issue = submit_email('ticket_on_given_project.eml')
970 issue = submit_email('ticket_on_given_project.eml')
970 assert_issue_created(issue)
971 assert_issue_created(issue)
971 assert issue.description.include?('This paragraph is before delimiters')
972 assert issue.description.include?('This paragraph is before delimiters')
972 assert !issue.description.include?('BREAK')
973 assert !issue.description.include?('BREAK')
973 assert !issue.description.include?('This paragraph is between delimiters')
974 assert !issue.description.include?('This paragraph is between delimiters')
974 assert !issue.description.match(/^---$/)
975 assert !issue.description.match(/^---$/)
975 assert !issue.description.include?('This paragraph is after the delimiter')
976 assert !issue.description.include?('This paragraph is after the delimiter')
976 end
977 end
977 end
978 end
978
979
979 def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored
980 def test_attachments_that_match_mail_handler_excluded_filenames_should_be_ignored
980 with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do
981 with_settings :mail_handler_excluded_filenames => '*.vcf, *.jpg' do
981 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
982 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
982 assert issue.is_a?(Issue)
983 assert issue.is_a?(Issue)
983 assert !issue.new_record?
984 assert !issue.new_record?
984 assert_equal 0, issue.reload.attachments.size
985 assert_equal 0, issue.reload.attachments.size
985 end
986 end
986 end
987 end
987
988
988 def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached
989 def test_attachments_that_do_not_match_mail_handler_excluded_filenames_should_be_attached
989 with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do
990 with_settings :mail_handler_excluded_filenames => '*.vcf, *.gif' do
990 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
991 issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'})
991 assert issue.is_a?(Issue)
992 assert issue.is_a?(Issue)
992 assert !issue.new_record?
993 assert !issue.new_record?
993 assert_equal 1, issue.reload.attachments.size
994 assert_equal 1, issue.reload.attachments.size
994 end
995 end
995 end
996 end
996
997
997 def test_email_with_long_subject_line
998 def test_email_with_long_subject_line
998 issue = submit_email('ticket_with_long_subject.eml')
999 issue = submit_email('ticket_with_long_subject.eml')
999 assert issue.is_a?(Issue)
1000 assert issue.is_a?(Issue)
1000 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]
1001 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]
1001 end
1002 end
1002
1003
1003 def test_first_keyword_should_be_matched
1004 def test_first_keyword_should_be_matched
1004 issue = submit_email('ticket_with_duplicate_keyword.eml', :allow_override => 'priority')
1005 issue = submit_email('ticket_with_duplicate_keyword.eml', :allow_override => 'priority')
1005 assert issue.is_a?(Issue)
1006 assert issue.is_a?(Issue)
1006 assert_equal 'High', issue.priority.name
1007 assert_equal 'High', issue.priority.name
1007 end
1008 end
1008
1009
1009 def test_keyword_after_delimiter_should_be_ignored
1010 def test_keyword_after_delimiter_should_be_ignored
1010 with_settings :mail_handler_body_delimiters => "== DELIMITER ==" do
1011 with_settings :mail_handler_body_delimiters => "== DELIMITER ==" do
1011 issue = submit_email('ticket_with_keyword_after_delimiter.eml', :allow_override => 'priority')
1012 issue = submit_email('ticket_with_keyword_after_delimiter.eml', :allow_override => 'priority')
1012 assert issue.is_a?(Issue)
1013 assert issue.is_a?(Issue)
1013 assert_equal 'Normal', issue.priority.name
1014 assert_equal 'Normal', issue.priority.name
1014 end
1015 end
1015 end
1016 end
1016
1017
1017 def test_new_user_from_attributes_should_return_valid_user
1018 def test_new_user_from_attributes_should_return_valid_user
1018 to_test = {
1019 to_test = {
1019 # [address, name] => [login, firstname, lastname]
1020 # [address, name] => [login, firstname, lastname]
1020 ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
1021 ['jsmith@example.net', nil] => ['jsmith@example.net', 'jsmith', '-'],
1021 ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
1022 ['jsmith@example.net', 'John'] => ['jsmith@example.net', 'John', '-'],
1022 ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
1023 ['jsmith@example.net', 'John Smith'] => ['jsmith@example.net', 'John', 'Smith'],
1023 ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
1024 ['jsmith@example.net', 'John Paul Smith'] => ['jsmith@example.net', 'John', 'Paul Smith'],
1024 ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
1025 ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsTheMaximumLength Smith'] => ['jsmith@example.net', 'AVeryLongFirstnameThatExceedsT', 'Smith'],
1025 ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
1026 ['jsmith@example.net', 'John AVeryLongLastnameThatExceedsTheMaximumLength'] => ['jsmith@example.net', 'John', 'AVeryLongLastnameThatExceedsTh']
1026 }
1027 }
1027
1028
1028 to_test.each do |attrs, expected|
1029 to_test.each do |attrs, expected|
1029 user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
1030 user = MailHandler.new_user_from_attributes(attrs.first, attrs.last)
1030
1031
1031 assert user.valid?, user.errors.full_messages.to_s
1032 assert user.valid?, user.errors.full_messages.to_s
1032 assert_equal attrs.first, user.mail
1033 assert_equal attrs.first, user.mail
1033 assert_equal expected[0], user.login
1034 assert_equal expected[0], user.login
1034 assert_equal expected[1], user.firstname
1035 assert_equal expected[1], user.firstname
1035 assert_equal expected[2], user.lastname
1036 assert_equal expected[2], user.lastname
1036 assert_equal 'only_my_events', user.mail_notification
1037 assert_equal 'only_my_events', user.mail_notification
1037 end
1038 end
1038 end
1039 end
1039
1040
1040 def test_new_user_from_attributes_should_use_default_login_if_invalid
1041 def test_new_user_from_attributes_should_use_default_login_if_invalid
1041 user = MailHandler.new_user_from_attributes('foo+bar@example.net')
1042 user = MailHandler.new_user_from_attributes('foo+bar@example.net')
1042 assert user.valid?
1043 assert user.valid?
1043 assert user.login =~ /^user[a-f0-9]+$/
1044 assert user.login =~ /^user[a-f0-9]+$/
1044 assert_equal 'foo+bar@example.net', user.mail
1045 assert_equal 'foo+bar@example.net', user.mail
1045 end
1046 end
1046
1047
1047 def test_new_user_with_utf8_encoded_fullname_should_be_decoded
1048 def test_new_user_with_utf8_encoded_fullname_should_be_decoded
1048 assert_difference 'User.count' do
1049 assert_difference 'User.count' do
1049 issue = submit_email(
1050 issue = submit_email(
1050 'fullname_of_sender_as_utf8_encoded.eml',
1051 'fullname_of_sender_as_utf8_encoded.eml',
1051 :issue => {:project => 'ecookbook'},
1052 :issue => {:project => 'ecookbook'},
1052 :unknown_user => 'create'
1053 :unknown_user => 'create'
1053 )
1054 )
1054 end
1055 end
1055 user = User.order('id DESC').first
1056 user = User.order('id DESC').first
1056 assert_equal "foo@example.org", user.mail
1057 assert_equal "foo@example.org", user.mail
1057 str1 = "\xc3\x84\xc3\xa4".force_encoding('UTF-8')
1058 str1 = "\xc3\x84\xc3\xa4".force_encoding('UTF-8')
1058 str2 = "\xc3\x96\xc3\xb6".force_encoding('UTF-8')
1059 str2 = "\xc3\x96\xc3\xb6".force_encoding('UTF-8')
1059 assert_equal str1, user.firstname
1060 assert_equal str1, user.firstname
1060 assert_equal str2, user.lastname
1061 assert_equal str2, user.lastname
1061 end
1062 end
1062
1063
1063 def test_extract_options_from_env_should_return_options
1064 def test_extract_options_from_env_should_return_options
1064 options = MailHandler.extract_options_from_env({
1065 options = MailHandler.extract_options_from_env({
1065 'tracker' => 'defect',
1066 'tracker' => 'defect',
1066 'project' => 'foo',
1067 'project' => 'foo',
1067 'unknown_user' => 'create'
1068 'unknown_user' => 'create'
1068 })
1069 })
1069
1070
1070 assert_equal({
1071 assert_equal({
1071 :issue => {:tracker => 'defect', :project => 'foo'},
1072 :issue => {:tracker => 'defect', :project => 'foo'},
1072 :unknown_user => 'create'
1073 :unknown_user => 'create'
1073 }, options)
1074 }, options)
1074 end
1075 end
1075
1076
1076 def test_safe_receive_should_rescue_exceptions_and_return_false
1077 def test_safe_receive_should_rescue_exceptions_and_return_false
1077 MailHandler.stubs(:receive).raises(Exception.new "Something went wrong")
1078 MailHandler.stubs(:receive).raises(Exception.new "Something went wrong")
1078
1079
1079 assert_equal false, MailHandler.safe_receive
1080 assert_equal false, MailHandler.safe_receive
1080 end
1081 end
1081
1082
1082 private
1083 private
1083
1084
1084 def submit_email(filename, options={})
1085 def submit_email(filename, options={})
1085 raw = IO.read(File.join(FIXTURES_PATH, filename))
1086 raw = IO.read(File.join(FIXTURES_PATH, filename))
1086 yield raw if block_given?
1087 yield raw if block_given?
1087 MailHandler.receive(raw, options)
1088 MailHandler.receive(raw, options)
1088 end
1089 end
1089
1090
1090 def assert_issue_created(issue)
1091 def assert_issue_created(issue)
1091 assert issue.is_a?(Issue)
1092 assert issue.is_a?(Issue)
1092 assert !issue.new_record?
1093 assert !issue.new_record?
1093 issue.reload
1094 issue.reload
1094 end
1095 end
1095 end
1096 end
@@ -1,192 +1,201
1 # Redmine - project management software
1 # Redmine - project management software
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
2 # Copyright (C) 2006-2016 Jean-Philippe Lang
3 #
3 #
4 # This program is free software; you can redistribute it and/or
4 # This program is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU General Public License
5 # modify it under the terms of the GNU General Public License
6 # as published by the Free Software Foundation; either version 2
6 # as published by the Free Software Foundation; either version 2
7 # of the License, or (at your option) any later version.
7 # of the License, or (at your option) any later version.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU General Public License
14 # You should have received a copy of the GNU General Public License
15 # along with this program; if not, write to the Free Software
15 # along with this program; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17
17
18 require File.expand_path('../../test_helper', __FILE__)
18 require File.expand_path('../../test_helper', __FILE__)
19
19
20 class WatcherTest < ActiveSupport::TestCase
20 class WatcherTest < ActiveSupport::TestCase
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :enabled_modules,
21 fixtures :projects, :users, :email_addresses, :members, :member_roles, :roles, :enabled_modules,
22 :issues, :issue_statuses, :enumerations, :trackers, :projects_trackers,
22 :issues, :issue_statuses, :enumerations, :trackers, :projects_trackers,
23 :boards, :messages,
23 :boards, :messages,
24 :wikis, :wiki_pages,
24 :wikis, :wiki_pages,
25 :watchers
25 :watchers
26
26
27 def setup
27 def setup
28 @user = User.find(1)
28 @user = User.find(1)
29 @issue = Issue.find(1)
29 @issue = Issue.find(1)
30 end
30 end
31
31
32 def test_validate
32 def test_validate
33 user = User.find(5)
33 user = User.find(5)
34 assert !user.active?
34 assert !user.active?
35 watcher = Watcher.new(:user_id => user.id)
35 watcher = Watcher.new(:user_id => user.id)
36 assert !watcher.save
36 assert !watcher.save
37 end
37 end
38
38
39 def test_watch
39 def test_watch
40 assert @issue.add_watcher(@user)
40 assert @issue.add_watcher(@user)
41 @issue.reload
41 @issue.reload
42 assert @issue.watchers.detect { |w| w.user == @user }
42 assert @issue.watchers.detect { |w| w.user == @user }
43 end
43 end
44
44
45 def test_cant_watch_twice
45 def test_cant_watch_twice
46 assert @issue.add_watcher(@user)
46 assert @issue.add_watcher(@user)
47 assert !@issue.add_watcher(@user)
47 assert !@issue.add_watcher(@user)
48 end
48 end
49
49
50 def test_watched_by
50 def test_watched_by
51 assert @issue.add_watcher(@user)
51 assert @issue.add_watcher(@user)
52 @issue.reload
52 @issue.reload
53 assert @issue.watched_by?(@user)
53 assert @issue.watched_by?(@user)
54 assert Issue.watched_by(@user).include?(@issue)
54 assert Issue.watched_by(@user).include?(@issue)
55 end
55 end
56
56
57 def test_watcher_users
57 def test_watcher_users
58 watcher_users = Issue.find(2).watcher_users
58 watcher_users = Issue.find(2).watcher_users
59 assert_kind_of Array, watcher_users.collect{|w| w}
59 assert_kind_of Array, watcher_users.collect{|w| w}
60 assert_kind_of User, watcher_users.first
60 assert_kind_of User, watcher_users.first
61 end
61 end
62
62
63 def test_watcher_users_should_be_reloaded_after_adding_a_watcher
64 issue = Issue.find(2)
65 user = User.generate!
66
67 assert_difference 'issue.watcher_users.to_a.size' do
68 issue.add_watcher user
69 end
70 end
71
63 def test_watcher_users_should_not_validate_user
72 def test_watcher_users_should_not_validate_user
64 User.where(:id => 1).update_all("firstname = ''")
73 User.where(:id => 1).update_all("firstname = ''")
65 @user.reload
74 @user.reload
66 assert !@user.valid?
75 assert !@user.valid?
67
76
68 issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
77 issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
69 issue.watcher_users << @user
78 issue.watcher_users << @user
70 issue.save!
79 issue.save!
71 assert issue.watched_by?(@user)
80 assert issue.watched_by?(@user)
72 end
81 end
73
82
74 def test_watcher_user_ids
83 def test_watcher_user_ids
75 assert_equal [1, 3], Issue.find(2).watcher_user_ids.sort
84 assert_equal [1, 3], Issue.find(2).watcher_user_ids.sort
76 end
85 end
77
86
78 def test_watcher_user_ids=
87 def test_watcher_user_ids=
79 issue = Issue.new
88 issue = Issue.new
80 issue.watcher_user_ids = ['1', '3']
89 issue.watcher_user_ids = ['1', '3']
81 assert issue.watched_by?(User.find(1))
90 assert issue.watched_by?(User.find(1))
82 end
91 end
83
92
84 def test_watcher_user_ids_should_make_ids_uniq
93 def test_watcher_user_ids_should_make_ids_uniq
85 issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
94 issue = Issue.new(:project => Project.find(1), :tracker_id => 1, :subject => "test", :author => User.find(2))
86 issue.watcher_user_ids = ['1', '3', '1']
95 issue.watcher_user_ids = ['1', '3', '1']
87 issue.save!
96 issue.save!
88 assert_equal 2, issue.watchers.count
97 assert_equal 2, issue.watchers.count
89 end
98 end
90
99
91 def test_addable_watcher_users
100 def test_addable_watcher_users
92 addable_watcher_users = @issue.addable_watcher_users
101 addable_watcher_users = @issue.addable_watcher_users
93 assert_kind_of Array, addable_watcher_users
102 assert_kind_of Array, addable_watcher_users
94 assert_kind_of User, addable_watcher_users.first
103 assert_kind_of User, addable_watcher_users.first
95 end
104 end
96
105
97 def test_addable_watcher_users_should_not_include_user_that_cannot_view_the_object
106 def test_addable_watcher_users_should_not_include_user_that_cannot_view_the_object
98 issue = Issue.new(:project => Project.find(1), :is_private => true)
107 issue = Issue.new(:project => Project.find(1), :is_private => true)
99 assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
108 assert_nil issue.addable_watcher_users.detect {|user| !issue.visible?(user)}
100 end
109 end
101
110
102 def test_any_watched_should_return_false_if_no_object_is_watched
111 def test_any_watched_should_return_false_if_no_object_is_watched
103 objects = (0..2).map {Issue.generate!}
112 objects = (0..2).map {Issue.generate!}
104
113
105 assert_equal false, Watcher.any_watched?(objects, @user)
114 assert_equal false, Watcher.any_watched?(objects, @user)
106 end
115 end
107
116
108 def test_any_watched_should_return_true_if_one_object_is_watched
117 def test_any_watched_should_return_true_if_one_object_is_watched
109 objects = (0..2).map {Issue.generate!}
118 objects = (0..2).map {Issue.generate!}
110 objects.last.add_watcher(@user)
119 objects.last.add_watcher(@user)
111
120
112 assert_equal true, Watcher.any_watched?(objects, @user)
121 assert_equal true, Watcher.any_watched?(objects, @user)
113 end
122 end
114
123
115 def test_any_watched_should_return_false_with_no_object
124 def test_any_watched_should_return_false_with_no_object
116 assert_equal false, Watcher.any_watched?([], @user)
125 assert_equal false, Watcher.any_watched?([], @user)
117 end
126 end
118
127
119 def test_recipients
128 def test_recipients
120 @issue.watchers.delete_all
129 @issue.watchers.delete_all
121 @issue.reload
130 @issue.reload
122
131
123 assert @issue.watcher_recipients.empty?
132 assert @issue.watcher_recipients.empty?
124 assert @issue.add_watcher(@user)
133 assert @issue.add_watcher(@user)
125
134
126 @user.mail_notification = 'all'
135 @user.mail_notification = 'all'
127 @user.save!
136 @user.save!
128 @issue.reload
137 @issue.reload
129 assert @issue.watcher_recipients.include?(@user.mail)
138 assert @issue.watcher_recipients.include?(@user.mail)
130
139
131 @user.mail_notification = 'none'
140 @user.mail_notification = 'none'
132 @user.save!
141 @user.save!
133 @issue.reload
142 @issue.reload
134 assert !@issue.watcher_recipients.include?(@user.mail)
143 assert !@issue.watcher_recipients.include?(@user.mail)
135 end
144 end
136
145
137 def test_unwatch
146 def test_unwatch
138 assert @issue.add_watcher(@user)
147 assert @issue.add_watcher(@user)
139 @issue.reload
148 @issue.reload
140 assert_equal 1, @issue.remove_watcher(@user)
149 assert_equal 1, @issue.remove_watcher(@user)
141 end
150 end
142
151
143 def test_prune_with_user
152 def test_prune_with_user
144 Watcher.delete_all("user_id = 9")
153 Watcher.delete_all("user_id = 9")
145 user = User.find(9)
154 user = User.find(9)
146
155
147 # public
156 # public
148 Watcher.create!(:watchable => Issue.find(1), :user => user)
157 Watcher.create!(:watchable => Issue.find(1), :user => user)
149 Watcher.create!(:watchable => Issue.find(2), :user => user)
158 Watcher.create!(:watchable => Issue.find(2), :user => user)
150 Watcher.create!(:watchable => Message.find(1), :user => user)
159 Watcher.create!(:watchable => Message.find(1), :user => user)
151 Watcher.create!(:watchable => Wiki.find(1), :user => user)
160 Watcher.create!(:watchable => Wiki.find(1), :user => user)
152 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
161 Watcher.create!(:watchable => WikiPage.find(2), :user => user)
153
162
154 # private project (id: 2)
163 # private project (id: 2)
155 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
164 Member.create!(:project => Project.find(2), :principal => user, :role_ids => [1])
156 Watcher.create!(:watchable => Issue.find(4), :user => user)
165 Watcher.create!(:watchable => Issue.find(4), :user => user)
157 Watcher.create!(:watchable => Message.find(7), :user => user)
166 Watcher.create!(:watchable => Message.find(7), :user => user)
158 Watcher.create!(:watchable => Wiki.find(2), :user => user)
167 Watcher.create!(:watchable => Wiki.find(2), :user => user)
159 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
168 Watcher.create!(:watchable => WikiPage.find(3), :user => user)
160
169
161 assert_no_difference 'Watcher.count' do
170 assert_no_difference 'Watcher.count' do
162 Watcher.prune(:user => User.find(9))
171 Watcher.prune(:user => User.find(9))
163 end
172 end
164
173
165 Member.delete_all
174 Member.delete_all
166
175
167 assert_difference 'Watcher.count', -4 do
176 assert_difference 'Watcher.count', -4 do
168 Watcher.prune(:user => User.find(9))
177 Watcher.prune(:user => User.find(9))
169 end
178 end
170
179
171 assert Issue.find(1).watched_by?(user)
180 assert Issue.find(1).watched_by?(user)
172 assert !Issue.find(4).watched_by?(user)
181 assert !Issue.find(4).watched_by?(user)
173 end
182 end
174
183
175 def test_prune_with_project
184 def test_prune_with_project
176 user = User.find(9)
185 user = User.find(9)
177 Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false) # project 2
186 Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false) # project 2
178 Watcher.new(:watchable => Issue.find(6), :user => User.find(9)).save(:validate => false) # project 5
187 Watcher.new(:watchable => Issue.find(6), :user => User.find(9)).save(:validate => false) # project 5
179
188
180 assert Watcher.prune(:project => Project.find(5)) > 0
189 assert Watcher.prune(:project => Project.find(5)) > 0
181 assert Issue.find(4).watched_by?(user)
190 assert Issue.find(4).watched_by?(user)
182 assert !Issue.find(6).watched_by?(user)
191 assert !Issue.find(6).watched_by?(user)
183 end
192 end
184
193
185 def test_prune_all
194 def test_prune_all
186 user = User.find(9)
195 user = User.find(9)
187 Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false)
196 Watcher.new(:watchable => Issue.find(4), :user => User.find(9)).save(:validate => false)
188
197
189 assert Watcher.prune > 0
198 assert Watcher.prune > 0
190 assert !Issue.find(4).watched_by?(user)
199 assert !Issue.find(4).watched_by?(user)
191 end
200 end
192 end
201 end
General Comments 0
You need to be logged in to leave comments. Login now