diff options
Diffstat (limited to 'spec/support/shared_examples/models')
9 files changed, 173 insertions, 22 deletions
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb index d189e91effd..fb08784f34f 100644 --- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb +++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb @@ -3,7 +3,6 @@ RSpec.shared_examples "chat integration" do |integration_name| describe "Associations" do it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } end describe "Validations" do @@ -13,6 +12,7 @@ RSpec.shared_examples "chat integration" do |integration_name| end it { is_expected.to validate_presence_of(:webhook) } + it_behaves_like "issue tracker integration URL attribute", :webhook end diff --git a/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb b/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb new file mode 100644 index 00000000000..0c71ebe7a4d --- /dev/null +++ b/spec/support/shared_examples/models/ci/metadata_id_tokens_shared_examples.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +RSpec.shared_examples_for 'has ID tokens' do |ci_type| + subject(:ci) { FactoryBot.build(ci_type) } + + describe 'delegations' do + it { is_expected.to delegate_method(:id_tokens).to(:metadata).allow_nil } + end + + describe '#id_tokens?' do + subject { ci.id_tokens? } + + context 'without metadata' do + let(:ci) { FactoryBot.build(ci_type) } + + it { is_expected.to be_falsy } + end + + context 'with metadata' do + let(:ci) { FactoryBot.build(ci_type, metadata: FactoryBot.build(:ci_build_metadata, id_tokens: id_tokens)) } + + context 'when ID tokens exist' do + let(:id_tokens) { { TEST_JOB_JWT: { id_token: { aud: 'developers ' } } } } + + it { is_expected.to be_truthy } + end + + context 'when ID tokens do not exist' do + let(:id_tokens) { {} } + + it { is_expected.to be_falsy } + end + end + end + + describe '#id_tokens=' do + it 'assigns the ID tokens to the CI job' do + id_tokens = [{ 'JOB_ID_TOKEN' => { 'id_token' => { 'aud' => 'https://gitlab.test ' } } }] + ci.id_tokens = id_tokens + + expect(ci.id_tokens).to match_array(id_tokens) + end + end +end diff --git a/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb b/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb index f92ed3d7396..f4d5ab3d5c6 100644 --- a/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/counter_attribute_shared_examples.rb @@ -2,6 +2,10 @@ require 'spec_helper' RSpec.shared_examples_for CounterAttribute do |counter_attributes| + before do + Gitlab::ApplicationContext.push(feature_category: 'test', caller_id: 'caller') + end + it 'defines a Redis counter_key' do expect(model.counter_key(:counter_name)) .to eq("project:{#{model.project_id}}:counters:CounterAttributeModel:#{model.id}:counter_name") @@ -22,7 +26,21 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes| where(:increment) { [10, -3] } with_them do - it 'increments the counter in Redis' do + it 'increments the counter in Redis and logs it' do + expect(Gitlab::AppLogger).to receive(:info).with( + hash_including( + message: 'Increment counter attribute', + attribute: attribute, + project_id: model.project_id, + increment: increment, + new_counter_value: 0 + increment, + current_db_value: model.read_attribute(attribute), + 'correlation_id' => an_instance_of(String), + 'meta.feature_category' => 'test', + 'meta.caller_id' => 'caller' + ) + ) + subject Gitlab::Redis::SharedState.with do |redis| @@ -86,7 +104,21 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes| model.delayed_increment_counter(incremented_attribute, -3) end - it 'updates the record' do + it 'updates the record and logs it' do + expect(Gitlab::AppLogger).to receive(:info).with( + hash_including( + message: 'Flush counter attribute to database', + attribute: incremented_attribute, + project_id: model.project_id, + increment: 7, + previous_db_value: 0, + new_db_value: 7, + 'correlation_id' => an_instance_of(String), + 'meta.feature_category' => 'test', + 'meta.caller_id' => 'caller' + ) + ) + expect { subject }.to change { model.reset.read_attribute(incremented_attribute) }.by(7) end @@ -153,4 +185,32 @@ RSpec.shared_examples_for CounterAttribute do |counter_attributes| end end end + + describe '#clear_counter!' do + let(:attribute) { counter_attributes.first } + + before do + model.increment_counter(attribute, 10) + end + + it 'deletes the counter key for the given attribute and logs it' do + expect(Gitlab::AppLogger).to receive(:info).with( + hash_including( + message: 'Clear counter attribute', + attribute: attribute, + project_id: model.project_id, + 'correlation_id' => an_instance_of(String), + 'meta.feature_category' => 'test', + 'meta.caller_id' => 'caller' + ) + ) + + model.clear_counter!(attribute) + + Gitlab::Redis::SharedState.with do |redis| + key_exists = redis.exists(model.counter_key(attribute)) + expect(key_exists).to be_falsey + end + end + end end diff --git a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb index d80be5be3b3..7512a9f2855 100644 --- a/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb +++ b/spec/support/shared_examples/models/concerns/integrations/slack_mattermost_notifier_shared_examples.rb @@ -13,7 +13,6 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |integration_name describe "Associations" do it { is_expected.to belong_to :project } - it { is_expected.to have_one :service_hook } end describe 'Validations' do @@ -23,6 +22,7 @@ RSpec.shared_examples Integrations::SlackMattermostNotifier do |integration_name end it { is_expected.to validate_presence_of(:webhook) } + it_behaves_like 'issue tracker integration URL attribute', :webhook end diff --git a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb index ae72cb6ec5d..2f693edeb53 100644 --- a/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb +++ b/spec/support/shared_examples/models/integrations/has_web_hook_shared_examples.rb @@ -3,6 +3,10 @@ RSpec.shared_examples Integrations::HasWebHook do include AfterNextHelpers + describe 'associations' do + it { is_expected.to have_one(:service_hook).inverse_of(:integration).with_foreign_key(:service_id) } + end + describe 'callbacks' do it 'calls #update_web_hook! when enabled' do expect(integration).to receive(:update_web_hook!) diff --git a/spec/support/shared_examples/models/issuable_link_shared_examples.rb b/spec/support/shared_examples/models/issuable_link_shared_examples.rb index 9892e66b582..42c7be5ddc3 100644 --- a/spec/support/shared_examples/models/issuable_link_shared_examples.rb +++ b/spec/support/shared_examples/models/issuable_link_shared_examples.rb @@ -16,6 +16,7 @@ RSpec.shared_examples 'issuable link' do it { is_expected.to validate_presence_of(:source) } it { is_expected.to validate_presence_of(:target) } + it do is_expected.to validate_uniqueness_of(:source) .scoped_to(:target_id) diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb index aa40a2c7135..287b046cbec 100644 --- a/spec/support/shared_examples/models/member_shared_examples.rb +++ b/spec/support/shared_examples/models/member_shared_examples.rb @@ -63,16 +63,23 @@ RSpec.shared_examples '#valid_level_roles' do |entity_name| let(:entity) { create(entity_name) } # rubocop:disable Rails/SaveBang let(:entity_member) { create("#{entity_name}_member", :developer, source: entity, user: member_user) } let(:presenter) { described_class.new(entity_member, current_user: member_user) } - let(:expected_roles) { { 'Developer' => 30, 'Maintainer' => 40, 'Reporter' => 20 } } - it 'returns all roles when no parent member is present' do - expect(presenter.valid_level_roles).to eq(entity_member.class.access_level_roles) + context 'when no parent member is present' do + let(:all_permissible_roles) { entity_member.class.permissible_access_level_roles(member_user, entity) } + + it 'returns all permissible roles' do + expect(presenter.valid_level_roles).to eq(all_permissible_roles) + end end - it 'returns higher roles when a parent member is present' do - group.add_reporter(member_user) + context 'when parent member is present' do + before do + group.add_reporter(member_user) + end - expect(presenter.valid_level_roles).to eq(expected_roles) + it 'returns higher roles when a parent member is present' do + expect(presenter.valid_level_roles).to eq(expected_roles) + end end end diff --git a/spec/support/shared_examples/models/project_shared_examples.rb b/spec/support/shared_examples/models/project_shared_examples.rb index 475ac1da04b..0b880f00a22 100644 --- a/spec/support/shared_examples/models/project_shared_examples.rb +++ b/spec/support/shared_examples/models/project_shared_examples.rb @@ -25,3 +25,38 @@ RSpec.shared_examples 'returns true if project is inactive' do end end end + +RSpec.shared_examples 'checks parent group feature flag' do + let(:group) { subject_project.group } + let(:root_group) { group.parent } + + subject { subject_project.public_send(feature_flag_method) } + + context 'when feature flag is disabled globally' do + before do + stub_feature_flags(feature_flag => false) + end + + it { is_expected.to be_falsey } + end + + context 'when feature flag is enabled globally' do + it { is_expected.to be_truthy } + end + + context 'when feature flag is enabled for the root group' do + before do + stub_feature_flags(feature_flag => root_group) + end + + it { is_expected.to be_truthy } + end + + context 'when feature flag is enabled for the group' do + before do + stub_feature_flags(feature_flag => group) + end + + it { is_expected.to be_truthy } + end +end diff --git a/spec/support/shared_examples/models/taskable_shared_examples.rb b/spec/support/shared_examples/models/taskable_shared_examples.rb index 34b1d735bcd..3ae240c8da8 100644 --- a/spec/support/shared_examples/models/taskable_shared_examples.rb +++ b/spec/support/shared_examples/models/taskable_shared_examples.rb @@ -18,9 +18,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('2 of') - expect(subject.task_status).to match('5 tasks completed') + expect(subject.task_status).to match('5 checklist items completed') expect(subject.task_status_short).to match('2/') - expect(subject.task_status_short).to match('5 tasks') + expect(subject.task_status_short).to match('5 checklist items') end describe '#tasks?' do @@ -53,9 +53,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('3 of') - expect(subject.task_status).to match('9 tasks completed') + expect(subject.task_status).to match('9 checklist items completed') expect(subject.task_status_short).to match('3/') - expect(subject.task_status_short).to match('9 tasks') + expect(subject.task_status_short).to match('9 checklist items') end end @@ -68,9 +68,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('0 of') - expect(subject.task_status).to match('1 task completed') + expect(subject.task_status).to match('1 checklist item completed') expect(subject.task_status_short).to match('0/') - expect(subject.task_status_short).to match('1 task') + expect(subject.task_status_short).to match('1 checklist item') end end @@ -87,9 +87,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('0 of') - expect(subject.task_status).to match('0 tasks completed') + expect(subject.task_status).to match('0 checklist items completed') expect(subject.task_status_short).to match('0/') - expect(subject.task_status_short).to match('0 task') + expect(subject.task_status_short).to match('0 checklist items') end end @@ -102,9 +102,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('1 of') - expect(subject.task_status).to match('1 task completed') + expect(subject.task_status).to match('1 checklist item completed') expect(subject.task_status_short).to match('1/') - expect(subject.task_status_short).to match('1 task') + expect(subject.task_status_short).to match('1 checklist item') end end @@ -123,9 +123,9 @@ RSpec.shared_examples 'a Taskable' do it 'returns the correct task status' do expect(subject.task_status).to match('2 of') - expect(subject.task_status).to match('4 tasks completed') + expect(subject.task_status).to match('4 checklist items completed') expect(subject.task_status_short).to match('2/') - expect(subject.task_status_short).to match('4 tasks') + expect(subject.task_status_short).to match('4 checklist items') end end end |