notify_spec.rb 45.2 KB
Newer Older
1
require 'spec_helper'
R
Robert Speicher 已提交
2
require 'email_spec'
3 4 5 6

describe Notify do
  include EmailSpec::Helpers
  include EmailSpec::Matchers
D
Dmitriy Zaporozhets 已提交
7
  include RepoHelpers
8

9
  include_context 'gitlab email notification'
10

R
Robb Kidd 已提交
11 12
  context 'for a project' do
    describe 'items that are assignable, the email' do
13
      let(:current_user) { create(:user, email: "current@email.com") }
14
      let(:assignee) { create(:user, email: 'assignee@example.com', name: 'John Doe') }
15
      let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
16

R
Robb Kidd 已提交
17
      shared_examples 'an assignee email' do
18 19
        it 'is sent as the author' do
          sender = subject.header[:from].addrs[0]
20 21
          expect(sender.display_name).to eq(current_user.name)
          expect(sender.address).to eq(gitlab_sender)
22 23
        end

R
Robb Kidd 已提交
24
        it 'is sent to the assignee' do
25
          is_expected.to deliver_to assignee.email
R
Robb Kidd 已提交
26 27
        end
      end
28

R
Robb Kidd 已提交
29
      context 'for issues' do
30
        let(:issue) { create(:issue, author: current_user, assignee: assignee, project: project) }
R
Robert Speicher 已提交
31
        let(:issue_with_description) { create(:issue, author: current_user, assignee: assignee, project: project, description: FFaker::Lorem.sentence) }
32

R
Robb Kidd 已提交
33
        describe 'that are new' do
34
          subject { Notify.new_issue_email(issue.assignee_id, issue.id) }
35

R
Robb Kidd 已提交
36
          it_behaves_like 'an assignee email'
37 38 39
          it_behaves_like 'an email starting a new thread with reply-by-email enabled' do
            let(:model) { issue }
          end
40
          it_behaves_like 'it should show Gmail Actions View Issue link'
41
          it_behaves_like 'an unsubscribeable thread'
42

R
Robb Kidd 已提交
43
          it 'has the correct subject' do
44
            is_expected.to have_subject /#{project.name} \| #{issue.title} \(##{issue.iid}\)/
R
Robb Kidd 已提交
45
          end
46

R
Robb Kidd 已提交
47
          it 'contains a link to the new issue' do
V
Vinnie Okada 已提交
48
            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
R
Robb Kidd 已提交
49
          end
50 51 52

          context 'when enabled email_author_in_body' do
            before do
S
Sean McGivern 已提交
53
              stub_application_setting(email_author_in_body: true)
54 55 56 57 58 59 60
            end

            it 'contains a link to note author' do
              is_expected.to have_body_text issue.author_name
              is_expected.to have_body_text /wrote\:/
            end
          end
R
Robb Kidd 已提交
61
        end
62

63 64 65
        describe 'that are new with a description' do
          subject { Notify.new_issue_email(issue_with_description.assignee_id, issue_with_description.id) }

66 67
          it_behaves_like 'it should show Gmail Actions View Issue link'

68
          it 'contains the description' do
69
            is_expected.to have_body_text /#{issue_with_description.description}/
70 71 72
          end
        end

R
Robb Kidd 已提交
73
        describe 'that have been reassigned' do
V
Valery Sizov 已提交
74
          subject { Notify.reassigned_issue_email(recipient.id, issue.id, previous_assignee.id, current_user.id) }
R
Robb Kidd 已提交
75 76

          it_behaves_like 'a multiple recipients email'
77 78 79
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { issue }
          end
80
          it_behaves_like 'it should show Gmail Actions View Issue link'
81
          it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
82

83 84
          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
85 86
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
87 88
          end

R
Robb Kidd 已提交
89
          it 'has the correct subject' do
90
            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
R
Robb Kidd 已提交
91 92 93
          end

          it 'contains the name of the previous assignee' do
94
            is_expected.to have_body_text /#{previous_assignee.name}/
R
Robb Kidd 已提交
95 96 97
          end

          it 'contains the name of the new assignee' do
98
            is_expected.to have_body_text /#{assignee.name}/
R
Robb Kidd 已提交
99 100 101
          end

          it 'contains a link to the issue' do
V
Vinnie Okada 已提交
102
            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
R
Robb Kidd 已提交
103 104
          end
        end
A
Alex Denisov 已提交
105

106 107 108 109
        describe 'that have been relabeled' do
          subject { Notify.relabeled_issue_email(recipient.id, issue.id, %w[foo bar baz], current_user.id) }

          it_behaves_like 'a multiple recipients email'
110 111 112
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { issue }
          end
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
          it_behaves_like 'it should show Gmail Actions View Issue link'
          it_behaves_like 'a user cannot unsubscribe through footer link'
          it_behaves_like 'an email with a labels subscriptions link in its footer'

          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
          end

          it 'has the correct subject' do
            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
          end

          it 'contains the names of the added labels' do
            is_expected.to have_body_text /foo, bar, and baz/
          end

          it 'contains a link to the issue' do
            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
          end
        end

