BigW Consortium Gitlab

note_spec.rb 7.81 KB
Newer Older
gitlabhq committed
1 2
require 'spec_helper'

Douwe Maan committed
3
describe Note, models: true do
4
  describe 'associations' do
5
    it { is_expected.to belong_to(:project) }
6
    it { is_expected.to belong_to(:noteable).touch(true) }
7
    it { is_expected.to belong_to(:author).class_name('User') }
8

9
    it { is_expected.to have_many(:todos).dependent(:destroy) }
gitlabhq committed
10 11
  end

12 13 14 15 16 17 18 19 20 21
  describe 'modules' do
    subject { described_class }

    it { is_expected.to include_module(Participable) }
    it { is_expected.to include_module(Mentionable) }
    it { is_expected.to include_module(Awardable) }

    it { is_expected.to include_module(Gitlab::CurrentSettings) }
  end

22
  describe 'validation' do
23 24
    it { is_expected.to validate_presence_of(:note) }
    it { is_expected.to validate_presence_of(:project) }
25

26
    context 'when note is on commit' do
27 28 29
      before { allow(subject).to receive(:for_commit?).and_return(true) }

      it { is_expected.to validate_presence_of(:commit_id) }
Robert Speicher committed
30
      it { is_expected.not_to validate_presence_of(:noteable_id) }
31 32
    end

33
    context 'when note is not on commit' do
34 35
      before { allow(subject).to receive(:for_commit?).and_return(false) }

Robert Speicher committed
36
      it { is_expected.not_to validate_presence_of(:commit_id) }
37 38 39
      it { is_expected.to validate_presence_of(:noteable_id) }
    end

40
    context 'when noteable and note project differ' do
41
      subject do
42 43
        build(:note, noteable: build_stubbed(:issue),
                     project: build_stubbed(:project))
44 45 46 47 48
      end

      it { is_expected.to be_invalid }
    end

49
    context 'when noteable and note project are the same' do
50 51 52
      subject { create(:note) }
      it { is_expected.to be_valid }
    end
gitlabhq committed
53 54
  end

55
  describe "Commit notes" do
Riyad Preukschas committed
56 57
    let!(:note) { create(:note_on_commit, note: "+1 from me") }
    let!(:commit) { note.noteable }
58

59
    it "should be accessible through #noteable" do
60 61 62
      expect(note.commit_id).to eq(commit.id)
      expect(note.noteable).to be_a(Commit)
      expect(note.noteable).to eq(commit)
63 64
    end

65
    it "should save a valid note" do
66
      expect(note.commit_id).to eq(commit.id)
Riyad Preukschas committed
67
      note.noteable == commit
68 69 70
    end

    it "should be recognized by #for_commit?" do
71
      expect(note).to be_for_commit
72
    end
Riyad Preukschas committed
73 74
  end

75
  describe 'authorization' do
Nihad Abbasov committed
76
    before do
77
      @p1 = create(:project)
78 79 80 81
      @p2 = create(:project)
      @u1 = create(:user)
      @u2 = create(:user)
      @u3 = create(:user)
gitlabhq committed
82 83 84 85
      @abilities = Six.new
      @abilities << Ability
    end

86
    describe 'read' do
Nihad Abbasov committed
87
      before do
88 89
        @p1.project_members.create(user: @u2, access_level: ProjectMember::GUEST)
        @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST)
gitlabhq committed
90 91
      end

92 93 94
      it { expect(@abilities.allowed?(@u1, :read_note, @p1)).to be_falsey }
      it { expect(@abilities.allowed?(@u2, :read_note, @p1)).to be_truthy }
      it { expect(@abilities.allowed?(@u3, :read_note, @p1)).to be_falsey }
gitlabhq committed
95 96
    end

97
    describe 'write' do
Nihad Abbasov committed
98
      before do
99 100
        @p1.project_members.create(user: @u2, access_level: ProjectMember::DEVELOPER)
        @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER)
gitlabhq committed
101 102
      end

103 104 105
      it { expect(@abilities.allowed?(@u1, :create_note, @p1)).to be_falsey }
      it { expect(@abilities.allowed?(@u2, :create_note, @p1)).to be_truthy }
      it { expect(@abilities.allowed?(@u3, :create_note, @p1)).to be_falsey }
gitlabhq committed
106 107
    end

108
    describe 'admin' do
Nihad Abbasov committed
109
      before do
110 111 112
        @p1.project_members.create(user: @u1, access_level: ProjectMember::REPORTER)
        @p1.project_members.create(user: @u2, access_level: ProjectMember::MASTER)
        @p2.project_members.create(user: @u3, access_level: ProjectMember::MASTER)
gitlabhq committed
113 114
      end

