issue_spec.rb 23 KB
Newer Older
gitlabhq's avatar
gitlabhq committed
1 2
require 'spec_helper'

3
describe Issue do
gitlabhq's avatar
gitlabhq committed
4
  describe "Associations" do
5
    it { is_expected.to belong_to(:milestone) }
6
    it { is_expected.to have_many(:assignees) }
gitlabhq's avatar
gitlabhq committed
7 8
  end

9
  describe 'modules' do
10 11
    subject { described_class }

12
    it { is_expected.to include_module(Issuable) }
13 14 15
    it { is_expected.to include_module(Referable) }
    it { is_expected.to include_module(Sortable) }
    it { is_expected.to include_module(Taskable) }
16 17 18 19

    it_behaves_like 'AtomicInternalId' do
      let(:internal_id_attribute) { :iid }
      let(:instance) { build(:issue) }
20
      let(:scope) { :project }
21 22 23
      let(:scope_attrs) { { project: instance.project } }
      let(:usage) { :issues }
    end
24 25
  end

26
  subject { create(:issue) }
27

28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
  describe 'callbacks' do
    describe '#ensure_metrics' do
      it 'creates metrics after saving' do
        issue = create(:issue)

        expect(issue.metrics).to be_persisted
        expect(Issue::Metrics.count).to eq(1)
      end

      it 'does not create duplicate metrics for an issue' do
        issue = create(:issue)

        issue.close!

        expect(issue.metrics).to be_persisted
        expect(Issue::Metrics.count).to eq(1)
      end

      it 'records current metrics' do
        expect_any_instance_of(Issue::Metrics).to receive(:record!)

        create(:issue)
      end
    end
  end

54
  describe '#order_by_position_and_priority' do
55
    let(:project) { create :project }
56 57 58 59 60 61 62 63
    let(:p1) { create(:label, title: 'P1', project: project, priority: 1) }
    let(:p2) { create(:label, title: 'P2', project: project, priority: 2) }
    let!(:issue1) { create(:labeled_issue, project: project, labels: [p1]) }
    let!(:issue2) { create(:labeled_issue, project: project, labels: [p2]) }
    let!(:issue3) { create(:issue, project: project, relative_position: 100) }
    let!(:issue4) { create(:issue, project: project, relative_position: 200) }

    it 'returns ordered list' do
64 65
      expect(project.issues.order_by_position_and_priority)
        .to match [issue3, issue4, issue1, issue2]
66 67 68
    end
  end

69 70 71 72 73
  describe '#card_attributes' do
    it 'includes the author name' do
      allow(subject).to receive(:author).and_return(double(name: 'Robert'))
      allow(subject).to receive(:assignees).and_return([])

74 75
      expect(subject.card_attributes)
        .to eq({ 'Author' => 'Robert', 'Assignee' => '' })
76 77 78 79 80 81
    end

    it 'includes the assignee name' do
      allow(subject).to receive(:author).and_return(double(name: 'Robert'))
      allow(subject).to receive(:assignees).and_return([double(name: 'Douwe')])

82 83
      expect(subject.card_attributes)
        .to eq({ 'Author' => 'Robert', 'Assignee' => 'Douwe' })
84 85 86
    end
  end

87 88
  describe '#close' do
    subject(:issue) { create(:issue, state: 'opened') }
89

90 91 92 93 94 95 96 97
    it 'sets closed_at to Time.now when an issue is closed' do
      expect { issue.close }.to change { issue.closed_at }.from(nil)
    end

    it 'changes the state to closed' do
      expect { issue.close }.to change { issue.state }.from('opened').to('closed')
    end
  end
98

99 100 101 102 103 104 105 106 107 108 109
  describe '#reopen' do
    let(:user) { create(:user) }
    let(:issue) { create(:issue, state: 'closed', closed_at: Time.now, closed_by: user) }

    it 'sets closed_at to nil when an issue is reopend' do
      expect { issue.reopen }.to change { issue.closed_at }.to(nil)
    end

    it 'sets closed_by to nil when an issue is reopend' do
      expect { issue.reopen }.to change { issue.closed_by }.from(user).to(nil)
    end
110