A
Alex Denisov 已提交
136 137
        describe 'status changed' do
          let(:status) { 'closed' }
V
Valery Sizov 已提交
138
          subject { Notify.issue_status_changed_email(recipient.id, issue.id, status, current_user.id) }
139

140 141 142
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { issue }
          end
143
          it_behaves_like 'it should show Gmail Actions View Issue link'
144
          it_behaves_like 'an unsubscribeable thread'
145

146 147
          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
148 149
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
150 151
          end

A
Alex Denisov 已提交
152
          it 'has the correct subject' do
153
            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/i
A
Alex Denisov 已提交
154 155 156
          end

          it 'contains the new status' do
157
            is_expected.to have_body_text /#{status}/i
A
Alex Denisov 已提交
158 159 160
          end

          it 'contains the user name' do
161
            is_expected.to have_body_text /#{current_user.name}/i
A
Alex Denisov 已提交
162 163 164
          end

          it 'contains a link to the issue' do
V
Vinnie Okada 已提交
165
            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
A
Alex Denisov 已提交
166
          end
167
        end
168 169 170 171 172

        describe 'moved to another project' do
          let(:new_issue) { create(:issue) }
          subject { Notify.issue_moved_email(recipient, issue, new_issue, current_user) }

173 174 175
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { issue }
          end
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
          it_behaves_like 'it should show Gmail Actions View Issue link'
          it_behaves_like 'an unsubscribeable thread'

          it 'contains description about action taken' do
            is_expected.to have_body_text 'Issue was moved to another project'
          end

          it 'has the correct subject' do
            is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/i
          end

          it 'contains link to new issue' do
            new_issue_url = namespace_project_issue_path(new_issue.project.namespace,
                                                         new_issue.project, new_issue)
            is_expected.to have_body_text new_issue_url
          end

          it 'contains a link to the original issue' do
            is_expected.to have_body_text /#{namespace_project_issue_path project.namespace, project, issue}/
          end
        end
R
Robb Kidd 已提交
197 198 199
      end

      context 'for merge requests' do
200
        let(:merge_author) { create(:user) }
201
        let(:merge_request) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project) }
R
Robert Speicher 已提交
202
        let(:merge_request_with_description) { create(:merge_request, author: current_user, assignee: assignee, source_project: project, target_project: project, description: FFaker::Lorem.sentence) }
R
Robb Kidd 已提交
203 204

        describe 'that are new' do
205
          subject { Notify.new_merge_request_email(merge_request.assignee_id, merge_request.id) }
R
Robb Kidd 已提交
206 207

          it_behaves_like 'an assignee email'
208 209 210
          it_behaves_like 'an email starting a new thread with reply-by-email enabled' do
            let(:model) { merge_request }
          end
211
          it_behaves_like 'it should show Gmail Actions View Merge request link'
212
          it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
213 214

          it 'has the correct subject' do
215
            is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/
R
Robb Kidd 已提交
216 217 218
          end

          it 'contains a link to the new merge request' do
V
Vinnie Okada 已提交
219
            is_expected.to have_body_text /#{namespace_project_merge_request_path(project.namespace, project, merge_request)}/
R
Robb Kidd 已提交
220 221 222
          end

          it 'contains the source branch for the merge request' do
223
            is_expected.to have_body_text /#{merge_request.source_branch}/
R
Robb Kidd 已提交
224 225 226
          end

          it 'contains the target branch for the merge request' do
227
            is_expected.to have_body_text /#{merge_request.target_branch}/
R
Robb Kidd 已提交
228
          end
P
Philip Blatter 已提交
229

230 231
          context 'when enabled email_author_in_body' do
            before do
S
Sean McGivern 已提交
232
              stub_application_setting(email_author_in_body: true)
233 234 235 236 237 238 239
            end

            it 'contains a link to note author' do
              is_expected.to have_body_text merge_request.author_name
              is_expected.to have_body_text /wrote\:/
            end
          end
R
Robb Kidd 已提交
240 241
        end

242 243 244
        describe 'that are new with a description' do
          subject { Notify.new_merge_request_email(merge_request_with_description.assignee_id, merge_request_with_description.id) }

245
          it_behaves_like 'it should show Gmail Actions View Merge request link'
246
          it_behaves_like "an unsubscribeable thread"
247

248
          it 'contains the description' do
249
            is_expected.to have_body_text /#{merge_request_with_description.description}/
250 251 252
          end
        end

R
Robb Kidd 已提交
253
        describe 'that are reassigned' do
254
          subject { Notify.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) }
R
Robb Kidd 已提交
255 256

          it_behaves_like 'a multiple recipients email'
257 258 259
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { merge_request }
          end
260
          it_behaves_like 'it should show Gmail Actions View Merge request link'
261
          it_behaves_like "an unsubscribeable thread"
R
Robb Kidd 已提交
262

263 264
          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
