debian-mirror-gitlab/spec/services/branches/create_service_spec.rb
2022-08-27 11:52:29 +05:30

219 lines
6.9 KiB
Ruby

# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Branches::CreateService, :use_clean_rails_redis_caching do
subject(:service) { described_class.new(project, user) }
let_it_be(:project) { create(:project_empty_repo) }
let_it_be(:user) { create(:user) }
describe '#bulk_create' do
subject { service.bulk_create(branches) }
let_it_be(:project) { create(:project, :custom_repo, files: { 'foo/a.txt' => 'foo' }) }
let(:branches) { { 'branch' => 'master', 'another_branch' => 'master' } }
it 'creates two branches' do
expect(subject[:status]).to eq(:success)
expect(subject[:branches].map(&:name)).to match_array(%w[branch another_branch])
expect(project.repository.branch_exists?('branch')).to be_truthy
expect(project.repository.branch_exists?('another_branch')).to be_truthy
end
context 'when branches are empty' do
let(:branches) { {} }
it 'is successful' do
expect(subject[:status]).to eq(:success)
expect(subject[:branches]).to eq([])
end
end
context 'when incorrect reference is provided' do
let(:branches) { { 'new-feature' => 'unknown' } }
before do
allow(project.repository).to receive(:add_branch).and_return(false)
end
it 'returns an error with a reference name' do
err_msg = 'Failed to create branch \'new-feature\': invalid reference name \'unknown\''
expect(subject[:status]).to eq(:error)
expect(subject[:message]).to match_array([err_msg])
end
end
context 'when branch already exists' do
let(:branches) { { 'master' => 'master' } }
it 'returns an error' do
expect(subject[:status]).to eq(:error)
expect(subject[:message]).to match_array(['Branch already exists'])
end
end
context 'when an ambiguous branch name is provided' do
let(:branches) { { 'ambiguous/test' => 'master', 'ambiguous' => 'master' } }
it 'returns an error that branch could not be created' do
err_msg = 'Failed to create branch \'ambiguous\': 13:reference is ambiguous.'
expect(subject[:status]).to eq(:error)
expect(subject[:message]).to match_array([err_msg])
end
end
context 'when PreReceiveError exception' do
let(:branches) { { 'error' => 'master' } }
it 'logs and returns an error if there is a PreReceiveError exception' do
error_message = 'pre receive error'
raw_message = "GitLab: #{error_message}"
pre_receive_error = Gitlab::Git::PreReceiveError.new(raw_message)
allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
pre_receive_error,
pre_receive_message: raw_message,
branch_name: 'error',
ref: 'master'
)
expect(subject[:status]).to eq(:error)
expect(subject[:message]).to match_array([error_message])
end
end
context 'when multiple errors occur' do
let(:branches) { { 'master' => 'master', '' => 'master', 'failed_branch' => 'master' } }
it 'returns all errors' do
allow(project.repository).to receive(:add_branch).with(
user,
'failed_branch',
'master',
expire_cache: false
).and_return(false)
expect(subject[:status]).to eq(:error)
expect(subject[:message]).to match_array(
[
'Branch already exists',
'Branch name is invalid',
"Failed to create branch 'failed_branch': invalid reference name 'master'"
]
)
end
end
context 'without N+1 for Redis cache' do
let(:branches) { { 'branch1' => 'master', 'branch2' => 'master', 'branch3' => 'master' } }
it 'does not trigger Redis recreation' do
project.repository.expire_branches_cache
control = RedisCommands::Recorder.new(pattern: ':branch_names:') { subject }
expect(control.by_command(:sadd).count).to eq(1)
end
end
context 'without N+1 branch cache expiration' do
let(:branches) { { 'branch_1' => 'master', 'branch_2' => 'master', 'branch_3' => 'master' } }
it 'triggers branch cache expiration only once' do
expect(project.repository).to receive(:expire_branches_cache).once
subject
end
context 'when branches were not added' do
let(:branches) { { 'master' => 'master' } }
it 'does not trigger branch expiration' do
expect(project.repository).not_to receive(:expire_branches_cache)
subject
end
end
end
end
describe '#execute' do
context 'when repository is empty' do
it 'creates master branch' do
result = service.execute('my-feature', 'master')
expect(result[:status]).to eq(:success)
expect(result[:branch].name).to eq('my-feature')
expect(project.repository.branch_exists?('master')).to be_truthy
end
it 'creates another-feature branch' do
service.execute('another-feature', 'master')
expect(project.repository.branch_exists?('another-feature')).to be_truthy
end
end
context 'when branch already exists' do
it 'returns an error' do
result = service.execute('master', 'master')
expect(result[:status]).to eq(:error)
expect(result[:message]).to eq('Branch already exists')
end
end
context 'when incorrect reference is provided' do
before do
allow(project.repository).to receive(:add_branch).and_return(false)
end
it 'returns an error with a reference name' do
err_msg = 'Failed to create branch \'new-feature\': invalid reference name \'unknown\''
result = service.execute('new-feature', 'unknown')
expect(result[:status]).to eq(:error)
expect(result[:message]).to eq(err_msg)
end
end
context 'when an ambiguous branch name is provided' do
it 'returns an error that branch could not be created' do
err_msg = 'Failed to create branch \'feature\': 13:reference is ambiguous.'
service.execute('feature/widget', 'master')
result = service.execute('feature', 'master')
expect(result[:status]).to eq(:error)
expect(result[:message]).to eq(err_msg)
end
end
it 'logs and returns an error if there is a PreReceiveError exception' do
error_message = 'pre receive error'
raw_message = "GitLab: #{error_message}"
pre_receive_error = Gitlab::Git::PreReceiveError.new(raw_message)
allow(project.repository).to receive(:add_branch).and_raise(pre_receive_error)
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(
pre_receive_error,
pre_receive_message: raw_message,
branch_name: 'new-feature',
ref: 'unknown'
)
result = service.execute('new-feature', 'unknown')
expect(result[:status]).to eq(:error)
expect(result[:message]).to eq(error_message)
end
end
end