notify_spec.rb 42.6 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
        let(:project) { create(:project, :public).tap { |p| p.team << [p.owner, :master, p.owner] } }
405 406 407
        let(:user) { create(:user) }
        let(:project_member) do
          project.request_access(user)
408
          project.requesters.find_by(user_id: user.id)
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425
        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 已提交
426 427
      end

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

439 440 441 442 443 444 445 446 447 448 449 450 451 452
        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 已提交
453
      end
R
Rémy Coutable 已提交
454 455 456 457 458 459 460
    end

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

      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 已提交
469 470 471 472 473
      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 已提交
474 475
    end

476
    describe 'project access changed' do
477
      let(:project) { create(:project) }
478
      let(:user) { create(:user) }
479
      let(:project_member) { create(:project_member, project: project, user: user) }
480
      subject { Notify.member_access_granted_email('project', project_member.id) }
481 482

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

R
Rémy Coutable 已提交
486 487 488 489 490 491
      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
492
    end
493

494 495 496 497 498 499 500 501 502
    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
503
      )
504 505 506 507 508
    end

    describe 'project invitation' do
      let(:project) { create(:project) }
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
509
      let(:project_member) { invite_to_project(project, inviter: master) }
510 511 512 513 514 515 516

      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 已提交
517 518 519 520 521 522 523
      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
524 525 526 527
    end

    describe 'project invitation accepted' do
      let(:project) { create(:project) }
528
      let(:invited_user) { create(:user, name: 'invited user') }
529 530
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
531
        invitee = invite_to_project(project, inviter: master)
532 533
        invitee.accept_invite!(invited_user)
        invitee
534
      end
535

536 537 538 539 540 541
      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 已提交
542 543 544 545 546 547 548
      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
549 550 551 552 553 554
    end

    describe 'project invitation declined' do
      let(:project) { create(:project) }
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
555
        invitee = invite_to_project(project, inviter: master)
556 557
        invitee.decline_invite!
        invitee
558
      end
559 560 561 562 563 564 565

      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 已提交
566 567 568 569 570 571
      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
572 573
    end

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

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

R
Robb Kidd 已提交
582
      shared_examples 'a note email' do
583 584
        it_behaves_like 'it should have Gmail Actions links'

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

R
Robb Kidd 已提交
591
        it 'is sent to the given recipient' do
592
          is_expected.to deliver_to recipient.notification_email
R
Robb Kidd 已提交
593 594 595
        end

        it 'contains the message from the note' do
596
          is_expected.to have_body_text /#{note.note}/
R
Robb Kidd 已提交
597
        end
598

599
        it 'does not contain note author' do
600 601 602 603 604
          is_expected.not_to have_body_text /wrote\:/
        end

        context 'when enabled email_author_in_body' do
          before do
605
            allow_any_instance_of(ApplicationSetting).to receive(:email_author_in_body).and_return(true)
606 607 608 609 610 611 612
          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 已提交
613 614 615
      end

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

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

D
Dmitriy Zaporozhets 已提交
620
        subject { Notify.note_commit_email(recipient.id, note.id) }
R
Robb Kidd 已提交
621 622

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

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

        it 'contains a link to the commit' do
634
          is_expected.to have_body_text commit.short_id
R
Robb Kidd 已提交
635 636 637 638
        end
      end

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

643
        subject { Notify.note_merge_request_email(recipient.id, note.id) }
R
Robb Kidd 已提交
644 645

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

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

        it 'contains a link to the merge request note' do
657
          is_expected.to have_body_text /#{note_on_merge_request_path}/
R
Robb Kidd 已提交
658 659 660 661
        end
      end

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

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

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

        it 'has the correct subject' do
676
          is_expected.to have_subject /#{issue.title} \(##{issue.iid}\)/
R
Robb Kidd 已提交
677 678 679
        end

        it 'contains a link to the issue note' do
680
          is_expected.to have_body_text /#{note_on_issue_path}/
R
Robb Kidd 已提交
681 682
        end
      end
683 684
    end
  end
685

686 687 688 689 690 691
  context 'for a group' do
    describe 'group access requested' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
692
        group.requesters.find_by(user_id: user.id)
693 694
      end
      subject { Notify.member_access_requested_email('group', group_member.id) }
R
Rémy Coutable 已提交
695

696 697 698
      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 已提交
699

R
Rémy Coutable 已提交
700 701 702 703 704 705
      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 已提交
706 707
    end

708 709 710 711 712
    describe 'group access denied' do
      let(:group) { create(:group) }
      let(:user) { create(:user) }
      let(:group_member) do
        group.request_access(user)
713
        group.requesters.find_by(user_id: user.id)
714 715
      end
      subject { Notify.member_access_denied_email('group', group.id, user.id) }