265 266
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
267 268
          end

R
Robb Kidd 已提交
269
          it 'has the correct subject' do
270
            is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/
R
Robb Kidd 已提交
271 272 273
          end

          it 'contains the name of the previous assignee' do
274
            is_expected.to have_body_text /#{previous_assignee.name}/
R
Robb Kidd 已提交
275 276 277
          end

          it 'contains the name of the new assignee' do
278
            is_expected.to have_body_text /#{assignee.name}/
R
Robb Kidd 已提交
279 280 281
          end

          it 'contains a link to the merge request' do
V
Vinnie Okada 已提交
282
            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
R
Robb Kidd 已提交
283
          end
284 285
        end

286 287 288 289
        describe 'that have been relabeled' do
          subject { Notify.relabeled_merge_request_email(recipient.id, merge_request.id, %w[foo bar baz], current_user.id) }

          it_behaves_like 'a multiple recipients email'
290 291 292
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { merge_request }
          end
293 294 295 296 297 298 299 300 301 302 303
          it_behaves_like 'it should show Gmail Actions View Merge request link'
          it_behaves_like 'a user cannot unsubscribe through footer link'
          it_behaves_like 'an email with a labels subscriptions link in its footer'

          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
          end

          it 'has the correct subject' do
304
            is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/
305 306 307 308 309 310 311 312 313 314 315
          end

          it 'contains the names of the added labels' do
            is_expected.to have_body_text /foo, bar, and baz/
          end

          it 'contains a link to the merge request' do
            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
          end
        end

316 317
        describe 'status changed' do
          let(:status) { 'reopened' }
V
Valery Sizov 已提交
318
          subject { Notify.merge_request_status_email(recipient.id, merge_request.id, status, current_user.id) }
319

320 321 322
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { merge_request }
          end
323
          it_behaves_like 'it should show Gmail Actions View Merge request link'
324
          it_behaves_like 'an unsubscribeable thread'
325 326 327

          it 'is sent as the author' do
            sender = subject.header[:from].addrs[0]
328 329
            expect(sender.display_name).to eq(current_user.name)
            expect(sender.address).to eq(gitlab_sender)
330 331 332
          end

          it 'has the correct subject' do
333
            is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/i
334 335 336
          end

          it 'contains the new status' do
337
            is_expected.to have_body_text /#{status}/i
338 339 340
          end

          it 'contains the user name' do
341
            is_expected.to have_body_text /#{current_user.name}/i
342 343 344
          end

          it 'contains a link to the merge request' do
V
Vinnie Okada 已提交
345
            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
346 347 348
          end
        end

349 350 351 352
        describe 'that are merged' do
          subject { Notify.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }

          it_behaves_like 'a multiple recipients email'
353 354 355
          it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
            let(:model) { merge_request }
          end
356
          it_behaves_like 'it should show Gmail Actions View Merge request link'
357
          it_behaves_like 'an unsubscribeable thread'
358 359 360

          it 'is sent as the merge author' do
            sender = subject.header[:from].addrs[0]
361 362
            expect(sender.display_name).to eq(merge_author.name)
            expect(sender.address).to eq(gitlab_sender)
363 364 365
          end

          it 'has the correct subject' do
366
            is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/
367
          end
R
Robb Kidd 已提交
368

369
          it 'contains the new status' do
370
            is_expected.to have_body_text /merged/i
371 372 373
          end

          it 'contains a link to the merge request' do
V
Vinnie Okada 已提交
374
            is_expected.to have_body_text /#{namespace_project_merge_request_path project.namespace, project, merge_request}/
375
          end
R
Robb Kidd 已提交
376 377
        end
      end
378 379
    end

380 381 382
    describe 'project was moved' do
      let(:project) { create(:project) }
      let(:user) { create(:user) }
