summaryrefslogtreecommitdiff
path: root/spec/models
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models')
-rw-r--r--spec/models/ability_spec.rb41
-rw-r--r--spec/models/ci/pipeline_spec.rb24
-rw-r--r--spec/models/clusters/platforms/kubernetes_spec.rb10
-rw-r--r--spec/models/container_expiration_policy_spec.rb16
-rw-r--r--spec/models/integrations/emails_on_push_spec.rb8
-rw-r--r--spec/models/integrations/flowdock_spec.rb20
-rw-r--r--spec/models/merge_request_spec.rb11
-rw-r--r--spec/models/packages/package_spec.rb20
-rw-r--r--spec/models/project_spec.rb51
-rw-r--r--spec/models/remote_mirror_spec.rb41
-rw-r--r--spec/models/user_spec.rb64
11 files changed, 255 insertions, 51 deletions
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 3418d7d39ad..4bfa953df40 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -342,4 +342,45 @@ RSpec.describe Ability do
end
end
end
+
+ describe 'forgetting', :request_store do
+ it 'allows us to discard specific values from the DeclarativePolicy cache' do
+ user_a = build_stubbed(:user)
+ user_b = build_stubbed(:user)
+
+ # expect these keys to remain
+ Gitlab::SafeRequestStore[:administrator] = :wibble
+ Gitlab::SafeRequestStore['admin'] = :wobble
+ described_class.allowed?(user_b, :read_all_resources)
+ # expect the DeclarativePolicy cache keys added by this action not to remain
+ described_class.forgetting(/admin/) do
+ described_class.allowed?(user_a, :read_all_resources)
+ end
+
+ keys = Gitlab::SafeRequestStore.storage.keys
+
+ expect(keys).to include(
+ :administrator,
+ 'admin',
+ "/dp/condition/BasePolicy/admin/#{user_b.id}"
+ )
+ expect(keys).not_to include("/dp/condition/BasePolicy/admin/#{user_a.id}")
+ end
+
+ # regression spec for re-entrant admin condition checks
+ # See: https://gitlab.com/gitlab-org/gitlab/-/issues/332983
+ context 'when bypassing the session' do
+ let(:user) { build_stubbed(:admin) }
+ let(:ability) { :admin_all_resources } # any admin-only ability is fine here.
+
+ def check_ability
+ described_class.forgetting(/admin/) { described_class.allowed?(user, ability) }
+ end
+
+ it 'allows us to have re-entrant evaluation of admin-only permissions' do
+ expect { Gitlab::Auth::CurrentUserMode.bypass_session!(user.id) }
+ .to change { check_ability }.from(false).to(true)
+ end
+ end
+ end
end
diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb
index 72af40e31e0..26fc4b140c1 100644
--- a/spec/models/ci/pipeline_spec.rb
+++ b/spec/models/ci/pipeline_spec.rb
@@ -4625,8 +4625,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
end
describe '#build_matchers' do
- let_it_be(:pipeline) { create(:ci_pipeline) }
- let_it_be(:builds) { create_list(:ci_build, 2, pipeline: pipeline, project: pipeline.project) }
+ let_it_be(:user) { create(:user) }
+ let_it_be(:pipeline) { create(:ci_pipeline, user: user) }
+ let_it_be(:builds) { create_list(:ci_build, 2, pipeline: pipeline, project: pipeline.project, user: user) }
+
+ let(:project) { pipeline.project }
subject(:matchers) { pipeline.build_matchers }
@@ -4635,5 +4638,22 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
expect(matchers).to all be_a(Gitlab::Ci::Matching::BuildMatcher)
expect(matchers.first.build_ids).to match_array(builds.map(&:id))
end
+
+ context 'with retried builds' do
+ let(:retried_build) { builds.first }
+
+ before do
+ stub_not_protect_default_branch
+ project.add_developer(user)
+
+ retried_build.cancel!
+ ::Ci::Build.retry(retried_build, user)
+ end
+
+ it 'does not include retried builds' do
+ expect(matchers.size).to eq(1)
+ expect(matchers.first.build_ids).not_to include(retried_build.id)
+ end
+ end
end
end
diff --git a/spec/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb
index 07e64889b93..a4cae93ff84 100644
--- a/spec/models/clusters/platforms/kubernetes_spec.rb
+++ b/spec/models/clusters/platforms/kubernetes_spec.rb
@@ -439,16 +439,6 @@ RSpec.describe Clusters::Platforms::Kubernetes do
include_examples 'successful deployment request'
end
-
- context 'when canary_ingress_weight_control feature flag is disabled' do
- before do
- stub_feature_flags(canary_ingress_weight_control: false)
- end
-
- it 'does not fetch ingress data from kubernetes' do
- expect(subject[:ingresses]).to be_empty
- end
- end
end
context 'when the kubernetes integration is disabled' do
diff --git a/spec/models/container_expiration_policy_spec.rb b/spec/models/container_expiration_policy_spec.rb
index 32ec5ed161a..191913ed454 100644
--- a/spec/models/container_expiration_policy_spec.rb
+++ b/spec/models/container_expiration_policy_spec.rb
@@ -139,15 +139,23 @@ RSpec.describe ContainerExpirationPolicy, type: :model do
end
end
- describe '.with_container_repositories' do
- subject { described_class.with_container_repositories }
-
+ context 'policies with container repositories' do
let_it_be(:policy1) { create(:container_expiration_policy) }
let_it_be(:container_repository1) { create(:container_repository, project: policy1.project) }
let_it_be(:policy2) { create(:container_expiration_policy) }
let_it_be(:container_repository2) { create(:container_repository, project: policy2.project) }
let_it_be(:policy3) { create(:container_expiration_policy) }
- it { is_expected.to contain_exactly(policy1, policy2) }
+ describe '.with_container_repositories' do
+ subject { described_class.with_container_repositories }
+
+ it { is_expected.to contain_exactly(policy1, policy2) }
+ end
+
+ describe '.without_container_repositories' do
+ subject { described_class.without_container_repositories }
+
+ it { is_expected.to contain_exactly(policy3) }
+ end
end
end
diff --git a/spec/models/integrations/emails_on_push_spec.rb b/spec/models/integrations/emails_on_push_spec.rb
index ca060f4155e..c82d4bdff9b 100644
--- a/spec/models/integrations/emails_on_push_spec.rb
+++ b/spec/models/integrations/emails_on_push_spec.rb
@@ -88,7 +88,7 @@ RSpec.describe Integrations::EmailsOnPush do
describe '#execute' do
let(:push_data) { { object_kind: 'push' } }
let(:project) { create(:project, :repository) }
- let(:service) { create(:emails_on_push_service, project: project) }
+ let(:integration) { create(:emails_on_push_integration, project: project) }
let(:recipients) { 'test@gitlab.com' }
before do
@@ -105,7 +105,7 @@ RSpec.describe Integrations::EmailsOnPush do
it 'sends email' do
expect(EmailsOnPushWorker).not_to receive(:perform_async)
- service.execute(push_data)
+ integration.execute(push_data)
end
end
@@ -119,7 +119,7 @@ RSpec.describe Integrations::EmailsOnPush do
it 'does not send email' do
expect(EmailsOnPushWorker).not_to receive(:perform_async)
- service.execute(push_data)
+ integration.execute(push_data)
end
end
@@ -128,7 +128,7 @@ RSpec.describe Integrations::EmailsOnPush do
expect(project).to receive(:emails_disabled?).and_return(true)
expect(EmailsOnPushWorker).not_to receive(:perform_async)
- service.execute(push_data)
+ integration.execute(push_data)
end
end
diff --git a/spec/models/integrations/flowdock_spec.rb b/spec/models/integrations/flowdock_spec.rb
index 2de6f7dd2f1..189831fa32d 100644
--- a/spec/models/integrations/flowdock_spec.rb
+++ b/spec/models/integrations/flowdock_spec.rb
@@ -29,27 +29,29 @@ RSpec.describe Integrations::Flowdock do
describe "Execute" do
let(:user) { create(:user) }
let(:project) { create(:project, :repository) }
+ let(:sample_data) { Gitlab::DataBuilder::Push.build_sample(project, user) }
+ let(:api_url) { 'https://api.flowdock.com/v1/messages' }
+
+ subject(:flowdock_integration) { described_class.new }
before do
- @flowdock_service = described_class.new
- allow(@flowdock_service).to receive_messages(
+ allow(flowdock_integration).to receive_messages(
project_id: project.id,
project: project,
service_hook: true,
token: 'verySecret'
)
- @sample_data = Gitlab::DataBuilder::Push.build_sample(project, user)
- @api_url = 'https://api.flowdock.com/v1/messages'
- WebMock.stub_request(:post, @api_url)
+ WebMock.stub_request(:post, api_url)
end
it "calls FlowDock API" do
- @flowdock_service.execute(@sample_data)
- @sample_data[:commits].each do |commit|
+ flowdock_integration.execute(sample_data)
+
+ sample_data[:commits].each do |commit|
# One request to Flowdock per new commit
- next if commit[:id] == @sample_data[:before]
+ next if commit[:id] == sample_data[:before]
- expect(WebMock).to have_requested(:post, @api_url).with(
+ expect(WebMock).to have_requested(:post, api_url).with(
body: /#{commit[:id]}.*#{project.path}/
).once
end
diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb
index 94b4c1901b8..73b1cb13f19 100644
--- a/spec/models/merge_request_spec.rb
+++ b/spec/models/merge_request_spec.rb
@@ -4951,4 +4951,15 @@ RSpec.describe MergeRequest, factory_default: :keep do
it { is_expected.to eq(true) }
end
end
+
+ describe '.from_fork' do
+ let!(:project) { create(:project, :repository) }
+ let!(:forked_project) { fork_project(project) }
+ let!(:fork_mr) { create(:merge_request, source_project: forked_project, target_project: project) }
+ let!(:regular_mr) { create(:merge_request, source_project: project) }
+
+ it 'returns merge requests from forks only' do
+ expect(described_class.from_fork).to eq([fork_mr])
+ end
+ end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 1e44327c089..b2c1d51e4af 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -1019,10 +1019,24 @@ RSpec.describe Packages::Package, type: :model do
package.composer_metadatum.reload
end
- it 'schedule the update job' do
- expect(::Packages::Composer::CacheUpdateWorker).to receive(:perform_async).with(project.id, package_name, package.composer_metadatum.version_cache_sha)
+ context 'with feature flag disabled' do
+ before do
+ stub_feature_flags(disable_composer_callback: false)
+ end
+
+ it 'schedule the update job' do
+ expect(::Packages::Composer::CacheUpdateWorker).to receive(:perform_async).with(project.id, package_name, package.composer_metadatum.version_cache_sha)
+
+ package.destroy!
+ end
+ end
- package.destroy!
+ context 'with feature flag enabled' do
+ it 'does nothing' do
+ expect(::Packages::Composer::CacheUpdateWorker).not_to receive(:perform_async)
+
+ package.destroy!
+ end
end
end
end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 78e32571d7d..7eb02749f72 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_one(:slack_service) }
it { is_expected.to have_one(:microsoft_teams_service) }
it { is_expected.to have_one(:mattermost_service) }
- it { is_expected.to have_one(:hangouts_chat_service) }
+ it { is_expected.to have_one(:hangouts_chat_integration) }
it { is_expected.to have_one(:unify_circuit_service) }
it { is_expected.to have_one(:webex_teams_service) }
it { is_expected.to have_one(:packagist_service) }
@@ -49,11 +49,11 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_one(:datadog_integration) }
it { is_expected.to have_one(:discord_integration) }
it { is_expected.to have_one(:drone_ci_integration) }
- it { is_expected.to have_one(:emails_on_push_service) }
+ it { is_expected.to have_one(:emails_on_push_integration) }
it { is_expected.to have_one(:pipelines_email_service) }
- it { is_expected.to have_one(:irker_service) }
+ it { is_expected.to have_one(:irker_integration) }
it { is_expected.to have_one(:pivotaltracker_service) }
- it { is_expected.to have_one(:flowdock_service) }
+ it { is_expected.to have_one(:flowdock_integration) }
it { is_expected.to have_one(:assembla_integration) }
it { is_expected.to have_one(:slack_slash_commands_service) }
it { is_expected.to have_one(:mattermost_slash_commands_service) }
@@ -65,8 +65,8 @@ RSpec.describe Project, factory_default: :keep do
it { is_expected.to have_one(:youtrack_service) }
it { is_expected.to have_one(:custom_issue_tracker_integration) }
it { is_expected.to have_one(:bugzilla_integration) }
- it { is_expected.to have_one(:ewm_service) }
- it { is_expected.to have_one(:external_wiki_service) }
+ it { is_expected.to have_one(:ewm_integration) }
+ it { is_expected.to have_one(:external_wiki_integration) }
it { is_expected.to have_one(:confluence_integration) }
it { is_expected.to have_one(:project_feature) }
it { is_expected.to have_one(:project_repository) }
@@ -1661,6 +1661,45 @@ RSpec.describe Project, factory_default: :keep do
end
end
+ describe '.find_by_url' do
+ subject { described_class.find_by_url(url) }
+
+ let_it_be(:project) { create(:project) }
+
+ before do
+ stub_config_setting(host: 'gitlab.com')
+ end
+
+ context 'url is internal' do
+ let(:url) { "https://#{Gitlab.config.gitlab.host}/#{path}" }
+
+ context 'path is recognised as a project path' do
+ let(:path) { project.full_path }
+
+ it { is_expected.to eq(project) }
+
+ it 'returns nil if the path detection throws an error' do
+ expect(Rails.application.routes).to receive(:recognize_path).with(url) { raise ActionController::RoutingError, 'test' }
+
+ expect { subject }.not_to raise_error(ActionController::RoutingError)
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'path is not a project path' do
+ let(:path) { 'probably/missing.git' }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ context 'url is external' do
+ let(:url) { "https://foo.com/bar/baz.git" }
+
+ it { is_expected.to be_nil }
+ end
+ end
+
context 'repository storage by default' do
let(:project) { build(:project) }
diff --git a/spec/models/remote_mirror_spec.rb b/spec/models/remote_mirror_spec.rb
index d6951b5926e..a64b01967ef 100644
--- a/spec/models/remote_mirror_spec.rb
+++ b/spec/models/remote_mirror_spec.rb
@@ -157,19 +157,34 @@ RSpec.describe RemoteMirror, :mailer do
end
describe '#update_repository' do
- it 'performs update including options' do
- git_remote_mirror = stub_const('Gitlab::Git::RemoteMirror', spy)
- mirror = build(:remote_mirror)
-
- expect(mirror).to receive(:options_for_update).and_return(keep_divergent_refs: true)
- mirror.update_repository
-
- expect(git_remote_mirror).to have_received(:new).with(
- mirror.project.repository.raw,
- mirror.remote_name,
- keep_divergent_refs: true
- )
- expect(git_remote_mirror).to have_received(:update)
+ shared_examples 'an update' do
+ it 'performs update including options' do
+ git_remote_mirror = stub_const('Gitlab::Git::RemoteMirror', spy)
+ mirror = build(:remote_mirror)
+
+ expect(mirror).to receive(:options_for_update).and_return(keep_divergent_refs: true)
+ mirror.update_repository(inmemory_remote: inmemory)
+
+ expect(git_remote_mirror).to have_received(:new).with(
+ mirror.project.repository.raw,
+ mirror.remote_name,
+ inmemory ? mirror.url : nil,
+ keep_divergent_refs: true
+ )
+ expect(git_remote_mirror).to have_received(:update)
+ end
+ end
+
+ context 'with inmemory remote' do
+ let(:inmemory) { true }
+
+ it_behaves_like 'an update'
+ end
+
+ context 'with on-disk remote' do
+ let(:inmemory) { false }
+
+ it_behaves_like 'an update'
end
end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index f1c30a646f5..e5c86e69ffc 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -5224,6 +5224,70 @@ RSpec.describe User do
end
end
+ describe '#password_expired_if_applicable?' do
+ let(:user) { build(:user, password_expires_at: password_expires_at) }
+
+ subject { user.password_expired_if_applicable? }
+
+ context 'when user is not ldap user' do
+ context 'when password_expires_at is not set' do
+ let(:password_expires_at) {}
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'when password_expires_at is in the past' do
+ let(:password_expires_at) { 1.minute.ago }
+
+ it 'returns true' do
+ is_expected.to be_truthy
+ end
+ end
+
+ context 'when password_expires_at is in the future' do
+ let(:password_expires_at) { 1.minute.from_now }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+
+ context 'when user is ldap user' do
+ let(:user) { build(:user, password_expires_at: password_expires_at) }
+
+ before do
+ allow(user).to receive(:ldap_user?).and_return(true)
+ end
+
+ context 'when password_expires_at is not set' do
+ let(:password_expires_at) {}
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'when password_expires_at is in the past' do
+ let(:password_expires_at) { 1.minute.ago }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+
+ context 'when password_expires_at is in the future' do
+ let(:password_expires_at) { 1.minute.from_now }
+
+ it 'returns false' do
+ is_expected.to be_falsey
+ end
+ end
+ end
+ end
+
describe '#read_only_attribute?' do
context 'when synced attributes metadata is present' do
it 'delegates to synced_attributes_metadata' do