notify_spec.rb 48.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

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
  set(:user) { create(:user) }
  set(:current_user) { create(:user, email: "current@email.com") }
  set(:assignee) { create(:user, email: 'assignee@example.com', name: 'John Doe') }

  set(:merge_request) do
    create(:merge_request, source_project: project,
                           target_project: project,
                           author: current_user,
                           assignee: assignee,
                           description: 'Awesome description')
  end

  set(:issue) do
    create(:issue, author: current_user,
                   assignees: [assignee],
                   project: project,
                   description: 'My awesome description!')
  end

30
  def have_referable_subject(referable, reply: false)
31 32
    prefix = referable.project ? "#{referable.project.name} | " : ''
    prefix.prepend('Re: ') if reply
33 34 35

    suffix = "#{referable.title} (#{referable.to_reference})"

36
    have_subject [prefix, suffix].compact.join
37 38
  end

R
Robb Kidd 已提交
39
  context 'for a project' do
40 41 42 43 44 45 46 47 48 49 50
    shared_examples 'an assignee email' do
      it 'is sent to the assignee as the author' do
        sender = subject.header[:from].addrs.first

        aggregate_failures do
          expect(sender.display_name).to eq(current_user.name)
          expect(sender.address).to eq(gitlab_sender)
          expect(subject).to deliver_to(assignee.email)
        end
      end
    end
51

52 53 54
    context 'for issues' do
      describe 'that are new' do
        subject { described_class.new_issue_email(issue.assignees.first.id, issue.id) }
55

56 57 58 59 60 61 62 63
        it_behaves_like 'an assignee email'
        it_behaves_like 'an email starting a new thread with reply-by-email enabled' do
          let(:model) { issue }
        end
        it_behaves_like 'it should show Gmail Actions View Issue link'
        it_behaves_like 'an unsubscribeable thread'

        it 'has the correct subject and body' do
64
          aggregate_failures do
65 66
            is_expected.to have_referable_subject(issue)
            is_expected.to have_body_text(project_issue_path(project, issue))
67
          end
R
Robb Kidd 已提交
68
        end
69

70 71 72
        it 'contains the description' do
          is_expected.to have_html_escaped_body_text issue.description
        end
73

74 75 76
        context 'when enabled email_author_in_body' do
          before do
            stub_application_setting(email_author_in_body: true)
R
Robb Kidd 已提交
77
          end
78

79 80 81
          it 'contains a link to note author' do
            is_expected.to have_html_escaped_body_text(issue.author_name)
            is_expected.to have_body_text 'created an issue:'
82
          end
83 84
        end
      end
85

86 87 88
      describe 'that are reassigned' do
        let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
        subject { described_class.reassigned_issue_email(recipient.id, issue.id, [previous_assignee.id], current_user.id) }
89

90 91 92
        it_behaves_like 'a multiple recipients email'
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
R
Robb Kidd 已提交
93
        end
94 95
        it_behaves_like 'it should show Gmail Actions View Issue link'
        it_behaves_like 'an unsubscribeable thread'
96

97 98 99 100 101
        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
R
Robb Kidd 已提交
102

103 104 105 106 107 108
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(issue, reply: true)
            is_expected.to have_html_escaped_body_text(previous_assignee.name)
            is_expected.to have_html_escaped_body_text(assignee.name)
            is_expected.to have_body_text(project_issue_path(project, issue))
109
          end
110 111
        end
      end
R
Robb Kidd 已提交
112

113 114
      describe 'that have been relabeled' do
        subject { described_class.relabeled_issue_email(recipient.id, issue.id, %w[foo bar baz], current_user.id) }
115

116 117 118
        it_behaves_like 'a multiple recipients email'
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
R
Robb Kidd 已提交
119
        end
120 121 122
        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'
A
Alex Denisov 已提交
123

124 125 126 127 128
        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
129

130 131 132 133 134
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(issue, reply: true)
            is_expected.to have_body_text('foo, bar, and baz')
            is_expected.to have_body_text(project_issue_path(project, issue))
135
          end
136
        end
137

138 139 140
        context 'with a preferred language' do
          before do
            Gitlab::I18n.locale = :es
141 142
          end

143 144
          after do
            Gitlab::I18n.use_default_locale
145
          end
146

147 148
          it 'always generates the email using the default language' do
            is_expected.to have_body_text('foo, bar, and baz')
149
          end
150
        end
151
      end
152

153 154 155
      describe 'status changed' do
        let(:status) { 'closed' }
        subject { described_class.issue_status_changed_email(recipient.id, issue.id, status, current_user.id) }
156

157 158 159 160 161
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
        end
        it_behaves_like 'it should show Gmail Actions View Issue link'
        it_behaves_like 'an unsubscribeable thread'
162

163 164 165 166 167
        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
168

169 170 171 172 173 174
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(issue, reply: true)
            is_expected.to have_body_text(status)
            is_expected.to have_html_escaped_body_text(current_user.name)
            is_expected.to have_body_text(project_issue_path project, issue)