383
      subject { Notify.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
384

385
      it_behaves_like 'an email sent from GitLab'
386
      it_behaves_like 'it should not have Gmail Actions links'
387
      it_behaves_like "a user cannot unsubscribe through footer link"
388

389
      it 'has the correct subject' do
390
        is_expected.to have_subject /Project was moved/
391 392 393
      end

      it 'contains name of project' do
394
        is_expected.to have_body_text /#{project.name_with_namespace}/
395 396 397
      end

      it 'contains new user role' do
398
        is_expected.to have_body_text /#{project.ssh_url_to_repo}/
399 400 401
      end
    end

R
Rémy Coutable 已提交
402
    describe 'project access requested' do
403
      context 'for a project in a user namespace' do
404 405 406 407 408 409
        let(:project) do
          create(:empty_project, :public, :access_requestable) do |project|
            project.team << [project.owner, :master, project.owner]
          end
        end

410 411 412
        let(:user) { create(:user) }
        let(:project_member) do
          project.request_access(user)
413
          project.requesters.find_by(user_id: user.id)
414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
        end
        subject { Notify.member_access_requested_email('project', project_member.id) }

        it_behaves_like 'an email sent from GitLab'
        it_behaves_like 'it should not have Gmail Actions links'
        it_behaves_like "a user cannot unsubscribe through footer link"

        it 'contains all the useful information' do
          to_emails = subject.header[:to].addrs
          expect(to_emails.size).to eq(1)
          expect(to_emails[0].address).to eq(project.members.owners_and_masters.first.user.notification_email)

          is_expected.to have_subject "Request to join the #{project.name_with_namespace} project"
          is_expected.to have_body_text /#{project.name_with_namespace}/
          is_expected.to have_body_text /#{namespace_project_project_members_url(project.namespace, project)}/
          is_expected.to have_body_text /#{project_member.human_access}/
        end
R
Rémy Coutable 已提交
431 432
      end

433 434 435
      context 'for a project in a group' do
        let(:group_owner) { create(:user) }
        let(:group) { create(:group).tap { |g| g.add_owner(group_owner) } }
436
        let(:project) { create(:empty_project, :public, :access_requestable, namespace: group) }
437 438 439
        let(:user) { create(:user) }
        let(:project_member) do
          project.request_access(user)
440
          project.requesters.find_by(user_id: user.id)
441 442
        end
        subject { Notify.member_access_requested_email('project', project_member.id) }
R
Rémy Coutable 已提交
443

444 445 446 447 448 449 450 451 452 453 454 455 456 457
        it_behaves_like 'an email sent from GitLab'
        it_behaves_like 'it should not have Gmail Actions links'
        it_behaves_like "a user cannot unsubscribe through footer link"

        it 'contains all the useful information' do
          to_emails = subject.header[:to].addrs
          expect(to_emails.size).to eq(1)
          expect(to_emails[0].address).to eq(group.members.owners_and_masters.first.user.notification_email)

          is_expected.to have_subject "Request to join the #{project.name_with_namespace} project"
          is_expected.to have_body_text /#{project.name_with_namespace}/
          is_expected.to have_body_text /#{namespace_project_project_members_url(project.namespace, project)}/
          is_expected.to have_body_text /#{project_member.human_access}/
        end
R
Rémy Coutable 已提交
458
      end
R
Rémy Coutable 已提交
459 460 461
    end

    describe 'project access denied' do
462
      let(:project) { create(:empty_project, :public, :access_requestable) }
R
Rémy Coutable 已提交
463 464 465
      let(:user) { create(:user) }
      let(:project_member) do
        project.request_access(user)
466
        project.requesters.find_by(user_id: user.id)
R
Rémy Coutable 已提交
467
      end
468
      subject { Notify.member_access_denied_email('project', project.id, user.id) }
R
Rémy Coutable 已提交
469 470 471 472 473

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
474 475 476 477 478
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{project.name_with_namespace} project was denied"
        is_expected.to have_body_text /#{project.name_with_namespace}/
        is_expected.to have_body_text /#{project.web_url}/
      end
R
Rémy Coutable 已提交
479 480
    end

481
    describe 'project access changed' do
482
      let(:project) { create(:empty_project, :public, :access_requestable) }
483
      let(:user) { create(:user) }
484
      let(:project_member) { create(:project_member, project: project, user: user) }
485
      subject { Notify.member_access_granted_email('project', project_member.id) }
486 487

      it_behaves_like 'an email sent from GitLab'
488
      it_behaves_like 'it should not have Gmail Actions links'
489
      it_behaves_like "a user cannot unsubscribe through footer link"
490

R
Rémy Coutable 已提交
491 492 493 494 495 496
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{project.name_with_namespace} project was granted"
        is_expected.to have_body_text /#{project.name_with_namespace}/
        is_expected.to have_body_text /#{project.web_url}/
        is_expected.to have_body_text /#{project_member.human_access}/
      end
497
    end
498

499 500 501 502 503 504 505 506 507
    def invite_to_project(project, inviter:)
      create(
        :project_member,
        :developer,
        project: project,
        invite_token: '1234',
        invite_email: 'toto@example.com',
        user: nil,
        created_by: inviter
508
      )
509 510 511 512 513
    end

    describe 'project invitation' do
      let(:project) { create(:project) }
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
514
      let(:project_member) { invite_to_project(project, inviter: master) }
515 516 517 518 519 520 521

      subject { Notify.member_invited_email('project', project_member.id, project_member.invite_token) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
522 523 524 525 526 527 528
      it 'contains all the useful information' do
        is_expected.to have_subject "Invitation to join the #{project.name_with_namespace} project"
        is_expected.to have_body_text /#{project.name_with_namespace}/
        is_expected.to have_body_text /#{project.web_url}/
        is_expected.to have_body_text /#{project_member.human_access}/
        is_expected.to have_body_text /#{project_member.invite_token}/
      end
529 530 531 532
    end

    describe 'project invitation accepted' do
      let(:project) { create(:project) }
533
      let(:invited_user) { create(:user, name: 'invited user') }
534 535
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
536
        invitee = invite_to_project(project, inviter: master)
537 538
        invitee.accept_invite!(invited_user)
        invitee
539
      end
540

541 542 543 544 545 546
      subject { Notify.member_invite_accepted_email('project', project_member.id) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
547 548 549 550 551 552 553
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation accepted'
        is_expected.to have_body_text /#{project.name_with_namespace}/
        is_expected.to have_body_text /#{project.web_url}/
        is_expected.to have_body_text /#{project_member.invite_email}/
        is_expected.to have_body_text /#{invited_user.name}/
      end
554 555 556 557 558 559
    end

    describe 'project invitation declined' do
      let(:project) { create(:project) }
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
560
        invitee = invite_to_project(project, inviter: master)
561 562
        invitee.decline_invite!
        invitee
563
      end
564 565 566 567 568 569 570

      subject { Notify.member_invite_declined_email('project', project.id, project_member.invite_email, master.id) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
571 572 573 574 575 576
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation declined'
        is_expected.to have_body_text /#{project.name_with_namespace}/
        is_expected.to have_body_text /#{project.web_url}/
        is_expected.to have_body_text /#{project_member.invite_email}/
      end
577 578
    end

R
Robb Kidd 已提交
579
    context 'items that are noteable, the email for a note' do
580 581
      let(:note_author) { create(:user, name: 'author_name') }
      let(:note) { create(:note, project: project, author: note_author) }
R
Robb Kidd 已提交
582

583 584
      before :each do
        allow(Note).to receive(:find).with(note.id).and_return(note)
585 586
      end

R
Robb Kidd 已提交
587
      shared_examples 'a note email' do
588 589
        it_behaves_like 'it should have Gmail Actions links'

590 591
        it 'is sent as the author' do
          sender = subject.header[:from].addrs[0]
592 593
          expect(sender.display_name).to eq(note_author.name)
          expect(sender.address).to eq(gitlab_sender)
594 595
        end

R
Robb Kidd 已提交
596
        it 'is sent to the given recipient' do
597
          is_expected.to deliver_to recipient.notification_email
R
Robb Kidd 已提交
598 599 600
        end

        it 'contains the message from the note' do
601
          is_expected.to have_body_text /#{note.note}/
R
Robb Kidd 已提交
602
        end
603

604
        it 'does not contain note author' do
605 606 607 608 609
          is_expected.not_to have_body_text /wrote\:/
        end

        context 'when enabled email_author_in_body' do
          before do
S
Sean McGivern 已提交
610
            stub_application_setting(email_author_in_body: true)
611 612 613 614 615 616 617
          end

          it 'contains a link to note author' do
            is_expected.to have_body_text note.author_name
            is_expected.to have_body_text /wrote\:/
          end
        end
R
Robb Kidd 已提交
618 619 620
      end

      describe 'on a commit' do
621
        let(:commit) { project.commit }
D
Dmitriy Zaporozhets 已提交
622

623
        before(:each) { allow(note).to receive(:noteable).and_return(commit) }
R
Robb Kidd 已提交
624

D
Dmitriy Zaporozhets 已提交
625
        subject { Notify.note_commit_email(recipient.id, note.id) }
R
Robb Kidd 已提交
626 627

        it_behaves_like 'a note email'
628 629 630
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { commit }
        end
631
        it_behaves_like 'it should show Gmail Actions View Commit link'
632
        it_behaves_like 'a user cannot unsubscribe through footer link'
R
Robb Kidd 已提交
633 634

        it 'has the correct subject' do
635
          is_expected.to have_subject /Re: #{project.name} | #{commit.title} \(#{commit.short_id}\)/
R
Robb Kidd 已提交
636 637 638
        end

        it 'contains a link to the commit' do
639
          is_expected.to have_body_text commit.short_id
R
Robb Kidd 已提交
640 641 642 643
        end
      end

      describe 'on a merge request' do
I
Izaak Alpert 已提交
644
        let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
V
Vinnie Okada 已提交
645
        let(:note_on_merge_request_path) { namespace_project_merge_request_path(project.namespace, project, merge_request, anchor: "note_#{note.id}") }
646
        before(:each) { allow(note).to receive(:noteable).and_return(merge_request) }
R
Robb Kidd 已提交
647

648
        subject { Notify.note_merge_request_email(recipient.id, note.id) }
R
Robb Kidd 已提交
649
        it_behaves_like 'a note email'
650 651 652
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
        end
653
        it_behaves_like 'it should show Gmail Actions View Merge request link'
654
        it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
655 656

        it 'has the correct subject' do
657
          is_expected.to have_subject /#{merge_request.title} \(#{merge_request.to_reference}\)/
R
Robb Kidd 已提交
658 659 660
        end

        it 'contains a link to the merge request note' do
661
          is_expected.to have_body_text /#{note_on_merge_request_path}/
R
Robb Kidd 已提交
662 663 664 665
        end
      end

      describe 'on an issue' do
666
        let(:issue) { create(:issue, project: project) }
V
Vinnie Okada 已提交
667
        let(:note_on_issue_path) { namespace_project_issue_path(project.namespace, project, issue, anchor: "note_#{note.id}") }
668
        before(:each) { allow(note).to receive(:noteable).and_return(issue) }
669 670

        subject { Notify.note_issue_email(recipient.id, note.id) }
R
Robb Kidd 已提交
671 672

        it_behaves_like 'a note email'
673 674 675
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
        end
676
        it_behaves_like 'it should show Gmail Actions View Issue link'
677
        it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
678 679

        it 'has the correct subject' do
680
          is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
R
Robb Kidd 已提交
681 682 683
        end

        it 'contains a link to the issue note' do
684
          is_expected.to have_body_text /#{note_on_issue_path}/
R
Robb Kidd 已提交
685 686
        end
      end
687
    end
688 689 690 691 692 693 694 695

    context 'items that are noteable, emails for a note on a diff' do
      let(:note_author) { create(:user, name: 'author_name') }

      before :each do
        allow(Note).to receive(:find).with(note.id).and_return(note)
      end

H
hhoopes 已提交
696
      shared_examples 'a note email on a diff' do  |model|
697 698 699
        let(:note) { create(model, project: project, author: note_author) }

        it "includes diffs with character-level highlighting" do
700
          is_expected.to have_body_text /<span class=\"p\">}<\/span><\/span>/
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
        end

        it 'contains a link to the diff file' do
          is_expected.to have_body_text /#{note.diff_file.file_path}/
        end

        it_behaves_like 'it should have Gmail Actions links'

        it 'is sent as the author' do
          sender = subject.header[:from].addrs[0]
          expect(sender.display_name).to eq(note_author.name)
          expect(sender.address).to eq(gitlab_sender)
        end

        it 'is sent to the given recipient' do
          is_expected.to deliver_to recipient.notification_email
        end

        it 'contains the message from the note' do
          is_expected.to have_body_text /#{note.note}/
        end

        it 'does not contain note author' do
          is_expected.not_to have_body_text /wrote\:/
        end

        context 'when enabled email_author_in_body' do
          before do
S
Sean McGivern 已提交
729
            stub_application_setting(email_author_in_body: true)
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760
          end

          it 'contains a link to note author' do
            is_expected.to have_body_text note.author_name
            is_expected.to have_body_text /wrote\:/
          end
        end
      end

      describe 'on a commit' do
        let(:commit) { project.commit }
        let(:note) { create(:diff_note_on_commit) }

        subject { Notify.note_commit_email(recipient.id, note.id) }

        it_behaves_like 'a note email on a diff', :diff_note_on_commit
        it_behaves_like 'it should show Gmail Actions View Commit link'
        it_behaves_like 'a user cannot unsubscribe through footer link'
      end

      describe 'on a merge request' do
        let(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
        let(:note) { create(:diff_note_on_merge_request) }

        subject { Notify.note_merge_request_email(recipient.id, note.id) }

        it_behaves_like 'a note email on a diff', :diff_note_on_merge_request
        it_behaves_like 'it should show Gmail Actions View Merge request link'
        it_behaves_like 'an unsubscribeable thread'
      end
    end
761
  end
762

763 764
  context 'for a group' do
    describe 'group access requested' do
765
      let(:group) { create(:group, :public, :access_requestable) }
766 767 768
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
769
        group.requesters.find_by(user_id: user.id)
770 771
      end
      subject { Notify.member_access_requested_email('group', group_member.id) }
R
Rémy Coutable 已提交
772

773 774 775
      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"
R
Rémy Coutable 已提交
776

R
Rémy Coutable 已提交
777 778 779 780 781 782
      it 'contains all the useful information' do
        is_expected.to have_subject "Request to join the #{group.name} group"
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group_group_members_url(group)}/
        is_expected.to have_body_text /#{group_member.human_access}/
      end
R
Rémy Coutable 已提交
783 784
    end

785 786 787 788 789
    describe 'group access denied' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
790
        group.requesters.find_by(user_id: user.id)
791 792
      end
      subject { Notify.member_access_denied_email('group', group.id, user.id) }
R
Rémy Coutable 已提交
793

794 795 796
      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"
R
Rémy Coutable 已提交
797

R
Rémy Coutable 已提交
798 799 800 801 802
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{group.name} group was denied"
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group.web_url}/
      end
R
Rémy Coutable 已提交
803 804
    end

805 806 807 808
    describe 'group access changed' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) { create(:group_member, group: group, user: user) }
R
Rémy Coutable 已提交
809

810 811 812 813 814 815
      subject { Notify.member_access_granted_email('group', group_member.id) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
816 817 818 819 820 821
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{group.name} group was granted"
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group.web_url}/
        is_expected.to have_body_text /#{group_member.human_access}/
      end
R
Rémy Coutable 已提交
822 823
    end

824 825 826 827 828 829 830 831 832
    def invite_to_group(group, inviter:)
      create(
        :group_member,
        :developer,
        group: group,
        invite_token: '1234',
        invite_email: 'toto@example.com',
        user: nil,
        created_by: inviter
833
      )
R
Rémy Coutable 已提交
834 835
    end

836 837 838
    describe 'group invitation' do
      let(:group) { create(:group) }
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
839
      let(:group_member) { invite_to_group(group, inviter: owner) }
840

841
      subject { Notify.member_invited_email('group', group_member.id, group_member.invite_token) }
842

843 844 845
      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"
846

R
Rémy Coutable 已提交
847 848 849 850 851 852 853
      it 'contains all the useful information' do
        is_expected.to have_subject "Invitation to join the #{group.name} group"
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group.web_url}/
        is_expected.to have_body_text /#{group_member.human_access}/
        is_expected.to have_body_text /#{group_member.invite_token}/
      end
854 855
    end

856 857
    describe 'group invitation accepted' do
      let(:group) { create(:group) }
858
      let(:invited_user) { create(:user, name: 'invited user') }
859 860
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
861
        invitee = invite_to_group(group, inviter: owner)
862 863 864 865 866 867 868 869 870 871
        invitee.accept_invite!(invited_user)
        invitee
      end

      subject { Notify.member_invite_accepted_email('group', group_member.id) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
872 873 874 875 876 877 878
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation accepted'
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group.web_url}/
        is_expected.to have_body_text /#{group_member.invite_email}/
        is_expected.to have_body_text /#{invited_user.name}/
      end
879 880
    end

881 882 883 884
    describe 'group invitation declined' do
      let(:group) { create(:group) }
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
885
        invitee = invite_to_group(group, inviter: owner)
886 887 888 889 890 891 892 893 894 895
        invitee.decline_invite!
        invitee
      end

      subject { Notify.member_invite_declined_email('group', group.id, group_member.invite_email, owner.id) }

      it_behaves_like 'an email sent from GitLab'
      it_behaves_like 'it should not have Gmail Actions links'
      it_behaves_like "a user cannot unsubscribe through footer link"

R
Rémy Coutable 已提交
896 897 898 899 900 901
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation declined'
        is_expected.to have_body_text /#{group.name}/
        is_expected.to have_body_text /#{group.web_url}/
        is_expected.to have_body_text /#{group_member.invite_email}/
      end
902 903
    end
  end
904 905 906 907 908 909

  describe 'confirmation if email changed' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user, email: 'old-email@mail.com') }

    before do
