2012-10-09 04:14:17 -04:00
|
|
|
# == Schema Information
|
|
|
|
#
|
|
|
|
# Table name: merge_requests
|
|
|
|
#
|
2013-08-21 05:34:02 -04:00
|
|
|
# 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)
|
2014-04-09 08:05:03 -04:00
|
|
|
# created_at :datetime
|
|
|
|
# updated_at :datetime
|
2013-08-21 05:34:02 -04:00
|
|
|
# milestone_id :integer
|
|
|
|
# state :string(255)
|
|
|
|
# merge_status :string(255)
|
|
|
|
# target_project_id :integer not null
|
|
|
|
# iid :integer
|
2013-10-01 08:15:28 -04:00
|
|
|
# description :text
|
2014-08-25 05:25:02 -04:00
|
|
|
# position :integer default(0)
|
2015-01-22 12:40:03 -05:00
|
|
|
# locked_at :datetime
|
2015-09-06 10:48:48 -04:00
|
|
|
# updated_by_id :integer
|
2015-11-13 13:22:46 -05:00
|
|
|
# merge_error :string(255)
|
2012-10-09 04:14:17 -04:00
|
|
|
#
|
|
|
|
|
2011-11-28 02:39:43 -05:00
|
|
|
require 'spec_helper'
|
|
|
|
|
|
|
|
describe MergeRequest do
|
2015-05-02 23:11:21 -04:00
|
|
|
subject { create(:merge_request) }
|
|
|
|
|
2015-05-02 23:14:31 -04:00
|
|
|
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
|
|
|
|
|
2015-05-02 23:11:21 -04:00
|
|
|
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
|
2015-02-12 13:17:35 -05:00
|
|
|
it { is_expected.to validate_presence_of(:target_branch) }
|
|
|
|
it { is_expected.to validate_presence_of(:source_branch) }
|
2011-11-28 16:24:08 -05:00
|
|
|
end
|
|
|
|
|
2015-05-02 23:14:31 -04:00
|
|
|
describe 'respond to' do
|
2015-02-12 13:17:35 -05:00
|
|
|
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?) }
|
2013-02-20 08:15:01 -05:00
|
|
|
end
|
2013-03-20 17:46:30 -04:00
|
|
|
|
2015-05-02 23:11:21 -04:00
|
|
|
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
|
2012-08-09 13:45:12 -04:00
|
|
|
end
|
2012-10-04 18:25:40 -04:00
|
|
|
|
|
|
|
describe "#mr_and_commit_notes" do
|
2012-11-05 22:31:55 -05:00
|
|
|
let!(:merge_request) { create(:merge_request) }
|
2012-10-04 18:25:40 -04:00
|
|
|
|
|
|
|
before do
|
2015-02-12 13:17:35 -05:00
|
|
|
allow(merge_request).to receive(:commits) { [merge_request.source_project.repository.commit] }
|
2013-10-07 12:42:59 -04:00
|
|
|
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)
|
2012-10-04 18:25:40 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it "should include notes for commits" do
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(merge_request.commits).not_to be_empty
|
|
|
|
expect(merge_request.mr_and_commit_notes.count).to eq(2)
|
2012-10-04 18:25:40 -04:00
|
|
|
end
|
2015-10-22 12:38:00 -04:00
|
|
|
|
|
|
|
it "should include notes for commits from target project as well" do
|
|
|
|
create(:note, commit_id: merge_request.commits.first.id, noteable_type: 'Commit', project: merge_request.target_project)
|
|
|
|
expect(merge_request.commits).not_to be_empty
|
|
|
|
expect(merge_request.mr_and_commit_notes.count).to eq(3)
|
|
|
|
end
|
2012-10-04 18:25:40 -04:00
|
|
|
end
|
2012-10-09 18:25:29 -04:00
|
|
|
|
|
|
|
describe '#is_being_reassigned?' do
|
|
|
|
it 'returns true if the merge_request assignee has changed' do
|
2012-11-05 22:31:55 -05:00
|
|
|
subject.assignee = create(:user)
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.is_being_reassigned?).to be_truthy
|
2012-10-09 18:25:29 -04:00
|
|
|
end
|
|
|
|
it 'returns false if the merge request assignee has not changed' do
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.is_being_reassigned?).to be_falsey
|
2012-10-09 18:25:29 -04:00
|
|
|
end
|
|
|
|
end
|
2013-04-25 10:15:33 -04:00
|
|
|
|
|
|
|
describe '#for_fork?' do
|
|
|
|
it 'returns true if the merge request is for a fork' do
|
2014-01-23 06:24:25 -05:00
|
|
|
subject.source_project = create(:project, namespace: create(:group))
|
|
|
|
subject.target_project = create(:project, namespace: create(:group))
|
2013-04-25 10:15:33 -04:00
|
|
|
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.for_fork?).to be_truthy
|
2013-04-25 10:15:33 -04:00
|
|
|
end
|
2014-01-23 06:24:25 -05:00
|
|
|
|
2013-04-25 10:15:33 -04:00
|
|
|
it 'returns false if is not for a fork' do
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.for_fork?).to be_falsey
|
2013-04-25 10:15:33 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2013-05-30 19:16:49 -04:00
|
|
|
describe 'detection of issues to be closed' do
|
|
|
|
let(:issue0) { create :issue, project: subject.project }
|
|
|
|
let(:issue1) { create :issue, project: subject.project }
|
2013-12-14 08:43:48 -05:00
|
|
|
let(:commit0) { double('commit0', closes_issues: [issue0]) }
|
|
|
|
let(:commit1) { double('commit1', closes_issues: [issue0]) }
|
|
|
|
let(:commit2) { double('commit2', closes_issues: [issue1]) }
|
2013-05-30 19:16:49 -04:00
|
|
|
|
|
|
|
before do
|
2015-05-21 17:49:06 -04:00
|
|
|
allow(subject).to receive(:commits).and_return([commit0, commit1, commit2])
|
2013-05-30 19:16:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'accesses the set of issues that will be closed on acceptance' do
|
2015-05-21 17:49:06 -04:00
|
|
|
allow(subject.project).to receive(:default_branch).
|
|
|
|
and_return(subject.target_branch)
|
2013-05-30 19:16:49 -04:00
|
|
|
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.closes_issues).to eq([issue0, issue1].sort_by(&:id))
|
2013-05-30 19:16:49 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
it 'only lists issues as to be closed if it targets the default branch' do
|
2015-05-21 17:49:06 -04:00
|
|
|
allow(subject.project).to receive(:default_branch).and_return('master')
|
2013-05-30 19:16:49 -04:00
|
|
|
subject.target_branch = 'something-else'
|
|
|
|
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.closes_issues).to be_empty
|
2013-05-30 19:16:49 -04:00
|
|
|
end
|
2014-06-13 10:19:08 -04:00
|
|
|
|
|
|
|
it 'detects issues mentioned in the description' do
|
|
|
|
issue2 = create(:issue, project: subject.project)
|
2015-05-21 16:35:15 -04:00
|
|
|
subject.description = "Closes #{issue2.to_reference}"
|
2015-05-21 17:49:06 -04:00
|
|
|
allow(subject.project).to receive(:default_branch).
|
|
|
|
and_return(subject.target_branch)
|
2014-06-13 10:19:08 -04:00
|
|
|
|
2015-02-12 13:17:35 -05:00
|
|
|
expect(subject.closes_issues).to include(issue2)
|
2014-06-13 10:19:08 -04:00
|
|
|
end
|
2013-05-30 19:16:49 -04:00
|
|
|
end
|
|
|
|
|
2015-04-30 09:43:32 -04:00
|
|
|
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
|
|
|
|
|
2015-09-25 16:07:08 -04:00
|
|
|
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
|
|
|
|
|
2013-05-30 19:16:49 -04:00
|
|
|
it_behaves_like 'an editable mentionable' do
|
2015-08-11 08:33:31 -04:00
|
|
|
subject { create(:merge_request) }
|
2015-04-16 16:25:25 -04:00
|
|
|
|
2015-06-17 20:40:26 -04:00
|
|
|
let(:backref_text) { "merge request #{subject.to_reference}" }
|
|
|
|
let(:set_mentionable_text) { ->(txt){ subject.description = txt } }
|
2013-05-30 19:16:49 -04:00
|
|
|
end
|
2014-10-05 22:17:28 -04:00
|
|
|
|
|
|
|
it_behaves_like 'a Taskable' do
|
2015-04-16 16:25:25 -04:00
|
|
|
subject { create :merge_request, :simple }
|
2014-10-05 22:17:28 -04:00
|
|
|
end
|
2015-11-20 17:43:10 -05:00
|
|
|
|
|
|
|
describe '#ci_commit' do
|
|
|
|
describe 'when the source project exists' do
|
|
|
|
it 'returns the latest commit' do
|
|
|
|
commit = double(:commit, id: '123abc')
|
|
|
|
ci_commit = double(:ci_commit)
|
|
|
|
|
|
|
|
allow(subject).to receive(:last_commit).and_return(commit)
|
|
|
|
|
|
|
|
expect(subject.source_project).to receive(:ci_commit).
|
|
|
|
with('123abc').
|
|
|
|
and_return(ci_commit)
|
|
|
|
|
|
|
|
expect(subject.ci_commit).to eq(ci_commit)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
describe 'when the source project does not exist' do
|
|
|
|
it 'returns nil' do
|
|
|
|
allow(subject).to receive(:source_project).and_return(nil)
|
|
|
|
|
|
|
|
expect(subject.ci_commit).to be_nil
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2011-11-28 02:39:43 -05:00
|
|
|
end
|