R
Rémy Coutable 已提交
716

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

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

728 729 730 731
    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 已提交
732

733 734 735 736 737 738
      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 已提交
739 740 741 742 743 744
      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 已提交
745 746
    end

747 748 749 750 751 752 753 754 755
    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
756
      )
R
Rémy Coutable 已提交
757 758
    end

759 760 761
    describe 'group invitation' do
      let(:group) { create(:group) }
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
762
      let(:group_member) { invite_to_group(group, inviter: owner) }
763

764
      subject { Notify.member_invited_email('group', group_member.id, group_member.invite_token) }
765

766 767 768
      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"
769

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

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

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

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

    subject { ActionMailer::Base.deliveries.last }

842
    it_behaves_like 'an email sent from GitLab'
843
    it_behaves_like "a user cannot unsubscribe through footer link"
844

845
    it 'is sent to the new user' do
846
      is_expected.to deliver_to 'new-email@mail.com'
847 848 849
    end

    it 'has the correct subject' do
F
Fu Xu 已提交
850
      is_expected.to have_subject /^Confirmation instructions/
851 852 853
    end

    it 'includes a link to the site' do
854
      is_expected.to have_body_text /#{example_site_path}/
855 856
    end
  end
D
Dmitriy Zaporozhets 已提交
857

858 859 860 861 862
  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") }

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

865
    it_behaves_like 'it should not have Gmail Actions links'
866
    it_behaves_like 'a user cannot unsubscribe through footer link'
867 868
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
869

870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889
    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") }

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

892
    it_behaves_like 'it should not have Gmail Actions links'
893
    it_behaves_like "a user cannot unsubscribe through footer link"
894 895
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
896

897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915
    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) }

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

918
    it_behaves_like 'it should not have Gmail Actions links'
919
    it_behaves_like 'a user cannot unsubscribe through footer link'
920 921
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
922

923 924 925 926 927 928 929 930 931 932 933 934 935 936 937
    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) }

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

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

945 946 947 948 949 950 951 952 953 954 955
    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

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

966
    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 已提交
967

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

973 974
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
975 976
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
977 978
    end

D
Dmitriy Zaporozhets 已提交
979
    it 'has the correct subject' do
980
      is_expected.to have_subject /\[#{project.path_with_namespace}\]\[master\] #{commits.length} commits:/
D
Dmitriy Zaporozhets 已提交
981 982 983
    end

    it 'includes commits list' do
984
      is_expected.to have_body_text /Change some files/
D
Dmitriy Zaporozhets 已提交
985 986
    end

987 988
    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 已提交
989
    end
990 991

    it 'contains a link to the diff' do
992
      is_expected.to have_body_text /#{diff_path}/
993
    end
994

995
    it 'does not contain the misleading footer' do
996 997
      is_expected.not_to have_body_text /you are a member of/
    end
998 999 1000 1001

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

1002 1003 1004 1005 1006
      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
1007
        before do
1008
          user.update_attribute(:email, "user@company.com")
1009
          user.confirm
1010 1011 1012 1013 1014 1015
        end

        it "is sent from the committer email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(user.email)
        end
1016 1017 1018 1019 1020

        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
1021 1022
      end

1023 1024 1025
      context "when the committer email domain is not completely within the GitLab domain" do
        before do
          user.update_attribute(:email, "user@something.company.com")
1026
          user.confirm
1027 1028 1029 1030 1031 1032
        end

        it "is sent from the default email" do
          sender = subject.header[:from].addrs[0]
          expect(sender.address).to eq(gitlab_sender)
        end
1033 1034 1035 1036 1037

        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
1038 1039 1040 1041 1042
      end

      context "when the committer email domain is outside the GitLab domain" do
        before do
          user.update_attribute(:email, "user@mpany.com")
1043
          user.confirm
1044
        end
1045 1046 1047 1048 1049

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

        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
1055 1056
      end
    end
D
Dmitriy Zaporozhets 已提交
1057
  end
1058 1059 1060 1061

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

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

1070
    it_behaves_like 'it should show Gmail Actions View Commit link'
1071
    it_behaves_like 'a user cannot unsubscribe through footer link'
1072 1073
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1074

1075 1076
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1077 1078
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1079 1080 1081
    end

    it 'has the correct subject' do
1082
      is_expected.to have_subject /#{commits.first.title}/
1083 1084 1085
    end

    it 'includes commits list' do
1086
      is_expected.to have_body_text /Change some files/
1087 1088
    end

1089 1090
    it 'includes diffs with character-level highlighting' do
      is_expected.to have_body_text /def<\/span> <span class=\"nf\">archive_formats_regex/
1091 1092 1093
    end

    it 'contains a link to the diff' do
1094
      is_expected.to have_body_text /#{diff_path}/
1095 1096
    end
  end
1097
end