BigW Consortium Gitlab

note_spec.rb 9.18 KB
Newer Older
Dmitriy Zaporozhets committed
1 2 3 4
# == Schema Information
#
# Table name: notes
#
5
#  id            :integer          not null, primary key
Dmitriy Zaporozhets committed
6 7 8
#  note          :text
#  noteable_type :string(255)
#  author_id     :integer
Dmitriy Zaporozhets committed
9 10
#  created_at    :datetime
#  updated_at    :datetime
Dmitriy Zaporozhets committed
11 12 13
#  project_id    :integer
#  attachment    :string(255)
#  line_code     :string(255)
14 15
#  commit_id     :string(255)
#  noteable_id   :integer
Dmitriy Zaporozhets committed
16
#  system        :boolean          default(FALSE), not null
Dmitriy Zaporozhets committed
17
#  st_diff       :text
Stan Hu committed
18
#  updated_by_id :integer
Stan Hu committed
19
#  is_award      :boolean          default(FALSE), not null
Dmitriy Zaporozhets committed
20 21
#

gitlabhq committed
22 23
require 'spec_helper'

Douwe Maan committed
24
describe Note, models: true do
25
  describe 'associations' do
26
    it { is_expected.to belong_to(:project) }
27
    it { is_expected.to belong_to(:noteable).touch(true) }
28
    it { is_expected.to belong_to(:author).class_name('User') }
29

30
    it { is_expected.to have_many(:todos).dependent(:destroy) }
gitlabhq committed
31 32
  end

33
  describe 'validation' do
34 35
    it { is_expected.to validate_presence_of(:note) }
    it { is_expected.to validate_presence_of(:project) }
gitlabhq committed
36 37
  end

38
  describe "Commit notes" do
Riyad Preukschas committed
39 40
    let!(:note) { create(:note_on_commit, note: "+1 from me") }
    let!(:commit) { note.noteable }
41

42
    it "should be accessible through #noteable" do
43 44 45
      expect(note.commit_id).to eq(commit.id)
      expect(note.noteable).to be_a(Commit)
      expect(note.noteable).to eq(commit)
46 47
    end

48
    it "should save a valid note" do
49
      expect(note.commit_id).to eq(commit.id)
Riyad Preukschas committed
50
      note.noteable == commit
51 52 53
    end

    it "should be recognized by #for_commit?" do
54
      expect(note).to be_for_commit
55
    end
Riyad Preukschas committed
56 57 58
  end

  describe "Commit diff line notes" do
59
    let!(:note) { create(:note_on_commit_diff, note: "+1 from me") }
Riyad Preukschas committed
60
    let!(:commit) { note.noteable }
61 62

    it "should save a valid note" do
63 64
      expect(note.commit_id).to eq(commit.id)
      expect(note.noteable.id).to eq(commit.id)
65 66 67
    end

    it "should be recognized by #for_diff_line?" do
68
      expect(note).to be_for_diff_line
Riyad Preukschas committed
69 70 71
    end

    it "should be recognized by #for_commit_diff_line?" do
72
      expect(note).to be_for_commit_diff_line
Riyad Preukschas committed
73 74 75
    end
  end

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

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

93 94 95
      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
96 97
    end

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

104 105 106
      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
107 108
    end

109
    describe 'admin' do
Nihad Abbasov committed
110
      before do
111 112 113
        @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
114 115
      end

116 117 118
      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
119 120
    end
  end
121 122

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

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

Douwe Maan committed
130 131 132 133 134 135 136 137 138 139 140 141 142
  describe "#all_references" do
    let!(:note1) { create(:note) }
    let!(:note2) { create(:note) }

    it "reads the rendered note body from the cache" do
      expect(Banzai::Renderer).to receive(:render).with(note1.note, pipeline: :note, cache_key: [note1, "note"], project: note1.project)
      expect(Banzai::Renderer).to receive(:render).with(note2.note, pipeline: :note, cache_key: [note2, "note"], project: note2.project)

      note1.all_references
      note2.all_references
    end
  end

