notify_spec.rb 42.8 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
      before :each do
584
        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
610
            allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(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 650

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

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

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

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

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

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

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

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

691 692
  context 'for a group' do
    describe 'group access requested' do
693
      let(:group) { create(:group, :public, :access_requestable) }
694 695 696
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
697
        group.requesters.find_by(user_id: user.id)
698 699
      end
      subject { Notify.member_access_requested_email('group', group_member.id) }
R
Rémy Coutable 已提交
700

701 702 703
      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 已提交
704

R
Rémy Coutable 已提交
705 706 707 708 709 710
      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 已提交
711 712
    end

713 714 715 716 717
    describe 'group access denied' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
718
        group.requesters.find_by(user_id: user.id)
719 720
      end
      subject { Notify.member_access_denied_email('group', group.id, user.id) }
R
Rémy Coutable 已提交
721

722 723 724
      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 已提交
725

R
Rémy Coutable 已提交
726 727 728 729 730
      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 已提交
731 732
    end

733 734 735 736
    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 已提交
737

738 739 740 741 742 743
      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 已提交
744 745 746 747 748 749
      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 已提交
750 751
    end

752 753 754 755 756 757 758 759 760
    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
761
      )
R
Rémy Coutable 已提交
762 763
    end

764 765 766
    describe 'group invitation' do
      let(:group) { create(:group) }
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
767
      let(:group_member) { invite_to_group(group, inviter: owner) }
768

769
      subject { Notify.member_invited_email('group', group_member.id, group_member.invite_token) }
770

771 772 773
      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"
774

R
Rémy Coutable 已提交
775 776 777 778 779 780 781
      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
782 783
    end

784 785
    describe 'group invitation accepted' do
      let(:group) { create(:group) }
786
      let(:invited_user) { create(:user, name: 'invited user') }
787 788
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
789
        invitee = invite_to_group(group, inviter: owner)
790 791 792 793 794 795 796 797 798 799
        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 已提交
800 801 802 803 804 805 806
      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
807 808
    end

809 810 811 812
    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
813
        invitee = invite_to_group(group, inviter: owner)
814 815 816 817 818 819 820 821 822 823
        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 已提交
824 825 826 827 828 829
      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
830 831
    end
  end
832 833 834 835 836 837

  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 已提交
838
      stub_config_setting(email_subject_suffix: 'A Nice Suffix')
V
Valery Sizov 已提交
839 840 841 842
      perform_enqueued_jobs do
        user.email = "new-email@mail.com"
        user.save
      end
843 844 845 846
    end

    subject { ActionMailer::Base.deliveries.last }

847
    it_behaves_like 'an email sent from GitLab'
848
    it_behaves_like "a user cannot unsubscribe through footer link"
849

850
    it 'is sent to the new user' do
851
      is_expected.to deliver_to 'new-email@mail.com'
852 853 854
    end

    it 'has the correct subject' do
F
Fu Xu 已提交
855
      is_expected.to have_subject /^Confirmation instructions/
856 857 858
    end

    it 'includes a link to the site' do
859
      is_expected.to have_body_text /#{example_site_path}/
860 861
    end
  end
D
Dmitriy Zaporozhets 已提交
862

863 864 865 866 867
  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") }

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

870
    it_behaves_like 'it should not have Gmail Actions links'
871
    it_behaves_like 'a user cannot unsubscribe through footer link'
872 873
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
874

875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894
    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") }

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

897
    it_behaves_like 'it should not have Gmail Actions links'
898
    it_behaves_like "a user cannot unsubscribe through footer link"
899 900
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
901

902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
    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) }

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

923
    it_behaves_like 'it should not have Gmail Actions links'
924
    it_behaves_like 'a user cannot unsubscribe through footer link'
925 926
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
927

928 929 930 931 932 933 934 935 936 937 938 939 940 941 942
    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) }

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

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

950 951 952 953 954 955 956 957 958 959 960
    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

961
  describe 'email on push with multiple commits' do
D
Dmitriy Zaporozhets 已提交
962 963
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
964 965 966
    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 }
967
    let(:diff_path) { namespace_project_compare_path(project.namespace, project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
968
    let(:send_from_committer_email) { false }
969
    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 已提交
970

971
    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 已提交
972

973
    it_behaves_like 'it should not have Gmail Actions links'
974
    it_behaves_like 'a user cannot unsubscribe through footer link'
975 976
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
977

978 979
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
980 981
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
982 983
    end

D
Dmitriy Zaporozhets 已提交
984
    it 'has the correct subject' do
985
      is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
D
Dmitriy Zaporozhets 已提交
986 987 988
    end

    it 'includes commits list' do
989
      is_expected.to have_body_text /Change some files/
D
Dmitriy Zaporozhets 已提交
990 991
    end

992 993
    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 已提交
994
    end
995 996

    it 'contains a link to the diff' do
997
      is_expected.to have_body_text /#{diff_path}/
998
    end
999

1000
    it 'does not contain the misleading footer' do
1001 1002
      is_expected.not_to have_body_text /you are a member of/
    end
1003 1004 1005 1006

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

1007 1008 1009 1010 1011
      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
1012
        before do
1013
          user.update_attribute(:email, "user@company.com")
1014
          user.confirm
1015 1016 1017 1018 1019 1020
        end

        it "is sent from the committer email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(user.email)
        end
1021 1022 1023 1024 1025

        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
1026 1027
      end

1028 1029 1030
      context "when the committer email domain is not completely within the GitLab domain" do
        before do
          user.update_attribute(:email, "user@something.company.com")
1031
          user.confirm
1032 1033 1034 1035 1036 1037
        end

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1038 1039 1040 1041 1042

        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
1043 1044 1045 1046 1047
      end

      context "when the committer email domain is outside the GitLab domain" do
        before do
          user.update_attribute(:email, "user@mpany.com")
1048
          user.confirm
1049
        end
1050 1051 1052 1053 1054

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

        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
1060 1061
      end
    end
D
Dmitriy Zaporozhets 已提交
1062
  end
1063 1064 1065 1066

  describe 'email on push with a single commit' do
    let(:example_site_path) { root_path }
    let(:user) { create(:user) }
1067 1068 1069
    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 已提交
1070
    let(:diff_path) { namespace_project_commit_path(project.namespace, project, commits.first) }
1071
    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) }
1072

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

1075
    it_behaves_like 'it should show Gmail Actions View Commit link'
1076
    it_behaves_like 'a user cannot unsubscribe through footer link'
1077 1078
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1079

1080 1081
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1082 1083
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1084 1085 1086
    end

    it 'has the correct subject' do
1087
      is_expected.to have_subject /#{commits.first.title}/
1088 1089 1090
    end

    it 'includes commits list' do
1091
      is_expected.to have_body_text /Change some files/
1092 1093
    end

1094 1095
    it 'includes diffs with character-level highlighting' do
      is_expected.to have_body_text /def<\/span> <span class=\"nf\">archive_formats_regex/
1096 1097 1098
    end

    it 'contains a link to the diff' do
1099
      is_expected.to have_body_text /#{diff_path}/
1100 1101
    end
  end
1102
end