diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-13 15:10:13 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-10-13 15:10:13 +0300 |
commit | 70ce746bd011b101605e6d84f141d1f0c3175831 (patch) | |
tree | 1b76e654f61579b79b34116fa6bb06db2f511d94 /spec/support/shared_examples | |
parent | 61ca90e0b462bfe69e0b400dfe403bd95281b90f (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/support/shared_examples')
4 files changed, 362 insertions, 2 deletions
diff --git a/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb b/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb new file mode 100644 index 00000000000..d7a5bc6cc41 --- /dev/null +++ b/spec/support/shared_examples/models/concerns/cascading_namespace_setting_shared_examples.rb @@ -0,0 +1,355 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.shared_examples 'a cascading namespace setting boolean attribute' do + |settings_association: :namespace_settings, settings_attribute_name:| + let_it_be_with_reload(:group) { create(:group) } + let_it_be_with_reload(:subgroup) { create(:group, parent: group) } + let(:group_settings) { group.send(settings_association) } + let(:subgroup_settings) { subgroup.send(settings_association) } + + describe "##{settings_attribute_name}" do + subject(:cascading_attribute) { subgroup_settings.send(settings_attribute_name) } + + before do + stub_application_setting(settings_attribute_name => false) + end + + context 'when there is no parent' do + context 'and the value is not nil' do + before do + group_settings.update!(settings_attribute_name => true) + end + + it 'returns the local value' do + expect(group_settings.send(settings_attribute_name)).to eq(true) + end + end + + context 'and the value is nil' do + before do + group_settings.update!(settings_attribute_name => nil) + end + + it 'returns the application settings value' do + expect(group_settings.send(settings_attribute_name)).to eq(false) + end + end + end + + context 'when parent does not lock the attribute' do + context 'and value is not nil' do + before do + group_settings.update!(settings_attribute_name => false) + end + + it 'returns local setting when present' do + subgroup_settings.update!(settings_attribute_name => true) + + expect(cascading_attribute).to eq(true) + end + + it 'returns the parent value when local value is nil' do + subgroup_settings.update!(settings_attribute_name => nil) + + expect(cascading_attribute).to eq(false) + end + + it 'returns the correct dirty value' do + subgroup_settings.send("#{settings_attribute_name}=", true) + + expect(cascading_attribute).to eq(true) + end + + it 'does not return the application setting value when parent value is false' do + stub_application_setting(settings_attribute_name => true) + + expect(cascading_attribute).to eq(false) + end + end + + context 'and the value is nil' do + before do + group_settings.update!(settings_attribute_name => nil, "lock_#{settings_attribute_name}".to_sym => false) + subgroup_settings.update!(settings_attribute_name => nil) + + subgroup_settings.clear_memoization(settings_attribute_name) + end + + it 'cascades to the application settings value' do + expect(cascading_attribute).to eq(false) + end + end + + context 'when multiple ancestors set a value' do + let(:third_level_subgroup) { create(:group, parent: subgroup) } + + before do + group_settings.update!(settings_attribute_name => true) + subgroup_settings.update!(settings_attribute_name => false) + end + + it 'returns the closest ancestor value' do + expect(third_level_subgroup.send(settings_association).send(settings_attribute_name)).to eq(false) + end + end + end + + context 'when parent locks the attribute' do + before do + subgroup_settings.update!(settings_attribute_name => true) + group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false) + + subgroup_settings.clear_memoization(settings_attribute_name) + subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor") + end + + it 'returns the parent value' do + expect(cascading_attribute).to eq(false) + end + + it 'does not allow the local value to be saved' do + subgroup_settings.send("#{settings_attribute_name}=", nil) + + expect { subgroup_settings.save! } + .to raise_error(ActiveRecord::RecordInvalid, + /cannot be changed because it is locked by an ancestor/) + end + end + + context 'when the application settings locks the attribute' do + before do + subgroup_settings.update!(settings_attribute_name => true) + stub_application_setting("lock_#{settings_attribute_name}" => true, settings_attribute_name => true) + end + + it 'returns the application setting value' do + expect(cascading_attribute).to eq(true) + end + + it 'does not allow the local value to be saved' do + subgroup_settings.send("#{settings_attribute_name}=", false) + + expect { subgroup_settings.save! } + .to raise_error( + ActiveRecord::RecordInvalid, + /cannot be changed because it is locked by an ancestor/ + ) + end + end + + context 'when parent locked the attribute then the application settings locks it' do + before do + subgroup_settings.update!(settings_attribute_name => true) + group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false) + stub_application_setting("lock_#{settings_attribute_name}" => true, settings_attribute_name => true) + + subgroup_settings.clear_memoization(settings_attribute_name) + subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor") + end + + it 'returns the application setting value' do + expect(cascading_attribute).to eq(true) + end + end + end + + describe "##{settings_attribute_name}?" do + before do + subgroup_settings.update!(settings_attribute_name => true) + group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false) + + subgroup_settings.clear_memoization(settings_attribute_name) + subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor") + end + + it 'aliases the method when the attribute is a boolean' do + expect(subgroup_settings.send("#{settings_attribute_name}?")) + .to eq(subgroup_settings.send(settings_attribute_name)) + end + end + + describe "##{settings_attribute_name}=" do + before do + subgroup_settings.update!(settings_attribute_name => nil) + group_settings.update!(settings_attribute_name => true) + end + + it 'does not save the value locally when it matches the cascaded value' do + subgroup_settings.update!(settings_attribute_name => true) + + expect(subgroup_settings.read_attribute(settings_attribute_name)).to eq(nil) + end + end + + describe "##{settings_attribute_name}_locked?" do + shared_examples 'not locked' do + it 'is not locked by an ancestor' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(false) + end + + it 'is not locked by application setting' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(false) + end + + it 'does not return a locked namespace' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor")).to be_nil + end + end + + context 'when attribute is locked by self' do + before do + subgroup_settings.update!("lock_#{settings_attribute_name}" => true) + end + + it 'is not locked by default' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked?")).to eq(false) + end + + it 'is locked when including self' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked?", include_self: true)).to eq(true) + end + end + + context 'when parent does not lock the attribute' do + it_behaves_like 'not locked' + end + + context 'when parent locks the attribute' do + before do + group_settings.update!("lock_#{settings_attribute_name}".to_sym => true, settings_attribute_name => false) + + subgroup_settings.clear_memoization(settings_attribute_name) + subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor") + end + + it 'is locked by an ancestor' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(true) + end + + it 'is not locked by application setting' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(false) + end + + it 'returns a locked namespace settings object' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor").namespace_id) + .to eq(group_settings.namespace_id) + end + end + + context 'when not locked by application settings' do + before do + stub_application_setting("lock_#{settings_attribute_name}" => false) + end + + it_behaves_like 'not locked' + end + + context 'when locked by application settings' do + before do + stub_application_setting("lock_#{settings_attribute_name}" => true) + end + + it 'is not locked by an ancestor' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_ancestor?")).to eq(false) + end + + it 'is locked by application setting' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_by_application_setting?")).to eq(true) + end + + it 'does not return a locked namespace' do + expect(subgroup_settings.send("#{settings_attribute_name}_locked_ancestor")).to be_nil + end + end + end + + describe "#lock_#{settings_attribute_name}=" do + context 'when parent locks the attribute' do + before do + group_settings.update!("lock_#{settings_attribute_name}".to_sym => true, settings_attribute_name => false) + + subgroup_settings.clear_memoization(settings_attribute_name) + subgroup_settings.clear_memoization("#{settings_attribute_name}_locked_ancestor") + end + + it 'does not allow the attribute to be saved' do + subgroup_settings.send("lock_#{settings_attribute_name}=", true) + + expect { subgroup_settings.save! } + .to raise_error(ActiveRecord::RecordInvalid, + /cannot be changed because it is locked by an ancestor/) + end + end + + context 'when parent does not lock the attribute' do + before do + group_settings.update!("lock_#{settings_attribute_name}" => false, settings_attribute_name => false) + + subgroup_settings.send("lock_#{settings_attribute_name}=", true) + end + + it 'allows the lock to be set when the attribute is not nil' do + subgroup_settings.send("#{settings_attribute_name}=", true) + + expect(subgroup_settings.save).to eq(true) + end + + it 'does not allow the lock to be saved when the attribute is nil' do + subgroup_settings.send("#{settings_attribute_name}=", nil) + + expect { subgroup_settings.save! } + .to raise_error(ActiveRecord::RecordInvalid, + /cannot be nil when locking the attribute/) + end + + it 'copies the cascaded value when locking the attribute if the local value is nil', :aggregate_failures do + subgroup_settings.send("#{settings_attribute_name}=", nil) + subgroup_settings.send("lock_#{settings_attribute_name}=", true) + + expect(subgroup_settings.read_attribute(settings_attribute_name)).to eq(false) + end + end + + context 'when application settings locks the attribute' do + before do + stub_application_setting("lock_#{settings_attribute_name}".to_sym => true) + end + + it 'does not allow the attribute to be saved' do + subgroup_settings.send("lock_#{settings_attribute_name}=", true) + + expect { subgroup_settings.save! } + .to raise_error(ActiveRecord::RecordInvalid, + /cannot be changed because it is locked by an ancestor/) + end + end + + context 'when application_settings does not lock the attribute' do + before do + stub_application_setting("lock_#{settings_attribute_name}".to_sym => false) + end + + it 'allows the attribute to be saved' do + subgroup_settings.send("#{settings_attribute_name}=", true) + subgroup_settings.send("lock_#{settings_attribute_name}=", true) + + expect(subgroup_settings.save).to eq(true) + end + end + end + + describe 'after update callback' do + before do + group_settings.update!("lock_#{settings_attribute_name}" => false, settings_attribute_name => false) + subgroup_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => false) + end + + it 'clears descendant locks' do + group_settings.update!("lock_#{settings_attribute_name}" => true, settings_attribute_name => true) + + expect(subgroup_settings.reload.send("lock_#{settings_attribute_name}")).to eq(false) + end + end +end diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb index b651ffc8996..85ac2b5e1ea 100644 --- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb @@ -260,7 +260,11 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project| project.send("add_#{user_role}", user) if user_role project.update!(visibility: visibility.to_s) package.update!(name: package_name) unless package_name == 'non-existing-package' - allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward) + if scope == :instance + allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward) + else + allow_fetch_cascade_application_setting(attribute: "npm_package_requests_forwarding", return_value: request_forward) + end end example_name = "#{params[:expected_result]} metadata request" diff --git a/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb index 86b6975bf9f..1d79a61fbb0 100644 --- a/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/npm_packages_tags_shared_examples.rb @@ -14,6 +14,7 @@ RSpec.shared_examples 'accept package tags request' do |status:| before do allow_fetch_application_setting(attribute: "npm_package_requests_forwarding", return_value: false) + allow_fetch_cascade_application_setting(attribute: "npm_package_requests_forwarding", return_value: false) end context 'with valid package name' do diff --git a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb index f411b5699a9..11e19d8d067 100644 --- a/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb +++ b/spec/support/shared_examples/requests/api/pypi_packages_shared_examples.rb @@ -291,7 +291,7 @@ RSpec.shared_examples 'pypi simple API endpoint' do end before do - allow_fetch_application_setting(attribute: "pypi_package_requests_forwarding", return_value: forward) + allow_fetch_cascade_application_setting(attribute: "pypi_package_requests_forwarding", return_value: forward) end it_behaves_like params[:shared_examples_name], :reporter, params[:expected_status] |