143 144
  describe '.search' do
    let(:note) { create(:note, note: 'WoW') }
145

146 147 148 149 150 151 152
    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
153
  end
Valery Sizov committed
154

155
  describe '.grouped_awards' do
Valery Sizov committed
156
    before do
Valery Sizov committed
157 158
      create :note, note: "smile", is_award: true
      create :note, note: "smile", is_award: true
Valery Sizov committed
159 160
    end

161 162 163 164 165 166 167 168
    it "returns grouped hash of notes" do
      expect(Note.grouped_awards.keys.size).to eq(3)
      expect(Note.grouped_awards["smile"]).to match_array(Note.all)
    end

    it "returns thumbsup and thumbsdown always" do
      expect(Note.grouped_awards["thumbsup"]).to match_array(Note.none)
      expect(Note.grouped_awards["thumbsdown"]).to match_array(Note.none)
Valery Sizov committed
169 170
    end
  end
171

172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
  describe '#active?' do
    it 'is always true when the note has no associated diff' do
      note = build(:note)

      expect(note).to receive(:diff).and_return(nil)

      expect(note).to be_active
    end

    it 'is never true when the note has no noteable associated' do
      note = build(:note)

      expect(note).to receive(:diff).and_return(double)
      expect(note).to receive(:noteable).and_return(nil)

      expect(note).not_to be_active
    end

    it 'returns the memoized value if defined' do
      note = build(:note)

      expect(note).to receive(:diff).and_return(double)
      expect(note).to receive(:noteable).and_return(double)

      note.instance_variable_set(:@active, 'foo')
      expect(note).not_to receive(:find_noteable_diff)

      expect(note.active?).to eq 'foo'
    end

    context 'for a merge request noteable' do
      it 'is false when noteable has no matching diff' do
        merge = build_stubbed(:merge_request, :simple)
        note = build(:note, noteable: merge)

        allow(note).to receive(:diff).and_return(double)
        expect(note).to receive(:find_noteable_diff).and_return(nil)

        expect(note).not_to be_active
      end

      it 'is true when noteable has a matching diff' do
        merge = create(:merge_request, :simple)

        # Generate a real line_code value so we know it will match. We use a
        # random line from a random diff just for funsies.
        diff = merge.diffs.to_a.sample
        line = Gitlab::Diff::Parser.new.parse(diff.diff.each_line).to_a.sample
        code = Gitlab::Diff::LineCode.generate(diff.new_path, line.new_pos, line.old_pos)

        # We're persisting in order to trigger the set_diff callback
        note = create(:note, noteable: merge, line_code: code)

        # Make sure we don't get a false positive from a guard clause
        expect(note).to receive(:find_noteable_diff).and_call_original
        expect(note).to be_active
      end
    end
  end

232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
  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

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

249 250 251 252 253 254 255 256
  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) }

257
    let(:note) do
258 259 260 261
      create :note,
        noteable: ext_issue, project: ext_proj,
        note: "mentioned in issue #{private_issue.to_reference(ext_proj)}",
        system: true
262
    end
263 264 265 266 267 268 269 270 271 272

    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

Valery Sizov committed
273
  describe "set_award!" do
274
    let(:merge_request) { create :merge_request }
Valery Sizov committed
275 276

    it "converts aliases to actual name" do
277
      note = create(:note, note: ":+1:", noteable: merge_request)
Valery Sizov committed
278
      expect(note.reload.note).to eq("thumbsup")
Valery Sizov committed
279
    end
280 281 282

    it "is not an award emoji when comment is on a diff" do
      note = create(:note, note: ":blowfish:", noteable: merge_request, line_code: "11d5d2e667e9da4f7f610f81d86c974b146b13bd_0_2")
283 284 285 286
      note = note.reload

      expect(note.note).to eq(":blowfish:")
      expect(note.is_award?).to be_falsy
287
    end
Valery Sizov committed
288
  end
289 290 291 292 293 294 295 296

  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
gitlabhq committed
297
end