111 112
    it 'changes the state to opened' do
      expect { issue.reopen }.to change { issue.state }.from('closed').to('opened')
113 114 115
    end
  end

116
  describe '#to_reference' do
117
    let(:namespace) { build(:namespace, path: 'sample-namespace') }
118
    let(:project)   { build(:project, name: 'sample-project', namespace: namespace) }
119 120
    let(:issue)     { build(:issue, iid: 1, project: project) }
    let(:group)     { create(:group, name: 'Group', path: 'sample-group') }
121

122 123 124 125
    context 'when nil argument' do
      it 'returns issue id' do
        expect(issue.to_reference).to eq "#1"
      end
126 127
    end

128
    context 'when full is true' do
129
      it 'returns complete path to the issue' do
130 131 132
        expect(issue.to_reference(full: true)).to          eq 'sample-namespace/sample-project#1'
        expect(issue.to_reference(project, full: true)).to eq 'sample-namespace/sample-project#1'
        expect(issue.to_reference(group, full: true)).to   eq 'sample-namespace/sample-project#1'
133
      end
134 135
    end

136 137 138 139 140 141 142
    context 'when same project argument' do
      it 'returns issue id' do
        expect(issue.to_reference(project)).to eq("#1")
      end
    end

    context 'when cross namespace project argument' do
143
      let(:another_namespace_project) { create(:project, name: 'another-project') }
144 145 146 147

      it 'returns complete path to the issue' do
        expect(issue.to_reference(another_namespace_project)).to eq 'sample-namespace/sample-project#1'
      end
148 149
    end

150
    it 'supports a cross-project reference' do
151
      another_project = build(:project, name: 'another-project', namespace: project.namespace)
152
      expect(issue.to_reference(another_project)).to eq "sample-project#1"
153
    end
154

155
    context 'when same namespace / cross-project argument' do
156
      let(:another_project) { create(:project, namespace: namespace) }
157 158 159 160 161 162 163 164

      it 'returns path to the issue with the project name' do
        expect(issue.to_reference(another_project)).to eq 'sample-project#1'
      end
    end

    context 'when different namespace / cross-project argument' do
      let(:another_namespace) { create(:namespace, path: 'another-namespace') }
165
      let(:another_project)   { create(:project, path: 'another-project', namespace: another_namespace) }
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183

      it 'returns full path to the issue' do
        expect(issue.to_reference(another_project)).to eq 'sample-namespace/sample-project#1'
      end
    end

    context 'when argument is a namespace' do
      context 'with same project path' do
        it 'returns path to the issue with the project name' do
          expect(issue.to_reference(namespace)).to eq 'sample-project#1'
        end
      end

      context 'with different project path' do
        it 'returns full path to the issue' do
          expect(issue.to_reference(group)).to eq 'sample-namespace/sample-project#1'
        end
      end
184
    end
185 186
  end

187 188 189 190 191 192 193 194
  describe '#assignee_or_author?' do
    let(:user) { create(:user) }
    let(:issue) { create(:issue) }

    it 'returns true for a user that is assigned to an issue' do
      issue.assignees << user

      expect(issue.assignee_or_author?(user)).to be_truthy
195
    end
196 197 198 199 200 201 202 203 204

    it 'returns true for a user that is the author of an issue' do
      issue.update(author: user)

      expect(issue.assignee_or_author?(user)).to be_truthy
    end

    it 'returns false for a user that is not the assignee or author' do
      expect(issue.assignee_or_author?(user)).to be_falsey
205 206
    end
  end
207

208 209 210 211 212 213 214 215 216 217
  describe '#can_move?' do
    let(:user) { create(:user) }
    let(:issue) { create(:issue) }
    subject { issue.can_move?(user) }

    context 'user is not a member of project issue belongs to' do
      it { is_expected.to eq false}
    end

    context 'user is reporter in project issue belongs to' do
218
      let(:project) { create(:project) }
219 220
      let(:issue) { create(:issue, project: project) }

221
      before do
222
        project.add_reporter(user)
223
      end
224 225 226

      it { is_expected.to eq true }

227 228 229 230 231
      context 'issue not persisted' do
        let(:issue) { build(:issue, project: project) }
        it { is_expected.to eq false }
      end