F
Fu Xu 已提交
910
      stub_config_setting(email_subject_suffix: 'A Nice Suffix')
V
Valery Sizov 已提交
911 912 913 914
      perform_enqueued_jobs do
        user.email = "new-email@mail.com"
        user.save
      end
915 916 917 918
    end

    subject { ActionMailer::Base.deliveries.last }

919
    it_behaves_like 'an email sent from GitLab'
920
    it_behaves_like "a user cannot unsubscribe through footer link"
921

922
    it 'is sent to the new user' do
923
      is_expected.to deliver_to 'new-email@mail.com'
924 925 926
    end

    it 'has the correct subject' do
F
Fu Xu 已提交
927
      is_expected.to have_subject /^Confirmation instructions/
928 929 930
    end

    it 'includes a link to the site' do
931
      is_expected.to have_body_text /#{example_site_path}/
932 933
    end
  end
D
Dmitriy Zaporozhets 已提交
934

935 936 937 938 939
  describe 'email on push for a created branch' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
    let(:tree_path) { namespace_project_tree_path(project.namespace, project, "master") }

940
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :create) }
941

942
    it_behaves_like 'it should not have Gmail Actions links'
943
    it_behaves_like 'a user cannot unsubscribe through footer link'
944 945
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
946

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
    end

    it 'has the correct subject' do
      is_expected.to have_subject /Pushed new branch master/
    end

    it 'contains a link to the branch' do
      is_expected.to have_body_text /#{tree_path}/
    end
  end

  describe 'email on push for a created tag' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
    let(:tree_path) { namespace_project_tree_path(project.namespace, project, "v1.0") }

