notify_spec.rb 43.5 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
53
              allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(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
232
              allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(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 585 586
      before do |example|
        unless example.metadata[:skip_before]
          allow(Note).to receive(:find).with(note.id).and_return(note)
        end
587 588
      end

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

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

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

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

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

        context 'when enabled email_author_in_body' do
          before do
612
            allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
613 614 615 616 617 618 619
          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 已提交
620 621 622
      end

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

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

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

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

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

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

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

650
        subject { Notify.note_merge_request_email(recipient.id, note.id) }
R
Robb Kidd 已提交
651 652

        it_behaves_like 'a note email'
653 654 655
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
        end
656
        it_behaves_like 'it should show Gmail Actions View Merge request link'
657
        it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
658 659

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

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

668 669 670 671 672 673 674 675 676 677 678 679 680
      describe "on a merge request with diffs", :skip_before do
        let(:merge_request) { create(:merge_request_with_diffs) }
        let(:note_with_diff) {create(:diff_note_on_merge_request)}

        before(:each) { allow(note_with_diff).to receive(:noteable).and_return(merge_request) }
        subject { Notify.note_merge_request_email(recipient.id, note_with_diff.id) }

        it 'includes diffs with character-level highlighting' do
          expected_line_text = Discussion.new([note_with_diff]).truncated_diff_lines.first.text
          is_expected.to have_body_text expected_line_text
        end
      end

R
Robb Kidd 已提交
681
      describe 'on an issue' do
682
        let(:issue) { create(:issue, project: project) }
V
Vinnie Okada 已提交
683
        let(:note_on_issue_path) { namespace_project_issue_path(project.namespace, project, issue, anchor: "note_#{note.id}") }
684
        before(:each) { allow(note).to receive(:noteable).and_return(issue) }
685 686

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

        it_behaves_like 'a note email'
689 690 691
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
        end
692
        it_behaves_like 'it should show Gmail Actions View Issue link'
693
        it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
694 695

        it 'has the correct subject' do
696
          is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
R
Robb Kidd 已提交
697 698 699
        end

        it 'contains a link to the issue note' do
700
          is_expected.to have_body_text /#{note_on_issue_path}/
R
Robb Kidd 已提交
701 702
        end
      end
703 704
    end
  end
705

706 707
  context 'for a group' do
    describe 'group access requested' do
708
      let(:group) { create(:group, :public, :access_requestable) }
709 710 711
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
712
        group.requesters.find_by(user_id: user.id)
713 714
      end
      subject { Notify.member_access_requested_email('group', group_member.id) }
R
Rémy Coutable 已提交
715

716 717 718
      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 已提交
719

R
Rémy Coutable 已提交
720 721 722 723 724 725
      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 已提交
726 727
    end

728 729 730 731 732
    describe 'group access denied' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
733
        group.requesters.find_by(user_id: user.id)
734 735
      end
      subject { Notify.member_access_denied_email('group', group.id, user.id) }
R
Rémy Coutable 已提交
736

737 738 739
      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 已提交
740

R
Rémy Coutable 已提交
741 742 743 744 745
      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 已提交
746 747
    end

748 749 750 751
    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 已提交
752

753 754 755 756 757 758
      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 已提交
759 760 761 762 763 764
      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 已提交
765 766
    end

767 768 769 770 771 772 773 774 775
    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
776
      )
R
Rémy Coutable 已提交
777 778
    end

779 780 781
    describe 'group invitation' do
      let(:group) { create(:group) }
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
782
      let(:group_member) { invite_to_group(group, inviter: owner) }
783

784
      subject { Notify.member_invited_email('group', group_member.id, group_member.invite_token) }
785

786 787 788
      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"
789

R
Rémy Coutable 已提交
790 791 792 793 794 795 796
      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
797 798
    end

799 800
    describe 'group invitation accepted' do
      let(:group) { create(:group) }
801
      let(:invited_user) { create(:user, name: 'invited user') }
802 803
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
804
        invitee = invite_to_group(group, inviter: owner)
805 806 807 808 809 810 811 812 813 814
        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 已提交
815 816 817 818 819 820 821
      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
822 823
    end

824 825 826 827
    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
828
        invitee = invite_to_group(group, inviter: owner)
829 830 831 832 833 834 835 836 837 838
        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 已提交
839 840 841 842 843 844
      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
845 846
    end
  end
847 848 849 850 851 852

  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 已提交
853
      stub_config_setting(email_subject_suffix: 'A Nice Suffix')
V
Valery Sizov 已提交
854 855 856 857
      perform_enqueued_jobs do
        user.email = "new-email@mail.com"
        user.save
      end
858 859 860 861
    end

    subject { ActionMailer::Base.deliveries.last }

862
    it_behaves_like 'an email sent from GitLab'
863
    it_behaves_like "a user cannot unsubscribe through footer link"
864

865
    it 'is sent to the new user' do
866
      is_expected.to deliver_to 'new-email@mail.com'
867 868 869
    end

    it 'has the correct subject' do
F
Fu Xu 已提交
870
      is_expected.to have_subject /^Confirmation instructions/
871 872 873
    end

    it 'includes a link to the site' do
874
      is_expected.to have_body_text /#{example_site_path}/
875 876
    end
  end
D
Dmitriy Zaporozhets 已提交
877

878 879 880 881 882
  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") }

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

885
    it_behaves_like 'it should not have Gmail Actions links'
886
    it_behaves_like 'a user cannot unsubscribe through footer link'
887 888
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
889

890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909
    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") }

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

912
    it_behaves_like 'it should not have Gmail Actions links'
913
    it_behaves_like "a user cannot unsubscribe through footer link"
914 915
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
916

917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935
    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) }

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

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