A
Alex Denisov 已提交
175
          end
176
        end
177
      end
178

179 180 181
      describe 'moved to another project' do
        let(:new_issue) { create(:issue) }
        subject { described_class.issue_moved_email(recipient, issue, new_issue, current_user) }
182

183 184 185 186 187
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
        end
        it_behaves_like 'it should show Gmail Actions View Issue link'
        it_behaves_like 'an unsubscribeable thread'
188

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

193 194
        it 'has the correct subject and body' do
          new_issue_url = project_issue_path(new_issue.project, new_issue)
195

196 197 198 199
          aggregate_failures do
            is_expected.to have_referable_subject(issue, reply: true)
            is_expected.to have_body_text(new_issue_url)
            is_expected.to have_body_text(project_issue_path(project, issue))
200 201
          end
        end
R
Robb Kidd 已提交
202
      end
203
    end
R
Robb Kidd 已提交
204

205 206 207 208 209 210 211 212 213 214
    context 'for merge requests' do
      describe 'that are new' do
        subject { described_class.new_merge_request_email(merge_request.assignee_id, merge_request.id) }

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

216 217 218 219 220 221
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(merge_request)
            is_expected.to have_body_text(project_merge_request_path(project, merge_request))
            is_expected.to have_body_text(merge_request.source_branch)
            is_expected.to have_body_text(merge_request.target_branch)
222
          end
223 224 225 226 227 228 229 230 231
        end

        it 'contains the description' do
          is_expected.to have_html_escaped_body_text merge_request.description
        end

        context 'when enabled email_author_in_body' do
          before do
            stub_application_setting(email_author_in_body: true)
R
Robb Kidd 已提交
232
          end
P
Philip Blatter 已提交
233

234 235 236
          it 'contains a link to note author' do
            is_expected.to have_html_escaped_body_text merge_request.author_name
            is_expected.to have_body_text 'created a merge request:'
237
          end
238 239
        end
      end
240

241 242 243
      describe 'that are reassigned' do
        let(:previous_assignee) { create(:user, name: 'Previous Assignee') }
        subject { described_class.reassigned_merge_request_email(recipient.id, merge_request.id, previous_assignee.id, current_user.id) }
244

245 246 247
        it_behaves_like 'a multiple recipients email'
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
R
Robb Kidd 已提交
248
        end
249 250
        it_behaves_like 'it should show Gmail Actions View Merge request link'
        it_behaves_like "an unsubscribeable thread"
R
Robb Kidd 已提交
251

252 253 254 255 256
        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
R
Robb Kidd 已提交
257

258 259 260 261 262 263
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(merge_request, reply: true)
            is_expected.to have_html_escaped_body_text(previous_assignee.name)
            is_expected.to have_body_text(project_merge_request_path(project, merge_request))
            is_expected.to have_html_escaped_body_text(assignee.name)
264
          end
265 266
        end
      end
R
Robb Kidd 已提交
267

268 269
      describe 'that have been relabeled' do
        subject { described_class.relabeled_merge_request_email(recipient.id, merge_request.id, %w[foo bar baz], current_user.id) }
270

271 272 273
        it_behaves_like 'a multiple recipients email'
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
274
        end
275 276 277
        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'
278

279 280 281 282 283
        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
284

285 286 287 288 289 290
        it 'has the correct subject and body' do
          is_expected.to have_referable_subject(merge_request, reply: true)
          is_expected.to have_body_text('foo, bar, and baz')
          is_expected.to have_body_text(project_merge_request_path(project, merge_request))
        end
      end
291

292 293 294
      describe 'status changed' do
        let(:status) { 'reopened' }
        subject { described_class.merge_request_status_email(recipient.id, merge_request.id, status, current_user.id) }
295

296 297 298 299 300 301 302 303 304 305 306 307 308 309
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
        end
        it_behaves_like 'it should show Gmail Actions View Merge request link'
        it_behaves_like 'an unsubscribeable thread'

        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 and body' do
          aggregate_failures do
310
            is_expected.to have_referable_subject(merge_request, reply: true)
311 312
            is_expected.to have_body_text(status)
            is_expected.to have_html_escaped_body_text(current_user.name)
313
            is_expected.to have_body_text(project_merge_request_path(project, merge_request))
314 315
          end
        end
316
      end
317

318 319 320
      describe 'that are merged' do
        let(:merge_author) { create(:user) }
        subject { described_class.merged_merge_request_email(recipient.id, merge_request.id, merge_author.id) }
321

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

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

335 336 337 338 339
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(merge_request, reply: true)
            is_expected.to have_body_text('merged')
            is_expected.to have_body_text(project_merge_request_path(project, merge_request))
340 341
          end
        end
342 343
      end
    end
344

345 346 347
    context 'for snippet notes' do
      let(:project_snippet) { create(:project_snippet, project: project) }
      let(:project_snippet_note) { create(:note_on_project_snippet, project: project, noteable: project_snippet) }
348