967
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
968

969
    it_behaves_like 'it should not have Gmail Actions links'
970
    it_behaves_like "a user cannot unsubscribe through footer link"
971 972
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
973

974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
    end

    it 'has the correct subject' do
      is_expected.to have_subject /Pushed new tag v1\.0/
    end

    it 'contains a link to the tag' do
      is_expected.to have_body_text /#{tree_path}/
    end
  end

  describe 'email on push for a deleted branch' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }

993
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) }
994

995
    it_behaves_like 'it should not have Gmail Actions links'
996
    it_behaves_like 'a user cannot unsubscribe through footer link'
997 998
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
999

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
    end

    it 'has the correct subject' do
      is_expected.to have_subject /Deleted branch master/
    end
  end

  describe 'email on push for a deleted tag' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }

1015
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
1016

1017
    it_behaves_like 'it should not have Gmail Actions links'
1018
    it_behaves_like 'a user cannot unsubscribe through footer link'
1019 1020
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1021

1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
    end

    it 'has the correct subject' do
      is_expected.to have_subject /Deleted tag v1\.0/
    end
  end

1033
  describe 'email on push with multiple commits' do
D
Dmitriy Zaporozhets 已提交
1034 1035
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
1036 1037 1038
    let(:raw_compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_image_commit.id, sample_commit.id) }
    let(:compare) { Compare.decorate(raw_compare, project) }
    let(:commits) { compare.commits }
