Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-02-18 12:45:46 +0300
commita7b3560714b4d9cc4ab32dffcd1f74a284b93580 (patch)
tree7452bd5c3545c2fa67a28aa013835fb4fa071baf /spec/services/projects
parentee9173579ae56a3dbfe5afe9f9410c65bb327ca7 (diff)
Add latest changes from gitlab-org/gitlab@14-8-stable-eev14.8.0-rc42
Diffstat (limited to 'spec/services/projects')
-rw-r--r--spec/services/projects/autocomplete_service_spec.rb26
-rw-r--r--spec/services/projects/container_repository/delete_tags_service_spec.rb18
-rw-r--r--spec/services/projects/create_service_spec.rb98
-rw-r--r--spec/services/projects/destroy_service_spec.rb45
-rw-r--r--spec/services/projects/import_export/export_service_spec.rb15
-rw-r--r--spec/services/projects/import_service_spec.rb2
-rw-r--r--spec/services/projects/overwrite_project_service_spec.rb69
-rw-r--r--spec/services/projects/readme_renderer_service_spec.rb75
-rw-r--r--spec/services/projects/transfer_service_spec.rb31
9 files changed, 316 insertions, 63 deletions
diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb
index ef7741c2d0f..ed043bacf31 100644
--- a/spec/services/projects/autocomplete_service_spec.rb
+++ b/spec/services/projects/autocomplete_service_spec.rb
@@ -148,6 +148,32 @@ RSpec.describe Projects::AutocompleteService do
end
end
+ describe '#contacts' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group) { create(:group, :crm_enabled) }
+ let_it_be(:project) { create(:project, group: group) }
+ let_it_be(:contact_1) { create(:contact, group: group) }
+ let_it_be(:contact_2) { create(:contact, group: group) }
+
+ subject { described_class.new(project, user).contacts.as_json }
+
+ before do
+ stub_feature_flags(customer_relations: true)
+ group.add_developer(user)
+ end
+
+ it 'returns contact data correctly' do
+ expected_contacts = [
+ { 'id' => contact_1.id, 'email' => contact_1.email,
+ 'first_name' => contact_1.first_name, 'last_name' => contact_1.last_name },
+ { 'id' => contact_2.id, 'email' => contact_2.email,
+ 'first_name' => contact_2.first_name, 'last_name' => contact_2.last_name }
+ ]
+
+ expect(subject).to match_array(expected_contacts)
+ end
+ end
+
describe '#labels_as_hash' do
def expect_labels_to_equal(labels, expected_labels)
expect(labels.size).to eq(expected_labels.size)
diff --git a/spec/services/projects/container_repository/delete_tags_service_spec.rb b/spec/services/projects/container_repository/delete_tags_service_spec.rb
index 94037d6de1e..246ca301cfa 100644
--- a/spec/services/projects/container_repository/delete_tags_service_spec.rb
+++ b/spec/services/projects/container_repository/delete_tags_service_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
]
end
- RSpec.shared_examples 'logging a success response' do
+ shared_examples 'logging a success response' do
it 'logs an info message' do
expect(service).to receive(:log_info).with(
service_class: 'Projects::ContainerRepository::DeleteTagsService',
@@ -28,7 +28,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}|
+ shared_examples 'logging an error response' do |message: 'could not delete tags', extra_log: {}|
it 'logs an error message' do
log_data = {
service_class: 'Projects::ContainerRepository::DeleteTagsService',
@@ -45,7 +45,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'calling the correct delete tags service' do |expected_service_class|
+ shared_examples 'calling the correct delete tags service' do |expected_service_class|
let(:service_response) { { status: :success, deleted: tags } }
let(:excluded_service_class) { available_service_classes.excluding(expected_service_class).first }
@@ -69,7 +69,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'handling invalid params' do
+ shared_examples 'handling invalid params' do
context 'with invalid params' do
before do
expect(::Projects::ContainerRepository::Gitlab::DeleteTagsService).not_to receive(:new)
@@ -91,7 +91,7 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
end
end
- RSpec.shared_examples 'supporting fast delete' do
+ shared_examples 'supporting fast delete' do
context 'when the registry supports fast delete' do
before do
allow(repository.client).to receive(:supports_tag_delete?).and_return(true)
@@ -155,6 +155,14 @@ RSpec.describe Projects::ContainerRepository::DeleteTagsService do
it_behaves_like 'handling invalid params'
end
+
+ context 'when the repository is importing' do
+ before do
+ repository.update_columns(migration_state: 'importing', migration_import_started_at: Time.zone.now)
+ end
+
+ it { is_expected.to include(status: :error, message: 'repository importing') }
+ end
end
context 'without user' do
diff --git a/spec/services/projects/create_service_spec.rb b/spec/services/projects/create_service_spec.rb
index d5fbf96ce74..10f694827e1 100644
--- a/spec/services/projects/create_service_spec.rb
+++ b/spec/services/projects/create_service_spec.rb
@@ -7,9 +7,10 @@ RSpec.describe Projects::CreateService, '#execute' do
include GitHelpers
let(:user) { create :user }
+ let(:project_name) { 'GitLab' }
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: user.namespace.id
}
end
@@ -144,6 +145,12 @@ RSpec.describe Projects::CreateService, '#execute' do
subject { create_project(user, opts) }
end
+
+ it 'logs creation' do
+ expect(Gitlab::AppLogger).to receive(:info).with(/#{user.name} created a new project/)
+
+ create_project(user, opts)
+ end
end
context "admin creates project with other user's namespace_id" do
@@ -183,9 +190,13 @@ RSpec.describe Projects::CreateService, '#execute' do
user.refresh_authorized_projects # Ensure cache is warm
end
- it do
- project = create_project(user, opts.merge!(namespace_id: group.id))
+ subject(:project) { create_project(user, opts.merge!(namespace_id: group.id)) }
+ shared_examples 'has sync-ed traversal_ids' do
+ specify { expect(project.reload.project_namespace.traversal_ids).to eq([project.namespace.traversal_ids, project.project_namespace.id].flatten.compact) }
+ end
+
+ it 'creates the project' do
expect(project).to be_valid
expect(project.owner).to eq(group)
expect(project.namespace).to eq(group)
@@ -193,6 +204,18 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(user.authorized_projects).to include(project)
expect(project.project_namespace).to be_in_sync_with_project(project)
end
+
+ context 'with before_commit callback' do
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
+
+ context 'with after_create callback' do
+ before do
+ stub_feature_flags(sync_traversal_ids_before_commit: false)
+ end
+
+ it_behaves_like 'has sync-ed traversal_ids'
+ end
end
context 'group sharing', :sidekiq_inline do
@@ -202,7 +225,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: shared_group.id
}
end
@@ -237,7 +260,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:share_max_access_level) { Gitlab::Access::MAINTAINER }
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: subgroup_for_projects.id
}
end
@@ -583,58 +606,55 @@ RSpec.describe Projects::CreateService, '#execute' do
opts[:initialize_with_readme] = '1'
end
- shared_examples 'creates README.md' do
+ shared_examples 'a repo with a README.md' do
it { expect(project.repository.commit_count).to be(1) }
it { expect(project.repository.readme.name).to eql('README.md') }
- it { expect(project.repository.readme.data).to include('# GitLab') }
+ it { expect(project.repository.readme.data).to include(expected_content) }
end
- it_behaves_like 'creates README.md'
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) do
+ <<~MARKDOWN
+ cd existing_repo
+ git remote add origin #{project.http_url_to_repo}
+ git branch -M master
+ git push -uf origin master
+ MARKDOWN
+ end
+ end
- context 'and a default_branch_name is specified' do
+ context 'and a readme_template is specified' do
before do
- allow(Gitlab::CurrentSettings)
- .to receive(:default_branch_name)
- .and_return('example_branch')
+ opts[:readme_template] = "# GitLab\nThis is customized readme."
end
- it_behaves_like 'creates README.md'
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) { "# GitLab\nThis is customized readme." }
+ end
+ end
+
+ context 'and a default_branch_name is specified' do
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:default_branch_name).and_return('example_branch')
+ end
- it 'creates README.md within the specified branch rather than master' do
+ it 'creates the correct branch' do
branches = project.repository.branches
expect(branches.size).to eq(1)
expect(branches.collect(&:name)).to contain_exactly('example_branch')
end
- describe 'advanced readme content', experiment: :new_project_readme_content do
- before do
- stub_experiments(new_project_readme_content: :advanced)
- end
-
- it_behaves_like 'creates README.md'
-
- it 'includes advanced content in the README.md' do
- content = project.repository.readme.data
- expect(content).to include <<~MARKDOWN
+ it_behaves_like 'a repo with a README.md' do
+ let(:expected_content) do
+ <<~MARKDOWN
+ cd existing_repo
git remote add origin #{project.http_url_to_repo}
git branch -M example_branch
git push -uf origin example_branch
MARKDOWN
end
end
-
- context 'and readme_template is specified' do
- before do
- opts[:readme_template] = "# GitLab\nThis is customized template."
- end
-
- it_behaves_like 'creates README.md'
-
- it 'creates README.md with specified template' do
- expect(project.repository.readme.data).to include('This is customized template.')
- end
- end
end
end
@@ -676,7 +696,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: group.id
}
end
@@ -697,7 +717,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: subgroup.id
}
end
@@ -808,7 +828,7 @@ RSpec.describe Projects::CreateService, '#execute' do
let(:opts) do
{
- name: 'GitLab',
+ name: project_name,
namespace_id: group.id
}
end
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 9475f562d71..d60ec8c2958 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -15,20 +15,39 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
before do
stub_container_registry_config(enabled: true)
stub_container_registry_tags(repository: :any, tags: [])
+ allow(Gitlab::EventStore).to receive(:publish)
end
shared_examples 'deleting the project' do
- before do
- # Run sidekiq immediately to check that renamed repository will be removed
+ it 'deletes the project', :sidekiq_inline do
destroy_project(project, user, {})
- end
- it 'deletes the project', :sidekiq_inline do
expect(Project.unscoped.all).not_to include(project)
expect(project.gitlab_shell.repository_exists?(project.repository_storage, path + '.git')).to be_falsey
expect(project.gitlab_shell.repository_exists?(project.repository_storage, remove_path + '.git')).to be_falsey
end
+
+ it 'publishes a ProjectDeleted event with project id and namespace id' do
+ expected_data = { project_id: project.id, namespace_id: project.namespace_id }
+ expect(Gitlab::EventStore)
+ .to receive(:publish)
+ .with(event_type(Projects::ProjectDeletedEvent).containing(expected_data))
+
+ destroy_project(project, user, {})
+ end
+
+ context 'when feature flag publish_project_deleted_event is disabled' do
+ before do
+ stub_feature_flags(publish_project_deleted_event: false)
+ end
+
+ it 'does not publish an event' do
+ expect(Gitlab::EventStore).not_to receive(:publish).with(event_type(Projects::ProjectDeletedEvent))
+
+ destroy_project(project, user, {})
+ end
+ end
end
shared_examples 'deleting the project with pipeline and build' do
@@ -97,6 +116,24 @@ RSpec.describe Projects::DestroyService, :aggregate_failures do
end
end
+ context "deleting a project with merge requests" do
+ let!(:merge_request) { create(:merge_request, source_project: project) }
+
+ before do
+ allow(project).to receive(:destroy!).and_return(true)
+ end
+
+ it "deletes merge request and related records" do
+ merge_request_diffs = merge_request.merge_request_diffs
+ expect(merge_request_diffs.size).to eq(1)
+
+ mrdc_count = MergeRequestDiffCommit.where(merge_request_diff_id: merge_request_diffs.first.id).count
+
+ expect { destroy_project(project, user, {}) }
+ .to change { MergeRequestDiffCommit.count }.by(-mrdc_count)
+ end
+ end
+
it_behaves_like 'deleting the project'
it 'invalidates personal_project_count cache' do
diff --git a/spec/services/projects/import_export/export_service_spec.rb b/spec/services/projects/import_export/export_service_spec.rb
index 6002aaf427a..54abbc04084 100644
--- a/spec/services/projects/import_export/export_service_spec.rb
+++ b/spec/services/projects/import_export/export_service_spec.rb
@@ -93,11 +93,23 @@ RSpec.describe Projects::ImportExport::ExportService do
end
it 'saves the project in the file system' do
- expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared)
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
service.execute
end
+ context 'when the upload fails' do
+ before do
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(false)
+ end
+
+ it 'notifies the user of an error' do
+ expect(service).to receive(:notify_error).and_call_original
+
+ expect { service.execute }.to raise_error(Gitlab::ImportExport::Error)
+ end
+ end
+
it 'calls the after export strategy' do
expect(after_export_strategy).to receive(:execute)
@@ -107,6 +119,7 @@ RSpec.describe Projects::ImportExport::ExportService do
context 'when after export strategy fails' do
before do
allow(after_export_strategy).to receive(:execute).and_return(false)
+ expect(Gitlab::ImportExport::Saver).to receive(:save).with(exportable: project, shared: shared).and_return(true)
end
after do
diff --git a/spec/services/projects/import_service_spec.rb b/spec/services/projects/import_service_spec.rb
index 1d63f72ec38..ccfd119b55b 100644
--- a/spec/services/projects/import_service_spec.rb
+++ b/spec/services/projects/import_service_spec.rb
@@ -298,7 +298,7 @@ RSpec.describe Projects::ImportService do
end
def stub_github_omniauth_provider
- provider = OpenStruct.new(
+ provider = ActiveSupport::InheritableOptions.new(
'name' => 'github',
'app_id' => 'asd123',
'app_secret' => 'asd123',
diff --git a/spec/services/projects/overwrite_project_service_spec.rb b/spec/services/projects/overwrite_project_service_spec.rb
index cc6a863a11d..7038910508f 100644
--- a/spec/services/projects/overwrite_project_service_spec.rb
+++ b/spec/services/projects/overwrite_project_service_spec.rb
@@ -81,16 +81,58 @@ RSpec.describe Projects::OverwriteProjectService do
end
end
- it 'removes the original project' do
- subject.execute(project_from)
+ it 'schedules original project for deletion' do
+ expect_next_instance_of(Projects::DestroyService) do |service|
+ expect(service).to receive(:async_execute)
+ end
- expect { Project.find(project_from.id) }.to raise_error(ActiveRecord::RecordNotFound)
+ subject.execute(project_from)
end
it 'renames the project' do
+ original_path = project_from.full_path
+
subject.execute(project_from)
- expect(project_to.full_path).to eq project_from.full_path
+ expect(project_to.full_path).to eq(original_path)
+ end
+
+ it 'renames source project to temp name' do
+ allow(SecureRandom).to receive(:hex).and_return('test')
+
+ subject.execute(project_from)
+
+ expect(project_from.full_path).to include('-old-test')
+ end
+
+ context 'when project rename fails' do
+ before do
+ expect(subject).to receive(:move_relationships_between).with(project_from, project_to)
+ expect(subject).to receive(:move_relationships_between).with(project_to, project_from)
+ end
+
+ context 'source rename' do
+ it 'moves relations back to source project and raises an exception' do
+ allow(subject).to receive(:rename_project).and_return(status: :error)
+
+ expect { subject.execute(project_from) }.to raise_error(StandardError, 'Source project rename failed during project overwrite')
+ end
+ end
+
+ context 'new project rename' do
+ it 'moves relations back, renames source project back to original name and raises' do
+ name = project_from.name
+ path = project_from.path
+
+ allow(subject).to receive(:rename_project).and_call_original
+ allow(subject).to receive(:rename_project).with(project_to, name, path).and_return(status: :error)
+
+ expect { subject.execute(project_from) }.to raise_error(StandardError, 'New project rename failed during project overwrite')
+
+ expect(project_from.name).to eq(name)
+ expect(project_from.path).to eq(path)
+ end
+ end
end
end
@@ -121,7 +163,7 @@ RSpec.describe Projects::OverwriteProjectService do
end
end
- context 'forks' do
+ context 'forks', :sidekiq_inline do
context 'when moving a root forked project' do
it 'moves the descendant forks' do
expect(project_from.forks.count).to eq 2
@@ -147,6 +189,7 @@ RSpec.describe Projects::OverwriteProjectService do
expect(project_to.fork_network.fork_network_members.map(&:project)).not_to include project_from
end
end
+
context 'when moving a intermediate forked project' do
let(:project_to) { create(:project, namespace: lvl1_forked_project_1.namespace) }
@@ -180,22 +223,26 @@ RSpec.describe Projects::OverwriteProjectService do
end
context 'if an exception is raised' do
+ before do
+ allow(subject).to receive(:rename_project).and_raise(StandardError)
+ end
+
it 'rollbacks changes' do
updated_at = project_from.updated_at
- allow(subject).to receive(:rename_project).and_raise(StandardError)
-
expect { subject.execute(project_from) }.to raise_error(StandardError)
expect(Project.find(project_from.id)).not_to be_nil
expect(project_from.reload.updated_at.change(usec: 0)).to eq updated_at.change(usec: 0)
end
- it 'tries to restore the original project repositories' do
- allow(subject).to receive(:rename_project).and_raise(StandardError)
-
- expect(subject).to receive(:attempt_restore_repositories).with(project_from)
+ it 'removes fork network member' do
+ expect(ForkNetworkMember).to receive(:create!)
+ expect(ForkNetworkMember).to receive(:find_by)
+ expect(subject).to receive(:remove_source_project_from_fork_network).and_call_original
expect { subject.execute(project_from) }.to raise_error(StandardError)
+
+ expect(project_from.fork_network_member).to be_nil
end
end
end
diff --git a/spec/services/projects/readme_renderer_service_spec.rb b/spec/services/projects/readme_renderer_service_spec.rb
new file mode 100644
index 00000000000..14cdcf67640
--- /dev/null
+++ b/spec/services/projects/readme_renderer_service_spec.rb
@@ -0,0 +1,75 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Projects::ReadmeRendererService, '#execute' do
+ using RSpec::Parameterized::TableSyntax
+
+ subject(:service) { described_class.new(project, nil, opts) }
+
+ let_it_be(:project) { create(:project, title: 'My Project', description: '_custom_description_') }
+
+ let(:opts) { {} }
+
+ it 'renders the an ERB readme template' do
+ expect(service.execute).to start_with(<<~MARKDOWN)
+ # My Project
+
+ _custom_description_
+
+ ## Getting started
+
+ To make it easy for you to get started with GitLab, here's a list of recommended next steps.
+
+ Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
+
+ ## Add your files
+
+ - [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
+ - [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
+
+ ```
+ cd existing_repo
+ git remote add origin #{project.http_url_to_repo}
+ git branch -M master
+ git push -uf origin master
+ ```
+ MARKDOWN
+ end
+
+ context 'with a custom template' do
+ before do
+ allow(File).to receive(:read).and_call_original
+ end
+
+ it 'renders that template file' do
+ opts[:template_name] = :custom_readme
+
+ expect(service).to receive(:sanitized_filename).with(:custom_readme).and_return('custom_readme.md.tt')
+ expect(File).to receive(:read).with('custom_readme.md.tt').and_return('_custom_readme_file_content_')
+ expect(service.execute).to eq('_custom_readme_file_content_')
+ end
+
+ context 'with path traversal in mind' do
+ where(:template_name, :exception, :expected_path) do
+ '../path/traversal/bad' | [Gitlab::Utils::PathTraversalAttackError, 'Invalid path'] | nil
+ '/bad/template' | [StandardError, 'path /bad/template.md.tt is not allowed'] | nil
+ 'good/template' | nil | 'good/template.md.tt'
+ end
+
+ with_them do
+ it 'raises the expected exception on bad paths' do
+ opts[:template_name] = template_name
+
+ if exception
+ expect { subject.execute }.to raise_error(*exception)
+ else
+ expect(File).to receive(:read).with(described_class::TEMPLATE_PATH.join(expected_path).to_s).and_return('')
+
+ expect { subject.execute }.not_to raise_error
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/services/projects/transfer_service_spec.rb b/spec/services/projects/transfer_service_spec.rb
index ddd16100b40..fb94e94fd18 100644
--- a/spec/services/projects/transfer_service_spec.rb
+++ b/spec/services/projects/transfer_service_spec.rb
@@ -5,13 +5,14 @@ require 'spec_helper'
RSpec.describe Projects::TransferService do
include GitHelpers
- let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
+ let_it_be(:user) { create(:user) }
let_it_be(:group_integration) { create(:integrations_slack, :group, group: group, webhook: 'http://group.slack.com') }
let(:project) { create(:project, :repository, :legacy_storage, namespace: user.namespace) }
+ let(:target) { group }
- subject(:execute_transfer) { described_class.new(project, user).execute(group).tap { project.reload } }
+ subject(:execute_transfer) { described_class.new(project, user).execute(target).tap { project.reload } }
context 'with npm packages' do
before do
@@ -690,6 +691,32 @@ RSpec.describe Projects::TransferService do
end
end
+ context 'handling issue contacts' do
+ let_it_be(:root_group) { create(:group) }
+
+ let(:project) { create(:project, group: root_group) }
+
+ before do
+ root_group.add_owner(user)
+ target.add_owner(user)
+ create_list(:issue_customer_relations_contact, 2, :for_issue, issue: create(:issue, project: project))
+ end
+
+ context 'with the same root_ancestor' do
+ let(:target) { create(:group, parent: root_group) }
+
+ it 'retains issue contacts' do
+ expect { execute_transfer }.not_to change { CustomerRelations::IssueContact.count }
+ end
+ end
+
+ context 'with a different root_ancestor' do
+ it 'deletes issue contacts' do
+ expect { execute_transfer }.to change { CustomerRelations::IssueContact.count }.by(-2)
+ end
+ end
+ end
+
def rugged_config
rugged_repo(project.repository).config
end