349
      subject { described_class.note_snippet_email(project_snippet_note.author_id, project_snippet_note.id) }
350

351 352 353 354
      it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
        let(:model) { project_snippet }
      end
      it_behaves_like 'a user cannot unsubscribe through footer link'
355

356 357 358
      it 'has the correct subject and body' do
        is_expected.to have_referable_subject(project_snippet, reply: true)
        is_expected.to have_html_escaped_body_text project_snippet_note.note
R
Robb Kidd 已提交
359
      end
360 361
    end

362
    describe 'project was moved' do
363
      subject { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
364

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

369 370
      it 'has the correct subject and body' do
        is_expected.to have_subject("#{project.name} | Project was moved")
371
        is_expected.to have_html_escaped_body_text project.name_with_namespace
372
        is_expected.to have_body_text(project.ssh_url_to_repo)
373 374 375
      end
    end

R
Rémy Coutable 已提交
376
    describe 'project access requested' do
377
      context 'for a project in a user namespace' do
378
        let(:project) do
379
          create(:project, :public, :access_requestable) do |project|
380 381 382 383
            project.team << [project.owner, :master, project.owner]
          end
        end

384 385
        let(:project_member) do
          project.request_access(user)
386
          project.requesters.find_by(user_id: user.id)
387
        end
388
        subject { described_class.member_access_requested_email('project', project_member.id) }
389 390 391 392 393 394 395 396 397 398 399

        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"
400
          is_expected.to have_html_escaped_body_text project.name_with_namespace
401
          is_expected.to have_body_text project_project_members_url(project)
402
          is_expected.to have_body_text project_member.human_access
403
        end
R
Rémy Coutable 已提交
404 405
      end

406 407 408
      context 'for a project in a group' do
        let(:group_owner) { create(:user) }
        let(:group) { create(:group).tap { |g| g.add_owner(group_owner) } }
409
        let(:project) { create(:project, :public, :access_requestable, namespace: group) }
410 411
        let(:project_member) do
          project.request_access(user)
412
          project.requesters.find_by(user_id: user.id)
413
        end
414
        subject { described_class.member_access_requested_email('project', project_member.id) }
R
Rémy Coutable 已提交
415

416 417 418 419 420 421 422 423 424 425
        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"
426
          is_expected.to have_html_escaped_body_text project.name_with_namespace
427
          is_expected.to have_body_text project_project_members_url(project)
428
          is_expected.to have_body_text project_member.human_access
429
        end
R
Rémy Coutable 已提交
430
      end
R
Rémy Coutable 已提交
431 432 433
    end

    describe 'project access denied' do
434
      let(:project) { create(:project, :public, :access_requestable) }
R
Rémy Coutable 已提交
435 436
      let(:project_member) do
        project.request_access(user)
437
        project.requesters.find_by(user_id: user.id)
R
Rémy Coutable 已提交
438
      end
439
      subject { described_class.member_access_denied_email('project', project.id, user.id) }
R
Rémy Coutable 已提交
440 441 442 443 444

      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 已提交
445 446
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{project.name_with_namespace} project was denied"
447
        is_expected.to have_html_escaped_body_text project.name_with_namespace
448
        is_expected.to have_body_text project.web_url
R
Rémy Coutable 已提交
449
      end
R
Rémy Coutable 已提交
450 451
    end

452
    describe 'project access changed' do
453
      let(:owner) { create(:user, name: "Chang O'Keefe") }
454
      let(:project) { create(:project, :public, :access_requestable, namespace: owner.namespace) }
455
      let(:project_member) { create(:project_member, project: project, user: user) }
456
      subject { described_class.member_access_granted_email('project', project_member.id) }
457 458

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

R
Rémy Coutable 已提交
462 463
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{project.name_with_namespace} project was granted"
464
        is_expected.to have_html_escaped_body_text project.name_with_namespace
465 466
        is_expected.to have_body_text project.web_url
        is_expected.to have_body_text project_member.human_access
R
Rémy Coutable 已提交
467
      end
468
    end
469

470 471 472 473 474 475 476 477 478
    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
479
      )
480 481 482 483
    end

    describe 'project invitation' do
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
484
      let(:project_member) { invite_to_project(project, inviter: master) }
485

486
      subject { described_class.member_invited_email('project', project_member.id, project_member.invite_token) }
487 488 489 490 491

      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 已提交
492 493
      it 'contains all the useful information' do
        is_expected.to have_subject "Invitation to join the #{project.name_with_namespace} project"
494
        is_expected.to have_html_escaped_body_text project.name_with_namespace
495 496 497
        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
R
Rémy Coutable 已提交
498
      end
499 500 501
    end

    describe 'project invitation accepted' do
502
      let(:invited_user) { create(:user, name: 'invited user') }
503 504
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
505
        invitee = invite_to_project(project, inviter: master)
506 507
        invitee.accept_invite!(invited_user)
        invitee
508
      end
509

510
      subject { described_class.member_invite_accepted_email('project', project_member.id) }
511 512 513 514 515

      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 已提交