943 944 945 946 947 948 949 950 951 952 953 954 955 956 957
    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) }

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

960
    it_behaves_like 'it should not have Gmail Actions links'
961
    it_behaves_like 'a user cannot unsubscribe through footer link'
962 963
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
964

965 966 967 968 969 970 971 972 973 974 975
    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

976
  describe 'email on push with multiple commits' do
D
Dmitriy Zaporozhets 已提交
977 978
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
979 980 981
    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 }
982
    let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
983
    let(:send_from_committer_email) { false }
984
    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 已提交
985

986
    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 已提交
987

988
    it_behaves_like 'it should not have Gmail Actions links'
989
    it_behaves_like 'a user cannot unsubscribe through footer link'
990 991
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
992

993 994
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
995 996
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
997 998
    end

D
Dmitriy Zaporozhets 已提交
999
    it 'has the correct subject' do
1000
      is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
D
Dmitriy Zaporozhets 已提交
1001 1002 1003
    end

    it 'includes commits list' do
1004
      is_expected.to have_body_text /Change some files/
D
Dmitriy Zaporozhets 已提交
1005 1006
    end

1007 1008
    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 已提交
1009
    end
1010 1011

    it 'contains a link to the diff' do
1012
      is_expected.to have_body_text /#{diff_path}/
1013
    end
1014

1015
    it 'does not contain the misleading footer' do
1016 1017
      is_expected.not_to have_body_text /you are a member of/
    end
1018 1019 1020 1021

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

1022 1023 1024 1025 1026
      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
1027
        before do
1028
          user.update_attribute(:email, "user@company.com")
1029
          user.confirm
1030 1031 1032 1033 1034 1035
        end

        it "is sent from the committer email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(user.email)
        end
1036 1037 1038 1039 1040

        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
1041 1042
      end

1043 1044 1045
      context "when the committer email domain is not completely within the GitLab domain" do
        before do
          user.update_attribute(:email, "user@something.company.com")
1046
          user.confirm
1047 1048 1049 1050 1051 1052
        end

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1053 1054 1055 1056 1057

        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
1058 1059 1060 1061 1062
      end

      context "when the committer email domain is outside the GitLab domain" do
        before do
          user.update_attribute(:email, "user@mpany.com")
1063
          user.confirm
1064
        end
1065 1066 1067 1068 1069

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1070 1071 1072 1073 1074

        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
1075 1076
      end
    end
D
Dmitriy Zaporozhets 已提交
1077
  end
1078 1079 1080 1081

  describe 'email on push with a single commit' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
1082 1083 1084
    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 已提交
1085
    let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
1086
    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) }
1087

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

1090
    it_behaves_like 'it should show Gmail Actions View Commit link'
1091
    it_behaves_like 'a user cannot unsubscribe through footer link'
1092 1093
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1094

1095 1096
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1097 1098
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1099 1100 1101
    end

    it 'has the correct subject' do
1102
      is_expected.to have_subject /#{commits.first.title}/
1103 1104 1105
    end

    it 'includes commits list' do
1106
      is_expected.to have_body_text /Change some files/
1107 1108
    end

1109 1110
    it 'includes diffs with character-level highlighting' do
      is_expected.to have_body_text /def<\/span> <span class=\"nf\">archive_formats_regex/
1111 1112 1113
    end

    it 'contains a link to the diff' do
1114
      is_expected.to have_body_text /#{diff_path}/
1115 1116
    end
  end
1117
end