merge_request_spec.rb 5.77 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
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
22 23
#

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

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

29 30 31 32 33 34 35
  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

36 37 38 39 40 41 42 43 44 45 46
  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
47 48
    it { is_expected.to validate_presence_of(:target_branch) }
    it { is_expected.to validate_presence_of(:source_branch) }
49 50
  end

51
  describe 'respond to' do
52 53 54
    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?) }
55
  end
Andrey Kumanyaev's avatar
Andrey Kumanyaev committed
56

57 58 59 60 61 62 63 64 65
  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
66
  end
67 68

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

    before do
72
      allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] }
73 74
      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)
75 76 77
    end

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

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

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

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

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

106 107 108
  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
109 110 111
    let(:commit0) { double('commit0', closes_issues: [issue0]) }
    let(:commit1) { double('commit1', closes_issues: [issue0]) }
    let(:commit2) { double('commit2', closes_issues: [issue1]) }
112 113

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

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

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

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

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

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

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

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 166
  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

167
  it_behaves_like 'an editable mentionable' do
168 169
    subject { create(:merge_request, source_project: project, target_project: project) }

170 171 172
    let(:backref_text) { "merge request !#{subject.iid}" }
    let(:set_mentionable_text) { ->(txt){ subject.title = txt } }
  end
Vinnie Okada's avatar
Vinnie Okada committed
173 174

  it_behaves_like 'a Taskable' do
175
    subject { create :merge_request, :simple }
Vinnie Okada's avatar
Vinnie Okada committed
176
  end
Dmitriy Zaporozhets's avatar
Dmitriy Zaporozhets committed
177
end