516 517
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation accepted'
518
        is_expected.to have_html_escaped_body_text project.name_with_namespace
519 520
        is_expected.to have_body_text project.web_url
        is_expected.to have_body_text project_member.invite_email
521
        is_expected.to have_html_escaped_body_text invited_user.name
R
Rémy Coutable 已提交
522
      end
523 524 525 526 527
    end

    describe 'project invitation declined' do
      let(:master) { create(:user).tap { |u| project.team << [u, :master] } }
      let(:project_member) do
528
        invitee = invite_to_project(project, inviter: master)
529 530
        invitee.decline_invite!
        invitee
531
      end
532

533
      subject { described_class.member_invite_declined_email('project', project.id, project_member.invite_email, master.id) }
534 535 536 537 538

      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 已提交
539 540
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation declined'
541
        is_expected.to have_html_escaped_body_text project.name_with_namespace
542 543
        is_expected.to have_body_text project.web_url
        is_expected.to have_body_text project_member.invite_email
R
Rémy Coutable 已提交
544
      end
545 546
    end

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

551
      before do
552
        allow(Note).to receive(:find).with(note.id).and_return(note)
553 554
      end

R
Robb Kidd 已提交
555
      shared_examples 'a note email' do
556 557
        it_behaves_like 'it should have Gmail Actions links'

558
        it 'is sent to the given recipient as the author' do
559 560
          sender = subject.header[:from].addrs[0]

561 562 563 564 565
          aggregate_failures do
            expect(sender.display_name).to eq(note_author.name)
            expect(sender.address).to eq(gitlab_sender)
            expect(subject).to deliver_to(recipient.notification_email)
          end
R
Robb Kidd 已提交
566 567 568
        end

        it 'contains the message from the note' do
569
          is_expected.to have_html_escaped_body_text note.note
R
Robb Kidd 已提交
570
        end
571

572
        it 'does not contain note author' do
D
Douwe Maan 已提交
573
          is_expected.not_to have_body_text note.author_name
574 575 576 577
        end

        context 'when enabled email_author_in_body' do
          before do
S
Sean McGivern 已提交
578
            stub_application_setting(email_author_in_body: true)
579 580 581
          end

          it 'contains a link to note author' do
582
            is_expected.to have_html_escaped_body_text note.author_name
583 584
          end
        end
R
Robb Kidd 已提交
585 586 587
      end

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

590 591 592
        before do
          allow(note).to receive(:noteable).and_return(commit)
        end
R
Robb Kidd 已提交
593

594
        subject { described_class.note_commit_email(recipient.id, note.id) }
R
Robb Kidd 已提交
595 596

        it_behaves_like 'a note email'
597 598 599
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { commit }
        end
600
        it_behaves_like 'it should show Gmail Actions View Commit link'
601
        it_behaves_like 'a user cannot unsubscribe through footer link'
R
Robb Kidd 已提交
602

603 604 605 606 607
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_subject("Re: #{project.name} | #{commit.title.strip} (#{commit.short_id})")
            is_expected.to have_body_text(commit.short_id)
          end
R
Robb Kidd 已提交
608 609 610 611
        end
      end

      describe 'on a merge request' do
612
        let(:note_on_merge_request_path) { project_merge_request_path(project, merge_request, anchor: "note_#{note.id}") }
613 614 615 616

        before do
          allow(note).to receive(:noteable).and_return(merge_request)
        end
R
Robb Kidd 已提交
617

618
        subject { described_class.note_merge_request_email(recipient.id, note.id) }
S
Sean McGivern 已提交
619

R
Robb Kidd 已提交
620
        it_behaves_like 'a note email'
621 622 623
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
        end
624
        it_behaves_like 'it should show Gmail Actions View Merge request link'
625
        it_behaves_like 'an unsubscribeable thread'
R
Robb Kidd 已提交
626

627 628 629 630 631
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(merge_request, reply: true)
            is_expected.to have_body_text note_on_merge_request_path
          end
R
Robb Kidd 已提交
632 633 634 635
        end
      end

      describe 'on an issue' do
636
        let(:note_on_issue_path) { project_issue_path(project, issue, anchor: "note_#{note.id}") }
637 638 639 640

        before do
          allow(note).to receive(:noteable).and_return(issue)
        end
641

642
        subject { described_class.note_issue_email(recipient.id, note.id) }
R
Robb Kidd 已提交
643 644

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

651 652 653 654 655
        it 'has the correct subject and body' do
          aggregate_failures do
            is_expected.to have_referable_subject(issue, reply: true)
            is_expected.to have_body_text(note_on_issue_path)
          end
R
Robb Kidd 已提交
656 657
        end
      end
658
    end
659

D
Douwe Maan 已提交
660
    context 'items that are noteable, the email for a discussion note' do
661 662
      let(:note_author) { create(:user, name: 'author_name') }

663
      before do
664 665 666
        allow(Note).to receive(:find).with(note.id).and_return(note)
      end

