diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2021-02-18 10:34:06 +0000 |
commit | 859a6fb938bb9ee2a317c46dfa4fcc1af49608f0 (patch) | |
tree | d7f2700abe6b4ffcb2dcfc80631b2d87d0609239 /spec/models/concerns | |
parent | 446d496a6d000c73a304be52587cd9bbc7493136 (diff) | |
download | gitlab-ce-859a6fb938bb9ee2a317c46dfa4fcc1af49608f0.tar.gz |
Add latest changes from gitlab-org/gitlab@13-9-stable-eev13.9.0-rc42
Diffstat (limited to 'spec/models/concerns')
-rw-r--r-- | spec/models/concerns/atomic_internal_id_spec.rb | 152 | ||||
-rw-r--r-- | spec/models/concerns/bulk_insert_safe_spec.rb | 7 | ||||
-rw-r--r-- | spec/models/concerns/featurable_spec.rb | 16 | ||||
-rw-r--r-- | spec/models/concerns/issuable_spec.rb | 19 | ||||
-rw-r--r-- | spec/models/concerns/nullify_if_blank_spec.rb | 51 | ||||
-rw-r--r-- | spec/models/concerns/protected_ref_spec.rb | 77 | ||||
-rw-r--r-- | spec/models/concerns/spammable_spec.rb | 55 | ||||
-rw-r--r-- | spec/models/concerns/token_authenticatable_spec.rb | 4 | ||||
-rw-r--r-- | spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb | 8 |
9 files changed, 353 insertions, 36 deletions
diff --git a/spec/models/concerns/atomic_internal_id_spec.rb b/spec/models/concerns/atomic_internal_id_spec.rb index 5ee3c012dc9..35b0f107676 100644 --- a/spec/models/concerns/atomic_internal_id_spec.rb +++ b/spec/models/concerns/atomic_internal_id_spec.rb @@ -87,6 +87,158 @@ RSpec.describe AtomicInternalId do end end + describe '#clear_scope_iid!' do + context 'when no ensure_if condition is given' do + it 'clears automatically set IIDs' do + expect(milestone).to receive(:clear_project_iid!).and_call_original + + expect_iid_to_be_set_and_rollback(milestone) + + expect(milestone.iid).to be_nil + end + + it 'does not clear manually set IIDS' do + milestone.iid = external_iid + + expect(milestone).to receive(:clear_project_iid!).and_call_original + + expect_iid_to_be_set_and_rollback(milestone) + + expect(milestone.iid).to eq(external_iid) + end + end + + context 'when an ensure_if condition is given' do + let(:test_class) do + Class.new(ApplicationRecord) do + include AtomicInternalId + include Importable + + self.table_name = :milestones + + belongs_to :project + + has_internal_id :iid, scope: :project, track_if: -> { !importing }, ensure_if: -> { !importing } + + def self.name + 'TestClass' + end + end + end + + let(:instance) { test_class.new(milestone.attributes) } + + context 'when the ensure_if condition evaluates to true' do + it 'clears automatically set IIDs' do + expect(instance).to receive(:clear_project_iid!).and_call_original + + expect_iid_to_be_set_and_rollback(instance) + + expect(instance.iid).to be_nil + end + + it 'does not clear manually set IIDs' do + instance.iid = external_iid + + expect(instance).to receive(:clear_project_iid!).and_call_original + + expect_iid_to_be_set_and_rollback(instance) + + expect(instance.iid).to eq(external_iid) + end + end + + context 'when the ensure_if condition evaluates to false' do + before do + instance.importing = true + end + + it 'does not clear IIDs' do + instance.iid = external_iid + + expect(instance).not_to receive(:clear_project_iid!) + + expect_iid_to_be_set_and_rollback(instance) + + expect(instance.iid).to eq(external_iid) + end + end + end + + def expect_iid_to_be_set_and_rollback(instance) + ActiveRecord::Base.transaction(requires_new: true) do + instance.save! + + expect(instance.iid).not_to be_nil + + raise ActiveRecord::Rollback + end + end + end + + describe '#validate_scope_iid_exists!' do + let(:test_class) do + Class.new(ApplicationRecord) do + include AtomicInternalId + include Importable + + self.table_name = :milestones + + belongs_to :project + + def self.name + 'TestClass' + end + end + end + + let(:instance) { test_class.new(milestone.attributes) } + + before do + test_class.has_internal_id :iid, scope: :project, presence: presence, ensure_if: -> { !importing } + + instance.importing = true + end + + context 'when the presence flag is set' do + let(:presence) { true } + + it 'raises an error for blank iids on create' do + expect do + instance.save! + end.to raise_error(described_class::MissingValueError, 'iid was unexpectedly blank!') + end + + it 'raises an error for blank iids on update' do + instance.iid = 100 + instance.save! + + instance.iid = nil + + expect do + instance.save! + end.to raise_error(described_class::MissingValueError, 'iid was unexpectedly blank!') + end + end + + context 'when the presence flag is not set' do + let(:presence) { false } + + it 'does not raise an error for blank iids on create' do + expect { instance.save! }.not_to raise_error + end + + it 'does not raise an error for blank iids on update' do + instance.iid = 100 + instance.save! + + instance.iid = nil + + expect { instance.save! }.not_to raise_error + end + end + end + describe '.with_project_iid_supply' do let(:iid) { 100 } diff --git a/spec/models/concerns/bulk_insert_safe_spec.rb b/spec/models/concerns/bulk_insert_safe_spec.rb index 82b0c00b396..e40b0cf11ff 100644 --- a/spec/models/concerns/bulk_insert_safe_spec.rb +++ b/spec/models/concerns/bulk_insert_safe_spec.rb @@ -44,7 +44,6 @@ RSpec.describe BulkInsertSafe do insecure_mode: false default_value_for :enum_value, 'case_1' - default_value_for :secret_value, 'my-secret' default_value_for :sha_value, '2fd4e1c67a2d28fced849ee1bb76e7391b93eb12' default_value_for :jsonb_value, { "key" => "value" } @@ -53,11 +52,11 @@ RSpec.describe BulkInsertSafe do end def self.valid_list(count) - Array.new(count) { |n| new(name: "item-#{n}") } + Array.new(count) { |n| new(name: "item-#{n}", secret_value: 'my-secret') } end def self.invalid_list(count) - Array.new(count) { new } + Array.new(count) { new(secret_value: 'my-secret') } end end end @@ -102,7 +101,7 @@ RSpec.describe BulkInsertSafe do context 'primary keys' do it 'raises error if primary keys are set prior to insertion' do - item = bulk_insert_item_class.new(name: 'valid', id: 10) + item = bulk_insert_item_class.new(name: 'valid', id: 10, secret_value: 'my-secret') expect { bulk_insert_item_class.bulk_insert!([item]) } .to raise_error(bulk_insert_item_class::PrimaryKeySetError) diff --git a/spec/models/concerns/featurable_spec.rb b/spec/models/concerns/featurable_spec.rb index 99acc563950..b550d22f686 100644 --- a/spec/models/concerns/featurable_spec.rb +++ b/spec/models/concerns/featurable_spec.rb @@ -134,22 +134,6 @@ RSpec.describe Featurable do expect(project.feature_available?(:issues, user)).to eq(true) end end - - context 'when feature is disabled by a feature flag' do - it 'returns false' do - stub_feature_flags(issues: false) - - expect(project.feature_available?(:issues, user)).to eq(false) - end - end - - context 'when feature is enabled by a feature flag' do - it 'returns true' do - stub_feature_flags(issues: true) - - expect(project.feature_available?(:issues, user)).to eq(true) - end - end end describe '#*_enabled?' do diff --git a/spec/models/concerns/issuable_spec.rb b/spec/models/concerns/issuable_spec.rb index ff5b270cf33..3545c8e9686 100644 --- a/spec/models/concerns/issuable_spec.rb +++ b/spec/models/concerns/issuable_spec.rb @@ -4,6 +4,7 @@ require 'spec_helper' RSpec.describe Issuable do include ProjectForksHelper + using RSpec::Parameterized::TableSyntax let(:issuable_class) { Issue } let(:issue) { create(:issue, title: 'An issue', description: 'A description') } @@ -45,13 +46,17 @@ RSpec.describe Issuable do end it { is_expected.to validate_presence_of(:project) } - it { is_expected.to validate_presence_of(:iid) } it { is_expected.to validate_presence_of(:author) } it { is_expected.to validate_presence_of(:title) } it { is_expected.to validate_length_of(:title).is_at_most(described_class::TITLE_LENGTH_MAX) } it { is_expected.to validate_length_of(:description).is_at_most(described_class::DESCRIPTION_LENGTH_MAX).on(:create) } - it_behaves_like 'validates description length with custom validation' + it_behaves_like 'validates description length with custom validation' do + before do + allow(InternalId).to receive(:generate_next).and_call_original + end + end + it_behaves_like 'truncates the description to its allowed maximum length on import' end end @@ -820,8 +825,6 @@ RSpec.describe Issuable do end describe '#supports_time_tracking?' do - using RSpec::Parameterized::TableSyntax - where(:issuable_type, :supports_time_tracking) do :issue | true :incident | true @@ -838,8 +841,6 @@ RSpec.describe Issuable do end describe '#supports_severity?' do - using RSpec::Parameterized::TableSyntax - where(:issuable_type, :supports_severity) do :issue | false :incident | true @@ -856,8 +857,6 @@ RSpec.describe Issuable do end describe '#incident?' do - using RSpec::Parameterized::TableSyntax - where(:issuable_type, :incident) do :issue | false :incident | true @@ -874,8 +873,6 @@ RSpec.describe Issuable do end describe '#supports_issue_type?' do - using RSpec::Parameterized::TableSyntax - where(:issuable_type, :supports_issue_type) do :issue | true :merge_request | false @@ -894,8 +891,6 @@ RSpec.describe Issuable do subject { issuable.severity } context 'when issuable is not an incident' do - using RSpec::Parameterized::TableSyntax - where(:issuable_type, :severity) do :issue | 'unknown' :merge_request | 'unknown' diff --git a/spec/models/concerns/nullify_if_blank_spec.rb b/spec/models/concerns/nullify_if_blank_spec.rb new file mode 100644 index 00000000000..2d1bdba39dd --- /dev/null +++ b/spec/models/concerns/nullify_if_blank_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe NullifyIfBlank do + let_it_be(:model) do + Class.new(ApplicationRecord) do + include NullifyIfBlank + + nullify_if_blank :name + + self.table_name = 'users' + end + end + + context 'attribute exists' do + let(:instance) { model.new(name: name) } + + subject { instance.name } + + before do + instance.validate + end + + context 'attribute is blank' do + let(:name) { '' } + + it { is_expected.to be_nil } + end + + context 'attribute is nil' do + let(:name) { nil } + + it { is_expected.to be_nil} + end + + context 'attribute is not blank' do + let(:name) { 'name' } + + it { is_expected.to eq('name') } + end + end + + context 'attribute does not exist' do + before do + model.table_name = 'issues' + end + + it { expect { model.new.valid? }.to raise_error(ActiveModel::UnknownAttributeError) } + end +end diff --git a/spec/models/concerns/protected_ref_spec.rb b/spec/models/concerns/protected_ref_spec.rb new file mode 100644 index 00000000000..0a020736269 --- /dev/null +++ b/spec/models/concerns/protected_ref_spec.rb @@ -0,0 +1,77 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe ProtectedRef do + using RSpec::Parameterized::TableSyntax + + let_it_be(:project) { create(:project, :repository) } + let_it_be(:user) { create(:user, maintainer_projects: [project]) } + + where(:klass, :factory, :action) do + ProtectedBranch | :protected_branch | :push + ProtectedTag | :protected_tag | :create + end + + with_them do + describe '#protected_ref_accessible_to?' do + subject do + klass.protected_ref_accessible_to?('release', user, project: project, action: action) + end + + it 'user cannot do action if rules do not exist' do + is_expected.to be_falsy + end + + context 'the ref is protected' do + let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') } + + context 'all rules permit action' do + let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') } + + it 'user can do action' do + is_expected.to be_truthy + end + end + + context 'one of the rules forbids action' do + let!(:no_one_can) { create(factory, :"no_one_can_#{action}", project: project, name: 'release*') } + + it 'user cannot do action' do + is_expected.to be_falsy + end + end + end + end + + describe '#developers_can?' do + subject do + klass.developers_can?(action, 'release') + end + + it 'developers cannot do action if rules do not exist' do + is_expected.to be_falsy + end + + context 'the ref is protected' do + let!(:default_rule) { create(factory, :"developers_can_#{action}", project: project, name: 'release') } + + context 'all rules permit developers to do action' do + let!(:developers_can) { create(factory, :"developers_can_#{action}", project: project, name: 'release*') } + + it 'developers can do action' do + is_expected.to be_truthy + end + end + + context 'one of the rules forbids developers to do action' do + let!(:maintainers_can) { create(factory, :"maintainers_can_#{action}", project: project, name: 'release*') } + + it 'developers cannot do action' do + is_expected.to be_falsy + end + end + end + end + end +end diff --git a/spec/models/concerns/spammable_spec.rb b/spec/models/concerns/spammable_spec.rb index d4fcb2e99eb..3c5f3b2d2ad 100644 --- a/spec/models/concerns/spammable_spec.rb +++ b/spec/models/concerns/spammable_spec.rb @@ -120,6 +120,61 @@ RSpec.describe Spammable do end end + describe '#render_recaptcha?' do + before do + allow(Gitlab::Recaptcha).to receive(:enabled?) { recaptcha_enabled } + end + + context 'when recaptcha is not enabled' do + let(:recaptcha_enabled) { false } + + it 'returns false' do + expect(issue.render_recaptcha?).to eq(false) + end + end + + context 'when recaptcha is enabled' do + let(:recaptcha_enabled) { true } + + context 'when there are two or more errors' do + before do + issue.errors.add(:base, 'a spam error') + issue.errors.add(:base, 'some other error') + end + + it 'returns false' do + expect(issue.render_recaptcha?).to eq(false) + end + end + + context 'when there are less than two errors' do + before do + issue.errors.add(:base, 'a spam error') + end + + context 'when spammable does not need recaptcha' do + before do + issue.needs_recaptcha = false + end + + it 'returns false' do + expect(issue.render_recaptcha?).to eq(false) + end + end + + context 'when spammable needs recaptcha' do + before do + issue.needs_recaptcha! + end + + it 'returns false' do + expect(issue.render_recaptcha?).to eq(true) + end + end + end + end + end + describe '#clear_spam_flags!' do it 'clears spam and recaptcha flags' do issue.spam = true diff --git a/spec/models/concerns/token_authenticatable_spec.rb b/spec/models/concerns/token_authenticatable_spec.rb index d8b77e1cd0d..2df76684d71 100644 --- a/spec/models/concerns/token_authenticatable_spec.rb +++ b/spec/models/concerns/token_authenticatable_spec.rb @@ -54,7 +54,7 @@ RSpec.describe ApplicationSetting, 'TokenAuthenticatable' do it 'persists new token as an encrypted string' do expect(subject).to eq settings.reload.runners_registration_token expect(settings.read_attribute('runners_registration_token_encrypted')) - .to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject) + .to eq Gitlab::CryptoHelper.aes256_gcm_encrypt(subject, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC) expect(settings).to be_persisted end @@ -243,7 +243,7 @@ RSpec.describe Ci::Build, 'TokenAuthenticatable' do it 'persists new token as an encrypted string' do build.ensure_token! - encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token) + encrypted = Gitlab::CryptoHelper.aes256_gcm_encrypt(build.token, nonce: Gitlab::CryptoHelper::AES256_GCM_IV_STATIC) expect(build.read_attribute('token_encrypted')).to eq encrypted end diff --git a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb index f6b8cf7def4..1e1cd97e410 100644 --- a/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb +++ b/spec/models/concerns/token_authenticatable_strategies/encrypted_spec.rb @@ -68,6 +68,10 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do context 'when using optional strategy' do let(:options) { { encrypted: :optional } } + before do + stub_feature_flags(dynamic_nonce_creation: false) + end + it 'returns decrypted token when an encrypted token is present' do allow(instance).to receive(:read_attribute) .with('some_field_encrypted') @@ -124,7 +128,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do it 'writes encrypted token and removes plaintext token and returns it' do expect(instance).to receive(:[]=) - .with('some_field_encrypted', encrypted) + .with('some_field_encrypted', any_args) expect(instance).to receive(:[]=) .with('some_field', nil) @@ -137,7 +141,7 @@ RSpec.describe TokenAuthenticatableStrategies::Encrypted do it 'writes encrypted token and writes plaintext token' do expect(instance).to receive(:[]=) - .with('some_field_encrypted', encrypted) + .with('some_field_encrypted', any_args) expect(instance).to receive(:[]=) .with('some_field', 'my-value') |