@@ -0,0 +1,118 | |||
|
1 | # redMine - project management software | |
|
2 | # Copyright (C) 2006-2009 Jean-Philippe Lang | |
|
3 | # | |
|
4 | # This program is free software; you can redistribute it and/or | |
|
5 | # modify it under the terms of the GNU General Public License | |
|
6 | # as published by the Free Software Foundation; either version 2 | |
|
7 | # of the License, or (at your option) any later version. | |
|
8 | # | |
|
9 | # This program is distributed in the hope that it will be useful, | |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
|
12 | # GNU General Public License for more details. | |
|
13 | # | |
|
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 | |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
|
17 | ||
|
18 | require File.dirname(__FILE__) + '/../test_helper' | |
|
19 | ||
|
20 | class JournalObserverTest < ActiveSupport::TestCase | |
|
21 | fixtures :issues, :issue_statuses, :journals, :journal_details | |
|
22 | ||
|
23 | def setup | |
|
24 | ActionMailer::Base.deliveries.clear | |
|
25 | @journal = Journal.find 1 | |
|
26 | end | |
|
27 | ||
|
28 | # context: issue_updated notified_events | |
|
29 | def test_create_should_send_email_notification_with_issue_updated | |
|
30 | Setting.notified_events = ['issue_updated'] | |
|
31 | issue = Issue.find(:first) | |
|
32 | user = User.find(:first) | |
|
33 | journal = issue.init_journal(user, issue) | |
|
34 | ||
|
35 | assert journal.save | |
|
36 | assert_equal 1, ActionMailer::Base.deliveries.size | |
|
37 | end | |
|
38 | ||
|
39 | def test_create_should_not_send_email_notification_without_issue_updated | |
|
40 | Setting.notified_events = [] | |
|
41 | issue = Issue.find(:first) | |
|
42 | user = User.find(:first) | |
|
43 | journal = issue.init_journal(user, issue) | |
|
44 | ||
|
45 | assert journal.save | |
|
46 | assert_equal 0, ActionMailer::Base.deliveries.size | |
|
47 | end | |
|
48 | ||
|
49 | # context: issue_note_added notified_events | |
|
50 | def test_create_should_send_email_notification_with_issue_note_added | |
|
51 | Setting.notified_events = ['issue_note_added'] | |
|
52 | issue = Issue.find(:first) | |
|
53 | user = User.find(:first) | |
|
54 | journal = issue.init_journal(user, issue) | |
|
55 | journal.notes = 'This update has a note' | |
|
56 | ||
|
57 | assert journal.save | |
|
58 | assert_equal 1, ActionMailer::Base.deliveries.size | |
|
59 | end | |
|
60 | ||
|
61 | def test_create_should_not_send_email_notification_without_issue_note_added | |
|
62 | Setting.notified_events = [] | |
|
63 | issue = Issue.find(:first) | |
|
64 | user = User.find(:first) | |
|
65 | journal = issue.init_journal(user, issue) | |
|
66 | journal.notes = 'This update has a note' | |
|
67 | ||
|
68 | assert journal.save | |
|
69 | assert_equal 0, ActionMailer::Base.deliveries.size | |
|
70 | end | |
|
71 | ||
|
72 | # context: issue_status_updated notified_events | |
|
73 | def test_create_should_send_email_notification_with_issue_status_updated | |
|
74 | Setting.notified_events = ['issue_status_updated'] | |
|
75 | issue = Issue.find(:first) | |
|
76 | user = User.find(:first) | |
|
77 | issue.init_journal(user, issue) | |
|
78 | issue.status = IssueStatus.last | |
|
79 | ||
|
80 | assert issue.save | |
|
81 | assert_equal 1, ActionMailer::Base.deliveries.size | |
|
82 | end | |
|
83 | ||
|
84 | def test_create_should_not_send_email_notification_without_issue_status_updated | |
|
85 | Setting.notified_events = [] | |
|
86 | issue = Issue.find(:first) | |
|
87 | user = User.find(:first) | |
|
88 | issue.init_journal(user, issue) | |
|
89 | issue.status = IssueStatus.last | |
|
90 | ||
|
91 | assert issue.save | |
|
92 | assert_equal 0, ActionMailer::Base.deliveries.size | |
|
93 | end | |
|
94 | ||
|
95 | # context: issue_priority_updated notified_events | |
|
96 | def test_create_should_send_email_notification_with_issue_priority_updated | |
|
97 | Setting.notified_events = ['issue_priority_updated'] | |
|
98 | issue = Issue.find(:first) | |
|
99 | user = User.find(:first) | |
|
100 | issue.init_journal(user, issue) | |
|
101 | issue.priority = IssuePriority.last | |
|
102 | ||
|
103 | assert issue.save | |
|
104 | assert_equal 1, ActionMailer::Base.deliveries.size | |
|
105 | end | |
|
106 | ||
|
107 | def test_create_should_not_send_email_notification_without_issue_priority_updated | |
|
108 | Setting.notified_events = [] | |
|
109 | issue = Issue.find(:first) | |
|
110 | user = User.find(:first) | |
|
111 | issue.init_journal(user, issue) | |
|
112 | issue.priority = IssuePriority.last | |
|
113 | ||
|
114 | assert issue.save | |
|
115 | assert_equal 0, ActionMailer::Base.deliveries.size | |
|
116 | end | |
|
117 | ||
|
118 | end |
@@ -1,22 +1,27 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | class JournalObserver < ActiveRecord::Observer |
|
19 | 19 | def after_create(journal) |
|
20 |
|
|
|
20 | if Setting.notified_events.include?('issue_updated') || | |
|
21 | (Setting.notified_events.include?('issue_note_added') && journal.notes.present?) || | |
|
22 | (Setting.notified_events.include?('issue_status_updated') && journal.new_status.present?) || | |
|
23 | (Setting.notified_events.include?('issue_priority_updated') && journal.new_value_for('priority_id').present?) | |
|
24 | Mailer.deliver_issue_edit(journal) | |
|
25 | end | |
|
21 | 26 | end |
|
22 | 27 | end |
@@ -1,19 +1,22 | |||
|
1 | 1 | module Redmine |
|
2 | 2 | class Notifiable |
|
3 | 3 | CoreNotifications = [ |
|
4 | 4 | 'issue_added', |
|
5 | 5 | 'issue_updated', |
|
6 | 'issue_note_added', | |
|
7 | 'issue_status_updated', | |
|
8 | 'issue_priority_updated', | |
|
6 | 9 | 'news_added', |
|
7 | 10 | 'document_added', |
|
8 | 11 | 'file_added', |
|
9 | 12 | 'message_posted', |
|
10 | 13 | 'wiki_content_added', |
|
11 | 14 | 'wiki_content_updated' |
|
12 | 15 | ] |
|
13 | 16 | |
|
14 | 17 | # TODO: Plugin API for adding a new notification? |
|
15 | 18 | def self.all |
|
16 | 19 | CoreNotifications |
|
17 | 20 | end |
|
18 | 21 | end |
|
19 | 22 | end |
@@ -1,38 +1,38 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2008 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.dirname(__FILE__) + '/../../../test_helper' |
|
19 | 19 | |
|
20 | 20 | class Redmine::NotifiableTest < ActiveSupport::TestCase |
|
21 | 21 | def setup |
|
22 | 22 | end |
|
23 | 23 | |
|
24 | 24 | def test_included_core_notifications |
|
25 |
assert_equal |
|
|
25 | assert_equal 11, Redmine::Notifiable::CoreNotifications.length | |
|
26 | 26 | Redmine::Notifiable::CoreNotifications.length |
|
27 | 27 | |
|
28 | %w(issue_added issue_updated news_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable| | |
|
28 | %w(issue_added issue_updated issue_note_added issue_status_updated issue_priority_updated news_added document_added file_added message_posted wiki_content_added wiki_content_updated).each do |notifiable| | |
|
29 | 29 | assert Redmine::Notifiable::CoreNotifications.include?(notifiable), "missing #{notifiable}" |
|
30 | 30 | end |
|
31 | 31 | end |
|
32 | 32 | |
|
33 | 33 | def test_all_should_include_all_of_the_core_notifications |
|
34 | 34 | Redmine::Notifiable::CoreNotifications.each do |notifiable| |
|
35 | 35 | assert Redmine::Notifiable.all.include?(notifiable), "missing #{notifiable} in #all" |
|
36 | 36 | end |
|
37 | 37 | end |
|
38 | 38 | end |
@@ -1,371 +1,372 | |||
|
1 | 1 | # encoding: utf-8 |
|
2 | 2 | # |
|
3 | 3 | # Redmine - project management software |
|
4 | 4 | # Copyright (C) 2006-2009 Jean-Philippe Lang |
|
5 | 5 | # |
|
6 | 6 | # This program is free software; you can redistribute it and/or |
|
7 | 7 | # modify it under the terms of the GNU General Public License |
|
8 | 8 | # as published by the Free Software Foundation; either version 2 |
|
9 | 9 | # of the License, or (at your option) any later version. |
|
10 | 10 | # |
|
11 | 11 | # This program is distributed in the hope that it will be useful, |
|
12 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
13 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
14 | 14 | # GNU General Public License for more details. |
|
15 | 15 | # |
|
16 | 16 | # You should have received a copy of the GNU General Public License |
|
17 | 17 | # along with this program; if not, write to the Free Software |
|
18 | 18 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
19 | 19 | |
|
20 | 20 | require File.dirname(__FILE__) + '/../test_helper' |
|
21 | 21 | |
|
22 | 22 | class MailHandlerTest < ActiveSupport::TestCase |
|
23 | 23 | fixtures :users, :projects, |
|
24 | 24 | :enabled_modules, |
|
25 | 25 | :roles, |
|
26 | 26 | :members, |
|
27 | 27 | :member_roles, |
|
28 | 28 | :issues, |
|
29 | 29 | :issue_statuses, |
|
30 | 30 | :workflows, |
|
31 | 31 | :trackers, |
|
32 | 32 | :projects_trackers, |
|
33 | 33 | :enumerations, |
|
34 | 34 | :issue_categories, |
|
35 | 35 | :custom_fields, |
|
36 | 36 | :custom_fields_trackers, |
|
37 | 37 | :boards, |
|
38 | 38 | :messages |
|
39 | 39 | |
|
40 | 40 | FIXTURES_PATH = File.dirname(__FILE__) + '/../fixtures/mail_handler' |
|
41 | 41 | |
|
42 | 42 | def setup |
|
43 | 43 | ActionMailer::Base.deliveries.clear |
|
44 | 44 | end |
|
45 | 45 | |
|
46 | 46 | def test_add_issue |
|
47 | 47 | ActionMailer::Base.deliveries.clear |
|
48 | 48 | # This email contains: 'Project: onlinestore' |
|
49 | 49 | issue = submit_email('ticket_on_given_project.eml') |
|
50 | 50 | assert issue.is_a?(Issue) |
|
51 | 51 | assert !issue.new_record? |
|
52 | 52 | issue.reload |
|
53 | 53 | assert_equal 'New ticket on a given project', issue.subject |
|
54 | 54 | assert_equal User.find_by_login('jsmith'), issue.author |
|
55 | 55 | assert_equal Project.find(2), issue.project |
|
56 | 56 | assert_equal IssueStatus.find_by_name('Resolved'), issue.status |
|
57 | 57 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
58 | 58 | assert_equal '2010-01-01', issue.start_date.to_s |
|
59 | 59 | assert_equal '2010-12-31', issue.due_date.to_s |
|
60 | 60 | assert_equal User.find_by_login('jsmith'), issue.assigned_to |
|
61 | 61 | # keywords should be removed from the email body |
|
62 | 62 | assert !issue.description.match(/^Project:/i) |
|
63 | 63 | assert !issue.description.match(/^Status:/i) |
|
64 | 64 | # Email notification should be sent |
|
65 | 65 | mail = ActionMailer::Base.deliveries.last |
|
66 | 66 | assert_not_nil mail |
|
67 | 67 | assert mail.subject.include?('New ticket on a given project') |
|
68 | 68 | end |
|
69 | 69 | |
|
70 | 70 | def test_add_issue_with_status |
|
71 | 71 | # This email contains: 'Project: onlinestore' and 'Status: Resolved' |
|
72 | 72 | issue = submit_email('ticket_on_given_project.eml') |
|
73 | 73 | assert issue.is_a?(Issue) |
|
74 | 74 | assert !issue.new_record? |
|
75 | 75 | issue.reload |
|
76 | 76 | assert_equal Project.find(2), issue.project |
|
77 | 77 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status |
|
78 | 78 | end |
|
79 | 79 | |
|
80 | 80 | def test_add_issue_with_attributes_override |
|
81 | 81 | issue = submit_email('ticket_with_attributes.eml', :allow_override => 'tracker,category,priority') |
|
82 | 82 | assert issue.is_a?(Issue) |
|
83 | 83 | assert !issue.new_record? |
|
84 | 84 | issue.reload |
|
85 | 85 | assert_equal 'New ticket on a given project', issue.subject |
|
86 | 86 | assert_equal User.find_by_login('jsmith'), issue.author |
|
87 | 87 | assert_equal Project.find(2), issue.project |
|
88 | 88 | assert_equal 'Feature request', issue.tracker.to_s |
|
89 | 89 | assert_equal 'Stock management', issue.category.to_s |
|
90 | 90 | assert_equal 'Urgent', issue.priority.to_s |
|
91 | 91 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
92 | 92 | end |
|
93 | 93 | |
|
94 | 94 | def test_add_issue_with_partial_attributes_override |
|
95 | 95 | issue = submit_email('ticket_with_attributes.eml', :issue => {:priority => 'High'}, :allow_override => ['tracker']) |
|
96 | 96 | assert issue.is_a?(Issue) |
|
97 | 97 | assert !issue.new_record? |
|
98 | 98 | issue.reload |
|
99 | 99 | assert_equal 'New ticket on a given project', issue.subject |
|
100 | 100 | assert_equal User.find_by_login('jsmith'), issue.author |
|
101 | 101 | assert_equal Project.find(2), issue.project |
|
102 | 102 | assert_equal 'Feature request', issue.tracker.to_s |
|
103 | 103 | assert_nil issue.category |
|
104 | 104 | assert_equal 'High', issue.priority.to_s |
|
105 | 105 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
106 | 106 | end |
|
107 | 107 | |
|
108 | 108 | def test_add_issue_with_spaces_between_attribute_and_separator |
|
109 | 109 | issue = submit_email('ticket_with_spaces_between_attribute_and_separator.eml', :allow_override => 'tracker,category,priority') |
|
110 | 110 | assert issue.is_a?(Issue) |
|
111 | 111 | assert !issue.new_record? |
|
112 | 112 | issue.reload |
|
113 | 113 | assert_equal 'New ticket on a given project', issue.subject |
|
114 | 114 | assert_equal User.find_by_login('jsmith'), issue.author |
|
115 | 115 | assert_equal Project.find(2), issue.project |
|
116 | 116 | assert_equal 'Feature request', issue.tracker.to_s |
|
117 | 117 | assert_equal 'Stock management', issue.category.to_s |
|
118 | 118 | assert_equal 'Urgent', issue.priority.to_s |
|
119 | 119 | assert issue.description.include?('Lorem ipsum dolor sit amet, consectetuer adipiscing elit.') |
|
120 | 120 | end |
|
121 | 121 | |
|
122 | 122 | |
|
123 | 123 | def test_add_issue_with_attachment_to_specific_project |
|
124 | 124 | issue = submit_email('ticket_with_attachment.eml', :issue => {:project => 'onlinestore'}) |
|
125 | 125 | assert issue.is_a?(Issue) |
|
126 | 126 | assert !issue.new_record? |
|
127 | 127 | issue.reload |
|
128 | 128 | assert_equal 'Ticket created by email with attachment', issue.subject |
|
129 | 129 | assert_equal User.find_by_login('jsmith'), issue.author |
|
130 | 130 | assert_equal Project.find(2), issue.project |
|
131 | 131 | assert_equal 'This is a new ticket with attachments', issue.description |
|
132 | 132 | # Attachment properties |
|
133 | 133 | assert_equal 1, issue.attachments.size |
|
134 | 134 | assert_equal 'Paella.jpg', issue.attachments.first.filename |
|
135 | 135 | assert_equal 'image/jpeg', issue.attachments.first.content_type |
|
136 | 136 | assert_equal 10790, issue.attachments.first.filesize |
|
137 | 137 | end |
|
138 | 138 | |
|
139 | 139 | def test_add_issue_with_custom_fields |
|
140 | 140 | issue = submit_email('ticket_with_custom_fields.eml', :issue => {:project => 'onlinestore'}) |
|
141 | 141 | assert issue.is_a?(Issue) |
|
142 | 142 | assert !issue.new_record? |
|
143 | 143 | issue.reload |
|
144 | 144 | assert_equal 'New ticket with custom field values', issue.subject |
|
145 | 145 | assert_equal 'Value for a custom field', issue.custom_value_for(CustomField.find_by_name('Searchable field')).value |
|
146 | 146 | assert !issue.description.match(/^searchable field:/i) |
|
147 | 147 | end |
|
148 | 148 | |
|
149 | 149 | def test_add_issue_with_cc |
|
150 | 150 | issue = submit_email('ticket_with_cc.eml', :issue => {:project => 'ecookbook'}) |
|
151 | 151 | assert issue.is_a?(Issue) |
|
152 | 152 | assert !issue.new_record? |
|
153 | 153 | issue.reload |
|
154 | 154 | assert issue.watched_by?(User.find_by_mail('dlopper@somenet.foo')) |
|
155 | 155 | assert_equal 1, issue.watcher_user_ids.size |
|
156 | 156 | end |
|
157 | 157 | |
|
158 | 158 | def test_add_issue_by_unknown_user |
|
159 | 159 | assert_no_difference 'User.count' do |
|
160 | 160 | assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}) |
|
161 | 161 | end |
|
162 | 162 | end |
|
163 | 163 | |
|
164 | 164 | def test_add_issue_by_anonymous_user |
|
165 | 165 | Role.anonymous.add_permission!(:add_issues) |
|
166 | 166 | assert_no_difference 'User.count' do |
|
167 | 167 | issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept') |
|
168 | 168 | assert issue.is_a?(Issue) |
|
169 | 169 | assert issue.author.anonymous? |
|
170 | 170 | end |
|
171 | 171 | end |
|
172 | 172 | |
|
173 | 173 | def test_add_issue_by_anonymous_user_with_no_from_address |
|
174 | 174 | Role.anonymous.add_permission!(:add_issues) |
|
175 | 175 | assert_no_difference 'User.count' do |
|
176 | 176 | issue = submit_email('ticket_by_empty_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'accept') |
|
177 | 177 | assert issue.is_a?(Issue) |
|
178 | 178 | assert issue.author.anonymous? |
|
179 | 179 | end |
|
180 | 180 | end |
|
181 | 181 | |
|
182 | 182 | def test_add_issue_by_anonymous_user_on_private_project |
|
183 | 183 | Role.anonymous.add_permission!(:add_issues) |
|
184 | 184 | assert_no_difference 'User.count' do |
|
185 | 185 | assert_no_difference 'Issue.count' do |
|
186 | 186 | assert_equal false, submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :unknown_user => 'accept') |
|
187 | 187 | end |
|
188 | 188 | end |
|
189 | 189 | end |
|
190 | 190 | |
|
191 | 191 | def test_add_issue_by_anonymous_user_on_private_project_without_permission_check |
|
192 | 192 | assert_no_difference 'User.count' do |
|
193 | 193 | assert_difference 'Issue.count' do |
|
194 | 194 | issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'onlinestore'}, :no_permission_check => '1', :unknown_user => 'accept') |
|
195 | 195 | assert issue.is_a?(Issue) |
|
196 | 196 | assert issue.author.anonymous? |
|
197 | 197 | assert !issue.project.is_public? |
|
198 | 198 | end |
|
199 | 199 | end |
|
200 | 200 | end |
|
201 | 201 | |
|
202 | 202 | def test_add_issue_by_created_user |
|
203 | 203 | Setting.default_language = 'en' |
|
204 | 204 | assert_difference 'User.count' do |
|
205 | 205 | issue = submit_email('ticket_by_unknown_user.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create') |
|
206 | 206 | assert issue.is_a?(Issue) |
|
207 | 207 | assert issue.author.active? |
|
208 | 208 | assert_equal 'john.doe@somenet.foo', issue.author.mail |
|
209 | 209 | assert_equal 'John', issue.author.firstname |
|
210 | 210 | assert_equal 'Doe', issue.author.lastname |
|
211 | 211 | |
|
212 | 212 | # account information |
|
213 | 213 | email = ActionMailer::Base.deliveries.first |
|
214 | 214 | assert_not_nil email |
|
215 | 215 | assert email.subject.include?('account activation') |
|
216 | 216 | login = email.body.match(/\* Login: (.*)$/)[1] |
|
217 | 217 | password = email.body.match(/\* Password: (.*)$/)[1] |
|
218 | 218 | assert_equal issue.author, User.try_to_login(login, password) |
|
219 | 219 | end |
|
220 | 220 | end |
|
221 | 221 | |
|
222 | 222 | def test_add_issue_without_from_header |
|
223 | 223 | Role.anonymous.add_permission!(:add_issues) |
|
224 | 224 | assert_equal false, submit_email('ticket_without_from_header.eml') |
|
225 | 225 | end |
|
226 | 226 | |
|
227 | 227 | def test_add_issue_with_japanese_keywords |
|
228 | 228 | tracker = Tracker.create!(:name => 'ιηΊ') |
|
229 | 229 | Project.find(1).trackers << tracker |
|
230 | 230 | issue = submit_email('japanese_keywords_iso_2022_jp.eml', :issue => {:project => 'ecookbook'}, :allow_override => 'tracker') |
|
231 | 231 | assert_kind_of Issue, issue |
|
232 | 232 | assert_equal tracker, issue.tracker |
|
233 | 233 | end |
|
234 | 234 | |
|
235 | 235 | def test_should_ignore_emails_from_emission_address |
|
236 | 236 | Role.anonymous.add_permission!(:add_issues) |
|
237 | 237 | assert_no_difference 'User.count' do |
|
238 | 238 | assert_equal false, submit_email('ticket_from_emission_address.eml', :issue => {:project => 'ecookbook'}, :unknown_user => 'create') |
|
239 | 239 | end |
|
240 | 240 | end |
|
241 | 241 | |
|
242 | 242 | def test_add_issue_should_send_email_notification |
|
243 | Setting.notified_events = ['issue_added'] | |
|
243 | 244 | ActionMailer::Base.deliveries.clear |
|
244 | 245 | # This email contains: 'Project: onlinestore' |
|
245 | 246 | issue = submit_email('ticket_on_given_project.eml') |
|
246 | 247 | assert issue.is_a?(Issue) |
|
247 | 248 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
248 | 249 | end |
|
249 | 250 | |
|
250 | 251 | def test_add_issue_note |
|
251 | 252 | journal = submit_email('ticket_reply.eml') |
|
252 | 253 | assert journal.is_a?(Journal) |
|
253 | 254 | assert_equal User.find_by_login('jsmith'), journal.user |
|
254 | 255 | assert_equal Issue.find(2), journal.journalized |
|
255 | 256 | assert_match /This is reply/, journal.notes |
|
256 | 257 | end |
|
257 | 258 | |
|
258 | 259 | def test_add_issue_note_with_attribute_changes |
|
259 | 260 | # This email contains: 'Status: Resolved' |
|
260 | 261 | journal = submit_email('ticket_reply_with_status.eml') |
|
261 | 262 | assert journal.is_a?(Journal) |
|
262 | 263 | issue = Issue.find(journal.issue.id) |
|
263 | 264 | assert_equal User.find_by_login('jsmith'), journal.user |
|
264 | 265 | assert_equal Issue.find(2), journal.journalized |
|
265 | 266 | assert_match /This is reply/, journal.notes |
|
266 | 267 | assert_equal IssueStatus.find_by_name("Resolved"), issue.status |
|
267 | 268 | assert_equal '2010-01-01', issue.start_date.to_s |
|
268 | 269 | assert_equal '2010-12-31', issue.due_date.to_s |
|
269 | 270 | assert_equal User.find_by_login('jsmith'), issue.assigned_to |
|
270 | 271 | end |
|
271 | 272 | |
|
272 | 273 | def test_add_issue_note_should_send_email_notification |
|
273 | 274 | ActionMailer::Base.deliveries.clear |
|
274 | 275 | journal = submit_email('ticket_reply.eml') |
|
275 | 276 | assert journal.is_a?(Journal) |
|
276 | 277 | assert_equal 1, ActionMailer::Base.deliveries.size |
|
277 | 278 | end |
|
278 | 279 | |
|
279 | 280 | def test_reply_to_a_message |
|
280 | 281 | m = submit_email('message_reply.eml') |
|
281 | 282 | assert m.is_a?(Message) |
|
282 | 283 | assert !m.new_record? |
|
283 | 284 | m.reload |
|
284 | 285 | assert_equal 'Reply via email', m.subject |
|
285 | 286 | # The email replies to message #2 which is part of the thread of message #1 |
|
286 | 287 | assert_equal Message.find(1), m.parent |
|
287 | 288 | end |
|
288 | 289 | |
|
289 | 290 | def test_reply_to_a_message_by_subject |
|
290 | 291 | m = submit_email('message_reply_by_subject.eml') |
|
291 | 292 | assert m.is_a?(Message) |
|
292 | 293 | assert !m.new_record? |
|
293 | 294 | m.reload |
|
294 | 295 | assert_equal 'Reply to the first post', m.subject |
|
295 | 296 | assert_equal Message.find(1), m.parent |
|
296 | 297 | end |
|
297 | 298 | |
|
298 | 299 | def test_should_strip_tags_of_html_only_emails |
|
299 | 300 | issue = submit_email('ticket_html_only.eml', :issue => {:project => 'ecookbook'}) |
|
300 | 301 | assert issue.is_a?(Issue) |
|
301 | 302 | assert !issue.new_record? |
|
302 | 303 | issue.reload |
|
303 | 304 | assert_equal 'HTML email', issue.subject |
|
304 | 305 | assert_equal 'This is a html-only email.', issue.description |
|
305 | 306 | end |
|
306 | 307 | |
|
307 | 308 | context "truncate emails based on the Setting" do |
|
308 | 309 | context "with no setting" do |
|
309 | 310 | setup do |
|
310 | 311 | Setting.mail_handler_body_delimiters = '' |
|
311 | 312 | end |
|
312 | 313 | |
|
313 | 314 | should "add the entire email into the issue" do |
|
314 | 315 | issue = submit_email('ticket_on_given_project.eml') |
|
315 | 316 | assert_issue_created(issue) |
|
316 | 317 | assert issue.description.include?('---') |
|
317 | 318 | assert issue.description.include?('This paragraph is after the delimiter') |
|
318 | 319 | end |
|
319 | 320 | end |
|
320 | 321 | |
|
321 | 322 | context "with a single string" do |
|
322 | 323 | setup do |
|
323 | 324 | Setting.mail_handler_body_delimiters = '---' |
|
324 | 325 | end |
|
325 | 326 | |
|
326 | 327 | should "truncate the email at the delimiter for the issue" do |
|
327 | 328 | issue = submit_email('ticket_on_given_project.eml') |
|
328 | 329 | assert_issue_created(issue) |
|
329 | 330 | assert issue.description.include?('This paragraph is before delimiters') |
|
330 | 331 | assert issue.description.include?('--- This line starts with a delimiter') |
|
331 | 332 | assert !issue.description.match(/^---$/) |
|
332 | 333 | assert !issue.description.include?('This paragraph is after the delimiter') |
|
333 | 334 | end |
|
334 | 335 | end |
|
335 | 336 | |
|
336 | 337 | context "with multiple strings" do |
|
337 | 338 | setup do |
|
338 | 339 | Setting.mail_handler_body_delimiters = "---\nBREAK" |
|
339 | 340 | end |
|
340 | 341 | |
|
341 | 342 | should "truncate the email at the first delimiter found (BREAK)" do |
|
342 | 343 | issue = submit_email('ticket_on_given_project.eml') |
|
343 | 344 | assert_issue_created(issue) |
|
344 | 345 | assert issue.description.include?('This paragraph is before delimiters') |
|
345 | 346 | assert !issue.description.include?('BREAK') |
|
346 | 347 | assert !issue.description.include?('This paragraph is between delimiters') |
|
347 | 348 | assert !issue.description.match(/^---$/) |
|
348 | 349 | assert !issue.description.include?('This paragraph is after the delimiter') |
|
349 | 350 | end |
|
350 | 351 | end |
|
351 | 352 | end |
|
352 | 353 | |
|
353 | 354 | def test_email_with_long_subject_line |
|
354 | 355 | issue = submit_email('ticket_with_long_subject.eml') |
|
355 | 356 | assert issue.is_a?(Issue) |
|
356 | 357 | assert_equal issue.subject, 'New ticket on a given project with a very long subject line which exceeds 255 chars and should not be ignored but chopped off. And if the subject line is still not long enough, we just add more text. And more text. Wow, this is really annoying. Especially, if you have nothing to say...'[0,255] |
|
357 | 358 | end |
|
358 | 359 | |
|
359 | 360 | private |
|
360 | 361 | |
|
361 | 362 | def submit_email(filename, options={}) |
|
362 | 363 | raw = IO.read(File.join(FIXTURES_PATH, filename)) |
|
363 | 364 | MailHandler.receive(raw, options) |
|
364 | 365 | end |
|
365 | 366 | |
|
366 | 367 | def assert_issue_created(issue) |
|
367 | 368 | assert issue.is_a?(Issue) |
|
368 | 369 | assert !issue.new_record? |
|
369 | 370 | issue.reload |
|
370 | 371 | end |
|
371 | 372 | end |
@@ -1,154 +1,155 | |||
|
1 | 1 | # redMine - project management software |
|
2 | 2 | # Copyright (C) 2006-2007 Jean-Philippe Lang |
|
3 | 3 | # |
|
4 | 4 | # This program is free software; you can redistribute it and/or |
|
5 | 5 | # modify it under the terms of the GNU General Public License |
|
6 | 6 | # as published by the Free Software Foundation; either version 2 |
|
7 | 7 | # of the License, or (at your option) any later version. |
|
8 | 8 | # |
|
9 | 9 | # This program is distributed in the hope that it will be useful, |
|
10 | 10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 | 11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
12 | 12 | # GNU General Public License for more details. |
|
13 | 13 | # |
|
14 | 14 | # You should have received a copy of the GNU General Public License |
|
15 | 15 | # along with this program; if not, write to the Free Software |
|
16 | 16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
17 | 17 | |
|
18 | 18 | require File.dirname(__FILE__) + '/../test_helper' |
|
19 | 19 | |
|
20 | 20 | class RepositoryTest < ActiveSupport::TestCase |
|
21 | 21 | fixtures :projects, |
|
22 | 22 | :trackers, |
|
23 | 23 | :projects_trackers, |
|
24 | 24 | :repositories, |
|
25 | 25 | :issues, |
|
26 | 26 | :issue_statuses, |
|
27 | 27 | :changesets, |
|
28 | 28 | :changes, |
|
29 | 29 | :users, |
|
30 | 30 | :enumerations |
|
31 | 31 | |
|
32 | 32 | def setup |
|
33 | 33 | @repository = Project.find(1).repository |
|
34 | 34 | end |
|
35 | 35 | |
|
36 | 36 | def test_create |
|
37 | 37 | repository = Repository::Subversion.new(:project => Project.find(3)) |
|
38 | 38 | assert !repository.save |
|
39 | 39 | |
|
40 | 40 | repository.url = "svn://localhost" |
|
41 | 41 | assert repository.save |
|
42 | 42 | repository.reload |
|
43 | 43 | |
|
44 | 44 | project = Project.find(3) |
|
45 | 45 | assert_equal repository, project.repository |
|
46 | 46 | end |
|
47 | 47 | |
|
48 | 48 | def test_destroy |
|
49 | 49 | changesets = Changeset.count(:all, :conditions => "repository_id = 10") |
|
50 | 50 | changes = Change.count(:all, :conditions => "repository_id = 10", :include => :changeset) |
|
51 | 51 | assert_difference 'Changeset.count', -changesets do |
|
52 | 52 | assert_difference 'Change.count', -changes do |
|
53 | 53 | Repository.find(10).destroy |
|
54 | 54 | end |
|
55 | 55 | end |
|
56 | 56 | end |
|
57 | 57 | |
|
58 | 58 | def test_should_not_create_with_disabled_scm |
|
59 | 59 | # disable Subversion |
|
60 | 60 | Setting.enabled_scm = ['Darcs', 'Git'] |
|
61 | 61 | repository = Repository::Subversion.new(:project => Project.find(3), :url => "svn://localhost") |
|
62 | 62 | assert !repository.save |
|
63 | 63 | assert_equal I18n.translate('activerecord.errors.messages.invalid'), repository.errors.on(:type) |
|
64 | 64 | # re-enable Subversion for following tests |
|
65 | 65 | Setting.delete_all |
|
66 | 66 | end |
|
67 | 67 | |
|
68 | 68 | def test_scan_changesets_for_issue_ids |
|
69 | 69 | Setting.default_language = 'en' |
|
70 | Setting.notified_events = ['issue_added','issue_updated'] | |
|
70 | 71 | |
|
71 | 72 | # choosing a status to apply to fix issues |
|
72 | 73 | Setting.commit_fix_status_id = IssueStatus.find(:first, :conditions => ["is_closed = ?", true]).id |
|
73 | 74 | Setting.commit_fix_done_ratio = "90" |
|
74 | 75 | Setting.commit_ref_keywords = 'refs , references, IssueID' |
|
75 | 76 | Setting.commit_fix_keywords = 'fixes , closes' |
|
76 | 77 | Setting.default_language = 'en' |
|
77 | 78 | ActionMailer::Base.deliveries.clear |
|
78 | 79 | |
|
79 | 80 | # make sure issue 1 is not already closed |
|
80 | 81 | fixed_issue = Issue.find(1) |
|
81 | 82 | assert !fixed_issue.status.is_closed? |
|
82 | 83 | old_status = fixed_issue.status |
|
83 | 84 | |
|
84 | 85 | Repository.scan_changesets_for_issue_ids |
|
85 | 86 | assert_equal [101, 102], Issue.find(3).changeset_ids |
|
86 | 87 | |
|
87 | 88 | # fixed issues |
|
88 | 89 | fixed_issue.reload |
|
89 | 90 | assert fixed_issue.status.is_closed? |
|
90 | 91 | assert_equal 90, fixed_issue.done_ratio |
|
91 | 92 | assert_equal [101], fixed_issue.changeset_ids |
|
92 | 93 | |
|
93 | 94 | # issue change |
|
94 | 95 | journal = fixed_issue.journals.find(:first, :order => 'created_on desc') |
|
95 | 96 | assert_equal User.find_by_login('dlopper'), journal.user |
|
96 | 97 | assert_equal 'Applied in changeset r2.', journal.notes |
|
97 | 98 | |
|
98 | 99 | # 2 email notifications |
|
99 | 100 | assert_equal 2, ActionMailer::Base.deliveries.size |
|
100 | 101 | mail = ActionMailer::Base.deliveries.first |
|
101 | 102 | assert_kind_of TMail::Mail, mail |
|
102 | 103 | assert mail.subject.starts_with?("[#{fixed_issue.project.name} - #{fixed_issue.tracker.name} ##{fixed_issue.id}]") |
|
103 | 104 | assert mail.body.include?("Status changed from #{old_status} to #{fixed_issue.status}") |
|
104 | 105 | |
|
105 | 106 | # ignoring commits referencing an issue of another project |
|
106 | 107 | assert_equal [], Issue.find(4).changesets |
|
107 | 108 | end |
|
108 | 109 | |
|
109 | 110 | def test_for_changeset_comments_strip |
|
110 | 111 | repository = Repository::Mercurial.create( :project => Project.find( 4 ), :url => '/foo/bar/baz' ) |
|
111 | 112 | comment = <<-COMMENT |
|
112 | 113 | This is a loooooooooooooooooooooooooooong comment |
|
113 | 114 | |
|
114 | 115 | |
|
115 | 116 | COMMENT |
|
116 | 117 | changeset = Changeset.new( |
|
117 | 118 | :comments => comment, :commit_date => Time.now, :revision => 0, :scmid => 'f39b7922fb3c', |
|
118 | 119 | :committer => 'foo <foo@example.com>', :committed_on => Time.now, :repository => repository ) |
|
119 | 120 | assert( changeset.save ) |
|
120 | 121 | assert_not_equal( comment, changeset.comments ) |
|
121 | 122 | assert_equal( 'This is a loooooooooooooooooooooooooooong comment', changeset.comments ) |
|
122 | 123 | end |
|
123 | 124 | |
|
124 | 125 | def test_for_urls_strip |
|
125 | 126 | repository = Repository::Cvs.create(:project => Project.find(4), :url => ' :pserver:login:password@host:/path/to/the/repository', |
|
126 | 127 | :root_url => 'foo ') |
|
127 | 128 | assert repository.save |
|
128 | 129 | repository.reload |
|
129 | 130 | assert_equal ':pserver:login:password@host:/path/to/the/repository', repository.url |
|
130 | 131 | assert_equal 'foo', repository.root_url |
|
131 | 132 | end |
|
132 | 133 | |
|
133 | 134 | def test_manual_user_mapping |
|
134 | 135 | assert_no_difference "Changeset.count(:conditions => 'user_id <> 2')" do |
|
135 | 136 | c = Changeset.create!(:repository => @repository, :committer => 'foo', :committed_on => Time.now, :revision => 100, :comments => 'Committed by foo.') |
|
136 | 137 | assert_nil c.user |
|
137 | 138 | @repository.committer_ids = {'foo' => '2'} |
|
138 | 139 | assert_equal User.find(2), c.reload.user |
|
139 | 140 | # committer is now mapped |
|
140 | 141 | c = Changeset.create!(:repository => @repository, :committer => 'foo', :committed_on => Time.now, :revision => 101, :comments => 'Another commit by foo.') |
|
141 | 142 | assert_equal User.find(2), c.user |
|
142 | 143 | end |
|
143 | 144 | end |
|
144 | 145 | |
|
145 | 146 | def test_auto_user_mapping_by_username |
|
146 | 147 | c = Changeset.create!(:repository => @repository, :committer => 'jsmith', :committed_on => Time.now, :revision => 100, :comments => 'Committed by john.') |
|
147 | 148 | assert_equal User.find(2), c.user |
|
148 | 149 | end |
|
149 | 150 | |
|
150 | 151 | def test_auto_user_mapping_by_email |
|
151 | 152 | c = Changeset.create!(:repository => @repository, :committer => 'john <jsmith@somenet.foo>', :committed_on => Time.now, :revision => 100, :comments => 'Committed by john.') |
|
152 | 153 | assert_equal User.find(2), c.user |
|
153 | 154 | end |
|
154 | 155 | end |
General Comments 0
You need to be logged in to leave comments.
Login now