115 116 117
      it { expect(@abilities.allowed?(@u1, :admin_note, @p1)).to be_falsey }
      it { expect(@abilities.allowed?(@u2, :admin_note, @p1)).to be_truthy }
      it { expect(@abilities.allowed?(@u3, :admin_note, @p1)).to be_falsey }
gitlabhq committed
118 119
    end
  end
120 121

  it_behaves_like 'an editable mentionable' do
Douwe Maan committed
122
    subject { create :note, noteable: issue, project: issue.project }
123

Douwe Maan committed
124
    let(:issue) { create :issue }
125 126 127
    let(:backref_text) { issue.gfm_reference }
    let(:set_mentionable_text) { ->(txt) { subject.note = txt } }
  end
128

Douwe Maan committed
129
  describe "#all_references" do
130 131
    let!(:note1) { create(:note_on_issue) }
    let!(:note2) { create(:note_on_issue) }
Douwe Maan committed
132 133

    it "reads the rendered note body from the cache" do
Yorick Peterse committed
134 135 136 137 138 139 140 141 142 143 144 145 146
      expect(Banzai::Renderer).to receive(:render).
        with(note1.note,
             pipeline: :note,
             cache_key: [note1, "note"],
             project: note1.project,
             author: note1.author)

      expect(Banzai::Renderer).to receive(:render).
        with(note2.note,
             pipeline: :note,
             cache_key: [note2, "note"],
             project: note2.project,
             author: note2.author)
Douwe Maan committed
147 148 149 150 151 152

      note1.all_references
      note2.all_references
    end
  end

153
  describe '.search' do
154
    let(:note) { create(:note_on_issue, note: 'WoW') }
155

156 157 158 159 160 161 162
    it 'returns notes with matching content' do
      expect(described_class.search(note.note)).to eq([note])
    end

    it 'returns notes with matching content regardless of the casing' do
      expect(described_class.search('WOW')).to eq([note])
    end
163 164

    context "confidential issues" do
165 166 167 168
      let(:user) { create(:user) }
      let(:project) { create(:project) }
      let(:confidential_issue) { create(:issue, :confidential, project: project, author: user) }
      let(:confidential_note) { create(:note, note: "Random", noteable: confidential_issue, project: confidential_issue.project) }
169 170 171 172 173 174

      it "returns notes with matching content if user can see the issue" do
        expect(described_class.search(confidential_note.note, as_user: user)).to eq([confidential_note])
      end

      it "does not return notes with matching content if user can not see the issue" do
175 176 177 178 179 180 181
        user = create(:user)
        expect(described_class.search(confidential_note.note, as_user: user)).to be_empty
      end

      it "does not return notes with matching content for project members with guest role" do
        user = create(:user)
        project.team << [user, :guest]
182 183 184 185 186 187 188
        expect(described_class.search(confidential_note.note, as_user: user)).to be_empty
      end

      it "does not return notes with matching content for unauthenticated users" do
        expect(described_class.search(confidential_note.note)).to be_empty
      end
    end
189
  end
Valery Sizov committed
190

191 192 193 194 195 196 197 198 199 200 201
  describe "editable?" do
    it "returns true" do
      note = build(:note)
      expect(note.editable?).to be_truthy
    end

    it "returns false" do
      note = build(:note, system: true)
      expect(note.editable?).to be_falsy
    end
  end
Douwe Maan committed
202

203 204 205 206 207 208 209 210
  describe "cross_reference_not_visible_for?" do
    let(:private_user)    { create(:user) }
    let(:private_project) { create(:project, namespace: private_user.namespace).tap { |p| p.team << [private_user, :master] } }
    let(:private_issue)   { create(:issue, project: private_project) }

    let(:ext_proj)  { create(:project, :public) }
    let(:ext_issue) { create(:issue, project: ext_proj) }

211
    let(:note) do
212 213 214 215
      create :note,
        noteable: ext_issue, project: ext_proj,
        note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
        system: true
216
    end
217 218 219 220 221 222 223 224 225 226

    it "returns true" do
      expect(note.cross_reference_not_visible_for?(ext_issue.author)).to be_truthy
    end

    it "returns false" do
      expect(note.cross_reference_not_visible_for?(private_user)).to be_falsy
    end
  end

227 228 229 230 231 232 233
  describe 'clear_blank_line_code!' do
    it 'clears a blank line code before validation' do
      note = build(:note, line_code: ' ')

      expect { note.valid? }.to change(note, :line_code).to(nil)
    end
  end
Yorick Peterse committed
234 235 236 237 238 239 240 241 242 243

  describe '#participants' do
    it 'includes the note author' do
      project = create(:project, :public)
      issue = create(:issue, project: project)
      note = create(:note_on_issue, noteable: issue, project: project)

      expect(note.participants).to include(note.author)
    end
  end
gitlabhq committed
244
end