D
Douwe Maan 已提交
667 668 669
      shared_examples 'a discussion note email' do |model|
        it_behaves_like 'it should have Gmail Actions links'

D
Douwe Maan 已提交
670
        it 'is sent to the given recipient as the author' do
D
Douwe Maan 已提交
671 672
          sender = subject.header[:from].addrs[0]

D
Douwe Maan 已提交
673 674 675 676 677
          aggregate_failures do
            expect(sender.display_name).to eq(note_author.name)
            expect(sender.address).to eq(gitlab_sender)
            expect(subject).to deliver_to(recipient.notification_email)
          end
D
Douwe Maan 已提交
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700
        end

        it 'contains the message from the note' do
          is_expected.to have_body_text note.note
        end

        it 'contains an introduction' do
          is_expected.to have_body_text 'started a new discussion'
        end

        context 'when a comment on an existing discussion' do
          let!(:second_note) { create(model, author: note_author, noteable: nil, in_reply_to: note) }

          it 'contains an introduction' do
            is_expected.to have_body_text 'commented on a'
          end
        end
      end

      describe 'on a commit' do
        let(:commit) { project.commit }
        let(:note) { create(:discussion_note_on_commit, commit_id: commit.id, project: project, author: note_author) }

701 702 703
        before do
          allow(note).to receive(:noteable).and_return(commit)
        end
D
Douwe Maan 已提交
704

705
        subject { described_class.note_commit_email(recipient.id, note.id) }
D
Douwe Maan 已提交
706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724

        it_behaves_like 'a discussion note email', :discussion_note_on_commit
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { commit }
        end
        it_behaves_like 'it should show Gmail Actions View Commit link'
        it_behaves_like 'a user cannot unsubscribe through footer link'

        it 'has the correct subject' do
          is_expected.to have_subject "Re: #{project.name} | #{commit.title.strip} (#{commit.short_id})"
        end

        it 'contains a link to the commit' do
          is_expected.to have_body_text commit.short_id
        end
      end

      describe 'on a merge request' do
        let(:note) { create(:discussion_note_on_merge_request, noteable: merge_request, project: project, author: note_author) }
725
        let(:note_on_merge_request_path) { project_merge_request_path(project, merge_request, anchor: "note_#{note.id}") }
726 727 728 729

        before do
          allow(note).to receive(:noteable).and_return(merge_request)
        end
D
Douwe Maan 已提交
730

731
        subject { described_class.note_merge_request_email(recipient.id, note.id) }
D
Douwe Maan 已提交
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750

        it_behaves_like 'a discussion note email', :discussion_note_on_merge_request
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { merge_request }
        end
        it_behaves_like 'it should show Gmail Actions View Merge request link'
        it_behaves_like 'an unsubscribeable thread'

        it 'has the correct subject' do
          is_expected.to have_referable_subject(merge_request, reply: true)
        end

        it 'contains a link to the merge request note' do
          is_expected.to have_body_text note_on_merge_request_path
        end
      end

      describe 'on an issue' do
        let(:note) { create(:discussion_note_on_issue, noteable: issue, project: project, author: note_author) }
751
        let(:note_on_issue_path) { project_issue_path(project, issue, anchor: "note_#{note.id}") }
752 753 754 755

        before do
          allow(note).to receive(:noteable).and_return(issue)
        end
D
Douwe Maan 已提交
756

757
        subject { described_class.note_issue_email(recipient.id, note.id) }
D
Douwe Maan 已提交
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

        it_behaves_like 'a discussion note email', :discussion_note_on_issue
        it_behaves_like 'an answer to an existing thread with reply-by-email enabled' do
          let(:model) { issue }
        end
        it_behaves_like 'it should show Gmail Actions View Issue link'
        it_behaves_like 'an unsubscribeable thread'

        it 'has the correct subject' do
          is_expected.to have_referable_subject(issue, reply: true)
        end

        it 'contains a link to the issue note' do
          is_expected.to have_body_text note_on_issue_path
        end
      end
    end

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

779
      before do
D
Douwe Maan 已提交
780 781 782 783
        allow(Note).to receive(:find).with(note.id).and_return(note)
      end

      shared_examples 'an email for a note on a diff discussion' do  |model|
D
Douwe Maan 已提交
784
        let(:note) { create(model, author: note_author) }
785 786

        it "includes diffs with character-level highlighting" do
787
          is_expected.to have_body_text '<span class="p">}</span></span>'
788 789 790
        end

        it 'contains a link to the diff file' do
791
          is_expected.to have_body_text note.diff_file.file_path
792 793 794 795
        end

        it_behaves_like 'it should have Gmail Actions links'

796
        it 'is sent to the given recipient as the author' do
797 798
          sender = subject.header[:from].addrs[0]

799 800 801 802 803
          aggregate_failures do
            expect(sender.display_name).to eq(note_author.name)
            expect(sender.address).to eq(gitlab_sender)
            expect(subject).to deliver_to(recipient.notification_email)
          end
804 805 806
        end

        it 'contains the message from the note' do
