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

G
gitlabhq 已提交
20 21 22 23 24
require 'spec_helper'

describe Note do
  describe "Associations" do
    it { should belong_to(:project) }
25 26
    it { should belong_to(:noteable) }
    it { should belong_to(:author).class_name('User') }
G
gitlabhq 已提交
27 28
  end

29 30 31
  describe "Mass assignment" do
  end

G
gitlabhq 已提交
32 33 34 35 36
  describe "Validation" do
    it { should validate_presence_of(:note) }
    it { should validate_presence_of(:project) }
  end

37
  describe "Voting score" do
38
    let(:project) { create(:project) }
39 40

    it "recognizes a neutral note" do
R
Riyad Preukschas 已提交
41
      note = create(:votable_note, note: "This is not a +1 note")
42
      note.should_not be_upvote
43 44 45 46
      note.should_not be_downvote
    end

    it "recognizes a neutral emoji note" do
R
Riyad Preukschas 已提交
47
      note = build(:votable_note, note: "I would :+1: this, but I don't want to")
48 49
      note.should_not be_upvote
      note.should_not be_downvote
50 51 52
    end

    it "recognizes a +1 note" do
R
Riyad Preukschas 已提交
53
      note = create(:votable_note, note: "+1 for this")
54 55 56
      note.should be_upvote
    end

57
    it "recognizes a +1 emoji as a vote" do
R
Riyad Preukschas 已提交
58
      note = build(:votable_note, note: ":+1: for this")
59 60 61
      note.should be_upvote
    end

62 63 64 65 66
    it "recognizes a thumbsup emoji as a vote" do
      note = build(:votable_note, note: ":thumbsup: for this")
      note.should be_upvote
    end

67
    it "recognizes a -1 note" do
R
Riyad Preukschas 已提交
68
      note = create(:votable_note, note: "-1 for this")
69 70 71 72
      note.should be_downvote
    end

    it "recognizes a -1 emoji as a vote" do
R
Riyad Preukschas 已提交
73
      note = build(:votable_note, note: ":-1: for this")
74
      note.should be_downvote
75
    end
76 77 78 79 80

    it "recognizes a thumbsdown emoji as a vote" do
      note = build(:votable_note, note: ":thumbsdown: for this")
      note.should be_downvote
    end
81 82
  end

83
  let(:project) { create(:project) }
84

85
  describe "Commit notes" do
R
Riyad Preukschas 已提交
86 87
    let!(:note) { create(:note_on_commit, note: "+1 from me") }
    let!(:commit) { note.noteable }
D
Dmitriy Zaporozhets 已提交
88

R
Riyad Preukschas 已提交
89
    it "should be accessible through #noteable" do
90
      note.commit_id.should == commit.id
R
Riyad Preukschas 已提交
91 92
      note.noteable.should be_a(Commit)
      note.noteable.should == commit
R
Riyad Preukschas 已提交
93 94
    end

D
Dmitriy Zaporozhets 已提交
95
    it "should save a valid note" do
96
      note.commit_id.should == commit.id
R
Riyad Preukschas 已提交
97
      note.noteable == commit
R
Riyad Preukschas 已提交
98 99 100
    end

    it "should be recognized by #for_commit?" do
R
Riyad Preukschas 已提交
101
      note.should be_for_commit
D
Dmitriy Zaporozhets 已提交
102 103
    end

R
Riyad Preukschas 已提交
104 105
    it "should not be votable" do
      note.should_not be_votable
D
Dmitriy Zaporozhets 已提交
106
    end
R
Riyad Preukschas 已提交
107 108 109
  end

  describe "Commit diff line notes" do
D
Dmitriy Zaporozhets 已提交
110
    let!(:note) { create(:note_on_commit_diff, note: "+1 from me") }
R
Riyad Preukschas 已提交
111
    let!(:commit) { note.noteable }
D
Dmitriy Zaporozhets 已提交
112 113

    it "should save a valid note" do
114
      note.commit_id.should == commit.id
R
Riyad Preukschas 已提交
115
      note.noteable.id.should == commit.id
R
Riyad Preukschas 已提交
116 117 118
    end

    it "should be recognized by #for_diff_line?" do
