commit_spec.rb 6.74 KB
Newer Older
1 2
require 'spec_helper'

Douwe Maan's avatar
Douwe Maan committed
3
describe Commit, models: true do
4
  let(:project) { create(:project, :public) }
5 6 7 8 9 10 11 12 13 14 15 16 17
  let(:commit)  { project.commit }

  describe 'modules' do
    subject { described_class }

    it { is_expected.to include_module(Mentionable) }
    it { is_expected.to include_module(Participable) }
    it { is_expected.to include_module(Referable) }
    it { is_expected.to include_module(StaticModel) }
  end

  describe '#to_reference' do
    it 'returns a String reference to the object' do
18
      expect(commit.to_reference).to eq commit.id
19 20 21 22
    end

    it 'supports a cross-project reference' do
      cross = double('project')
23 24 25 26 27 28 29 30 31 32 33 34
      expect(commit.to_reference(cross)).to eq "#{project.to_reference}@#{commit.id}"
    end
  end

  describe '#reference_link_text' do
    it 'returns a String reference to the object' do
      expect(commit.reference_link_text).to eq commit.short_id
    end

    it 'supports a cross-project reference' do
      cross = double('project')
      expect(commit.reference_link_text(cross)).to eq "#{project.to_reference}@#{commit.short_id}"
35 36
    end
  end
37

38 39
  describe '#title' do
    it "returns no_commit_message when safe_message is blank" do
40 41
      allow(commit).to receive(:safe_message).and_return('')
      expect(commit.title).to eq("--no commit message")
42
    end
43

44
    it "truncates a message without a newline at 80 characters" do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
45
      message = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit. Vivamus egestas lacinia lacus, sed rutrum mauris.'
46

47
      allow(commit).to receive(:safe_message).and_return(message)
48
      expect(commit.title).to eq("#{message[0..79]}…")
49
    end
50

51 52
    it "truncates a message with a newline before 80 characters at the newline" do
      message = commit.safe_message.split(" ").first
53

54 55
      allow(commit).to receive(:safe_message).and_return(message + "\n" + message)
      expect(commit.title).to eq(message)
56
    end
57

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
58
    it "does not truncates a message with a newline after 80 but less 100 characters" do
59
      message = <<eos
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
60 61 62
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sodales id felis id blandit.
Vivamus egestas lacinia lacus, sed rutrum mauris.
eos
63

64 65
      allow(commit).to receive(:safe_message).and_return(message)
      expect(commit.title).to eq(message.split("\n").first)
66 67
    end
  end
68 69 70 71

  describe "delegation" do
    subject { commit }

72 73 74 75 76 77 78 79 80 81 82
    it { is_expected.to respond_to(:message) }
    it { is_expected.to respond_to(:authored_date) }
    it { is_expected.to respond_to(:committed_date) }
    it { is_expected.to respond_to(:committer_email) }
    it { is_expected.to respond_to(:author_email) }
    it { is_expected.to respond_to(:parents) }
    it { is_expected.to respond_to(:date) }
    it { is_expected.to respond_to(:diffs) }
    it { is_expected.to respond_to(:tree) }
    it { is_expected.to respond_to(:id) }
    it { is_expected.to respond_to(:to_patch) }
83
  end
84 85 86

  describe '#closes_issues' do
    let(:issue) { create :issue, project: project }
87 88
    let(:other_project) { create :project, :public }
    let(:other_issue) { create :issue, project: other_project }
89 90 91 92 93 94
    let(:commiter) { create :user }

    before do
      project.team << [commiter, :developer]
      other_project.team << [commiter, :developer]
    end
95 96

    it 'detects issues that this commit is marked as closing' do
97
      ext_ref = "#{other_project.path_with_namespace}##{other_issue.iid}"
98 99 100 101 102 103

      allow(commit).to receive_messages(
        safe_message: "Fixes ##{issue.iid} and #{ext_ref}",
        committer_email: commiter.email
      )

Douwe Maan's avatar
Douwe Maan committed
104 105
      expect(commit.closes_issues).to include(issue)
      expect(commit.closes_issues).to include(other_issue)
106
    end
107 108 109
  end

  it_behaves_like 'a mentionable' do
Douwe Maan's avatar
Douwe Maan committed
110
    subject { create(:project).commit }
111

Douwe Maan's avatar
Douwe Maan committed
112
    let(:author) { create(:user, email: subject.author_email) }
113
    let(:backref_text) { "commit #{subject.id}" }
114 115 116
    let(:set_mentionable_text) do
      ->(txt) { allow(subject).to receive(:safe_message).and_return(txt) }
    end
117 118 119 120

    # Include the subject in the repository stub.
    let(:extra_commits) { [subject] }
  end
121 122

  describe '#hook_attrs' do
Valery Sizov's avatar
Valery Sizov committed
123
    let(:data) { commit.hook_attrs(with_changed_files: true) }
124 125 126 127 128 129 130 131

    it { expect(data).to be_a(Hash) }
    it { expect(data[:message]).to include('Add submodule from gitlab.com') }
    it { expect(data[:timestamp]).to eq('2014-02-27T11:01:38+02:00') }
    it { expect(data[:added]).to eq(["gitlab-grack"]) }
    it { expect(data[:modified]).to eq([".gitmodules"]) }
    it { expect(data[:removed]).to eq([]) }
  end
132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

  describe '#reverts_commit?' do
    let(:another_commit) { double(:commit, revert_description: "This reverts commit #{commit.sha}") }

    it { expect(commit.reverts_commit?(another_commit)).to be_falsy }

    context 'commit has no description' do
      before { allow(commit).to receive(:description?).and_return(false) }

      it { expect(commit.reverts_commit?(another_commit)).to be_falsy }
    end

    context "another_commit's description does not revert commit" do
      before { allow(commit).to receive(:description).and_return("Foo Bar") }

      it { expect(commit.reverts_commit?(another_commit)).to be_falsy }
    end

    context "another_commit's description reverts commit" do
      before { allow(commit).to receive(:description).and_return("Foo #{another_commit.revert_description} Bar") }

      it { expect(commit.reverts_commit?(another_commit)).to be_truthy }
    end

    context "another_commit's description reverts merged merge request" do
      before do
        revert_description = "This reverts merge request !foo123"
        allow(another_commit).to receive(:revert_description).and_return(revert_description)
        allow(commit).to receive(:description).and_return("Foo #{another_commit.revert_description} Bar")
      end

      it { expect(commit.reverts_commit?(another_commit)).to be_truthy }
    end
  end
166 167 168 169 170 171 172 173

  describe '#ci_commits' do
    # TODO: kamil
  end

  describe '#status' do
    # TODO: kamil
  end
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

  describe '#participants' do
    let(:user1) { build(:user) }
    let(:user2) { build(:user) }

    let!(:note1) do
      create(:note_on_commit,
             commit_id: commit.id,
             project: project,
             note: 'foo')
    end

    let!(:note2) do
      create(:note_on_commit,
             commit_id: commit.id,
             project: project,
             note: 'bar')
    end

    before do
      allow(commit).to receive(:author).and_return(user1)
      allow(commit).to receive(:committer).and_return(user2)
    end

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

    it 'includes the committer' do
      expect(commit.participants).to include(commit.committer)
    end

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