diff options
Diffstat (limited to 'spec/support/shared_examples/models')
12 files changed, 441 insertions, 95 deletions
diff --git a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb index fe99b1cacd9..42f82987989 100644 --- a/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb +++ b/spec/support/shared_examples/models/atomic_internal_id_shared_examples.rb @@ -9,19 +9,30 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true| end describe 'Validation' do - before do - allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!") - - instance.valid? - end - context 'when presence validation is required' do before do skip unless validate_presence end - it 'validates presence' do - expect(instance.errors[internal_id_attribute]).to include("can't be blank") + context 'when creating an object' do + before do + allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!") + end + + it 'raises an error if the internal id is blank' do + expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError) + end + end + + context 'when updating an object' do + it 'raises an error if the internal id is blank' do + instance.save! + + write_internal_id(nil) + allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!") + + expect { instance.save! }.to raise_error(AtomicInternalId::MissingValueError) + end end end @@ -30,8 +41,27 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true| skip if validate_presence end - it 'does not validate presence' do - expect(instance.errors[internal_id_attribute]).to be_empty + context 'when creating an object' do + before do + allow_any_instance_of(described_class).to receive(:"ensure_#{scope}_#{internal_id_attribute}!") + end + + it 'does not raise an error if the internal id is blank' do + expect(read_internal_id).to be_nil + + expect { instance.save! }.not_to raise_error + end + end + + context 'when updating an object' do + it 'does not raise an error if the internal id is blank' do + instance.save! + + write_internal_id(nil) + allow(instance).to receive(:"ensure_#{scope}_#{internal_id_attribute}!") + + expect { instance.save! }.not_to raise_error + end end end end @@ -76,6 +106,51 @@ RSpec.shared_examples 'AtomicInternalId' do |validate_presence: true| end end + describe 'unsetting the instance internal id on rollback' do + context 'when the internal id has been changed' do + context 'when the internal id is automatically set' do + it 'clears it on the instance' do + expect_iid_to_be_set_and_rollback + + expect(read_internal_id).to be_nil + end + end + + context 'when the internal id is manually set' do + it 'does not clear it on the instance' do + write_internal_id(100) + + expect_iid_to_be_set_and_rollback + + expect(read_internal_id).not_to be_nil + end + end + end + + context 'when the internal id has not been changed' do + it 'preserves the value on the instance' do + instance.save! + original_id = read_internal_id + + expect(original_id).not_to be_nil + + expect_iid_to_be_set_and_rollback + + expect(read_internal_id).to eq(original_id) + end + end + + def expect_iid_to_be_set_and_rollback + ActiveRecord::Base.transaction(requires_new: true) do + instance.save! + + expect(read_internal_id).not_to be_nil + + raise ActiveRecord::Rollback + end + end + end + describe 'supply of internal ids' do let(:scope_value) { scope_attrs.each_value.first } let(:method_name) { :"with_#{scope}_#{internal_id_attribute}_supply" } diff --git a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb deleted file mode 100644 index 2f0b95427d2..00000000000 --- a/spec/support/shared_examples/models/concerns/can_housekeep_repository_shared_examples.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: true - -RSpec.shared_examples 'can housekeep repository' do - context 'with a clean redis state', :clean_gitlab_redis_shared_state do - describe '#pushes_since_gc' do - context 'without any pushes' do - it 'returns 0' do - expect(resource.pushes_since_gc).to eq(0) - end - end - - context 'with a number of pushes' do - it 'returns the number of pushes' do - 3.times { resource.increment_pushes_since_gc } - - expect(resource.pushes_since_gc).to eq(3) - end - end - end - - describe '#increment_pushes_since_gc' do - it 'increments the number of pushes since the last GC' do - 3.times { resource.increment_pushes_since_gc } - - expect(resource.pushes_since_gc).to eq(3) - end - end - - describe '#reset_pushes_since_gc' do - it 'resets the number of pushes since the last GC' do - 3.times { resource.increment_pushes_since_gc } - - resource.reset_pushes_since_gc - - expect(resource.pushes_since_gc).to eq(0) - end - end - - describe '#pushes_since_gc_redis_shared_state_key' do - it 'returns the proper redis key format' do - expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc") - end - end - end -end diff --git a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb index 85a2c6f1449..8deeecea30d 100644 --- a/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/can_move_repository_storage_shared_examples.rb @@ -2,11 +2,12 @@ RSpec.shared_examples 'can move repository storage' do let(:container) { raise NotImplementedError } + let(:repository) { container.repository } describe '#set_repository_read_only!' do it 'makes the repository read-only' do expect { container.set_repository_read_only! } - .to change(container, :repository_read_only?) + .to change { container.repository_read_only? } .from(false) .to(true) end @@ -28,7 +29,7 @@ RSpec.shared_examples 'can move repository storage' do allow(container).to receive(:git_transfer_in_progress?) { true } expect { container.set_repository_read_only!(skip_git_transfer_check: true) } - .to change(container, :repository_read_only?) + .to change { container.repository_read_only? } .from(false) .to(true) end @@ -38,16 +39,16 @@ RSpec.shared_examples 'can move repository storage' do describe '#set_repository_writable!' do it 'sets repository_read_only to false' do expect { container.set_repository_writable! } - .to change(container, :repository_read_only) + .to change { container.repository_read_only? } .from(true).to(false) end end describe '#reference_counter' do it 'returns a Gitlab::ReferenceCounter object' do - expect(Gitlab::ReferenceCounter).to receive(:new).with(container.repository.gl_repository).and_call_original + expect(Gitlab::ReferenceCounter).to receive(:new).with(repository.gl_repository).and_call_original - result = container.reference_counter(type: container.repository.repo_type) + result = container.reference_counter(type: repository.repo_type) expect(result).to be_a Gitlab::ReferenceCounter end diff --git a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb index 826ee453919..1be4d9b80a4 100644 --- a/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/has_repository_shared_examples.rb @@ -152,36 +152,4 @@ RSpec.shared_examples 'model with repository' do it { is_expected.to respond_to(:disk_path) } it { is_expected.to respond_to(:gitlab_shell) } end - - describe '.pick_repository_storage' do - subject { described_class.pick_repository_storage } - - before do - storages = { - 'default' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories'), - 'picked' => Gitlab::GitalyClient::StorageSettings.new('path' => 'tmp/tests/repositories') - } - allow(Gitlab.config.repositories).to receive(:storages).and_return(storages) - end - - it 'picks storage from ApplicationSetting' do - expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked') - - expect(subject).to eq('picked') - end - - it 'picks from the available storages based on weight', :request_store do - stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - Gitlab::CurrentSettings.expire_current_application_settings - Gitlab::CurrentSettings.current_application_settings - - settings = ApplicationSetting.last - settings.repository_storages_weighted = { 'picked' => 100, 'default' => 0 } - settings.save! - - expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 100 }) - expect(subject).to eq('picked') - expect(Gitlab::CurrentSettings.repository_storages_weighted).to eq({ 'default' => 0, 'picked' => 100 }) - end - end end diff --git a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb index 2f0b95427d2..4006b8226ce 100644 --- a/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/repositories/can_housekeep_repository_shared_examples.rb @@ -41,5 +41,11 @@ RSpec.shared_examples 'can housekeep repository' do expect(resource.send(:pushes_since_gc_redis_shared_state_key)).to eq("#{resource_key}/#{resource.id}/pushes_since_gc") end end + + describe '#git_garbage_collect_worker_klass' do + it 'defines a git gargabe collect worker' do + expect(resource.git_garbage_collect_worker_klass).to eq(expected_worker_class) + end + end end end diff --git a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb index 4c617f3ba46..819cf6018fe 100644 --- a/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/repository_storage_movable_shared_examples.rb @@ -33,7 +33,7 @@ RSpec.shared_examples 'handles repository moves' do subject { build(repository_storage_factory_key, container: container) } it "does not allow the container to be read-only on create" do - container.update!(repository_read_only: true) + container.set_repository_read_only! expect(subject).not_to be_valid expect(subject.errors[error_key].first).to match(/is read only/) @@ -45,8 +45,8 @@ RSpec.shared_examples 'handles repository moves' do context 'destination_storage_name' do subject { build(repository_storage_factory_key) } - it 'picks storage from ApplicationSetting' do - expect(Gitlab::CurrentSettings).to receive(:pick_repository_storage).and_return('picked').at_least(:once) + it 'can pick new storage' do + expect(Repository).to receive(:pick_storage_shard).and_return('picked').at_least(:once) expect(subject.destination_storage_name).to eq('picked') end @@ -99,6 +99,11 @@ RSpec.shared_examples 'handles repository moves' do expect(container).not_to be_repository_read_only end + + it 'updates the updated_at column of the container', :aggregate_failures do + expect { storage_move.finish_replication! }.to change { container.updated_at } + expect(storage_move.container.updated_at).to be >= storage_move.updated_at + end end context 'and transits to failed' do diff --git a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb index 38983f752f4..b73ff516670 100644 --- a/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb +++ b/spec/support/shared_examples/models/packages/debian/architecture_shared_examples.rb @@ -11,6 +11,7 @@ RSpec.shared_examples 'Debian Distribution Architecture' do |factory, container, describe 'relationships' do it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:architectures) } + it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:architecture) } end describe 'validations' do diff --git a/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb new file mode 100644 index 00000000000..02ced49ee94 --- /dev/null +++ b/spec/support/shared_examples/models/packages/debian/component_file_shared_example.rb @@ -0,0 +1,245 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'Debian Component File' do |container_type, can_freeze| + let_it_be(:container1, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang + let_it_be(:container2, freeze: can_freeze) { create(container_type) } # rubocop:disable Rails/SaveBang + let_it_be(:distribution1, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container1) } + let_it_be(:distribution2, freeze: can_freeze) { create("debian_#{container_type}_distribution", container: container2) } + let_it_be(:architecture1_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) } + let_it_be(:architecture1_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution1) } + let_it_be(:architecture2_1, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) } + let_it_be(:architecture2_2, freeze: can_freeze) { create("debian_#{container_type}_architecture", distribution: distribution2) } + let_it_be(:component1_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) } + let_it_be(:component1_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution1) } + let_it_be(:component2_1, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) } + let_it_be(:component2_2, freeze: can_freeze) { create("debian_#{container_type}_component", distribution: distribution2) } + + let_it_be_with_refind(:component_file_with_architecture) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1) } + let_it_be(:component_file_other_architecture, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_2) } + let_it_be(:component_file_other_component, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_2, architecture: architecture1_1) } + let_it_be(:component_file_other_compression_type, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, compression_type: :xz) } + let_it_be(:component_file_other_file_md5, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_md5: 'other_md5') } + let_it_be(:component_file_other_file_sha256, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, file_sha256: 'other_sha256') } + let_it_be(:component_file_other_container, freeze: can_freeze) { create("debian_#{container_type}_component_file", component: component2_1, architecture: architecture2_1) } + let_it_be_with_refind(:component_file_with_file_type_source) { create("debian_#{container_type}_component_file", :source, component: component1_1) } + let_it_be(:component_file_with_file_type_di_packages, freeze: can_freeze) { create("debian_#{container_type}_component_file", :di_packages, component: component1_1, architecture: architecture1_1) } + + subject { component_file_with_architecture } + + describe 'relationships' do + context 'with stubbed uploader' do + before do + allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader| + allow(uploader).to receive(:dynamic_segment).and_return('stubbed') + end + end + + it { is_expected.to belong_to(:component).class_name("Packages::Debian::#{container_type.capitalize}Component").inverse_of(:files) } + end + + context 'with packages file_type' do + it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files) } + end + + context 'with :source file_type' do + subject { component_file_with_file_type_source } + + it { is_expected.to belong_to(:architecture).class_name("Packages::Debian::#{container_type.capitalize}Architecture").inverse_of(:files).optional } + end + end + + describe 'validations' do + describe "#component" do + before do + allow_next_instance_of(Packages::Debian::ComponentFileUploader) do |uploader| + allow(uploader).to receive(:dynamic_segment).and_return('stubbed') + end + end + + it { is_expected.to validate_presence_of(:component) } + end + + describe "#architecture" do + context 'with packages file_type' do + it { is_expected.to validate_presence_of(:architecture) } + end + + context 'with :source file_type' do + subject { component_file_with_file_type_source } + + it { is_expected.to validate_absence_of(:architecture) } + end + end + + describe '#file_type' do + it { is_expected.to validate_presence_of(:file_type) } + + it { is_expected.to allow_value(:packages).for(:file_type) } + end + + describe '#compression_type' do + it { is_expected.not_to validate_presence_of(:compression_type) } + + it { is_expected.to allow_value(nil).for(:compression_type) } + it { is_expected.to allow_value(:gz).for(:compression_type) } + end + + describe '#file' do + subject { component_file_with_architecture.file } + + context 'the uploader api' do + it { is_expected.to respond_to(:store_dir) } + it { is_expected.to respond_to(:cache_dir) } + it { is_expected.to respond_to(:work_dir) } + end + end + + describe '#file_store' do + it { is_expected.to validate_presence_of(:file_store) } + end + + describe '#file_md5' do + it { is_expected.to validate_presence_of(:file_md5) } + end + + describe '#file_sha256' do + it { is_expected.to validate_presence_of(:file_sha256) } + end + end + + describe 'scopes' do + describe '.with_container' do + subject { described_class.with_container(container2) } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_container) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_codename_or_suite' do + subject { described_class.with_codename_or_suite(distribution2.codename) } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_container) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_component_name' do + subject { described_class.with_component_name(component1_2.name) } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_component) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_file_type' do + subject { described_class.with_file_type(:source) } + + it do + # let_it_be_with_refind triggers a query + component_file_with_file_type_source + + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_with_file_type_source) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_architecture_name' do + subject { described_class.with_architecture_name(architecture1_2.name) } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_architecture) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_compression_type' do + subject { described_class.with_compression_type(:xz) } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_compression_type) + end + + expect(queries.count).to eq(1) + end + end + + describe '.with_file_sha256' do + subject { described_class.with_file_sha256('other_sha256') } + + it do + queries = ActiveRecord::QueryRecorder.new do + expect(subject.to_a).to contain_exactly(component_file_other_file_sha256) + end + + expect(queries.count).to eq(1) + end + end + end + + describe 'callbacks' do + let(:component_file) { build("debian_#{container_type}_component_file", component: component1_1, architecture: architecture1_1, size: nil) } + + subject { component_file.save! } + + it 'updates metadata columns' do + expect(component_file) + .to receive(:update_file_store) + .and_call_original + + expect(component_file) + .to receive(:update_column) + .with(:file_store, ::Packages::PackageFileUploader::Store::LOCAL) + .and_call_original + + expect { subject }.to change { component_file.size }.from(nil).to(74) + end + end + + describe '#relative_path' do + context 'with a Packages file_type' do + subject { component_file_with_architecture.relative_path } + + it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages") } + end + + context 'with a Source file_type' do + subject { component_file_with_file_type_source.relative_path } + + it { is_expected.to eq("#{component1_1.name}/source/Source") } + end + + context 'with a DI Packages file_type' do + subject { component_file_with_file_type_di_packages.relative_path } + + it { is_expected.to eq("#{component1_1.name}/debian-installer/binary-#{architecture1_1.name}/Packages") } + end + + context 'with an xz compression_type' do + subject { component_file_other_compression_type.relative_path } + + it { is_expected.to eq("#{component1_1.name}/binary-#{architecture1_1.name}/Packages.xz") } + end + end +end diff --git a/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb new file mode 100644 index 00000000000..bf6fc23116c --- /dev/null +++ b/spec/support/shared_examples/models/packages/debian/component_shared_examples.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'Debian Distribution Component' do |factory, container, can_freeze| + let_it_be_with_refind(:component) { create(factory) } # rubocop:disable Rails/SaveBang + let_it_be(:component_same_distribution, freeze: can_freeze) { create(factory, distribution: component.distribution) } + let_it_be(:component_same_name, freeze: can_freeze) { create(factory, name: component.name) } + + subject { component } + + describe 'relationships' do + it { is_expected.to belong_to(:distribution).class_name("Packages::Debian::#{container.capitalize}Distribution").inverse_of(:components) } + it { is_expected.to have_many(:files).class_name("Packages::Debian::#{container.capitalize}ComponentFile").inverse_of(:component) } + end + + describe 'validations' do + describe "#distribution" do + it { is_expected.to validate_presence_of(:distribution) } + end + + describe '#name' do + it { is_expected.to validate_presence_of(:name) } + + it { is_expected.to allow_value('main').for(:name) } + it { is_expected.to allow_value('non-free').for(:name) } + it { is_expected.to allow_value('a' * 255).for(:name) } + it { is_expected.not_to allow_value('a' * 256).for(:name) } + it { is_expected.not_to allow_value('non/free').for(:name) } + it { is_expected.not_to allow_value('hé').for(:name) } + end + end + + describe 'scopes' do + describe '.with_distribution' do + subject { described_class.with_distribution(component.distribution) } + + it 'does not return other distributions' do + expect(subject.to_a).to eq([component, component_same_distribution]) + end + end + + describe '.with_name' do + subject { described_class.with_name(component.name) } + + it 'does not return other distributions' do + expect(subject.to_a).to eq([component, component_same_name]) + end + end + end +end diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb index af87d30099f..b4ec146df14 100644 --- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb +++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb @@ -17,7 +17,13 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze| it { is_expected.to belong_to(container) } it { is_expected.to belong_to(:creator).class_name('User') } + it { is_expected.to have_many(:components).class_name("Packages::Debian::#{container.capitalize}Component").inverse_of(:distribution) } it { is_expected.to have_many(:architectures).class_name("Packages::Debian::#{container.capitalize}Architecture").inverse_of(:distribution) } + + if container != :group + it { is_expected.to have_many(:publications).class_name('Packages::Debian::Publication').inverse_of(:distribution).with_foreign_key(:distribution_id) } + it { is_expected.to have_many(:packages).class_name('Packages::Package').through(:publications) } + end end describe 'validations' do diff --git a/spec/support/shared_examples/models/wiki_shared_examples.rb b/spec/support/shared_examples/models/wiki_shared_examples.rb index 62da9e15259..89d30688b5c 100644 --- a/spec/support/shared_examples/models/wiki_shared_examples.rb +++ b/spec/support/shared_examples/models/wiki_shared_examples.rb @@ -154,6 +154,15 @@ RSpec.shared_examples 'wiki model' do it 'returns true' do expect(subject.empty?).to be(true) end + + context 'when the repository does not exist' do + let(:wiki_container) { wiki_container_without_repo } + + it 'returns true and does not create the repo' do + expect(subject.empty?).to be(true) + expect(wiki.repository_exists?).to be false + end + end end context 'when the wiki has pages' do diff --git a/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb new file mode 100644 index 00000000000..e86f1e77447 --- /dev/null +++ b/spec/support/shared_examples/models/with_debian_distributions_shared_examples.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +RSpec.shared_examples 'model with Debian distributions' do + let(:container_type) { subject.class.name.downcase } + let!(:distributions) { create_list("debian_#{container_type}_distribution", 2, :with_file, container: subject) } + let!(:components) { create_list("debian_#{container_type}_component", 5, distribution: distributions[0]) } + let!(:component_files) { create_list("debian_#{container_type}_component_file", 3, component: components[0]) } + + it 'removes distribution files on removal' do + distribution_file_paths = distributions.map do |distribution| + [distribution.file.path] + + distribution.component_files.map do |component_file| + component_file.file.path + end + end.flatten + + expect { subject.destroy! } + .to change { + distribution_file_paths.select do |path| + File.exist? path + end.length + }.from(distribution_file_paths.length).to(0) + end +end |