232 233
      context 'checking destination project also' do
        subject { issue.can_move?(user, to_project) }
234
        let(:to_project) { create(:project) }
235 236

        context 'destination project allowed' do
237
          before do
238
            to_project.add_reporter(user)
239 240
          end

241 242 243 244
          it { is_expected.to eq true }
        end

        context 'destination project not allowed' do
245
          before do
246
            to_project.add_guest(user)
247 248
          end

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
          it { is_expected.to eq false }
        end
      end
    end
  end

  describe '#moved?' do
    let(:issue) { create(:issue) }
    subject { issue.moved? }

    context 'issue not moved' do
      it { is_expected.to eq false }
    end

    context 'issue already moved' do
      let(:moved_to_issue) { create(:issue) }
      let(:issue) { create(:issue, moved_to: moved_to_issue) }

      it { is_expected.to eq true }
    end
  end

271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312
  describe '#suggested_branch_name' do
    let(:repository) { double }

    subject { build(:issue) }

    before do
      allow(subject.project).to receive(:repository).and_return(repository)
    end

    context '#to_branch_name does not exists' do
      before do
        allow(repository).to receive(:branch_exists?).and_return(false)
      end

      it 'returns #to_branch_name' do
        expect(subject.suggested_branch_name).to eq(subject.to_branch_name)
      end
    end

    context '#to_branch_name exists not ending with -index' do
      before do
        allow(repository).to receive(:branch_exists?).and_return(true)
        allow(repository).to receive(:branch_exists?).with(/#{subject.to_branch_name}-\d/).and_return(false)
      end

      it 'returns #to_branch_name ending with -2' do
        expect(subject.suggested_branch_name).to eq("#{subject.to_branch_name}-2")
      end
    end

    context '#to_branch_name exists ending with -index' do
      before do
        allow(repository).to receive(:branch_exists?).and_return(true)
        allow(repository).to receive(:branch_exists?).with("#{subject.to_branch_name}-3").and_return(false)
      end

      it 'returns #to_branch_name ending with max index + 1' do
        expect(subject.suggested_branch_name).to eq("#{subject.to_branch_name}-3")
      end
    end
  end

313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
  describe '#has_related_branch?' do
    let(:issue) { create(:issue, title: "Blue Bell Knoll") }
    subject { issue.has_related_branch? }

    context 'branch found' do
      before do
        allow(issue.project.repository).to receive(:branch_names).and_return(["iceblink-luck", issue.to_branch_name])
      end

      it { is_expected.to eq true }
    end

    context 'branch not found' do
      before do
        allow(issue.project.repository).to receive(:branch_names).and_return(["lazy-calm"])
      end

      it { is_expected.to eq false }
    end
  end

334
  it_behaves_like 'an editable mentionable' do
335
    subject { create(:issue, project: create(:project, :repository)) }
336

337
    let(:backref_text) { "issue #{subject.to_reference}" }
338
    let(:set_mentionable_text) { ->(txt) { subject.description = txt } }
339
  end
Vinnie Okada's avatar
Vinnie Okada committed
340 341 342 343

  it_behaves_like 'a Taskable' do
    let(:subject) { create :issue }
  end
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
344 345

  describe "#to_branch_name" do
346
    let(:issue) { create(:issue, title: 'testing-issue') }
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
347

348
    it 'starts with the issue iid' do
349
      expect(issue.to_branch_name).to match /\A#{issue.iid}-[A-Za-z\-]+\z/
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
350
    end
351 352

    it "contains the issue title if not confidential" do
353
      expect(issue.to_branch_name).to match /testing-issue\z/
354 355 356 357
    end

    it "does not contain the issue title if confidential" do
      issue = create(:issue, title: 'testing-issue', confidential: true)
358
      expect(issue.to_branch_name).to match /confidential-issue\z/
359
    end
Zeger-Jan van de Weg's avatar
Zeger-Jan van de Weg committed
360
  end
Yorick Peterse's avatar
Yorick Peterse committed
361

362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
  describe '#can_be_worked_on?' do
    let(:project) { build(:project) }
    subject { build(:issue, :opened, project: project) }

    context 'is closed' do
      subject { build(:issue, :closed) }

      it { is_expected.not_to be_can_be_worked_on }
    end

    context 'project is forked' do
      before do
        allow(project).to receive(:forked?).and_return(true)
      end

      it { is_expected.not_to be_can_be_worked_on }
    end

    it { is_expected.to be_can_be_worked_on }
  end

Yorick Peterse's avatar
Yorick Peterse committed
383 384
  describe '#participants' do
    context 'using a public project' do
385
      let(:project) { create(:project, :public) }
Yorick Peterse's avatar
Yorick Peterse committed
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
      let(:issue) { create(:issue, project: project) }

      let!(:note1) do
        create(:note_on_issue, noteable: issue, project: project, note: 'a')
      end

      let!(:note2) do
        create(:note_on_issue, noteable: issue, project: project, note: 'b')
      end

      it 'includes the issue author' do
        expect(issue.participants).to include(issue.author)
      end

      it 'includes the authors of the notes' do
        expect(issue.participants).to include(note1.author, note2.author)
      end
    end

    context 'using a private project' do
      it 'does not include mentioned users that do not have access to the project' do
407
        project = create(:project)
Yorick Peterse's avatar
Yorick Peterse committed
408 409 410 411 412 413 414 415 416 417 418 419
        user = create(:user)
        issue = create(:issue, project: project)

        create(:note_on_issue,
               noteable: issue,
               project: project,
               note: user.to_reference)

        expect(issue.participants).not_to include(user)
      end
    end
  end
420 421 422 423 424

  describe 'cached counts' do
    it 'updates when assignees change' do
      user1 = create(:user)
      user2 = create(:user)
425
      project = create(:project)
426
      issue = create(:issue, assignees: [user1], project: project)
427 428
      project.add_developer(user1)
      project.add_developer(user2)
429 430 431 432

      expect(user1.assigned_open_issues_count).to eq(1)
      expect(user2.assigned_open_issues_count).to eq(0)

433
      issue.assignees = [user2]
434 435 436 437 438 439
      issue.save

      expect(user1.assigned_open_issues_count).to eq(0)
      expect(user2.assigned_open_issues_count).to eq(1)
    end
  end
440 441

  describe '#visible_to_user?' do
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
    context 'without a user' do
      let(:issue) { build(:issue) }

      it 'returns true when the issue is publicly visible' do
        expect(issue).to receive(:publicly_visible?).and_return(true)

        expect(issue.visible_to_user?).to eq(true)
      end

      it 'returns false when the issue is not publicly visible' do
        expect(issue).to receive(:publicly_visible?).and_return(false)

        expect(issue.visible_to_user?).to eq(false)
      end
    end

458
    context 'with a user' do
459
      let(:user) { create(:user) }
460 461 462 463 464 465 466 467 468 469 470 471 472 473
      let(:issue) { build(:issue) }

      it 'returns true when the issue is readable' do
        expect(issue).to receive(:readable_by?).with(user).and_return(true)

        expect(issue.visible_to_user?(user)).to eq(true)
      end

      it 'returns false when the issue is not readable' do
        expect(issue).to receive(:readable_by?).with(user).and_return(false)

        expect(issue.visible_to_user?(user)).to eq(false)
      end

474 475
      it 'returns false when feature is disabled' do
        expect(issue).not_to receive(:readable_by?)
476

477
        issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::DISABLED)