807
          is_expected.to have_html_escaped_body_text note.note
808 809
        end

D
Douwe Maan 已提交
810 811
        it 'contains an introduction' do
          is_expected.to have_body_text 'started a new discussion on'
812 813
        end

D
Douwe Maan 已提交
814 815
        context 'when a comment on an existing discussion' do
          let!(:second_note) { create(model, author: note_author, noteable: nil, in_reply_to: note) }
816

D
Douwe Maan 已提交
817 818
          it 'contains an introduction' do
            is_expected.to have_body_text 'commented on a discussion on'
819 820 821 822 823 824 825 826
          end
        end
      end

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

827
        subject { described_class.note_commit_email(recipient.id, note.id) }
828

D
Douwe Maan 已提交
829
        it_behaves_like 'an email for a note on a diff discussion', :diff_note_on_commit
830 831 832 833 834 835 836
        it_behaves_like 'it should show Gmail Actions View Commit link'
        it_behaves_like 'a user cannot unsubscribe through footer link'
      end

      describe 'on a merge request' do
        let(:note) { create(:diff_note_on_merge_request) }

837
        subject { described_class.note_merge_request_email(recipient.id, note.id) }
838

D
Douwe Maan 已提交
839
        it_behaves_like 'an email for a note on a diff discussion', :diff_note_on_merge_request
840 841 842 843
        it_behaves_like 'it should show Gmail Actions View Merge request link'
        it_behaves_like 'an unsubscribeable thread'
      end
    end
844
  end
845

846
  context 'for a group' do
847 848
    set(:group) { create(:group) }

849
    describe 'group access requested' do
850
      let(:group) { create(:group, :public, :access_requestable) }
851 852
      let(:group_member) do
        group.request_access(user)
853
        group.requesters.find_by(user_id: user.id)
854
      end
855
      subject { described_class.member_access_requested_email('group', group_member.id) }
R
Rémy Coutable 已提交
856

857 858 859
      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 已提交
860

R
Rémy Coutable 已提交
861 862
      it 'contains all the useful information' do
        is_expected.to have_subject "Request to join the #{group.name} group"
863
        is_expected.to have_html_escaped_body_text group.name
864 865
        is_expected.to have_body_text group_group_members_url(group)
        is_expected.to have_body_text group_member.human_access
R
Rémy Coutable 已提交
866
      end
R
Rémy Coutable 已提交
867 868
    end

869 870 871
    describe 'group access denied' do
      let(:group_member) do
        group.request_access(user)
872
        group.requesters.find_by(user_id: user.id)
873
      end
874
      subject { described_class.member_access_denied_email('group', group.id, user.id) }
R
Rémy Coutable 已提交
875

876 877 878
      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 已提交
879

R
Rémy Coutable 已提交
880 881
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{group.name} group was denied"
882
        is_expected.to have_html_escaped_body_text group.name
883
        is_expected.to have_body_text group.web_url
R
Rémy Coutable 已提交
884
      end
R
Rémy Coutable 已提交
885 886
    end

887 888
    describe 'group access changed' do
      let(:group_member) { create(:group_member, group: group, user: user) }
R
Rémy Coutable 已提交
889

890
      subject { described_class.member_access_granted_email('group', group_member.id) }
891 892 893 894 895

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

R
Rémy Coutable 已提交
896 897
      it 'contains all the useful information' do
        is_expected.to have_subject "Access to the #{group.name} group was granted"
898
        is_expected.to have_html_escaped_body_text group.name
899 900
        is_expected.to have_body_text group.web_url
        is_expected.to have_body_text group_member.human_access
R
Rémy Coutable 已提交
901
      end
R
Rémy Coutable 已提交
902 903
    end

904 905 906 907 908 909 910 911 912
    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
913
      )
R
Rémy Coutable 已提交
914 915
    end

916 917
    describe 'group invitation' do
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
918
      let(:group_member) { invite_to_group(group, inviter: owner) }
919

920
      subject { described_class.member_invited_email('group', group_member.id, group_member.invite_token) }
921

922 923 924
      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"
925

R
Rémy Coutable 已提交
926 927
      it 'contains all the useful information' do
        is_expected.to have_subject "Invitation to join the #{group.name} group"
928
        is_expected.to have_html_escaped_body_text group.name
929 930 931
        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
R
Rémy Coutable 已提交
932
      end
933 934
    end

935
    describe 'group invitation accepted' do
936
      let(:invited_user) { create(:user, name: 'invited user') }
937 938
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
939
        invitee = invite_to_group(group, inviter: owner)
940 941 942 943
        invitee.accept_invite!(invited_user)
        invitee
      end

944
      subject { described_class.member_invite_accepted_email('group', group_member.id) }
945 946 947 948 949

      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 已提交
950 951
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation accepted'
952
        is_expected.to have_html_escaped_body_text group.name
953 954
        is_expected.to have_body_text group.web_url
        is_expected.to have_body_text group_member.invite_email