1039
    let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
1040
    let(:send_from_committer_email) { false }
1041
    let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
D
Dmitriy Zaporozhets 已提交
1042

1043
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, reverse_compare: false, diff_refs: diff_refs, send_from_committer_email: send_from_committer_email) }
D
Dmitriy Zaporozhets 已提交
1044

1045
    it_behaves_like 'it should not have Gmail Actions links'
1046
    it_behaves_like 'a user cannot unsubscribe through footer link'
1047 1048
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1049

1050 1051
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1052 1053
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1054 1055
    end

D
Dmitriy Zaporozhets 已提交
1056
    it 'has the correct subject' do
1057
      is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
D
Dmitriy Zaporozhets 已提交
1058 1059 1060
    end

    it 'includes commits list' do
1061
      is_expected.to have_body_text /Change some files/
D
Dmitriy Zaporozhets 已提交
1062 1063
    end

1064 1065
    it 'includes diffs with character-level highlighting' do
      is_expected.to have_body_text /def<\/span> <span class=\"nf\">archive_formats_regex/
D
Dmitriy Zaporozhets 已提交
1066
    end
1067 1068

    it 'contains a link to the diff' do
1069
      is_expected.to have_body_text /#{diff_path}/
1070
    end
1071

1072
    it 'does not contain the misleading footer' do