478

479
        expect(issue.visible_to_user?(user)).to eq(false)
480 481
      end

482 483
      it 'returns false when restricted for members' do
        expect(issue).not_to receive(:readable_by?)
484

485 486 487
        issue.project.project_feature.update_attribute(:issues_access_level, ProjectFeature::PRIVATE)

        expect(issue.visible_to_user?(user)).to eq(false)
488 489 490 491 492 493 494
      end
    end

    describe 'with a regular user that is not a team member' do
      let(:user) { create(:user) }

      context 'using a public project' do
495
        let(:project) { create(:project, :public) }
496 497 498 499

        it 'returns true for a regular issue' do
          issue = build(:issue, project: project)

500
          expect(issue.visible_to_user?(user)).to eq(true)
501 502 503 504 505
        end

        it 'returns false for a confidential issue' do
          issue = build(:issue, project: project, confidential: true)

506
          expect(issue.visible_to_user?(user)).to eq(false)
507 508 509 510
        end
      end

      context 'using an internal project' do
511
        let(:project) { create(:project, :internal) }
512 513 514 515 516

        context 'using an internal user' do
          it 'returns true for a regular issue' do
            issue = build(:issue, project: project)

517
            expect(issue.visible_to_user?(user)).to eq(true)
518 519 520 521 522
          end

          it 'returns false for a confidential issue' do
            issue = build(:issue, :confidential, project: project)