R
Riyad Preukschas 已提交
119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
      note.should be_for_diff_line
    end

    it "should be recognized by #for_commit_diff_line?" do
      note.should be_for_commit_diff_line
    end

    it "should not be votable" do
      note.should_not be_votable
    end
  end

  describe "Issue notes" do
    let!(:note) { create(:note_on_issue, note: "+1 from me") }

    it "should not be votable" do
      note.should be_votable
    end
  end

  describe "Merge request notes" do
    let!(:note) { create(:note_on_merge_request, note: "+1 from me") }

142
    it "should be votable" do
R
Riyad Preukschas 已提交
143 144 145 146 147
      note.should be_votable
    end
  end

  describe "Merge request diff line notes" do
D
Dmitriy Zaporozhets 已提交
148
    let!(:note) { create(:note_on_merge_request_diff, note: "+1 from me") }
R
Riyad Preukschas 已提交
149 150 151

    it "should not be votable" do
      note.should_not be_votable
D
Dmitriy Zaporozhets 已提交
152 153 154
    end
  end

155
  describe '#create_status_change_note' do
I
Izaak Alpert 已提交
156 157 158 159
    let(:project) { create(:project) }
    let(:thing) { create(:issue, project: project) }
    let(:author) { create(:user) }
    let(:status) { 'new_status' }
160

161
    subject { Note.create_status_change_note(thing, project, author, status, nil) }
162 163 164 165 166 167 168

    it 'creates and saves a Note' do
      should be_a Note
      subject.id.should_not be_nil
    end

    its(:noteable) { should == thing }