1073 1074
      is_expected.not_to have_body_text /you are a member of/
    end
1075 1076 1077 1078

    context "when set to send from committer email if domain matches" do
      let(:send_from_committer_email) { true }

1079 1080 1081 1082 1083
      before do
        allow(Gitlab.config.gitlab).to receive(:host).and_return("gitlab.corp.company.com")
      end

      context "when the committer email domain is within the GitLab domain" do
1084
        before do
1085
          user.update_attribute(:email, "user@company.com")
1086
          user.confirm
1087 1088 1089 1090 1091 1092
        end

        it "is sent from the committer email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(user.email)
        end
1093 1094 1095 1096 1097

        it "is set to reply to the committer email" do
          sender = subject.header[:reply_to].addrs[0]
          expect(sender.address).to eq(user.email)
        end
1098 1099
      end

1100 1101 1102
      context "when the committer email domain is not completely within the GitLab domain" do
        before do
          user.update_attribute(:email, "user@something.company.com")
1103
          user.confirm
1104 1105 1106 1107 1108 1109
        end

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1110 1111 1112 1113 1114

        it "is set to reply to the default email" do
          sender = subject.header[:reply_to].addrs[0]
          expect(sender.address).to eq(gitlab_sender_reply_to)
        end
1115 1116 1117 1118 1119
      end

      context "when the committer email domain is outside the GitLab domain" do
        before do
          user.update_attribute(:email, "user@mpany.com")
1120
          user.confirm
1121
        end
1122 1123 1124 1125 1126

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1127 1128 1129 1130 1131

        it "is set to reply to the default email" do
          sender = subject.header[:reply_to].addrs[0]
          expect(sender.address).to eq(gitlab_sender_reply_to)
        end
1132 1133
      end
    end
D
Dmitriy Zaporozhets 已提交
1134
  end
1135 1136 1137 1138

  describe 'email on push with a single commit' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
1139 1140 1141
    let(:raw_compare) { Gitlab::Git::Compare.new(project.repository.raw_repository, sample_commit.parent_id, sample_commit.id) }
    let(:compare) { Compare.decorate(raw_compare, project) }
    let(:commits) { compare.commits }
V
Vinnie Okada 已提交
1142
    let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
1143
    let(:diff_refs) { Gitlab::Diff::DiffRefs.new(base_sha: project.merge_base_commit(sample_image_commit.id, sample_commit.id).id, head_sha: sample_commit.id) }
1144

1145
    subject { Notify.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) }
1146

1147
    it_behaves_like 'it should show Gmail Actions View Commit link'
1148
    it_behaves_like 'a user cannot unsubscribe through footer link'
1149 1150
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1151

1152 1153
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1154 1155
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1156 1157 1158
    end

    it 'has the correct subject' do
1159
      is_expected.to have_subject /#{commits.first.title}/
1160 1161 1162
    end

    it 'includes commits list' do
1163
      is_expected.to have_body_text /Change some files/
1164 1165
    end

1166 1167
    it 'includes diffs with character-level highlighting' do
      is_expected.to have_body_text /def<\/span> <span class=\"nf\">archive_formats_regex/
1168 1169 1170
    end

    it 'contains a link to the diff' do
1171
      is_expected.to have_body_text /#{diff_path}/
1172 1173
    end
  end
1174
end