955
        is_expected.to have_html_escaped_body_text invited_user.name
R
Rémy Coutable 已提交
956
      end
957 958
    end

959 960 961
    describe 'group invitation declined' do
      let(:owner) { create(:user).tap { |u| group.add_user(u, Gitlab::Access::OWNER) } }
      let(:group_member) do
962
        invitee = invite_to_group(group, inviter: owner)
963 964 965 966
        invitee.decline_invite!
        invitee
      end

967
      subject { described_class.member_invite_declined_email('group', group.id, group_member.invite_email, owner.id) }
968 969 970 971 972

      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 已提交
973 974
      it 'contains all the useful information' do
        is_expected.to have_subject 'Invitation declined'
975
        is_expected.to have_html_escaped_body_text group.name
976 977
        is_expected.to have_body_text group.web_url
        is_expected.to have_body_text group_member.invite_email
R
Rémy Coutable 已提交
978
      end
979 980
    end
  end
981 982 983 984 985 986

  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 已提交
987
      stub_config_setting(email_subject_suffix: 'A Nice Suffix')
V
Valery Sizov 已提交
988 989 990 991
      perform_enqueued_jobs do
        user.email = "new-email@mail.com"
        user.save
      end
992 993 994 995
    end

    subject { ActionMailer::Base.deliveries.last }

996
    it_behaves_like 'an email sent from GitLab'
997
    it_behaves_like "a user cannot unsubscribe through footer link"
998

999
    it 'is sent to the new user' do
1000
      is_expected.to deliver_to 'new-email@mail.com'
1001 1002
    end

1003 1004 1005 1006 1007
    it 'has the correct subject and body' do
      aggregate_failures do
        is_expected.to have_subject('Confirmation instructions | A Nice Suffix')
        is_expected.to have_body_text(example_site_path)
      end
1008 1009
    end
  end
D
Dmitriy Zaporozhets 已提交
1010

1011 1012
  describe 'email on push for a created branch' do
    let(:example_site_path) { root_path }
1013
    let(:tree_path) { project_tree_path(project, "empty-branch") }
1014

1015
    subject { described_class.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/empty-branch', action: :create) }
1016

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

1022 1023 1024 1025 1026 1027
    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

1028 1029 1030 1031 1032
    it 'has the correct subject and body' do
      aggregate_failures do
        is_expected.to have_subject("[Git][#{project.full_path}] Pushed new branch empty-branch")
        is_expected.to have_body_text(tree_path)
      end
1033 1034 1035 1036 1037
    end
  end

  describe 'email on push for a created tag' do
    let(:example_site_path) { root_path }
1038
    let(:tree_path) { project_tree_path(project, "v1.0") }
1039

1040
    subject { described_class.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :create) }
1041

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

1047 1048 1049 1050 1051 1052
    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

1053 1054 1055 1056 1057
    it 'has the correct subject and body' do
      aggregate_failures do
        is_expected.to have_subject("[Git][#{project.full_path}] Pushed new tag v1.0")
        is_expected.to have_body_text(tree_path)
      end
1058 1059 1060 1061 1062 1063
    end
  end

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

1064
    subject { described_class.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :delete) }
1065

1066
    it_behaves_like 'it should not have Gmail Actions links'
1067
    it_behaves_like 'a user cannot unsubscribe through footer link'
1068 1069
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1070

1071 1072 1073 1074 1075 1076 1077
    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
1078
      is_expected.to have_subject "[Git][#{project.full_path}] Deleted branch master"
1079 1080 1081 1082 1083 1084
    end
  end

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

1085
    subject { described_class.repository_push_email(project.id, author_id: user.id, ref: 'refs/tags/v1.0', action: :delete) }
1086

1087
    it_behaves_like 'it should not have Gmail Actions links'
1088
    it_behaves_like 'a user cannot unsubscribe through footer link'
1089 1090
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1091

1092 1093 1094 1095 1096 1097 1098
    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
1099
      is_expected.to have_subject "[Git][#{project.full_path}] Deleted tag v1.0"
1100 1101 1102
    end
  end

1103
  describe 'email on push with multiple commits' do
D
Dmitriy Zaporozhets 已提交
1104
    let(:example_site_path) { root_path }
1105 1106 1107
    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 }
1108
    let(:diff_path) { project_compare_path(project, from: Commit.new(compare.base, project), to: Commit.new(compare.head, project)) }
1109
    let(:send_from_committer_email) { false }
1110
    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 已提交
1111