I
Izaak Alpert 已提交
169 170 171
    its(:project) { should == thing.project }
    its(:author) { should == author }
    its(:note) { should =~ /Status changed to #{status}/ }
172 173 174 175 176 177 178 179 180

    it 'appends a back-reference if a closing mentionable is supplied' do
      commit = double('commit', gfm_reference: 'commit 123456')
      n = Note.create_status_change_note(thing, project, author, status, commit)

      n.note.should =~ /Status changed to #{status} by commit 123456/
    end
  end

D
Drew Blessing 已提交
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
  describe '#create_assignee_change_note' do
    let(:project) { create(:project) }
    let(:thing) { create(:issue, project: project) }
    let(:author) { create(:user) }
    let(:assignee) { create(:user) }

    subject { Note.create_assignee_change_note(thing, project, author, assignee) }

    context 'creates and saves a Note' do
      it { should be_a Note }
      its(:id) { should_not be_nil }
    end

    its(:noteable) { should == thing }
    its(:project) { should == thing.project }
    its(:author) { should == author }
    its(:note) { should =~ /Reassigned to @#{assignee.username}/ }

    context 'assignee is removed' do
      let(:assignee) { nil }

      its(:note) { should =~ /Assignee removed/ }
    end
  end

206
  describe '#create_cross_reference_note' do
D
Dmitriy Zaporozhets 已提交
207
    let(:project)    { create(:project) }
208 209
    let(:author)     { create(:user) }
    let(:issue)      { create(:issue, project: project) }
210
    let(:mergereq)   { create(:merge_request, :simple, target_project: project, source_project: project) }
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
    let(:commit)     { project.repository.commit }

    # Test all of {issue, merge request, commit} in both the referenced and referencing
    # roles, to ensure that the correct information can be inferred from any argument.

    context 'issue from a merge request' do
      subject { Note.create_cross_reference_note(issue, mergereq, author, project) }

      it { should be_valid }
      its(:noteable) { should == issue }
      its(:project)  { should == issue.project }
      its(:author)   { should == author }
      its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" }
    end

    context 'issue from a commit' do
      subject { Note.create_cross_reference_note(issue, commit, author, project) }

      it { should be_valid }
      its(:noteable) { should == issue }
      its(:note) { should == "_mentioned in commit #{commit.sha[0..5]}_" }
    end

    context 'merge request from an issue' do
      subject { Note.create_cross_reference_note(mergereq, issue, author, project) }

      it { should be_valid }
      its(:noteable) { should == mergereq }
      its(:project) { should == mergereq.project }
      its(:note) { should == "_mentioned in issue ##{issue.iid}_" }
    end

    context 'commit from a merge request' do
      subject { Note.create_cross_reference_note(commit, mergereq, author, project) }

      it { should be_valid }
      its(:noteable) { should == commit }
      its(:project) { should == project }
      its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" }
    end
251 252 253 254 255 256 257 258 259 260

    context 'commit from issue' do
      subject { Note.create_cross_reference_note(commit, issue, author, project) }

      it { should be_valid }
      its(:noteable_type) { should == "Commit" }
      its(:noteable_id) { should be_nil }
      its(:commit_id) { should == commit.id }
      its(:note) { should == "_mentioned in issue ##{issue.iid}_" }
    end
261 262 263 264 265 266
  end

  describe '#cross_reference_exists?' do
    let(:project) { create :project }
    let(:author) { create :user }
    let(:issue) { create :issue }
267 268
    let(:commit0) { project.repository.commit }
    let(:commit1) { project.repository.commit('HEAD~2') }
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287

    before do
      Note.create_cross_reference_note(issue, commit0, author, project)
    end

    it 'detects if a mentionable has already been mentioned' do
      Note.cross_reference_exists?(issue, commit0).should be_true
    end

    it 'detects if a mentionable has not already been mentioned' do
      Note.cross_reference_exists?(issue, commit1).should be_false
    end
  end

  describe '#system?' do
    let(:project) { create(:project) }
    let(:issue)   { create(:issue, project: project) }
    let(:other)   { create(:issue, project: project) }
    let(:author)  { create(:user) }
D
Drew Blessing 已提交
288
    let(:assignee) { create(:user) }
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303

    it 'should recognize user-supplied notes as non-system' do
      @note = create(:note_on_issue)
      @note.should_not be_system
    end

    it 'should identify status-change notes as system notes' do
      @note = Note.create_status_change_note(issue, project, author, 'closed', nil)
      @note.should be_system
    end

    it 'should identify cross-reference notes as system notes' do
      @note = Note.create_cross_reference_note(issue, other, author, project)
      @note.should be_system
    end
D
Drew Blessing 已提交
304 305 306 307 308

    it 'should identify assignee-change notes as system notes' do
      @note = Note.create_assignee_change_note(issue, project, author, assignee)
      @note.should be_system
    end
309 310
  end

N
Nihad Abbasov 已提交
311 312
  describe :authorization do
    before do
313
      @p1 = create(:project)
314 315 316 317
      @p2 = create(:project)
      @u1 = create(:user)
      @u2 = create(:user)
      @u3 = create(:user)
G
gitlabhq 已提交
318 319 320 321
      @abilities = Six.new
      @abilities << Ability
    end

N
Nihad Abbasov 已提交
322 323
    describe :read do
      before do
324 325
        @p1.project_members.create(user: @u2, access_level: ProjectMember::GUEST)
        @p2.project_members.create(user: @u3, access_level: ProjectMember::GUEST)
G
gitlabhq 已提交
326 327 328 329 330 331 332
      end

      it { @abilities.allowed?(@u1, :read_note, @p1).should be_false }
      it { @abilities.allowed?(@u2, :read_note, @p1).should be_true }
      it { @abilities.allowed?(@u3, :read_note, @p1).should be_false }
    end

N
Nihad Abbasov 已提交
333 334
    describe :write do
      before do
335 336
        @p1.project_members.create(user: @u2, access_level: ProjectMember::DEVELOPER)
        @p2.project_members.create(user: @u3, access_level: ProjectMember::DEVELOPER)
G
gitlabhq 已提交
337 338 339 340 341 342 343
      end

      it { @abilities.allowed?(@u1, :write_note, @p1).should be_false }
      it { @abilities.allowed?(@u2, :write_note, @p1).should be_true }
      it { @abilities.allowed?(@u3, :write_note, @p1).should be_false }
    end

N
Nihad Abbasov 已提交
344 345
    describe :admin do
      before do
346 347 348
        @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)
G
gitlabhq 已提交
349 350 351 352 353 354 355
      end

      it { @abilities.allowed?(@u1, :admin_note, @p1).should be_false }
      it { @abilities.allowed?(@u2, :admin_note, @p1).should be_true }
      it { @abilities.allowed?(@u3, :admin_note, @p1).should be_false }
    end
  end
356 357 358 359 360 361 362

  it_behaves_like 'an editable mentionable' do
    let(:issue) { create :issue, project: project }
    let(:subject) { create :note, noteable: issue, project: project }
    let(:backref_text) { issue.gfm_reference }
    let(:set_mentionable_text) { ->(txt) { subject.note = txt } }
  end
G
gitlabhq 已提交
363
end