Commit 96dded3ec8401e9832b3888338f37c846bd43583
1 parent
57cb1ca7
Exists in
spb-stable
and in
3 other branches
Send emails from the author
This changes the email "From" field from "gitlab@example.com" to either: * "John Doe <gitlab@example.com>" if the author of the action is known, * "GitLab <gitlab@example.com>" otherwise. Rationale: this allow mails to appear as if they were sent by the author. It appears in the mailbox more like a real discussion between the sender and the receiver ("John sent: we should refactor this") and less like a robot notifying about something.
Showing
9 changed files
with
126 additions
and
39 deletions
Show diff stats
app/mailers/emails/issues.rb
... | ... | @@ -3,15 +3,17 @@ module Emails |
3 | 3 | def new_issue_email(recipient_id, issue_id) |
4 | 4 | @issue = Issue.find(issue_id) |
5 | 5 | @project = @issue.project |
6 | - mail(to: recipient(recipient_id), | |
6 | + mail(from: sender(@issue.author_id), | |
7 | + to: recipient(recipient_id), | |
7 | 8 | subject: subject("#{@issue.title} (##{@issue.iid})")) |
8 | 9 | end |
9 | 10 | |
10 | - def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id) | |
11 | + def reassigned_issue_email(recipient_id, issue_id, previous_assignee_id, updated_by_user_id) | |
11 | 12 | @issue = Issue.find(issue_id) |
12 | 13 | @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id |
13 | 14 | @project = @issue.project |
14 | - mail(to: recipient(recipient_id), | |
15 | + mail(from: sender(updated_by_user_id), | |
16 | + to: recipient(recipient_id), | |
15 | 17 | subject: subject("#{@issue.title} (##{@issue.iid})")) |
16 | 18 | end |
17 | 19 | |
... | ... | @@ -19,7 +21,8 @@ module Emails |
19 | 21 | @issue = Issue.find issue_id |
20 | 22 | @project = @issue.project |
21 | 23 | @updated_by = User.find updated_by_user_id |
22 | - mail(to: recipient(recipient_id), | |
24 | + mail(from: sender(updated_by_user_id), | |
25 | + to: recipient(recipient_id), | |
23 | 26 | subject: subject("#{@issue.title} (##{@issue.iid})")) |
24 | 27 | end |
25 | 28 | |
... | ... | @@ -28,7 +31,8 @@ module Emails |
28 | 31 | @issue_status = status |
29 | 32 | @project = @issue.project |
30 | 33 | @updated_by = User.find updated_by_user_id |
31 | - mail(to: recipient(recipient_id), | |
34 | + mail(from: sender(updated_by_user_id), | |
35 | + to: recipient(recipient_id), | |
32 | 36 | subject: subject("#{@issue.title} (##{@issue.iid})")) |
33 | 37 | end |
34 | 38 | end | ... | ... |
app/mailers/emails/merge_requests.rb
... | ... | @@ -3,15 +3,17 @@ module Emails |
3 | 3 | def new_merge_request_email(recipient_id, merge_request_id) |
4 | 4 | @merge_request = MergeRequest.find(merge_request_id) |
5 | 5 | @project = @merge_request.project |
6 | - mail(to: recipient(recipient_id), | |
6 | + mail(from: sender(@merge_request.author_id), | |
7 | + to: recipient(recipient_id), | |
7 | 8 | subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) |
8 | 9 | end |
9 | 10 | |
10 | - def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id) | |
11 | + def reassigned_merge_request_email(recipient_id, merge_request_id, previous_assignee_id, updated_by_user_id) | |
11 | 12 | @merge_request = MergeRequest.find(merge_request_id) |
12 | 13 | @previous_assignee = User.find_by(id: previous_assignee_id) if previous_assignee_id |
13 | 14 | @project = @merge_request.project |
14 | - mail(to: recipient(recipient_id), | |
15 | + mail(from: sender(updated_by_user_id), | |
16 | + to: recipient(recipient_id), | |
15 | 17 | subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) |
16 | 18 | end |
17 | 19 | |
... | ... | @@ -19,14 +21,16 @@ module Emails |
19 | 21 | @merge_request = MergeRequest.find(merge_request_id) |
20 | 22 | @updated_by = User.find updated_by_user_id |
21 | 23 | @project = @merge_request.project |
22 | - mail(to: recipient(recipient_id), | |
24 | + mail(from: sender(updated_by_user_id), | |
25 | + to: recipient(recipient_id), | |
23 | 26 | subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) |
24 | 27 | end |
25 | 28 | |
26 | 29 | def merged_merge_request_email(recipient_id, merge_request_id) |
27 | 30 | @merge_request = MergeRequest.find(merge_request_id) |
28 | 31 | @project = @merge_request.project |
29 | - mail(to: recipient(recipient_id), | |
32 | + mail(from: sender(@merge_request.author_id_of_changes), | |
33 | + to: recipient(recipient_id), | |
30 | 34 | subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) |
31 | 35 | end |
32 | 36 | end | ... | ... |
app/mailers/emails/notes.rb
... | ... | @@ -4,7 +4,8 @@ module Emails |
4 | 4 | @note = Note.find(note_id) |
5 | 5 | @commit = @note.noteable |
6 | 6 | @project = @note.project |
7 | - mail(to: recipient(recipient_id), | |
7 | + mail(from: sender(@note.author_id), | |
8 | + to: recipient(recipient_id), | |
8 | 9 | subject: subject("#{@commit.title} (#{@commit.short_id})")) |
9 | 10 | end |
10 | 11 | |
... | ... | @@ -12,7 +13,8 @@ module Emails |
12 | 13 | @note = Note.find(note_id) |
13 | 14 | @issue = @note.noteable |
14 | 15 | @project = @note.project |
15 | - mail(to: recipient(recipient_id), | |
16 | + mail(from: sender(@note.author_id), | |
17 | + to: recipient(recipient_id), | |
16 | 18 | subject: subject("#{@issue.title} (##{@issue.iid})")) |
17 | 19 | end |
18 | 20 | |
... | ... | @@ -20,14 +22,16 @@ module Emails |
20 | 22 | @note = Note.find(note_id) |
21 | 23 | @merge_request = @note.noteable |
22 | 24 | @project = @note.project |
23 | - mail(to: recipient(recipient_id), | |
25 | + mail(from: sender(@note.author_id), | |
26 | + to: recipient(recipient_id), | |
24 | 27 | subject: subject("#{@merge_request.title} (!#{@merge_request.iid})")) |
25 | 28 | end |
26 | 29 | |
27 | 30 | def note_wall_email(recipient_id, note_id) |
28 | 31 | @note = Note.find(note_id) |
29 | 32 | @project = @note.project |
30 | - mail(to: recipient(recipient_id), | |
33 | + mail(from: sender(@note.author_id), | |
34 | + to: recipient(recipient_id), | |
31 | 35 | subject: subject("Note on wall")) |
32 | 36 | end |
33 | 37 | end | ... | ... |
app/mailers/emails/projects.rb
... | ... | @@ -22,7 +22,9 @@ module Emails |
22 | 22 | @diffs = compare.diffs |
23 | 23 | @branch = branch |
24 | 24 | |
25 | - mail(to: recipient, subject: subject("New push to repository")) | |
25 | + mail(from: sender(author_id), | |
26 | + to: recipient, | |
27 | + subject: subject("New push to repository")) | |
26 | 28 | end |
27 | 29 | end |
28 | 30 | end | ... | ... |
app/mailers/notify.rb
... | ... | @@ -15,7 +15,7 @@ class Notify < ActionMailer::Base |
15 | 15 | default_url_options[:port] = Gitlab.config.gitlab.port unless Gitlab.config.gitlab_on_standard_port? |
16 | 16 | default_url_options[:script_name] = Gitlab.config.gitlab.relative_url_root |
17 | 17 | |
18 | - default from: Gitlab.config.gitlab.email_from | |
18 | + default from: Proc.new { default_sender_address.format } | |
19 | 19 | default reply_to: "noreply@#{Gitlab.config.gitlab.host}" |
20 | 20 | |
21 | 21 | # Just send email with 2 seconds delay |
... | ... | @@ -25,6 +25,23 @@ class Notify < ActionMailer::Base |
25 | 25 | |
26 | 26 | private |
27 | 27 | |
28 | + # The default email address to send emails from | |
29 | + def default_sender_address | |
30 | + address = Mail::Address.new(Gitlab.config.gitlab.email_from) | |
31 | + address.display_name = "GitLab" | |
32 | + address | |
33 | + end | |
34 | + | |
35 | + # Return an email address that displays the name of the sender. | |
36 | + # Only the displayed name changes; the actual email address is always the same. | |
37 | + def sender(sender_id) | |
38 | + if sender = User.find(sender_id) | |
39 | + address = default_sender_address | |
40 | + address.display_name = sender.name | |
41 | + address.format | |
42 | + end | |
43 | + end | |
44 | + | |
28 | 45 | # Look up a User by their ID and return their email address |
29 | 46 | # |
30 | 47 | # recipient_id - User ID | ... | ... |
app/services/notification_service.rb
... | ... | @@ -257,7 +257,7 @@ class NotificationService |
257 | 257 | recipients.delete(current_user) |
258 | 258 | |
259 | 259 | recipients.each do |recipient| |
260 | - mailer.send(method, recipient.id, target.id, target.assignee_id_was) | |
260 | + mailer.send(method, recipient.id, target.id, target.assignee_id_was, current_user.id) | |
261 | 261 | end |
262 | 262 | end |
263 | 263 | ... | ... |
config/initializers/devise.rb
... | ... | @@ -4,7 +4,7 @@ Devise.setup do |config| |
4 | 4 | # ==> Mailer Configuration |
5 | 5 | # Configure the e-mail address which will be shown in Devise::Mailer, |
6 | 6 | # note that it will be overwritten if you use your own mailer class with default "from" parameter. |
7 | - config.mailer_sender = Gitlab.config.gitlab.email_from | |
7 | + config.mailer_sender = "GitLab <#{Gitlab.config.gitlab.email_from}>" | |
8 | 8 | |
9 | 9 | |
10 | 10 | # Configure the class responsible to send e-mails. | ... | ... |
spec/mailers/notify_spec.rb
... | ... | @@ -4,6 +4,7 @@ describe Notify do |
4 | 4 | include EmailSpec::Helpers |
5 | 5 | include EmailSpec::Matchers |
6 | 6 | |
7 | + let(:gitlab_sender) { Gitlab.config.gitlab.email_from } | |
7 | 8 | let(:recipient) { create(:user, email: 'recipient@example.com') } |
8 | 9 | let(:project) { create(:project) } |
9 | 10 | |
... | ... | @@ -13,12 +14,22 @@ describe Notify do |
13 | 14 | end |
14 | 15 | end |
15 | 16 | |
17 | + shared_examples 'an email sent from GitLab' do | |
18 | + it 'is sent from GitLab' do | |
19 | + sender = subject.header[:from].addrs[0] | |
20 | + sender.display_name.should eq('GitLab') | |
21 | + sender.address.should eq(gitlab_sender) | |
22 | + end | |
23 | + end | |
24 | + | |
16 | 25 | describe 'for new users, the email' do |
17 | 26 | let(:example_site_path) { root_path } |
18 | 27 | let(:new_user) { create(:user, email: 'newguy@example.com', created_by_id: 1) } |
19 | 28 | |
20 | 29 | subject { Notify.new_user_email(new_user.id, new_user.password) } |
21 | 30 | |
31 | + it_behaves_like 'an email sent from GitLab' | |
32 | + | |
22 | 33 | it 'is sent to the new user' do |
23 | 34 | should deliver_to new_user.email |
24 | 35 | end |
... | ... | @@ -47,6 +58,8 @@ describe Notify do |
47 | 58 | |
48 | 59 | subject { Notify.new_user_email(new_user.id, new_user.password) } |
49 | 60 | |
61 | + it_behaves_like 'an email sent from GitLab' | |
62 | + | |
50 | 63 | it 'is sent to the new user' do |
51 | 64 | should deliver_to new_user.email |
52 | 65 | end |
... | ... | @@ -73,6 +86,8 @@ describe Notify do |
73 | 86 | |
74 | 87 | subject { Notify.new_ssh_key_email(key.id) } |
75 | 88 | |
89 | + it_behaves_like 'an email sent from GitLab' | |
90 | + | |
76 | 91 | it 'is sent to the new user' do |
77 | 92 | should deliver_to key.user.email |
78 | 93 | end |
... | ... | @@ -114,17 +129,24 @@ describe Notify do |
114 | 129 | |
115 | 130 | context 'for a project' do |
116 | 131 | describe 'items that are assignable, the email' do |
132 | + let(:current_user) { create(:user, email: "current@email.com") } | |
117 | 133 | let(:assignee) { create(:user, email: 'assignee@example.com') } |
118 | 134 | let(:previous_assignee) { create(:user, name: 'Previous Assignee') } |
119 | 135 | |
120 | 136 | shared_examples 'an assignee email' do |
137 | + it 'is sent as the author' do | |
138 | + sender = subject.header[:from].addrs[0] | |
139 | + sender.display_name.should eq(current_user.name) | |
140 | + sender.address.should eq(gitlab_sender) | |
141 | + end | |
142 | + | |
121 | 143 | it 'is sent to the assignee' do |
122 | 144 | should deliver_to assignee.email |
123 | 145 | end |
124 | 146 | end |
125 | 147 | |
126 | 148 | context 'for issues' do |
127 | - let(:issue) { create(:issue, assignee: assignee, project: project ) } | |
149 | + let(:issue) { create(:issue, author: current_user, assignee: assignee, project: project ) } | |
128 | 150 | |
129 | 151 | describe 'that are new' do |
130 | 152 | subject { Notify.new_issue_email(issue.assignee_id, issue.id) } |
... | ... | @@ -132,7 +154,7 @@ describe Notify do |
132 | 154 | it_behaves_like 'an assignee email' |
133 | 155 | |
134 | 156 | it 'has the correct subject' do |
135 | - should have_subject /#{project.name} \| New issue ##{issue.iid} \| #{issue.title}/ | |
157 | + should have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/ | |
136 | 158 | end |
137 | 159 | |
138 | 160 | it 'contains a link to the new issue' do |
... | ... | @@ -141,14 +163,18 @@ describe Notify do |
141 | 163 | end |
142 | 164 | |
143 | 165 | describe 'that have been reassigned' do |
144 | - before(:each) { issue.stub(:assignee_id_was).and_return(previous_assignee.id) } | |
145 | - | |
146 | - subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id) } | |
166 | + subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id, current_user) } | |
147 | 167 | |
148 | 168 | it_behaves_like 'a multiple recipients email' |
149 | 169 | |
170 | + it 'is sent as the author' do | |
171 | + sender = subject.header[:from].addrs[0] | |
172 | + sender.display_name.should eq(current_user.name) | |
173 | + sender.address.should eq(gitlab_sender) | |
174 | + end | |
175 | + | |
150 | 176 | it 'has the correct subject' do |
151 | - should have_subject /Changed issue ##{issue.iid} \| #{issue.title}/ | |
177 | + should have_subject /#{issue.title} \(##{issue.iid}\)/ | |
152 | 178 | end |
153 | 179 | |
154 | 180 | it 'contains the name of the previous assignee' do |
... | ... | @@ -165,12 +191,17 @@ describe Notify do |
165 | 191 | end |
166 | 192 | |
167 | 193 | describe 'status changed' do |
168 | - let(:current_user) { create(:user, email: "current@email.com") } | |
169 | 194 | let(:status) { 'closed' } |
170 | 195 | subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user) } |
171 | 196 | |
197 | + it 'is sent as the author' do | |
198 | + sender = subject.header[:from].addrs[0] | |
199 | + sender.display_name.should eq(current_user.name) | |
200 | + sender.address.should eq(gitlab_sender) | |
201 | + end | |
202 | + | |
172 | 203 | it 'has the correct subject' do |
173 | - should have_subject /Changed issue ##{issue.iid} \| #{issue.title}/i | |
204 | + should have_subject /#{issue.title} \(##{issue.iid}\)/i | |
174 | 205 | end |
175 | 206 | |
176 | 207 | it 'contains the new status' do |
... | ... | @@ -189,7 +220,7 @@ describe Notify do |
189 | 220 | end |
190 | 221 | |
191 | 222 | context 'for merge requests' do |
192 | - let(:merge_request) { create(:merge_request, assignee: assignee, source_project: project, target_project: project) } | |
223 | + let(:merge_request) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project) } | |
193 | 224 | |
194 | 225 | describe 'that are new' do |
195 | 226 | subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) } |
... | ... | @@ -197,7 +228,7 @@ describe Notify do |
197 | 228 | it_behaves_like 'an assignee email' |
198 | 229 | |
199 | 230 | it 'has the correct subject' do |
200 | - should have_subject /New merge request ##{merge_request.iid}/ | |
231 | + should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/ | |
201 | 232 | end |
202 | 233 | |
203 | 234 | it 'contains a link to the new merge request' do |
... | ... | @@ -214,14 +245,18 @@ describe Notify do |
214 | 245 | end |
215 | 246 | |
216 | 247 | describe 'that are reassigned' do |
217 | - before(:each) { merge_request.stub(:assignee_id_was).and_return(previous_assignee.id) } | |
218 | - | |
219 | - subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id) } | |
248 | + subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) } | |
220 | 249 | |
221 | 250 | it_behaves_like 'a multiple recipients email' |
222 | 251 | |
252 | + it 'is sent as the author' do | |
253 | + sender = subject.header[:from].addrs[0] | |
254 | + sender.display_name.should eq(current_user.name) | |
255 | + sender.address.should eq(gitlab_sender) | |
256 | + end | |
257 | + | |
223 | 258 | it 'has the correct subject' do |
224 | - should have_subject /Changed merge request ##{merge_request.iid}/ | |
259 | + should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/ | |
225 | 260 | end |
226 | 261 | |
227 | 262 | it 'contains the name of the previous assignee' do |
... | ... | @@ -245,6 +280,8 @@ describe Notify do |
245 | 280 | let(:user) { create(:user) } |
246 | 281 | subject { Notify.project_was_moved_email(project.id, user.id) } |
247 | 282 | |
283 | + it_behaves_like 'an email sent from GitLab' | |
284 | + | |
248 | 285 | it 'has the correct subject' do |
249 | 286 | should have_subject /Project was moved/ |
250 | 287 | end |
... | ... | @@ -265,6 +302,9 @@ describe Notify do |
265 | 302 | project: project, |
266 | 303 | user: user) } |
267 | 304 | subject { Notify.project_access_granted_email(users_project.id) } |
305 | + | |
306 | + it_behaves_like 'an email sent from GitLab' | |
307 | + | |
268 | 308 | it 'has the correct subject' do |
269 | 309 | should have_subject /Access to project was granted/ |
270 | 310 | end |
... | ... | @@ -285,6 +325,12 @@ describe Notify do |
285 | 325 | end |
286 | 326 | |
287 | 327 | shared_examples 'a note email' do |
328 | + it 'is sent as the author' do | |
329 | + sender = subject.header[:from].addrs[0] | |
330 | + sender.display_name.should eq(note_author.name) | |
331 | + sender.address.should eq(gitlab_sender) | |
332 | + end | |
333 | + | |
288 | 334 | it 'is sent to the given recipient' do |
289 | 335 | should deliver_to recipient.email |
290 | 336 | end |
... | ... | @@ -324,7 +370,7 @@ describe Notify do |
324 | 370 | it_behaves_like 'a note email' |
325 | 371 | |
326 | 372 | it 'has the correct subject' do |
327 | - should have_subject /Note for commit #{commit.short_id}/ | |
373 | + should have_subject /#{commit.title} \(#{commit.short_id}\)/ | |
328 | 374 | end |
329 | 375 | |
330 | 376 | it 'contains a link to the commit' do |
... | ... | @@ -342,7 +388,7 @@ describe Notify do |
342 | 388 | it_behaves_like 'a note email' |
343 | 389 | |
344 | 390 | it 'has the correct subject' do |
345 | - should have_subject /Note for merge request ##{merge_request.iid}/ | |
391 | + should have_subject /#{merge_request.title} \(!#{merge_request.iid}\)/ | |
346 | 392 | end |
347 | 393 | |
348 | 394 | it 'contains a link to the merge request note' do |
... | ... | @@ -360,7 +406,7 @@ describe Notify do |
360 | 406 | it_behaves_like 'a note email' |
361 | 407 | |
362 | 408 | it 'has the correct subject' do |
363 | - should have_subject /Note for issue ##{issue.iid}/ | |
409 | + should have_subject /#{issue.title} \(##{issue.iid}\)/ | |
364 | 410 | end |
365 | 411 | |
366 | 412 | it 'contains a link to the issue note' do |
... | ... | @@ -377,6 +423,8 @@ describe Notify do |
377 | 423 | |
378 | 424 | subject { Notify.group_access_granted_email(membership.id) } |
379 | 425 | |
426 | + it_behaves_like 'an email sent from GitLab' | |
427 | + | |
380 | 428 | it 'has the correct subject' do |
381 | 429 | should have_subject /Access to group was granted/ |
382 | 430 | end |
... | ... | @@ -401,6 +449,8 @@ describe Notify do |
401 | 449 | |
402 | 450 | subject { ActionMailer::Base.deliveries.last } |
403 | 451 | |
452 | + it_behaves_like 'an email sent from GitLab' | |
453 | + | |
404 | 454 | it 'is sent to the new user' do |
405 | 455 | should deliver_to 'new-email@mail.com' |
406 | 456 | end |
... | ... | @@ -421,6 +471,12 @@ describe Notify do |
421 | 471 | |
422 | 472 | subject { Notify.repository_push_email(project.id, 'devs@company.name', user.id, 'master', compare) } |
423 | 473 | |
474 | + it 'is sent as the author' do | |
475 | + sender = subject.header[:from].addrs[0] | |
476 | + sender.display_name.should eq(user.name) | |
477 | + sender.address.should eq(gitlab_sender) | |
478 | + end | |
479 | + | |
424 | 480 | it 'is sent to recipient' do |
425 | 481 | should deliver_to 'devs@company.name' |
426 | 482 | end | ... | ... |
spec/services/notification_service_spec.rb
... | ... | @@ -137,11 +137,11 @@ describe NotificationService do |
137 | 137 | end |
138 | 138 | |
139 | 139 | def should_email(user_id) |
140 | - Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) | |
140 | + Notify.should_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id) | |
141 | 141 | end |
142 | 142 | |
143 | 143 | def should_not_email(user_id) |
144 | - Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id) | |
144 | + Notify.should_not_receive(:reassigned_issue_email).with(user_id, issue.id, issue.assignee_id, @u_disabled.id) | |
145 | 145 | end |
146 | 146 | end |
147 | 147 | |
... | ... | @@ -201,11 +201,11 @@ describe NotificationService do |
201 | 201 | end |
202 | 202 | |
203 | 203 | def should_email(user_id) |
204 | - Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) | |
204 | + Notify.should_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id) | |
205 | 205 | end |
206 | 206 | |
207 | 207 | def should_not_email(user_id) |
208 | - Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id) | |
208 | + Notify.should_not_receive(:reassigned_merge_request_email).with(user_id, merge_request.id, merge_request.assignee_id, merge_request.author_id) | |
209 | 209 | end |
210 | 210 | end |
211 | 211 | ... | ... |