diff options
author | Yorick Peterse <yorickpeterse@gmail.com> | 2019-01-11 18:29:01 +0100 |
---|---|---|
committer | Yorick Peterse <yorickpeterse@gmail.com> | 2019-01-16 14:25:14 +0100 |
commit | 52eeb56bf033e0695acba6c236ed6a9a40bc8a4d (patch) | |
tree | 0b144c95b893193457a5e40e899d1f311e48810d /spec/services | |
parent | 3e9c9f97273efab6b623966597242811f8896024 (diff) | |
download | gitlab-ce-52eeb56bf033e0695acba6c236ed6a9a40bc8a4d.tar.gz |
Refactor code for protecting default branches
This refactors some of the logic used for protecting default branches,
in particular Project#after_create_default_branch. The logic for this
method is moved into a separate service class. Ideally we'd get rid of
Project#after_create_default_branch entirely, but unfortunately
Project#after_import depends on it. This means it has to stick around
until we also refactor Project#after_import.
For branch protection levels we introduce
Gitlab::Access::BranchProtection, which provides a small wrapper around
Integer based branch protection levels. Using this class removes the
need for having to constantly refer to Gitlab::Access::PROTECTION_*
constants.
Diffstat (limited to 'spec/services')
-rw-r--r-- | spec/services/projects/protect_default_branch_service_spec.rb | 242 |
1 files changed, 242 insertions, 0 deletions
diff --git a/spec/services/projects/protect_default_branch_service_spec.rb b/spec/services/projects/protect_default_branch_service_spec.rb new file mode 100644 index 00000000000..c145b2c06c6 --- /dev/null +++ b/spec/services/projects/protect_default_branch_service_spec.rb @@ -0,0 +1,242 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::ProtectDefaultBranchService do + let(:service) { described_class.new(project) } + let(:project) { instance_spy(Project) } + + describe '#execute' do + before do + allow(service) + .to receive(:protect_default_branch) + end + + context 'without a default branch' do + it 'does nothing' do + allow(service) + .to receive(:default_branch) + .and_return(nil) + + service.execute + + expect(service) + .not_to have_received(:protect_default_branch) + end + end + + context 'with a default branch' do + it 'protects the default branch' do + allow(service) + .to receive(:default_branch) + .and_return('master') + + service.execute + + expect(service) + .to have_received(:protect_default_branch) + end + end + end + + describe '#protect_default_branch' do + before do + allow(service) + .to receive(:default_branch) + .and_return('master') + + allow(project) + .to receive(:change_head) + .with('master') + + allow(service) + .to receive(:create_protected_branch) + end + + context 'when branch protection is needed' do + before do + allow(service) + .to receive(:protect_branch?) + .and_return(true) + + allow(service) + .to receive(:create_protected_branch) + end + + it 'changes the HEAD of the project' do + service.protect_default_branch + + expect(project) + .to have_received(:change_head) + end + + it 'protects the default branch' do + service.protect_default_branch + + expect(service) + .to have_received(:create_protected_branch) + end + end + + context 'when branch protection is not needed' do + before do + allow(service) + .to receive(:protect_branch?) + .and_return(false) + end + + it 'changes the HEAD of the project' do + service.protect_default_branch + + expect(project) + .to have_received(:change_head) + end + + it 'does not protect the default branch' do + service.protect_default_branch + + expect(service) + .not_to have_received(:create_protected_branch) + end + end + end + + describe '#create_protected_branch' do + it 'creates the protected branch' do + creator = instance_spy(User) + create_service = instance_spy(ProtectedBranches::CreateService) + access_level = Gitlab::Access::DEVELOPER + params = { + name: 'master', + push_access_levels_attributes: [{ access_level: access_level }], + merge_access_levels_attributes: [{ access_level: access_level }] + } + + allow(project) + .to receive(:creator) + .and_return(creator) + + allow(ProtectedBranches::CreateService) + .to receive(:new) + .with(project, creator, params) + .and_return(create_service) + + allow(service) + .to receive(:push_access_level) + .and_return(access_level) + + allow(service) + .to receive(:merge_access_level) + .and_return(access_level) + + allow(service) + .to receive(:default_branch) + .and_return('master') + + allow(create_service) + .to receive(:execute) + .with(skip_authorization: true) + + service.create_protected_branch + + expect(create_service) + .to have_received(:execute) + end + end + + describe '#protect_branch?' do + context 'when default branch protection is disabled' do + it 'returns false' do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_NONE) + + expect(service.protect_branch?).to eq(false) + end + end + + context 'when default branch protection is enabled' do + before do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE) + + allow(service) + .to receive(:default_branch) + .and_return('master') + end + + it 'returns false if the branch is already protected' do + allow(ProtectedBranch) + .to receive(:protected?) + .with(project, 'master') + .and_return(true) + + expect(service.protect_branch?).to eq(false) + end + + it 'returns true if the branch is not yet protected' do + allow(ProtectedBranch) + .to receive(:protected?) + .with(project, 'master') + .and_return(false) + + expect(service.protect_branch?).to eq(true) + end + end + end + + describe '#default_branch' do + it 'returns the default branch of the project' do + allow(project) + .to receive(:default_branch) + .and_return('master') + + expect(service.default_branch).to eq('master') + end + end + + describe '#push_access_level' do + context 'when developers can push' do + it 'returns the DEVELOPER access level' do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_DEV_CAN_PUSH) + + expect(service.push_access_level).to eq(Gitlab::Access::DEVELOPER) + end + end + + context 'when developers can not push' do + it 'returns the MAINTAINER access level' do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE) + + expect(service.push_access_level).to eq(Gitlab::Access::MAINTAINER) + end + end + end + + describe '#merge_access_level' do + context 'when developers can merge' do + it 'returns the DEVELOPER access level' do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_DEV_CAN_MERGE) + + expect(service.merge_access_level).to eq(Gitlab::Access::DEVELOPER) + end + end + + context 'when developers can not merge' do + it 'returns the MAINTAINER access level' do + allow(Gitlab::CurrentSettings) + .to receive(:default_branch_protection) + .and_return(Gitlab::Access::PROTECTION_DEV_CAN_PUSH) + + expect(service.merge_access_level).to eq(Gitlab::Access::MAINTAINER) + end + end + end +end |