debian-mirror-gitlab/spec/lib/gitlab/github_import/importer/pull_request_importer_spec.rb
2021-02-22 17:27:13 +05:30

331 lines
10 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::GithubImport::Importer::PullRequestImporter, :clean_gitlab_redis_cache do
let(:project) { create(:project, :repository) }
let(:client) { double(:client) }
let(:user) { create(:user) }
let(:created_at) { Time.new(2017, 1, 1, 12, 00) }
let(:updated_at) { Time.new(2017, 1, 1, 12, 15) }
let(:merged_at) { Time.new(2017, 1, 1, 12, 17) }
let(:source_commit) { project.repository.commit('feature') }
let(:target_commit) { project.repository.commit('master') }
let(:milestone) { create(:milestone, project: project) }
let(:state) { :closed }
let(:pull_request) do
alice = Gitlab::GithubImport::Representation::User.new(id: 4, login: 'alice')
Gitlab::GithubImport::Representation::PullRequest.new(
iid: 42,
title: 'My Pull Request',
description: 'This is my pull request',
source_branch: 'feature',
source_branch_sha: source_commit.id,
target_branch: 'master',
target_branch_sha: target_commit.id,
source_repository_id: 400,
target_repository_id: 200,
source_repository_owner: 'alice',
state: state,
milestone_number: milestone.iid,
author: alice,
assignee: alice,
created_at: created_at,
updated_at: updated_at,
merged_at: state == :closed && merged_at
)
end
let(:importer) { described_class.new(pull_request, project, client) }
describe '#execute' do
it 'imports the pull request' do
mr = double(:merge_request, id: 10, merged?: false)
expect(importer)
.to receive(:create_merge_request)
.and_return([mr, false])
expect(importer)
.to receive(:set_merge_request_assignees)
.with(mr)
expect(importer)
.to receive(:insert_git_data)
.with(mr, false)
expect_any_instance_of(Gitlab::GithubImport::IssuableFinder)
.to receive(:cache_database_id)
.with(mr.id)
importer.execute
end
end
describe '#create_merge_request' do
before do
allow(importer.milestone_finder)
.to receive(:id_for)
.with(pull_request)
.and_return(milestone.id)
end
context 'when the author could be found' do
before do
allow(importer.user_finder)
.to receive(:author_id_for)
.with(pull_request)
.and_return([user.id, true])
end
it 'imports the pull request with the pull request author as the merge request author' do
expect(importer)
.to receive(:insert_and_return_id)
.with(
{
iid: 42,
title: 'My Pull Request',
description: 'This is my pull request',
source_project_id: project.id,
target_project_id: project.id,
source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state_id: 3,
milestone_id: milestone.id,
author_id: user.id,
created_at: created_at,
updated_at: updated_at
},
project.merge_requests
)
.and_call_original
importer.create_merge_request
end
it 'returns the created merge request' do
mr, exists = importer.create_merge_request
expect(mr).to be_instance_of(MergeRequest)
expect(exists).to eq(false)
end
context 'when the source and target branch are identical' do
before do
allow(pull_request).to receive_messages(
source_repository_id: pull_request.target_repository_id,
source_branch: 'master'
)
end
it 'uses a generated source branch name for the merge request' do
expect(importer)
.to receive(:insert_and_return_id)
.with(
{
iid: 42,
title: 'My Pull Request',
description: 'This is my pull request',
source_project_id: project.id,
target_project_id: project.id,
source_branch: 'master-42',
target_branch: 'master',
state_id: 3,
milestone_id: milestone.id,
author_id: user.id,
created_at: created_at,
updated_at: updated_at
},
project.merge_requests
)
.and_call_original
importer.create_merge_request
end
end
context 'when the import fails due to a foreign key error' do
it 'does not raise any errors' do
expect(importer)
.to receive(:insert_and_return_id)
.and_raise(ActiveRecord::InvalidForeignKey, 'invalid foreign key')
expect { importer.create_merge_request }.not_to raise_error
end
end
context 'when the merge request already exists' do
it 'returns the existing merge request' do
mr1, exists1 = importer.create_merge_request
mr2, exists2 = importer.create_merge_request
expect(mr2).to eq(mr1)
expect(exists1).to eq(false)
expect(exists2).to eq(true)
end
end
end
context 'when the author could not be found' do
before do
allow(importer.user_finder)
.to receive(:author_id_for)
.with(pull_request)
.and_return([project.creator_id, false])
end
it 'imports the pull request with the project creator as the merge request author' do
expect(importer)
.to receive(:insert_and_return_id)
.with(
{
iid: 42,
title: 'My Pull Request',
description: "*Created by: alice*\n\nThis is my pull request",
source_project_id: project.id,
target_project_id: project.id,
source_branch: 'github/fork/alice/feature',
target_branch: 'master',
state_id: 3,
milestone_id: milestone.id,
author_id: project.creator_id,
created_at: created_at,
updated_at: updated_at
},
project.merge_requests
)
.and_call_original
importer.create_merge_request
end
end
end
describe '#set_merge_request_assignees' do
let_it_be(:merge_request) { create(:merge_request) }
before do
allow(importer.user_finder)
.to receive(:assignee_id_for)
.with(pull_request)
.and_return(user_id)
importer.set_merge_request_assignees(merge_request)
end
context 'when pull request has an assignee' do
let(:user_id) { user.id }
it 'sets merge request assignees' do
expect(merge_request.assignee_ids).to eq [user.id]
end
end
context 'when pull request does not have any assignees' do
let(:user_id) { nil }
it 'does not set merge request assignees' do
expect(merge_request.assignee_ids).to eq []
end
end
end
describe '#insert_git_data' do
before do
allow(importer.milestone_finder)
.to receive(:id_for)
.with(pull_request)
.and_return(milestone.id)
allow(importer.user_finder)
.to receive(:author_id_for)
.with(pull_request)
.and_return([user.id, true])
end
it 'does not create the source branch if merge request is merged' do
mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end
context 'when merge request is open' do
let(:state) { :opened }
it 'creates the source branch' do
# Ensure the project creator is creating the branches because the
# merge request author may not have access to push to this
# repository. The project owner may also be a group.
allow(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original
mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end
it 'is able to retry on pre-receive errors' do
expect(importer).to receive(:insert_or_replace_git_data).twice.and_call_original
expect(project.repository).to receive(:add_branch).and_raise('exception')
expect { insert_git_data }.to raise_error('exception')
expect(project.repository).to receive(:add_branch).with(project.creator, anything, anything).and_call_original
mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_truthy
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
expect(mr.merge_request_diffs).to be_one
end
it 'ignores Git command errors when creating a branch' do
expect(project.repository).to receive(:add_branch).and_raise(Gitlab::Git::CommandError)
expect(Gitlab::ErrorTracking).to receive(:track_exception).and_call_original
mr = insert_git_data
expect(project.repository.branch_exists?(mr.source_branch)).to be_falsey
expect(project.repository.branch_exists?(mr.target_branch)).to be_truthy
end
end
it 'creates a merge request diff and sets it as the latest' do
mr = insert_git_data
expect(mr.merge_request_diffs.exists?).to eq(true)
expect(mr.reload.latest_merge_request_diff_id).to eq(mr.merge_request_diffs.first.id)
end
it 'creates the merge request diff commits' do
mr = insert_git_data
diff = mr.merge_request_diffs.reload.first
expect(diff.merge_request_diff_commits.exists?).to eq(true)
end
context 'when the merge request exists' do
it 'creates the merge request diffs if they do not yet exist' do
mr, _ = importer.create_merge_request
mr.merge_request_diffs.delete_all
importer.insert_git_data(mr, true)
expect(mr.merge_request_diffs.exists?).to eq(true)
end
end
def insert_git_data
mr, exists = importer.create_merge_request
importer.insert_git_data(mr, exists)
mr
end
end
end