523
            expect(issue.visible_to_user?(user)).to eq(false)
524 525 526 527 528 529 530 531 532 533 534
          end
        end

        context 'using an external user' do
          before do
            allow(user).to receive(:external?).and_return(true)
          end

          it 'returns false for a regular issue' do
            issue = build(:issue, project: project)

535
            expect(issue.visible_to_user?(user)).to eq(false)
536 537 538 539 540
          end

          it 'returns false for a confidential issue' do
            issue = build(:issue, :confidential, project: project)

541
            expect(issue.visible_to_user?(user)).to eq(false)
542 543 544 545 546
          end
        end
      end

      context 'using a private project' do
547
        let(:project) { create(:project, :private) }
548 549 550 551

        it 'returns false for a regular issue' do
          issue = build(:issue, project: project)

552
          expect(issue.visible_to_user?(user)).to eq(false)
553 554 555 556 557
        end

        it 'returns false for a confidential issue' do
          issue = build(:issue, :confidential, project: project)

558
          expect(issue.visible_to_user?(user)).to eq(false)
559 560 561
        end

        context 'when the user is the project owner' do
562
          before do
563
            project.add_maintainer(user)
564
          end
565

566 567 568
          it 'returns true for a regular issue' do
            issue = build(:issue, project: project)

569
            expect(issue.visible_to_user?(user)).to eq(true)
570 571 572 573 574
          end

          it 'returns true for a confidential issue' do
            issue = build(:issue, :confidential, project: project)

575
            expect(issue.visible_to_user?(user)).to eq(true)
576 577 578 579 580 581 582
          end
        end
      end
    end

    context 'with a regular user that is a team member' do
      let(:user) { create(:user) }
583
      let(:project) { create(:project, :public) }
584 585 586

      context 'using a public project' do
        before do
587
          project.add_developer(user)
588 589 590 591 592
        end

        it 'returns true for a regular issue' do
          issue = build(:issue, project: project)

593
          expect(issue.visible_to_user?(user)).to eq(true)
594 595 596 597 598
        end

        it 'returns true for a confidential issue' do
          issue = build(:issue, :confidential, project: project)

599
          expect(issue.visible_to_user?(user)).to eq(true)
600 601 602 603
        end
      end

      context 'using an internal project' do
604
        let(:project) { create(:project, :internal) }
605 606

        before do
607
          project.add_developer(user)
608 609 610 611 612
        end

        it 'returns true for a regular issue' do
          issue = build(:issue, project: project)

613
          expect(issue.visible_to_user?(user)).to eq(true)
614 615 616 617 618
        end

        it 'returns true for a confidential issue' do
          issue = build(:issue, :confidential, project: project)

619
          expect(issue.visible_to_user?(user)).to eq(true)
620 621 622 623
        end
      end

      context 'using a private project' do
624
        let(:project) { create(:project, :private) }
625 626

        before do
627
          project.add_developer(user)
628 629 630 631 632
        end

        it 'returns true for a regular issue' do
          issue = build(:issue, project: project)

633
          expect(issue.visible_to_user?(user)).to eq(true)
634 635 636 637 638
        end

        it 'returns true for a confidential issue' do
          issue = build(:issue, :confidential, project: project)

639
          expect(issue.visible_to_user?(user)).to eq(true)
640 641 642 643 644
        end
      end
    end

    context 'with an admin user' do
645
      let(:project) { create(:project) }
646
      let(:user) { create(:admin) }
647 648 649 650

      it 'returns true for a regular issue' do
        issue = build(:issue, project: project)

651
        expect(issue.visible_to_user?(user)).to eq(true)
652 653 654 655 656
      end

      it 'returns true for a confidential issue' do
        issue = build(:issue, :confidential, project: project)