1112
    subject { described_class.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 已提交
1113

1114
    it_behaves_like 'it should not have Gmail Actions links'
1115
    it_behaves_like 'a user cannot unsubscribe through footer link'
1116 1117
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1118

1119 1120
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1121 1122
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1123 1124
    end

1125 1126 1127 1128 1129 1130 1131 1132
    it 'has the correct subject and body' do
      aggregate_failures do
        is_expected.to have_subject("[Git][#{project.full_path}][master] #{commits.length} commits: Ruby files modified")
        is_expected.to have_body_text('Change some files')
        is_expected.to have_body_text('def</span> <span class="nf">archive_formats_regex')
        is_expected.to have_body_text(diff_path)
        is_expected.not_to have_body_text('you are a member of')
      end
1133
    end
1134 1135 1136 1137

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

1138 1139 1140 1141 1142
      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
1143
        before do
1144
          user.update_attribute(:email, "user@company.com")
1145
          user.confirm
1146 1147 1148
        end

        it "is sent from the committer email" do
1149 1150
          from  = subject.header[:from].addrs.first
          reply = subject.header[:reply_to].addrs.first
1151

1152 1153 1154 1155
          aggregate_failures do
            expect(from.address).to eq(user.email)
            expect(reply.address).to eq(user.email)
          end
1156
        end
1157 1158
      end

1159 1160 1161
      context "when the committer email domain is not completely within the GitLab domain" do
        before do
          user.update_attribute(:email, "user@something.company.com")
1162
          user.confirm
1163 1164 1165
        end

        it "is sent from the default email" do
1166 1167
          from  = subject.header[:from].addrs.first
          reply = subject.header[:reply_to].addrs.first
1168

1169 1170 1171 1172
          aggregate_failures do
            expect(from.address).to eq(gitlab_sender)
            expect(reply.address).to eq(gitlab_sender_reply_to)
          end
1173
        end
1174 1175 1176 1177 1178
      end

      context "when the committer email domain is outside the GitLab domain" do
        before do
          user.update_attribute(:email, "user@mpany.com")
1179
          user.confirm
1180
        end
1181 1182

        it "is sent from the default email" do
1183 1184
          from = subject.header[:from].addrs.first
          reply = subject.header[:reply_to].addrs.first
1185

1186 1187 1188 1189
          aggregate_failures do
            expect(from.address).to eq(gitlab_sender)
            expect(reply.address).to eq(gitlab_sender_reply_to)
          end
1190
        end
1191 1192
      end
    end
D
Dmitriy Zaporozhets 已提交
1193
  end
1194 1195 1196

  describe 'email on push with a single commit' do
    let(:example_site_path) { root_path }
1197 1198 1199
    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 }
1200
    let(:diff_path) { project_commit_path(project, commits.first) }
1201
    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) }
1202

1203
    subject { described_class.repository_push_email(project.id, author_id: user.id, ref: 'refs/heads/master', action: :push, compare: compare, diff_refs: diff_refs) }
1204

1205
    it_behaves_like 'it should show Gmail Actions View Commit link'
1206
    it_behaves_like 'a user cannot unsubscribe through footer link'
1207 1208
    it_behaves_like 'an email with X-GitLab headers containing project details'
    it_behaves_like 'an email that contains a header with author username'
1209

1210 1211
    it 'is sent as the author' do
      sender = subject.header[:from].addrs[0]
1212 1213
      expect(sender.display_name).to eq(user.name)
      expect(sender.address).to eq(gitlab_sender)
1214 1215
    end

1216 1217 1218 1219 1220 1221 1222
    it 'has the correct subject and body' do
      aggregate_failures do
        is_expected.to have_subject("[Git][#{project.full_path}][master] #{commits.first.title}")
        is_expected.to have_body_text('Change some files')
        is_expected.to have_body_text('def</span> <span class="nf">archive_formats_regex')
        is_expected.to have_body_text(diff_path)
      end
1223 1224
    end
  end
1225 1226

  describe 'HTML emails setting' do
1227
    let(:multipart_mail) { described_class.project_was_moved_email(project.id, user.id, "gitlab/gitlab") }
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256

    context 'when disabled' do
      it 'only sends the text template' do
        stub_application_setting(html_emails_enabled: false)

        EmailTemplateInterceptor.delivering_email(multipart_mail)

        expect(multipart_mail).to have_part_with('text/plain')
        expect(multipart_mail).not_to have_part_with('text/html')
      end
    end

    context 'when enabled' do
      it 'sends a multipart message' do
        stub_application_setting(html_emails_enabled: true)

        EmailTemplateInterceptor.delivering_email(multipart_mail)

        expect(multipart_mail).to have_part_with('text/plain')
        expect(multipart_mail).to have_part_with('text/html')
      end
    end

    matcher :have_part_with do |expected|
      match do |actual|
        actual.body.parts.any? { |part| part.content_type.try(:match, %r(#{expected})) }
      end
    end
  end
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270

  context 'for personal snippet notes' do
    let(:personal_snippet) { create(:personal_snippet) }
    let(:personal_snippet_note) { create(:note_on_personal_snippet, noteable: personal_snippet) }

    subject { described_class.note_personal_snippet_email(personal_snippet_note.author_id, personal_snippet_note.id) }

    it_behaves_like 'a user cannot unsubscribe through footer link'

    it 'has the correct subject and body' do
      is_expected.to have_referable_subject(personal_snippet, reply: true)
      is_expected.to have_html_escaped_body_text personal_snippet_note.note
    end
  end
1271
end