merge_request_spec.rb 6.07 KB
Newer Older
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
1 2 3 4
# == Schema Information
#
# Table name: merge_requests
#
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
5 6 7 8 9 10 11
#  id                :integer          not null, primary key
#  target_branch     :string(255)      not null
#  source_branch     :string(255)      not null
#  source_project_id :integer          not null
#  author_id         :integer
#  assignee_id       :integer
#  title             :string(255)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
12 13
#  created_at        :datetime
#  updated_at        :datetime
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
14 15 16 17 18
#  milestone_id      :integer
#  state             :string(255)
#  merge_status      :string(255)
#  target_project_id :integer          not null
#  iid               :integer
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
19
#  description       :text
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
20
#  position          :integer          default(0)
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
21
#  locked_at         :datetime
Stan Hu's avatar
Stan Hu committed
22
#  updated_by_id     :integer
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
23 24
#

Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
25 26 27
require 'spec_helper'

describe MergeRequest do
28 29
  subject { create(:merge_request) }

30 31 32 33 34 35 36
  describe 'associations' do
    it { is_expected.to belong_to(:target_project).with_foreign_key(:target_project_id).class_name('Project') }
    it { is_expected.to belong_to(:source_project).with_foreign_key(:source_project_id).class_name('Project') }

    it { is_expected.to have_one(:merge_request_diff).dependent(:destroy) }
  end

37 38 39 40 41 42 43 44 45 46 47
  describe 'modules' do
    subject { described_class }

    it { is_expected.to include_module(InternalId) }
    it { is_expected.to include_module(Issuable) }
    it { is_expected.to include_module(Referable) }
    it { is_expected.to include_module(Sortable) }
    it { is_expected.to include_module(Taskable) }
  end

  describe 'validation' do
48 49
    it { is_expected.to validate_presence_of(:target_branch) }
    it { is_expected.to validate_presence_of(:source_branch) }
50 51
  end

52
  describe 'respond to' do
53 54 55
    it { is_expected.to respond_to(:unchecked?) }
    it { is_expected.to respond_to(:can_be_merged?) }
    it { is_expected.to respond_to(:cannot_be_merged?) }
56
  end
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
57

58 59 60 61 62 63 64 65 66
  describe '#to_reference' do
    it 'returns a String reference to the object' do
      expect(subject.to_reference).to eq "!#{subject.iid}"
    end

    it 'supports a cross-project reference' do
      cross = double('project')
      expect(subject.to_reference(cross)).to eq "#{subject.source_project.to_reference}!#{subject.iid}"
    end
67
  end
68 69

  describe "#mr_and_commit_notes" do
70
    let!(:merge_request) { create(:merge_request) }
71 72

    before do
73
      allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] }
74 75
      create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.project)
      create(:note, noteable: merge_request, project: merge_request.project)
76 77 78
    end

    it "should include notes for commits" do
79 80
      expect(merge_request.commits).not_to be_empty
      expect(merge_request.mr_and_commit_notes.count).to eq(2)
81 82
    end
  end
83 84 85

  describe '#is_being_reassigned?' do
    it 'returns true if the merge_request assignee has changed' do
86
      subject.assignee = create(:user)
87
      expect(subject.is_being_reassigned?).to be_truthy
88 89
    end
    it 'returns false if the merge request assignee has not changed' do
90
      expect(subject.is_being_reassigned?).to be_falsey
91 92
    end
  end
93 94 95

  describe '#for_fork?' do
    it 'returns true if the merge request is for a fork' do
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
96 97
      subject.source_project = create(:project, namespace: create(:group))
      subject.target_project = create(:project, namespace: create(:group))
98

99
      expect(subject.for_fork?).to be_truthy
100
    end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
101

102
    it 'returns false if is not for a fork' do
103
      expect(subject.for_fork?).to be_falsey
104 105 106
    end
  end

107 108 109
  describe 'detection of issues to be closed' do
    let(:issue0) { create :issue, project: subject.project }
    let(:issue1) { create :issue, project: subject.project }
skv's avatar
skv committed
110 111 112
    let(:commit0) { double('commit0', closes_issues: [issue0]) }
    let(:commit1) { double('commit1', closes_issues: [issue0]) }
    let(:commit2) { double('commit2', closes_issues: [issue1]) }
113 114

    before do
115
      allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
116 117 118
    end

    it 'accesses the set of issues that will be closed on acceptance' do
119 120
      allow(subject.project).to receive(:default_branch).
        and_return(subject.target_branch)
121

122
      expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id))
123 124 125
    end

    it 'only lists issues as to be closed if it targets the default branch' do
126
      allow(subject.project).to receive(:default_branch).and_return('master')
127 128
      subject.target_branch = 'something-else'

129
      expect(subject.closes_issues).to be_empty
130
    end
131 132 133

    it 'detects issues mentioned in the description' do
      issue2 = create(:issue, project: subject.project)
134
      subject.description = "Closes #{issue2.to_reference}"
135 136
      allow(subject.project).to receive(:default_branch).
        and_return(subject.target_branch)
137

138
      expect(subject.closes_issues).to include(issue2)
139
    end
140 141
  end

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
  describe "#work_in_progress?" do
    it "detects the 'WIP ' prefix" do
      subject.title = "WIP #{subject.title}"
      expect(subject).to be_work_in_progress
    end

    it "detects the 'WIP: ' prefix" do
      subject.title = "WIP: #{subject.title}"
      expect(subject).to be_work_in_progress
    end

    it "detects the '[WIP] ' prefix" do
      subject.title = "[WIP] #{subject.title}"
      expect(subject).to be_work_in_progress
    end

    it "doesn't detect WIP for words starting with WIP" do
      subject.title = "Wipwap #{subject.title}"
      expect(subject).not_to be_work_in_progress
    end

    it "doesn't detect WIP by default" do
      expect(subject).not_to be_work_in_progress
    end
  end

168 169 170 171 172 173 174 175 176 177 178
  describe "#hook_attrs" do
    it "has all the required keys" do
      attrs = subject.hook_attrs
      attrs = attrs.to_h
      expect(attrs).to include(:source)
      expect(attrs).to include(:target)
      expect(attrs).to include(:last_commit)
      expect(attrs).to include(:work_in_progress)
    end
  end

179
  it_behaves_like 'an editable mentionable' do
180
    subject { create(:merge_request) }
181

182 183
    let(:backref_text) { "merge request #{subject.to_reference}" }
    let(:set_mentionable_text) { ->(txt){ subject.description = txt } }
184
  end
Vinnie Okada's avatar
Vinnie Okada committed
185 186

  it_behaves_like 'a Taskable' do
187
    subject { create :merge_request, :simple }
Vinnie Okada's avatar
Vinnie Okada committed
188
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
189
end