657
        expect(issue.visible_to_user?(user)).to eq(true)
658 659 660 661 662 663
      end
    end
  end

  describe '#publicly_visible?' do
    context 'using a public project' do
664
      let(:project) { create(:project, :public) }
665 666 667 668

      it 'returns true for a regular issue' do
        issue = build(:issue, project: project)

669
        expect(issue).to be_truthy
670 671 672 673 674
      end

      it 'returns false for a confidential issue' do
        issue = build(:issue, :confidential, project: project)

675
        expect(issue).not_to be_falsy
676 677 678 679
      end
    end

    context 'using an internal project' do
680
      let(:project) { create(:project, :internal) }
681 682 683 684

      it 'returns false for a regular issue' do
        issue = build(:issue, project: project)

685
        expect(issue).not_to be_falsy
686 687 688 689 690
      end

      it 'returns false for a confidential issue' do
        issue = build(:issue, :confidential, project: project)

691
        expect(issue).not_to be_falsy
692 693 694 695
      end
    end

    context 'using a private project' do
696
      let(:project) { create(:project, :private) }
697 698 699 700

      it 'returns false for a regular issue' do
        issue = build(:issue, project: project)

701
        expect(issue).not_to be_falsy
702 703 704 705 706
      end

      it 'returns false for a confidential issue' do
        issue = build(:issue, :confidential, project: project)

707
        expect(issue).not_to be_falsy
708 709 710
      end
    end
  end
711 712

  describe '#hook_attrs' do
713 714 715 716 717 718 719 720
    it 'delegates to Gitlab::HookData::IssueBuilder#build' do
      builder = double

      expect(Gitlab::HookData::IssueBuilder)
        .to receive(:new).with(subject).and_return(builder)
      expect(builder).to receive(:build)

      subject.hook_attrs
721
    end
722
  end
723

724 725
  describe '#check_for_spam?' do
    using RSpec::Parameterized::TableSyntax
726

727 728 729 730 731 732 733 734 735
    where(:visibility_level, :confidential, :new_attributes, :check_for_spam?) do
      Gitlab::VisibilityLevel::PUBLIC   | false | { description: 'woo' } | true
      Gitlab::VisibilityLevel::PUBLIC   | false | { title: 'woo' } | true
      Gitlab::VisibilityLevel::PUBLIC   | true  | { confidential: false } | true
      Gitlab::VisibilityLevel::PUBLIC   | true  | { description: 'woo' } | false
      Gitlab::VisibilityLevel::PUBLIC   | false | { title: 'woo', confidential: true } | false
      Gitlab::VisibilityLevel::PUBLIC   | false | { description: 'original description' } | false
      Gitlab::VisibilityLevel::INTERNAL | false | { description: 'woo' } | false
      Gitlab::VisibilityLevel::PRIVATE  | false | { description: 'woo' } | false
736 737
    end

738 739 740 741
    with_them do
      it 'checks for spam on issues that can be seen anonymously' do
        project = create(:project, visibility_level: visibility_level)
        issue = create(:issue, project: project, confidential: confidential, description: 'original description')
742

743
        issue.assign_attributes(new_attributes)
744

745
        expect(issue.check_for_spam?).to eq(check_for_spam?)
746 747 748
      end
    end
  end
749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766

  describe 'removing an issue' do
    it 'refreshes the number of open issues of the project' do
      project = subject.project

      expect { subject.destroy }
        .to change { project.open_issues_count }.from(1).to(0)
    end
  end

  describe '.public_only' do
    it 'only returns public issues' do
      public_issue = create(:issue)
      create(:issue, confidential: true)

      expect(described_class.public_only).to eq([public_issue])
    end
  end
767

768 769 770 771 772 773 774 775 776
  describe '.confidential_only' do
    it 'only returns confidential_only issues' do
      create(:issue)
      confidential_issue = create(:issue, confidential: true)

      expect(described_class.confidential_only).to eq([confidential_issue])
    end
  end

777 778 779
  it_behaves_like 'throttled touch' do
    subject { create(:issue, updated_at: 1.hour.ago) }
  end
gitlabhq's avatar
gitlabhq committed
780
end