Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-05-17 19:05:49 +0300
commit43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch)
treedceebdc68925362117480a5d672bcff122fb625b /spec/finders
parent20c84b99005abd1c82101dfeff264ac50d2df211 (diff)
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'spec/finders')
-rw-r--r--spec/finders/abuse_reports_finder_spec.rb129
-rw-r--r--spec/finders/access_requests_finder_spec.rb9
-rw-r--r--spec/finders/achievements/achievements_finder_spec.rb26
-rw-r--r--spec/finders/alert_management/alerts_finder_spec.rb17
-rw-r--r--spec/finders/ci/pipelines_for_merge_request_finder_spec.rb68
-rw-r--r--spec/finders/clusters/agent_tokens_finder_spec.rb9
-rw-r--r--spec/finders/clusters/agents/authorizations/ci_access/finder_spec.rb (renamed from spec/finders/clusters/agent_authorizations_finder_spec.rb)30
-rw-r--r--spec/finders/clusters/agents/authorizations/user_access/finder_spec.rb198
-rw-r--r--spec/finders/concerns/finder_with_group_hierarchy_spec.rb76
-rw-r--r--spec/finders/context_commits_finder_spec.rb21
-rw-r--r--spec/finders/crm/contacts_finder_spec.rb4
-rw-r--r--spec/finders/crm/organizations_finder_spec.rb22
-rw-r--r--spec/finders/data_transfer/group_data_transfer_finder_spec.rb84
-rw-r--r--spec/finders/data_transfer/mocked_transfer_finder_spec.rb22
-rw-r--r--spec/finders/data_transfer/project_data_transfer_finder_spec.rb80
-rw-r--r--spec/finders/deployments_finder_spec.rb71
-rw-r--r--spec/finders/fork_targets_finder_spec.rb25
-rw-r--r--spec/finders/group_descendants_finder_spec.rb22
-rw-r--r--spec/finders/group_members_finder_spec.rb149
-rw-r--r--spec/finders/groups/accepting_group_transfers_finder_spec.rb14
-rw-r--r--spec/finders/groups/accepting_project_creations_finder_spec.rb104
-rw-r--r--spec/finders/groups/accepting_project_imports_finder_spec.rb105
-rw-r--r--spec/finders/groups/accepting_project_shares_finder_spec.rb122
-rw-r--r--spec/finders/groups/accepting_project_transfers_finder_spec.rb42
-rw-r--r--spec/finders/groups/user_groups_finder_spec.rb20
-rw-r--r--spec/finders/issuables/crm_organization_filter_spec.rb22
-rw-r--r--spec/finders/members_finder_spec.rb39
-rw-r--r--spec/finders/merge_requests_finder_spec.rb76
-rw-r--r--spec/finders/milestones_finder_spec.rb92
-rw-r--r--spec/finders/notes_finder_spec.rb57
-rw-r--r--spec/finders/packages/conan/package_finder_spec.rb25
-rw-r--r--spec/finders/packages/group_packages_finder_spec.rb4
-rw-r--r--spec/finders/packages/npm/package_finder_spec.rb8
-rw-r--r--spec/finders/pending_todos_finder_spec.rb57
-rw-r--r--spec/finders/personal_access_tokens_finder_spec.rb2
-rw-r--r--spec/finders/projects_finder_spec.rb48
-rw-r--r--spec/finders/serverless_domain_finder_spec.rb103
-rw-r--r--spec/finders/snippets_finder_spec.rb21
-rw-r--r--spec/finders/template_finder_spec.rb14
-rw-r--r--spec/finders/users_finder_spec.rb8
40 files changed, 1589 insertions, 456 deletions
diff --git a/spec/finders/abuse_reports_finder_spec.rb b/spec/finders/abuse_reports_finder_spec.rb
index 52620b3e421..ee93d042ca2 100644
--- a/spec/finders/abuse_reports_finder_spec.rb
+++ b/spec/finders/abuse_reports_finder_spec.rb
@@ -3,25 +3,142 @@
require 'spec_helper'
RSpec.describe AbuseReportsFinder, '#execute' do
+ let_it_be(:user1) { create(:user) }
+ let_it_be(:user2) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:abuse_report_1) { create(:abuse_report, id: 20, category: 'spam', user: user1) }
+ let_it_be(:abuse_report_2) do
+ create(:abuse_report, :closed, id: 30, category: 'phishing', user: user2, reporter: reporter)
+ end
+
let(:params) { {} }
- let!(:user1) { create(:user) }
- let!(:user2) { create(:user) }
- let!(:abuse_report_1) { create(:abuse_report, user: user1) }
- let!(:abuse_report_2) { create(:abuse_report, user: user2) }
subject { described_class.new(params).execute }
- context 'empty params' do
+ context 'when params is empty' do
it 'returns all abuse reports' do
expect(subject).to match_array([abuse_report_1, abuse_report_2])
end
end
- context 'params[:user_id] is present' do
+ context 'when params[:user_id] is present' do
let(:params) { { user_id: user2 } }
it 'returns abuse reports for the specified user' do
expect(subject).to match_array([abuse_report_2])
end
end
+
+ shared_examples 'returns filtered reports' do |filter_field|
+ it "returns abuse reports filtered by #{filter_field}_id" do
+ expect(subject).to match_array(filtered_reports)
+ end
+
+ context "when no user has username = params[:#{filter_field}]" do
+ before do
+ allow(User).to receive_message_chain(:by_username, :pick)
+ .with(params[filter_field])
+ .with(:id)
+ .and_return(nil)
+ end
+
+ it 'returns all abuse reports' do
+ expect(subject).to match_array([abuse_report_1, abuse_report_2])
+ end
+ end
+ end
+
+ context 'when params[:user] is present' do
+ it_behaves_like 'returns filtered reports', :user do
+ let(:params) { { user: user1.username } }
+ let(:filtered_reports) { [abuse_report_1] }
+ end
+ end
+
+ context 'when params[:reporter] is present' do
+ it_behaves_like 'returns filtered reports', :reporter do
+ let(:params) { { reporter: reporter.username } }
+ let(:filtered_reports) { [abuse_report_2] }
+ end
+ end
+
+ context 'when params[:status] is present' do
+ context 'when value is "open"' do
+ let(:params) { { status: 'open' } }
+
+ it 'returns only open abuse reports' do
+ expect(subject).to match_array([abuse_report_1])
+ end
+ end
+
+ context 'when value is "closed"' do
+ let(:params) { { status: 'closed' } }
+
+ it 'returns only closed abuse reports' do
+ expect(subject).to match_array([abuse_report_2])
+ end
+ end
+
+ context 'when value is not a valid status' do
+ let(:params) { { status: 'partial' } }
+
+ it 'defaults to returning open abuse reports' do
+ expect(subject).to match_array([abuse_report_1])
+ end
+ end
+
+ context 'when abuse_reports_list feature flag is disabled' do
+ before do
+ stub_feature_flags(abuse_reports_list: false)
+ end
+
+ it 'does not filter by status' do
+ expect(subject).to match_array([abuse_report_1, abuse_report_2])
+ end
+ end
+ end
+
+ context 'when params[:category] is present' do
+ let(:params) { { category: 'phishing' } }
+
+ it 'returns abuse reports with the specified category' do
+ expect(subject).to match_array([abuse_report_2])
+ end
+ end
+
+ describe 'sorting' do
+ let(:params) { { sort: 'created_at_asc' } }
+
+ it 'returns reports sorted by the specified sort attribute' do
+ expect(subject).to eq [abuse_report_1, abuse_report_2]
+ end
+
+ context 'when sort is not specified' do
+ let(:params) { {} }
+
+ it "returns reports sorted by #{described_class::DEFAULT_SORT}" do
+ expect(subject).to eq [abuse_report_2, abuse_report_1]
+ end
+ end
+
+ context 'when sort is not supported' do
+ let(:params) { { sort: 'superiority' } }
+
+ it "returns reports sorted by #{described_class::DEFAULT_SORT}" do
+ expect(subject).to eq [abuse_report_2, abuse_report_1]
+ end
+ end
+
+ context 'when abuse_reports_list feature flag is disabled' do
+ let_it_be(:abuse_report_3) { create(:abuse_report, id: 10) }
+
+ before do
+ stub_feature_flags(abuse_reports_list: false)
+ end
+
+ it 'returns reports sorted by id in descending order' do
+ expect(subject).to eq [abuse_report_2, abuse_report_1, abuse_report_3]
+ end
+ end
+ end
end
diff --git a/spec/finders/access_requests_finder_spec.rb b/spec/finders/access_requests_finder_spec.rb
index b82495d55fd..5d7f35581ee 100644
--- a/spec/finders/access_requests_finder_spec.rb
+++ b/spec/finders/access_requests_finder_spec.rb
@@ -96,13 +96,4 @@ RSpec.describe AccessRequestsFinder do
it_behaves_like '#execute'
it_behaves_like '#execute!'
-
- context 'when project_members_index_by_project_namespace feature flag is disabled' do
- before do
- stub_feature_flags(project_members_index_by_project_namespace: false)
- end
-
- it_behaves_like '#execute'
- it_behaves_like '#execute!'
- end
end
diff --git a/spec/finders/achievements/achievements_finder_spec.rb b/spec/finders/achievements/achievements_finder_spec.rb
new file mode 100644
index 00000000000..3ac18c27494
--- /dev/null
+++ b/spec/finders/achievements/achievements_finder_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Achievements::AchievementsFinder, feature_category: :user_profile do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:achievements) { create_list(:achievement, 3, namespace: group) }
+
+ let(:params) { {} }
+
+ describe '#execute' do
+ subject { described_class.new(group, params).execute }
+
+ it 'returns all achievements' do
+ expect(subject).to match_array(achievements)
+ end
+
+ context 'when ids param provided' do
+ let(:params) { { ids: [achievements[0].id, achievements[1].id] } }
+
+ it 'returns specified achievements' do
+ expect(subject).to contain_exactly(achievements[0], achievements[1])
+ end
+ end
+ end
+end
diff --git a/spec/finders/alert_management/alerts_finder_spec.rb b/spec/finders/alert_management/alerts_finder_spec.rb
index 7fcbc7b20a1..3c37d52d6c3 100644
--- a/spec/finders/alert_management/alerts_finder_spec.rb
+++ b/spec/finders/alert_management/alerts_finder_spec.rb
@@ -222,14 +222,15 @@ RSpec.describe AlertManagement::AlertsFinder, '#execute' do
context 'search query given' do
let_it_be(:alert) do
- create(:alert_management_alert,
- :with_fingerprint,
- project: project,
- title: 'Title',
- description: 'Desc',
- service: 'Service',
- monitoring_tool: 'Monitor'
- )
+ create(
+ :alert_management_alert,
+ :with_fingerprint,
+ project: project,
+ title: 'Title',
+ description: 'Desc',
+ service: 'Service',
+ monitoring_tool: 'Monitor'
+ )
end
context 'searching title' do
diff --git a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
index 6e218db1254..35effc265c4 100644
--- a/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
+++ b/spec/finders/ci/pipelines_for_merge_request_finder_spec.rb
@@ -17,8 +17,10 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let_it_be(:forked_project) { fork_project(parent_project, nil, repository: true, target_project: create(:project, :private, :repository)) }
let(:merge_request) do
- create(:merge_request, source_project: forked_project, source_branch: 'feature',
- target_project: parent_project, target_branch: 'master')
+ create(
+ :merge_request, source_project: forked_project, source_branch: 'feature',
+ target_project: parent_project, target_branch: 'master'
+ )
end
let!(:pipeline_in_parent) do
@@ -125,8 +127,10 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:merge_request) { build(:merge_request, source_project: create(:project, :repository)) }
let!(:pipeline) do
- create(:ci_empty_pipeline, project: project,
- sha: merge_request.diff_head_sha, ref: merge_request.source_branch)
+ create(
+ :ci_empty_pipeline, project: project,
+ sha: merge_request.diff_head_sha, ref: merge_request.source_branch
+ )
end
it 'returns pipelines from diff_head_sha' do
@@ -139,8 +143,10 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
let(:target_ref) { 'master' }
let!(:branch_pipeline) do
- create(:ci_pipeline, source: :push, project: project,
- ref: source_ref, sha: merge_request.merge_request_diff.head_commit_sha)
+ create(
+ :ci_pipeline, source: :push, project: project,
+ ref: source_ref, sha: merge_request.merge_request_diff.head_commit_sha
+ )
end
let!(:tag_pipeline) do
@@ -148,13 +154,17 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
end
let!(:detached_merge_request_pipeline) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: source_ref, sha: shas.second, merge_request: merge_request)
+ create(
+ :ci_pipeline, source: :merge_request_event, project: project,
+ ref: source_ref, sha: shas.second, merge_request: merge_request
+ )
end
let(:merge_request) do
- create(:merge_request, source_project: project, source_branch: source_ref,
- target_project: project, target_branch: target_ref)
+ create(
+ :merge_request, source_project: project, source_branch: source_ref,
+ target_project: project, target_branch: target_ref
+ )
end
let(:project) { create(:project, :repository) }
@@ -166,13 +176,14 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
context 'when there are a branch pipeline and a merge request pipeline' do
let!(:branch_pipeline_2) do
- create(:ci_pipeline, source: :push, project: project,
- ref: source_ref, sha: shas.first)
+ create(:ci_pipeline, source: :push, project: project, ref: source_ref, sha: shas.first)
end
let!(:detached_merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: source_ref, sha: shas.first, merge_request: merge_request)
+ create(
+ :ci_pipeline, source: :merge_request_event, project: project,
+ ref: source_ref, sha: shas.first, merge_request: merge_request
+ )
end
it 'returns merge request pipelines first' do
@@ -183,8 +194,7 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
context 'when there are multiple merge request pipelines from the same branch' do
let!(:branch_pipeline_2) do
- create(:ci_pipeline, source: :push, project: project,
- ref: source_ref, sha: shas.first)
+ create(:ci_pipeline, source: :push, project: project, ref: source_ref, sha: shas.first)
end
let!(:branch_pipeline_with_sha_not_belonging_to_merge_request) do
@@ -192,20 +202,26 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
end
let!(:detached_merge_request_pipeline_2) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: source_ref, sha: shas.first, merge_request: merge_request_2)
+ create(
+ :ci_pipeline, source: :merge_request_event, project: project,
+ ref: source_ref, sha: shas.first, merge_request: merge_request_2
+ )
end
let(:merge_request_2) do
- create(:merge_request, source_project: project, source_branch: source_ref,
- target_project: project, target_branch: 'stable')
+ create(
+ :merge_request, source_project: project, source_branch: source_ref,
+ target_project: project, target_branch: 'stable'
+ )
end
before do
shas.each.with_index do |sha, index|
- create(:merge_request_diff_commit,
- merge_request_diff: merge_request_2.merge_request_diff,
- sha: sha, relative_order: index)
+ create(
+ :merge_request_diff_commit,
+ merge_request_diff: merge_request_2.merge_request_diff,
+ sha: sha, relative_order: index
+ )
end
end
@@ -219,8 +235,10 @@ RSpec.describe Ci::PipelinesForMergeRequestFinder do
context 'when detached merge request pipeline is run on head ref of the merge request' do
let!(:detached_merge_request_pipeline) do
- create(:ci_pipeline, source: :merge_request_event, project: project,
- ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request)
+ create(
+ :ci_pipeline, source: :merge_request_event, project: project,
+ ref: merge_request.ref_path, sha: shas.second, merge_request: merge_request
+ )
end
it 'sets the head ref of the merge request to the pipeline ref' do
diff --git a/spec/finders/clusters/agent_tokens_finder_spec.rb b/spec/finders/clusters/agent_tokens_finder_spec.rb
index 024e567a16e..1f5bfd58e85 100644
--- a/spec/finders/clusters/agent_tokens_finder_spec.rb
+++ b/spec/finders/clusters/agent_tokens_finder_spec.rb
@@ -44,6 +44,15 @@ RSpec.describe Clusters::AgentTokensFinder do
it { is_expected.to match_array(revoked_agent_tokens) }
end
+ context 'when filtering by an unrecognised status' do
+ subject(:execute) { described_class.new(agent, user, status: 'dummy').execute }
+
+ it 'raises an error' do
+ # 'dummy' is not a valid status as defined in the AgentToken status enum
+ expect { execute.count }.to raise_error(ActiveRecord::StatementInvalid)
+ end
+ end
+
context 'when user does not have permission' do
let(:user) { create(:user) }
diff --git a/spec/finders/clusters/agent_authorizations_finder_spec.rb b/spec/finders/clusters/agents/authorizations/ci_access/finder_spec.rb
index f680792d6c4..0d010729d5c 100644
--- a/spec/finders/clusters/agent_authorizations_finder_spec.rb
+++ b/spec/finders/clusters/agents/authorizations/ci_access/finder_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Clusters::AgentAuthorizationsFinder do
+RSpec.describe Clusters::Agents::Authorizations::CiAccess::Finder, feature_category: :deployment_management do
describe '#execute' do
let_it_be(:top_level_group) { create(:group) }
let_it_be(:subgroup1) { create(:group, parent: top_level_group) }
@@ -54,34 +54,34 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
let(:unrelated_agent) { create(:cluster_agent) }
before do
- create(:agent_project_authorization, agent: unrelated_agent, project: requesting_project)
+ create(:agent_ci_access_project_authorization, agent: unrelated_agent, project: requesting_project)
end
it { is_expected.to be_empty }
end
context 'agent configuration project shares a root namespace, but does not belong to an ancestor of the given project' do
- let!(:project_authorization) { create(:agent_project_authorization, agent: non_ancestor_agent, project: requesting_project) }
+ let!(:project_authorization) { create(:agent_ci_access_project_authorization, agent: non_ancestor_agent, project: requesting_project) }
it { is_expected.to match_array([project_authorization]) }
end
context 'with project authorizations present' do
- let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project) }
+ let!(:authorization) { create(:agent_ci_access_project_authorization, agent: production_agent, project: requesting_project) }
it { is_expected.to match_array [authorization] }
end
context 'with overlapping authorizations' do
let!(:agent) { create(:cluster_agent, project: requesting_project) }
- let!(:project_authorization) { create(:agent_project_authorization, agent: agent, project: requesting_project) }
- let!(:group_authorization) { create(:agent_group_authorization, agent: agent, group: bottom_level_group) }
+ let!(:project_authorization) { create(:agent_ci_access_project_authorization, agent: agent, project: requesting_project) }
+ let!(:group_authorization) { create(:agent_ci_access_group_authorization, agent: agent, group: bottom_level_group) }
it { is_expected.to match_array [project_authorization] }
end
it_behaves_like 'access_as' do
- let!(:authorization) { create(:agent_project_authorization, agent: production_agent, project: requesting_project, config: config) }
+ let!(:authorization) { create(:agent_ci_access_project_authorization, agent: production_agent, project: requesting_project, config: config) }
end
end
@@ -92,7 +92,7 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
expect(subject.count).to eq(1)
authorization = subject.first
- expect(authorization).to be_a(Clusters::Agents::ImplicitAuthorization)
+ expect(authorization).to be_a(Clusters::Agents::Authorizations::CiAccess::ImplicitAuthorization)
expect(authorization.agent).to eq(associated_agent)
end
end
@@ -102,15 +102,15 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
let(:unrelated_agent) { create(:cluster_agent) }
before do
- create(:agent_group_authorization, agent: unrelated_agent, group: top_level_group)
+ create(:agent_ci_access_group_authorization, agent: unrelated_agent, group: top_level_group)
end
it { is_expected.to be_empty }
end
context 'multiple agents are authorized for the same group' do
- let!(:staging_auth) { create(:agent_group_authorization, agent: staging_agent, group: bottom_level_group) }
- let!(:production_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) }
+ let!(:staging_auth) { create(:agent_ci_access_group_authorization, agent: staging_agent, group: bottom_level_group) }
+ let!(:production_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: bottom_level_group) }
it 'returns authorizations for all agents' do
expect(subject).to contain_exactly(staging_auth, production_auth)
@@ -118,8 +118,8 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
end
context 'a single agent is authorized to more than one matching group' do
- let!(:bottom_level_auth) { create(:agent_group_authorization, agent: production_agent, group: bottom_level_group) }
- let!(:top_level_auth) { create(:agent_group_authorization, agent: production_agent, group: top_level_group) }
+ let!(:bottom_level_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: bottom_level_group) }
+ let!(:top_level_auth) { create(:agent_ci_access_group_authorization, agent: production_agent, group: top_level_group) }
it 'picks the authorization for the closest group to the requesting project' do
expect(subject).to contain_exactly(bottom_level_auth)
@@ -127,13 +127,13 @@ RSpec.describe Clusters::AgentAuthorizationsFinder do
end
context 'agent configuration project does not belong to an ancestor of the authorized group' do
- let!(:group_authorization) { create(:agent_group_authorization, agent: non_ancestor_agent, group: bottom_level_group) }
+ let!(:group_authorization) { create(:agent_ci_access_group_authorization, agent: non_ancestor_agent, group: bottom_level_group) }
it { is_expected.to match_array([group_authorization]) }
end
it_behaves_like 'access_as' do
- let!(:authorization) { create(:agent_group_authorization, agent: production_agent, group: top_level_group, config: config) }
+ let!(:authorization) { create(:agent_ci_access_group_authorization, agent: production_agent, group: top_level_group, config: config) }
end
end
end
diff --git a/spec/finders/clusters/agents/authorizations/user_access/finder_spec.rb b/spec/finders/clusters/agents/authorizations/user_access/finder_spec.rb
new file mode 100644
index 00000000000..7e6897a723d
--- /dev/null
+++ b/spec/finders/clusters/agents/authorizations/user_access/finder_spec.rb
@@ -0,0 +1,198 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Clusters::Agents::Authorizations::UserAccess::Finder, feature_category: :deployment_management do
+ describe '#execute' do
+ let_it_be(:organization) { create(:group) }
+ let_it_be(:agent_configuration_project) { create(:project, namespace: organization) }
+ let_it_be(:agent) { create(:cluster_agent, project: agent_configuration_project) }
+ let_it_be(:deployment_project) { create(:project, namespace: organization) }
+ let_it_be(:deployment_maintainer) { create(:user).tap { |u| deployment_project.add_maintainer(u) } }
+ let_it_be(:deployment_developer) { create(:user).tap { |u| deployment_project.add_developer(u) } }
+ let_it_be(:deployment_guest) { create(:user).tap { |u| deployment_project.add_guest(u) } }
+
+ let(:user) { deployment_developer }
+ let(:params) { { agent: nil } }
+
+ subject { described_class.new(user, **params).execute }
+
+ it 'returns nothing' do
+ is_expected.to be_empty
+ end
+
+ context 'with project authorizations' do
+ let!(:authorization_1) do
+ create(:agent_user_access_project_authorization, agent: agent, project: deployment_project)
+ end
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1)
+
+ expect(subject.first.access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+
+ context 'when user is maintainer' do
+ let(:user) { deployment_maintainer }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1)
+
+ expect(subject.first.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:user) { deployment_guest }
+
+ it 'does not return authorization' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'with multiple authorizations' do
+ let_it_be(:agent_2) { create(:cluster_agent, project: agent_configuration_project) }
+ let_it_be(:agent_3) { create(:cluster_agent, project: agent_configuration_project) }
+ let_it_be(:deployment_project_2) { create(:project, namespace: organization) }
+
+ let_it_be(:authorization_2) do
+ create(:agent_user_access_project_authorization, agent: agent_2, project: deployment_project)
+ end
+
+ let_it_be(:authorization_3) do
+ create(:agent_user_access_project_authorization, agent: agent_3, project: deployment_project_2)
+ end
+
+ before_all do
+ deployment_project_2.add_developer(deployment_developer)
+ end
+
+ it 'returns authorizations' do
+ is_expected.to contain_exactly(authorization_1, authorization_2, authorization_3)
+ end
+
+ context 'with specific agent' do
+ let(:params) { { agent: agent_2 } }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_2)
+ end
+ end
+
+ context 'with specific project' do
+ let(:params) { { project: deployment_project_2 } }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_3)
+ end
+ end
+
+ context 'with limit' do
+ let(:params) { { limit: 1 } }
+
+ it 'returns authorization' do
+ expect(subject.count).to eq(1)
+ end
+ end
+ end
+ end
+
+ context 'with group authorizations' do
+ let!(:authorization_1) do
+ create(:agent_user_access_group_authorization, agent: agent, group: organization)
+ end
+
+ before_all do
+ organization.add_maintainer(deployment_maintainer)
+ organization.add_developer(deployment_developer)
+ organization.add_guest(deployment_guest)
+ end
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1)
+
+ expect(subject.first.access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+
+ context 'when user is maintainer' do
+ let(:user) { deployment_maintainer }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1)
+
+ expect(subject.first.access_level).to eq(Gitlab::Access::MAINTAINER)
+ end
+ end
+
+ context 'when user is guest' do
+ let(:user) { deployment_guest }
+
+ it 'does not return authorization' do
+ is_expected.to be_empty
+ end
+ end
+
+ context 'with multiple authorizations' do
+ let_it_be(:agent_2) { create(:cluster_agent, project: agent_configuration_project) }
+
+ let_it_be(:authorization_2) do
+ create(:agent_user_access_group_authorization, agent: agent_2, group: organization)
+ end
+
+ let_it_be(:authorization_3) { create(:agent_user_access_group_authorization) }
+
+ it 'returns authorizations' do
+ is_expected.to contain_exactly(authorization_1, authorization_2)
+ end
+
+ context 'with specific agent' do
+ let(:params) { { agent: agent_2 } }
+
+ it 'returns authorization' do
+ is_expected.to eq([authorization_2])
+ end
+ end
+
+ context 'with specific project' do
+ let(:params) { { project: deployment_project } }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1, authorization_2)
+ end
+ end
+
+ context 'with limit' do
+ let(:params) { { limit: 1 } }
+
+ it 'returns authorization' do
+ expect(subject.count).to eq(1)
+ end
+ end
+ end
+
+ context 'when sub-group is authorized' do
+ let_it_be(:subgroup_1) { create(:group, parent: organization) }
+ let_it_be(:subgroup_2) { create(:group, parent: organization) }
+ let_it_be(:deployment_project_1) { create(:project, group: subgroup_1) }
+ let_it_be(:deployment_project_2) { create(:project, group: subgroup_2) }
+
+ let!(:authorization_1) { create(:agent_user_access_group_authorization, agent: agent, group: subgroup_1) }
+ let!(:authorization_2) { create(:agent_user_access_group_authorization, agent: agent, group: subgroup_2) }
+
+ it 'returns authorization' do
+ is_expected.to contain_exactly(authorization_1, authorization_2)
+
+ expect(subject.first.access_level).to eq(Gitlab::Access::DEVELOPER)
+ end
+
+ context 'with specific deployment project' do
+ let(:params) { { project: deployment_project_1 } }
+
+ it 'returns only the authorization connected to the parent group' do
+ is_expected.to contain_exactly(authorization_1)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/concerns/finder_with_group_hierarchy_spec.rb b/spec/finders/concerns/finder_with_group_hierarchy_spec.rb
index c96e35372d6..27f5192176d 100644
--- a/spec/finders/concerns/finder_with_group_hierarchy_spec.rb
+++ b/spec/finders/concerns/finder_with_group_hierarchy_spec.rb
@@ -129,80 +129,4 @@ RSpec.describe FinderWithGroupHierarchy do
expect { run_query(private_group) }.not_to exceed_query_limit(control)
end
end
-
- context 'when preload_max_access_levels_for_labels_finder is disabled' do
- # All test cases were copied from above, these will be removed once the FF is removed.
-
- before do
- stub_feature_flags(preload_max_access_levels_for_labels_finder: false)
- end
-
- context 'when specifying group' do
- it 'returns only the group by default' do
- finder = finder_class.new(user, group: group)
-
- expect(finder.execute).to match_array([group.id])
- end
- end
-
- context 'when specifying group_id' do
- it 'returns only the group by default' do
- finder = finder_class.new(user, group_id: group.id)
-
- expect(finder.execute).to match_array([group.id])
- end
- end
-
- context 'when including items from group ancestors' do
- before do
- private_subgroup.add_developer(user)
- end
-
- it 'returns group and its ancestors' do
- private_group.add_developer(user)
-
- finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
-
- expect(finder.execute).to match_array([private_group.id, private_subgroup.id])
- end
-
- it 'ignores groups which user can not read' do
- finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
-
- expect(finder.execute).to match_array([private_subgroup.id])
- end
-
- it 'returns them all when skip_authorization is true' do
- finder = finder_class.new(user, group: private_subgroup, include_ancestor_groups: true)
-
- expect(finder.execute(skip_authorization: true)).to match_array([private_group.id, private_subgroup.id])
- end
- end
-
- context 'when including items from group descendants' do
- before do
- private_subgroup.add_developer(user)
- end
-
- it 'returns items from group and its descendants' do
- private_group.add_developer(user)
-
- finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
-
- expect(finder.execute).to match_array([private_group.id, private_subgroup.id])
- end
-
- it 'ignores items from groups which user can not read' do
- finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
-
- expect(finder.execute).to match_array([private_subgroup.id])
- end
-
- it 'returns them all when skip_authorization is true' do
- finder = finder_class.new(user, group: private_group, include_descendant_groups: true)
-
- expect(finder.execute(skip_authorization: true)).to match_array([private_group.id, private_subgroup.id])
- end
- end
- end
end
diff --git a/spec/finders/context_commits_finder_spec.rb b/spec/finders/context_commits_finder_spec.rb
index c22675bc67d..3de1d29b695 100644
--- a/spec/finders/context_commits_finder_spec.rb
+++ b/spec/finders/context_commits_finder_spec.rb
@@ -26,27 +26,30 @@ RSpec.describe ContextCommitsFinder do
end
it 'returns commits based in author filter' do
- params = { search: 'test text', author: 'Job van der Voort' }
+ params = { author: 'Job van der Voort' }
commits = described_class.new(project, merge_request, params).execute
expect(commits.length).to eq(1)
expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0')
end
- it 'returns commits based in before filter' do
- params = { search: 'test text', committed_before: 1474828200 }
+ it 'returns commits based in committed before and after filter' do
+ params = { committed_before: 1471631400, committed_after: 1471458600 } # August 18, 2016 - # August 20, 2016
commits = described_class.new(project, merge_request, params).execute
- expect(commits.length).to eq(1)
- expect(commits[0].id).to eq('498214de67004b1da3d820901307bed2a68a8ef6')
+ expect(commits.length).to eq(2)
+ expect(commits[0].id).to eq('1b12f15a11fc6e62177bef08f47bc7b5ce50b141')
+ expect(commits[1].id).to eq('38008cb17ce1466d8fec2dfa6f6ab8dcfe5cf49e')
end
- it 'returns commits based in after filter' do
- params = { search: 'test text', committed_after: 1474828200 }
- commits = described_class.new(project, merge_request, params).execute
+ it 'returns commits from target branch if no filter is applied' do
+ expect(project.repository).to receive(:commits).with(merge_request.target_branch, anything).and_call_original
- expect(commits.length).to eq(1)
+ commits = described_class.new(project, merge_request).execute
+
+ expect(commits.length).to eq(37)
expect(commits[0].id).to eq('b83d6e391c22777fca1ed3012fce84f633d7fed0')
+ expect(commits[1].id).to eq('498214de67004b1da3d820901307bed2a68a8ef6')
end
end
end
diff --git a/spec/finders/crm/contacts_finder_spec.rb b/spec/finders/crm/contacts_finder_spec.rb
index 43dcced53fd..d0339ce2b18 100644
--- a/spec/finders/crm/contacts_finder_spec.rb
+++ b/spec/finders/crm/contacts_finder_spec.rb
@@ -148,7 +148,7 @@ RSpec.describe Crm::ContactsFinder do
:contact,
group: search_test_group,
email: "a@test.com",
- organization: create(:organization, name: "Company Z")
+ organization: create(:crm_organization, name: "Company Z")
)
end
@@ -157,7 +157,7 @@ RSpec.describe Crm::ContactsFinder do
:contact,
group: search_test_group,
email: "b@test.com",
- organization: create(:organization, name: "Company A")
+ organization: create(:crm_organization, name: "Company A")
)
end
diff --git a/spec/finders/crm/organizations_finder_spec.rb b/spec/finders/crm/organizations_finder_spec.rb
index c89ac3b1cb5..bc174f927a7 100644
--- a/spec/finders/crm/organizations_finder_spec.rb
+++ b/spec/finders/crm/organizations_finder_spec.rb
@@ -12,8 +12,8 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:root_group) { create(:group, :crm_enabled) }
let_it_be(:group) { create(:group, parent: root_group) }
- let_it_be(:organization_1) { create(:organization, group: root_group) }
- let_it_be(:organization_2) { create(:organization, group: root_group) }
+ let_it_be(:crm_organization_1) { create(:crm_organization, group: root_group) }
+ let_it_be(:crm_organization_2) { create(:crm_organization, group: root_group) }
context 'when user does not have permissions to see organizations in the group' do
it 'returns an empty array' do
@@ -28,7 +28,7 @@ RSpec.describe Crm::OrganizationsFinder do
context 'when feature flag is enabled' do
it 'returns all group organizations' do
- expect(subject).to match_array([organization_1, organization_2])
+ expect(subject).to match_array([crm_organization_1, crm_organization_2])
end
end
end
@@ -46,7 +46,7 @@ RSpec.describe Crm::OrganizationsFinder do
context 'when customer relations feature is disabled for the group' do
let_it_be(:group) { create(:group) }
- let_it_be(:organization) { create(:organization, group: group) }
+ let_it_be(:crm_organization) { create(:crm_organization, group: group) }
before do
group.add_developer(user)
@@ -62,7 +62,7 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:search_test_a) do
create(
- :organization,
+ :crm_organization,
group: search_test_group,
name: "DEF",
description: "ghi_st",
@@ -72,7 +72,7 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:search_test_b) do
create(
- :organization,
+ :crm_organization,
group: search_test_group,
name: "ABC_st",
description: "JKL",
@@ -134,7 +134,7 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:sort_test_a) do
create(
- :organization,
+ :crm_organization,
group: group,
name: "ABC",
description: "1"
@@ -143,7 +143,7 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:sort_test_b) do
create(
- :organization,
+ :crm_organization,
group: group,
name: "DEF",
description: "2",
@@ -153,7 +153,7 @@ RSpec.describe Crm::OrganizationsFinder do
let_it_be(:sort_test_c) do
create(
- :organization,
+ :crm_organization,
group: group,
name: "GHI",
default_rate: 20
@@ -186,8 +186,8 @@ RSpec.describe Crm::OrganizationsFinder do
describe '.counts_by_state' do
let_it_be(:group) { create(:group, :crm_enabled) }
- let_it_be(:active_organizations) { create_list(:organization, 3, group: group, state: :active) }
- let_it_be(:inactive_organizations) { create_list(:organization, 2, group: group, state: :inactive) }
+ let_it_be(:active_crm_organizations) { create_list(:crm_organization, 3, group: group, state: :active) }
+ let_it_be(:inactive_crm_organizations) { create_list(:crm_organization, 2, group: group, state: :inactive) }
before do
group.add_developer(user)
diff --git a/spec/finders/data_transfer/group_data_transfer_finder_spec.rb b/spec/finders/data_transfer/group_data_transfer_finder_spec.rb
new file mode 100644
index 00000000000..0c54e6504e8
--- /dev/null
+++ b/spec/finders/data_transfer/group_data_transfer_finder_spec.rb
@@ -0,0 +1,84 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DataTransfer::GroupDataTransferFinder, feature_category: :source_code_management do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:namespace_1) { create(:group) }
+ let_it_be(:project_1) { create(:project, group: namespace_1) }
+ let_it_be(:project_2) { create(:project, group: namespace_1) }
+ let(:from_date) { Date.new(2022, 2, 1) }
+ let(:to_date) { Date.new(2023, 1, 1) }
+
+ before_all do
+ namespace_1.add_owner(user)
+ end
+
+ describe '#execute' do
+ let(:subject) { described_class.new(group: namespace_1, from: from_date, to: to_date, user: user) }
+
+ before do
+ create(:project_data_transfer, project: project_1, date: '2022-01-01')
+ create(:project_data_transfer, project: project_1, date: '2022-02-01')
+ create(:project_data_transfer, project: project_2, date: '2022-02-01')
+ end
+
+ it 'returns the correct number of egress' do
+ expect(subject.execute.to_a.size).to eq(1)
+ end
+
+ it 'returns the correct values grouped by date' do
+ first_result = subject.execute.first
+ expect(first_result.attributes).to include(
+ {
+ 'namespace_id' => namespace_1.id,
+ 'date' => from_date,
+ 'repository_egress' => 2,
+ 'artifacts_egress' => 4,
+ 'packages_egress' => 6,
+ 'registry_egress' => 8,
+ 'total_egress' => 20
+ }
+ )
+ end
+
+ context 'when there are no results for specified namespace' do
+ let_it_be(:namespace_2) { create(:group) }
+ let(:subject) { described_class.new(group: namespace_2, from: from_date, to: to_date, user: user) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+
+ context 'when there are no results for specified dates' do
+ let(:from_date) { Date.new(2021, 1, 1) }
+ let(:to_date) { Date.new(2021, 1, 1) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+
+ context 'when dates are not provided' do
+ let(:from_date) { nil }
+ let(:to_date) { nil }
+
+ it 'return all values for a namespace', :aggregate_failures do
+ results = subject.execute
+ expect(results.to_a.size).to eq(2)
+ results.each do |result|
+ expect(result.namespace).to eq(namespace_1)
+ end
+ end
+ end
+
+ context 'when user does not have permissions' do
+ let(:user) { build(:user) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/finders/data_transfer/mocked_transfer_finder_spec.rb b/spec/finders/data_transfer/mocked_transfer_finder_spec.rb
new file mode 100644
index 00000000000..f60bc98f587
--- /dev/null
+++ b/spec/finders/data_transfer/mocked_transfer_finder_spec.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DataTransfer::MockedTransferFinder, feature_category: :source_code_management do
+ describe '#execute' do
+ subject(:execute) { described_class.new.execute }
+
+ it 'returns mock data' do
+ expect(execute.first).to include(
+ date: '2023-01-01',
+ repository_egress: be_a(Integer),
+ artifacts_egress: be_a(Integer),
+ packages_egress: be_a(Integer),
+ registry_egress: be_a(Integer),
+ total_egress: be_a(Integer)
+ )
+
+ expect(execute.size).to eq(12)
+ end
+ end
+end
diff --git a/spec/finders/data_transfer/project_data_transfer_finder_spec.rb b/spec/finders/data_transfer/project_data_transfer_finder_spec.rb
new file mode 100644
index 00000000000..1d5cd0f3339
--- /dev/null
+++ b/spec/finders/data_transfer/project_data_transfer_finder_spec.rb
@@ -0,0 +1,80 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe DataTransfer::ProjectDataTransferFinder, feature_category: :source_code_management do
+ let_it_be(:project_1) { create(:project) }
+ let_it_be(:project_2) { create(:project) }
+ let_it_be(:user) { project_1.first_owner }
+ let(:from_date) { Date.new(2022, 2, 1) }
+ let(:to_date) { Date.new(2023, 1, 1) }
+
+ describe '#execute' do
+ let(:subject) { described_class.new(project: project_1, from: from_date, to: to_date, user: user) }
+
+ before do
+ create(:project_data_transfer, project: project_1, date: '2022-01-01')
+ create(:project_data_transfer, project: project_1, date: '2022-02-01')
+ create(:project_data_transfer, project: project_1, date: '2022-03-01')
+ create(:project_data_transfer, project: project_2, date: '2022-01-01')
+ end
+
+ it 'returns the correct number of egress' do
+ expect(subject.execute.size).to eq(2)
+ end
+
+ it 'returns the correct values' do
+ first_result = subject.execute.first
+ expect(first_result.attributes).to include(
+ {
+ 'project_id' => project_1.id,
+ 'date' => from_date,
+ 'repository_egress' => 1,
+ 'artifacts_egress' => 2,
+ 'packages_egress' => 3,
+ 'registry_egress' => 4,
+ 'total_egress' => 10
+ }
+ )
+ end
+
+ context 'when there are no results for specified dates' do
+ let(:from_date) { Date.new(2021, 1, 1) }
+ let(:to_date) { Date.new(2021, 1, 1) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+
+ context 'when there are no results for specified project' do
+ let_it_be(:project_3) { create(:project, :repository) }
+ let(:subject) { described_class.new(project: project_3, from: from_date, to: to_date, user: user) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+
+ context 'when dates are not provided' do
+ let(:from_date) { nil }
+ let(:to_date) { nil }
+
+ it 'return all values for a project', :aggregate_failures do
+ results = subject.execute
+ expect(results.size).to eq(3)
+ results.each do |result|
+ expect(result.project).to eq(project_1)
+ end
+ end
+ end
+
+ context 'when user does not have permissions' do
+ let(:user) { build(:user) }
+
+ it 'returns nothing' do
+ expect(subject.execute).to be_empty
+ end
+ end
+ end
+end
diff --git a/spec/finders/deployments_finder_spec.rb b/spec/finders/deployments_finder_spec.rb
index efb739c3d2f..86b6070a368 100644
--- a/spec/finders/deployments_finder_spec.rb
+++ b/spec/finders/deployments_finder_spec.rb
@@ -16,16 +16,6 @@ RSpec.describe DeploymentsFinder do
end
end
- context 'when updated_at filter and id sorting' do
- let(:params) { { updated_before: 1.day.ago, order_by: :id } }
-
- it 'raises an error' do
- expect { subject }.to raise_error(
- described_class::InefficientQueryError,
- '`updated_at` filter and `updated_at` sorting must be paired')
- end
- end
-
context 'when finished_at filter and id sorting' do
let(:params) { { finished_before: 1.day.ago, order_by: :id } }
@@ -178,8 +168,8 @@ RSpec.describe DeploymentsFinder do
'iid' | 'desc' | [:deployment_3, :deployment_2, :deployment_1]
'ref' | 'asc' | [:deployment_2, :deployment_1, :deployment_3]
'ref' | 'desc' | [:deployment_3, :deployment_1, :deployment_2]
- 'updated_at' | 'asc' | described_class::InefficientQueryError
- 'updated_at' | 'desc' | described_class::InefficientQueryError
+ 'updated_at' | 'asc' | [:deployment_2, :deployment_3, :deployment_1]
+ 'updated_at' | 'desc' | [:deployment_1, :deployment_3, :deployment_2]
'finished_at' | 'asc' | described_class::InefficientQueryError
'finished_at' | 'desc' | described_class::InefficientQueryError
'invalid' | 'asc' | [:deployment_1, :deployment_2, :deployment_3]
@@ -260,15 +250,52 @@ RSpec.describe DeploymentsFinder do
end
describe 'enforce sorting to `updated_at` sorting' do
- let(:params) { { **base_params, updated_before: 1.day.ago, order_by: 'id', sort: 'asc', raise_for_inefficient_updated_at_query: false } }
+ let(:params) { { **base_params, updated_before: 1.day.ago, order_by: 'id', sort: 'asc' } }
- it 'sorts by only one column' do
- expect(subject.order_values.size).to eq(2)
+ context 'when the deployments_raise_updated_at_inefficient_error FF is disabled' do
+ before do
+ stub_feature_flags(deployments_raise_updated_at_inefficient_error: false)
+ end
+
+ it 'sorts by only one column' do
+ expect(subject.order_values.size).to eq(2)
+ end
+
+ it 'sorts by `updated_at`' do
+ expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:updated_at].asc.to_sql)
+ expect(subject.order_values.second.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
+ end
end
- it 'sorts by `updated_at`' do
- expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:updated_at].asc.to_sql)
- expect(subject.order_values.second.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
+ context 'when the deployments_raise_updated_at_inefficient_error FF is enabled' do
+ before do
+ stub_feature_flags(deployments_raise_updated_at_inefficient_error: true)
+ end
+
+ context 'when the flag is overridden' do
+ before do
+ stub_feature_flags(deployments_raise_updated_at_inefficient_error_override: true)
+ end
+
+ it 'sorts by only one column' do
+ expect(subject.order_values.size).to eq(2)
+ end
+
+ it 'sorts by `updated_at`' do
+ expect(subject.order_values.first.to_sql).to eq(Deployment.arel_table[:updated_at].asc.to_sql)
+ expect(subject.order_values.second.to_sql).to eq(Deployment.arel_table[:id].asc.to_sql)
+ end
+ end
+
+ context 'when the flag is not overridden' do
+ before do
+ stub_feature_flags(deployments_raise_updated_at_inefficient_error_override: false)
+ end
+
+ it 'raises an error' do
+ expect { subject }.to raise_error(DeploymentsFinder::InefficientQueryError)
+ end
+ end
end
end
@@ -331,9 +358,11 @@ RSpec.describe DeploymentsFinder do
with_them do
it 'returns the deployments unordered' do
- expect(subject.to_a).to contain_exactly(group_project_1_deployment,
- group_project_2_deployment,
- subgroup_project_1_deployment)
+ expect(subject.to_a).to contain_exactly(
+ group_project_1_deployment,
+ group_project_2_deployment,
+ subgroup_project_1_deployment
+ )
end
end
end
diff --git a/spec/finders/fork_targets_finder_spec.rb b/spec/finders/fork_targets_finder_spec.rb
index 41651513f18..746c48a8fab 100644
--- a/spec/finders/fork_targets_finder_spec.rb
+++ b/spec/finders/fork_targets_finder_spec.rb
@@ -29,17 +29,38 @@ RSpec.describe ForkTargetsFinder do
create(:group).tap { |g| g.add_guest(user) }
end
+ let_it_be(:shared_group_to_group_with_owner_access) do
+ create(:group)
+ end
+
before do
project.namespace.add_owner(user)
+ create(:group_group_link, :maintainer,
+ shared_with_group: owned_group,
+ shared_group: shared_group_to_group_with_owner_access
+ )
end
shared_examples 'returns namespaces and groups' do
it 'returns all user manageable namespaces' do
- expect(finder.execute).to match_array([user.namespace, maintained_group, owned_group, project.namespace, developer_group])
+ expect(finder.execute).to match_array([
+ user.namespace,
+ maintained_group,
+ owned_group,
+ project.namespace,
+ developer_group,
+ shared_group_to_group_with_owner_access
+ ])
end
it 'returns only groups when only_groups option is passed' do
- expect(finder.execute(only_groups: true)).to match_array([maintained_group, owned_group, project.namespace, developer_group])
+ expect(finder.execute(only_groups: true)).to match_array([
+ maintained_group,
+ owned_group,
+ project.namespace,
+ developer_group,
+ shared_group_to_group_with_owner_access
+ ])
end
it 'returns groups relation when only_groups option is passed' do
diff --git a/spec/finders/group_descendants_finder_spec.rb b/spec/finders/group_descendants_finder_spec.rb
index 2a9e887450c..9d528355f54 100644
--- a/spec/finders/group_descendants_finder_spec.rb
+++ b/spec/finders/group_descendants_finder_spec.rb
@@ -130,8 +130,10 @@ RSpec.describe GroupDescendantsFinder do
it 'does not include projects shared with the group' do
project = create(:project, namespace: group)
other_project = create(:project)
- other_project.project_group_links.create!(group: group,
- group_access: Gitlab::Access::MAINTAINER)
+ other_project.project_group_links.create!(
+ group: group,
+ group_access: Gitlab::Access::MAINTAINER
+ )
expect(finder.execute).to contain_exactly(project)
end
@@ -140,9 +142,11 @@ RSpec.describe GroupDescendantsFinder do
context 'with shared groups' do
let_it_be(:other_group) { create(:group) }
let_it_be(:shared_group_link) do
- create(:group_group_link,
- shared_group: group,
- shared_with_group: other_group)
+ create(
+ :group_group_link,
+ shared_group: group,
+ shared_with_group: other_group
+ )
end
context 'without common ancestor' do
@@ -230,9 +234,11 @@ RSpec.describe GroupDescendantsFinder do
other_user = create(:user)
other_subgroup.add_developer(other_user)
- finder = described_class.new(current_user: other_user,
- parent_group: group,
- params: params)
+ finder = described_class.new(
+ current_user: other_user,
+ parent_group: group,
+ params: params
+ )
expect(finder.execute).to contain_exactly(other_subgroup, public_subgroup, other_subsubgroup)
end
diff --git a/spec/finders/group_members_finder_spec.rb b/spec/finders/group_members_finder_spec.rb
index 4a5eb389906..4fc49289fa4 100644
--- a/spec/finders/group_members_finder_spec.rb
+++ b/spec/finders/group_members_finder_spec.rb
@@ -56,44 +56,67 @@ RSpec.describe GroupMembersFinder, '#execute', feature_category: :subgroups do
}
end
- it 'raises an error if a non-supported relation type is used' do
- expect do
- described_class.new(group).execute(include_relations: [:direct, :invalid_relation_type])
- end.to raise_error(ArgumentError, "invalid_relation_type is not a valid relation type. Valid relation types are direct, inherited, descendants, shared_from_groups.")
- end
-
- using RSpec::Parameterized::TableSyntax
-
- where(:subject_relations, :subject_group, :expected_members) do
- [] | :group | []
- GroupMembersFinder::DEFAULT_RELATIONS | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
- [:direct] | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
- [:inherited] | :group | []
- [:descendants] | :group | [:user1_sub_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
- [:shared_from_groups] | :group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
- [:direct, :inherited, :descendants, :shared_from_groups] | :group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
- [] | :sub_group | []
- GroupMembersFinder::DEFAULT_RELATIONS | :sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
- [:direct] | :sub_group | [:user1_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
- [:inherited] | :sub_group | [:user1_group, :user2_group, :user3_group, :user4_group]
- [:descendants] | :sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
- [:shared_from_groups] | :sub_group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
- [:direct, :inherited, :descendants, :shared_from_groups] | :sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
- [] | :sub_sub_group | []
- GroupMembersFinder::DEFAULT_RELATIONS | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
- [:direct] | :sub_sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
- [:inherited] | :sub_sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
- [:descendants] | :sub_sub_group | []
- [:shared_from_groups] | :sub_sub_group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
- [:direct, :inherited, :descendants, :shared_from_groups] | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
- end
-
- with_them do
- it 'returns correct members' do
- result = described_class.new(groups[subject_group]).execute(include_relations: subject_relations)
-
- expect(result.to_a).to match_array(expected_members.map { |name| members[name] })
+ shared_examples 'member relations' do
+ it 'raises an error if a non-supported relation type is used' do
+ expect do
+ described_class.new(group).execute(include_relations: [:direct, :invalid_relation_type])
+ end.to raise_error(ArgumentError, "invalid_relation_type is not a valid relation type. Valid relation types are direct, inherited, descendants, shared_from_groups.")
end
+
+ using RSpec::Parameterized::TableSyntax
+
+ where(:subject_relations, :subject_group, :expected_members) do
+ [] | :group | []
+ GroupMembersFinder::DEFAULT_RELATIONS | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:direct] | :group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:inherited] | :group | []
+ [:descendants] | :group | [:user1_sub_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:shared_from_groups] | :group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
+ [:direct, :inherited, :descendants, :shared_from_groups] | :group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
+ [] | :sub_group | []
+ GroupMembersFinder::DEFAULT_RELATIONS | :sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct] | :sub_group | [:user1_sub_group, :user2_sub_group, :user3_sub_group, :user4_sub_group]
+ [:inherited] | :sub_group | [:user1_group, :user2_group, :user3_group, :user4_group]
+ [:descendants] | :sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
+ [:shared_from_groups] | :sub_group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
+ [:direct, :inherited, :descendants, :shared_from_groups] | :sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
+ [] | :sub_sub_group | []
+ GroupMembersFinder::DEFAULT_RELATIONS | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:direct] | :sub_sub_group | [:user1_sub_sub_group, :user2_sub_sub_group, :user3_sub_sub_group, :user4_sub_sub_group]
+ [:inherited] | :sub_sub_group | [:user1_sub_group, :user2_group, :user3_sub_group, :user4_group]
+ [:descendants] | :sub_sub_group | []
+ [:shared_from_groups] | :sub_sub_group | [:user1_public_shared_group, :user2_public_shared_group, :user3_public_shared_group, :user4_public_shared_group]
+ [:direct, :inherited, :descendants, :shared_from_groups] | :sub_sub_group | [:user1_sub_sub_group, :user2_group, :user3_sub_group, :user4_public_shared_group]
+ end
+
+ with_them do
+ it 'returns correct members' do
+ result = described_class.new(groups[subject_group]).execute(include_relations: subject_relations)
+
+ expect(result.to_a).to match_array(expected_members.map { |name| members[name] })
+ end
+ end
+ end
+
+ it_behaves_like 'member relations'
+
+ it 'returns the correct access level of the members shared through group sharing' do
+ shared_members_access = described_class
+ .new(groups[:group])
+ .execute(include_relations: [:shared_from_groups])
+ .to_a
+ .map(&:access_level)
+
+ correct_access_levels = ([Gitlab::Access::DEVELOPER] * 3) << Gitlab::Access::REPORTER
+ expect(shared_members_access).to match_array(correct_access_levels)
+ end
+
+ context 'when members_with_shared_group_access feature flag is disabled' do
+ before do
+ stub_feature_flags(members_with_shared_group_access: false)
+ end
+
+ it_behaves_like 'member relations'
end
end
@@ -225,4 +248,56 @@ RSpec.describe GroupMembersFinder, '#execute', feature_category: :subgroups do
end
end
end
+
+ context 'filter by user type' do
+ subject(:by_user_type) { described_class.new(group, user1, params: { user_type: user_type }).execute }
+
+ let_it_be(:service_account) { create(:user, :service_account) }
+ let_it_be(:project_bot) { create(:user, :project_bot) }
+
+ let_it_be(:service_account_member) { group.add_developer(service_account) }
+ let_it_be(:project_bot_member) { group.add_developer(project_bot) }
+
+ context 'when the user is an owner' do
+ before do
+ group.add_owner(user1)
+ end
+
+ context 'when filtering by project bots' do
+ let(:user_type) { 'project_bot' }
+
+ it 'returns filtered members' do
+ expect(by_user_type).to match_array([project_bot_member])
+ end
+ end
+
+ context 'when filtering by service accounts' do
+ let(:user_type) { 'service_account' }
+
+ it 'returns filtered members' do
+ expect(by_user_type).to match_array([service_account_member])
+ end
+ end
+ end
+
+ context 'when the user is a maintainer' do
+ let(:user_type) { 'service_account' }
+
+ let_it_be(:user1_member) { group.add_maintainer(user1) }
+
+ it 'returns unfiltered members' do
+ expect(by_user_type).to match_array([user1_member, service_account_member, project_bot_member])
+ end
+ end
+
+ context 'when the user is a developer' do
+ let(:user_type) { 'service_account' }
+
+ let_it_be(:user1_member) { group.add_developer(user1) }
+
+ it 'returns unfiltered members' do
+ expect(by_user_type).to match_array([user1_member, service_account_member, project_bot_member])
+ end
+ end
+ end
end
diff --git a/spec/finders/groups/accepting_group_transfers_finder_spec.rb b/spec/finders/groups/accepting_group_transfers_finder_spec.rb
index 06e6fa05892..18407dd0196 100644
--- a/spec/finders/groups/accepting_group_transfers_finder_spec.rb
+++ b/spec/finders/groups/accepting_group_transfers_finder_spec.rb
@@ -39,14 +39,16 @@ RSpec.describe Groups::AcceptingGroupTransfersFinder do
describe '#execute' do
before_all do
- create(:group_group_link, :owner,
- shared_with_group: group_where_user_has_owner_access,
- shared_group: shared_with_group_where_direct_owner_as_owner
+ create(
+ :group_group_link, :owner,
+ shared_with_group: group_where_user_has_owner_access,
+ shared_group: shared_with_group_where_direct_owner_as_owner
)
- create(:group_group_link, :guest,
- shared_with_group: group_where_user_has_owner_access,
- shared_group: shared_with_group_where_direct_owner_as_guest
+ create(
+ :group_group_link, :guest,
+ shared_with_group: group_where_user_has_owner_access,
+ shared_group: shared_with_group_where_direct_owner_as_guest
)
end
diff --git a/spec/finders/groups/accepting_project_creations_finder_spec.rb b/spec/finders/groups/accepting_project_creations_finder_spec.rb
new file mode 100644
index 00000000000..2ea5577dd90
--- /dev/null
+++ b/spec/finders/groups/accepting_project_creations_finder_spec.rb
@@ -0,0 +1,104 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::AcceptingProjectCreationsFinder, feature_category: :subgroups do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group_where_direct_owner) { create(:group) }
+ let_it_be(:subgroup_of_group_where_direct_owner) { create(:group, parent: group_where_direct_owner) }
+ let_it_be(:group_where_direct_maintainer) { create(:group) }
+ let_it_be(:group_where_direct_maintainer_but_cant_create_projects) do
+ create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS)
+ end
+
+ let_it_be(:group_where_direct_developer_but_developers_cannot_create_projects) { create(:group) }
+ let_it_be(:group_where_direct_developer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_owner) { create(:group) }
+
+ let_it_be(:shared_with_group_where_direct_owner_as_developer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_developer_but_developers_cannot_create_projects) do
+ create(:group)
+ end
+
+ let_it_be(:shared_with_group_where_direct_developer_as_maintainer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_guest) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_owner_as_maintainer) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_developer_as_owner) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:subgroup_of_shared_with_group_where_direct_owner_as_maintainer) do
+ create(:group, parent: shared_with_group_where_direct_owner_as_maintainer)
+ end
+
+ before do
+ group_where_direct_owner.add_owner(user)
+ group_where_direct_maintainer.add_maintainer(user)
+ group_where_direct_developer_but_developers_cannot_create_projects.add_developer(user)
+ group_where_direct_developer.add_developer(user)
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_owner
+ )
+
+ create(:group_group_link, :developer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_developer_but_developers_cannot_create_projects
+ )
+
+ create(:group_group_link, :maintainer,
+ shared_with_group: group_where_direct_developer,
+ shared_group: shared_with_group_where_direct_developer_as_maintainer
+ )
+
+ create(:group_group_link, :developer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_developer
+ )
+
+ create(:group_group_link, :guest,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_guest
+ )
+
+ create(:group_group_link, :maintainer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_maintainer
+ )
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_developer_but_developers_cannot_create_projects,
+ shared_group: shared_with_group_where_direct_developer_as_owner
+ )
+ end
+
+ describe '#execute' do
+ subject(:result) { described_class.new(user).execute }
+
+ it 'only returns groups where the user has access to create projects' do
+ expect(result).to match_array([
+ group_where_direct_owner,
+ subgroup_of_group_where_direct_owner,
+ group_where_direct_maintainer,
+ group_where_direct_developer,
+ # groups arising from group shares
+ shared_with_group_where_direct_owner_as_owner,
+ shared_with_group_where_direct_owner_as_maintainer,
+ subgroup_of_shared_with_group_where_direct_owner_as_maintainer,
+ shared_with_group_where_direct_developer_as_owner,
+ shared_with_group_where_direct_developer_as_maintainer,
+ shared_with_group_where_direct_owner_as_developer
+ ])
+ end
+ end
+end
diff --git a/spec/finders/groups/accepting_project_imports_finder_spec.rb b/spec/finders/groups/accepting_project_imports_finder_spec.rb
new file mode 100644
index 00000000000..4e06c2cbc67
--- /dev/null
+++ b/spec/finders/groups/accepting_project_imports_finder_spec.rb
@@ -0,0 +1,105 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::AcceptingProjectImportsFinder, feature_category: :importers do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:group_where_direct_owner) { create(:group) }
+ let_it_be(:subgroup_of_group_where_direct_owner) { create(:group, parent: group_where_direct_owner) }
+ let_it_be(:group_where_direct_maintainer) { create(:group) }
+ let_it_be(:group_where_direct_maintainer_but_cant_create_projects) do
+ create(:group, project_creation_level: Gitlab::Access::NO_ONE_PROJECT_ACCESS)
+ end
+
+ let_it_be(:group_where_direct_developer_but_developers_cannot_create_projects) { create(:group) }
+ let_it_be(:group_where_direct_developer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_owner) { create(:group) }
+
+ let_it_be(:shared_with_group_where_direct_owner_as_developer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_developer_but_developers_cannot_create_projects) do
+ create(:group)
+ end
+
+ let_it_be(:shared_with_group_where_direct_developer_as_maintainer) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:shared_with_group_where_direct_owner_as_guest) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_owner_as_maintainer) { create(:group) }
+ let_it_be(:shared_with_group_where_direct_developer_as_owner) do
+ create(:group, project_creation_level: Gitlab::Access::DEVELOPER_MAINTAINER_PROJECT_ACCESS)
+ end
+
+ let_it_be(:subgroup_of_shared_with_group_where_direct_owner_as_maintainer) do
+ create(:group, parent: shared_with_group_where_direct_owner_as_maintainer)
+ end
+
+ before do
+ group_where_direct_owner.add_owner(user)
+ group_where_direct_maintainer.add_maintainer(user)
+ group_where_direct_developer_but_developers_cannot_create_projects.add_developer(user)
+ group_where_direct_developer.add_developer(user)
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_owner
+ )
+
+ create(:group_group_link, :developer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_developer_but_developers_cannot_create_projects
+ )
+
+ create(:group_group_link, :maintainer,
+ shared_with_group: group_where_direct_developer,
+ shared_group: shared_with_group_where_direct_developer_as_maintainer
+ )
+
+ create(:group_group_link, :developer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_developer
+ )
+
+ create(:group_group_link, :guest,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_guest
+ )
+
+ create(:group_group_link, :maintainer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_maintainer
+ )
+
+ create(:group_group_link, :owner,
+ shared_with_group: group_where_direct_developer_but_developers_cannot_create_projects,
+ shared_group: shared_with_group_where_direct_developer_as_owner
+ )
+ end
+
+ describe '#execute' do
+ subject(:result) { described_class.new(user).execute }
+
+ it 'only returns groups where the user has access to import projects' do
+ expect(result).to match_array([
+ group_where_direct_owner,
+ subgroup_of_group_where_direct_owner,
+ group_where_direct_maintainer,
+ # groups arising from group shares
+ shared_with_group_where_direct_owner_as_owner,
+ shared_with_group_where_direct_owner_as_maintainer,
+ subgroup_of_shared_with_group_where_direct_owner_as_maintainer
+ ])
+
+ expect(result).not_to include(group_where_direct_developer)
+ expect(result).not_to include(shared_with_group_where_direct_developer_as_owner)
+ expect(result).not_to include(shared_with_group_where_direct_developer_as_maintainer)
+ expect(result).not_to include(shared_with_group_where_direct_owner_as_developer)
+ end
+ end
+end
diff --git a/spec/finders/groups/accepting_project_shares_finder_spec.rb b/spec/finders/groups/accepting_project_shares_finder_spec.rb
new file mode 100644
index 00000000000..6af3fad2110
--- /dev/null
+++ b/spec/finders/groups/accepting_project_shares_finder_spec.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Groups::AcceptingProjectSharesFinder, feature_category: :subgroups do
+ subject(:result) { described_class.new(current_user, project, params).execute }
+
+ let_it_be_with_reload(:current_user) { create(:user) }
+ let_it_be(:group_1) { create(:group) }
+ let_it_be(:group_1_subgroup) { create(:group, parent: group_1) }
+ let_it_be(:group_2) { create(:group, name: 'hello-world-group') }
+ let_it_be(:group_3) { create(:group) }
+ let_it_be_with_reload(:group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, group: group) }
+
+ let(:params) { {} }
+
+ context 'when admin', :enable_admin_mode do
+ let_it_be(:current_user) { create(:admin) }
+
+ it 'returns all groups' do
+ expect(result).to match_array([group_1, group_1_subgroup, group_2, group_3])
+ end
+ end
+
+ context 'when normal user' do
+ context 'when the user has no access to the project to be shared' do
+ it 'does not return any group' do
+ expect(result).to be_empty
+ end
+ end
+
+ context 'when the user has no access to any group' do
+ before do
+ project.add_maintainer(current_user)
+ end
+
+ it 'does not return any group' do
+ expect(result).to be_empty
+ end
+ end
+
+ context "when the project's group has enabled lock on group sharing" do
+ before do
+ project.add_maintainer(current_user)
+ project.namespace.update!(share_with_group_lock: true)
+ group_1.add_maintainer(current_user)
+ end
+
+ it 'does not return any group' do
+ expect(result).to be_empty
+ end
+ end
+
+ context 'when the user has access to groups' do
+ before do
+ project.add_maintainer(current_user)
+
+ group_1.add_guest(current_user)
+ group_2.add_guest(current_user)
+ end
+
+ it 'returns groups where the user has at least guest access' do
+ expect(result).to match_array([group_1, group_1_subgroup, group_2])
+ end
+
+ context 'when searching' do
+ let(:params) { { search: 'hello' } }
+
+ it 'returns groups where the search term matches' do
+ expect(result).to match_array([group_2])
+ end
+ end
+ end
+
+ context 'for sharing outside hierarchy' do
+ let_it_be_with_reload(:grandparent_group) { create(:group) }
+ let_it_be(:child_group) { create(:group, parent: grandparent_group) }
+ let_it_be(:grandchild_group) { create(:group, parent: child_group) }
+ let_it_be(:grandchild_group_subgroup) { create(:group, parent: grandchild_group) }
+ let_it_be(:unrelated_group) { create(:group) }
+ let_it_be_with_reload(:project) { create(:project, group: child_group) }
+
+ before do
+ project.add_maintainer(current_user)
+
+ grandparent_group.add_guest(current_user)
+ unrelated_group.add_guest(current_user)
+ end
+
+ context 'when sharing outside hierarchy is allowed' do
+ before do
+ grandparent_group.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: false)
+ end
+
+ it 'returns all groups where the user has at least guest access' do
+ expect(result).to match_array([grandchild_group, grandchild_group_subgroup, unrelated_group])
+ end
+ end
+
+ context 'when sharing outside hierarchy is not allowed' do
+ before do
+ grandparent_group.namespace_settings.update!(prevent_sharing_groups_outside_hierarchy: true)
+ end
+
+ it 'returns groups where the user has at least guest access, but only from within the hierarchy' do
+ expect(result).to match_array([grandchild_group, grandchild_group_subgroup])
+ end
+
+ context 'when groups are already linked to the project' do
+ before do
+ create(:project_group_link, project: project, group: grandchild_group_subgroup)
+ end
+
+ it 'does not appear in the result' do
+ expect(result).to match_array([grandchild_group])
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/finders/groups/accepting_project_transfers_finder_spec.rb b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
index e73318c763f..bb6731abbba 100644
--- a/spec/finders/groups/accepting_project_transfers_finder_spec.rb
+++ b/spec/finders/groups/accepting_project_transfers_finder_spec.rb
@@ -25,24 +25,28 @@ RSpec.describe Groups::AcceptingProjectTransfersFinder do
group_where_direct_maintainer.add_maintainer(user)
group_where_direct_developer.add_developer(user)
- create(:group_group_link, :owner,
- shared_with_group: group_where_direct_owner,
- shared_group: shared_with_group_where_direct_owner_as_owner
+ create(
+ :group_group_link, :owner,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_owner
)
- create(:group_group_link, :guest,
- shared_with_group: group_where_direct_owner,
- shared_group: shared_with_group_where_direct_owner_as_guest
+ create(
+ :group_group_link, :guest,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_guest
)
- create(:group_group_link, :maintainer,
- shared_with_group: group_where_direct_owner,
- shared_group: shared_with_group_where_direct_owner_as_maintainer
+ create(
+ :group_group_link, :maintainer,
+ shared_with_group: group_where_direct_owner,
+ shared_group: shared_with_group_where_direct_owner_as_maintainer
)
- create(:group_group_link, :owner,
- shared_with_group: group_where_direct_developer,
- shared_group: shared_with_group_where_direct_developer_as_owner
+ create(
+ :group_group_link, :owner,
+ shared_with_group: group_where_direct_developer,
+ shared_group: shared_with_group_where_direct_developer_as_owner
)
end
@@ -51,13 +55,13 @@ RSpec.describe Groups::AcceptingProjectTransfersFinder do
it 'only returns groups where the user has access to transfer projects to' do
expect(result).to match_array([
- group_where_direct_owner,
- subgroup_of_group_where_direct_owner,
- group_where_direct_maintainer,
- shared_with_group_where_direct_owner_as_owner,
- shared_with_group_where_direct_owner_as_maintainer,
- subgroup_of_shared_with_group_where_direct_owner_as_maintainer
- ])
+ group_where_direct_owner,
+ subgroup_of_group_where_direct_owner,
+ group_where_direct_maintainer,
+ shared_with_group_where_direct_owner_as_owner,
+ shared_with_group_where_direct_owner_as_maintainer,
+ subgroup_of_shared_with_group_where_direct_owner_as_maintainer
+ ])
end
end
end
diff --git a/spec/finders/groups/user_groups_finder_spec.rb b/spec/finders/groups/user_groups_finder_spec.rb
index 999079468e5..f6df396037c 100644
--- a/spec/finders/groups/user_groups_finder_spec.rb
+++ b/spec/finders/groups/user_groups_finder_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe Groups::UserGroupsFinder do
+RSpec.describe Groups::UserGroupsFinder, feature_category: :subgroups do
describe '#execute' do
let_it_be(:user) { create(:user) }
let_it_be(:root_group) { create(:group, name: 'Root group', path: 'root-group') }
@@ -98,6 +98,24 @@ RSpec.describe Groups::UserGroupsFinder do
end
end
+ context 'when permission is :import_projects' do
+ let(:arguments) { { permission_scope: :import_projects } }
+
+ specify do
+ is_expected.to contain_exactly(
+ public_maintainer_group,
+ public_owner_group,
+ private_maintainer_group
+ )
+ end
+
+ it_behaves_like 'user group finder searching by name or path' do
+ let(:keyword_search_expected_groups) do
+ [public_maintainer_group]
+ end
+ end
+ end
+
context 'when permission is :transfer_projects' do
let(:arguments) { { permission_scope: :transfer_projects } }
diff --git a/spec/finders/issuables/crm_organization_filter_spec.rb b/spec/finders/issuables/crm_organization_filter_spec.rb
index 2a521dcf721..9a910091fd2 100644
--- a/spec/finders/issuables/crm_organization_filter_spec.rb
+++ b/spec/finders/issuables/crm_organization_filter_spec.rb
@@ -6,11 +6,11 @@ RSpec.describe Issuables::CrmOrganizationFilter do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
- let_it_be(:organization1) { create(:organization, group: group) }
- let_it_be(:organization2) { create(:organization, group: group) }
- let_it_be(:contact1) { create(:contact, group: group, organization: organization1) }
- let_it_be(:contact2) { create(:contact, group: group, organization: organization1) }
- let_it_be(:contact3) { create(:contact, group: group, organization: organization2) }
+ let_it_be(:crm_organization1) { create(:crm_organization, group: group) }
+ let_it_be(:crm_organization2) { create(:crm_organization, group: group) }
+ let_it_be(:contact1) { create(:contact, group: group, organization: crm_organization1) }
+ let_it_be(:contact2) { create(:contact, group: group, organization: crm_organization1) }
+ let_it_be(:contact3) { create(:contact, group: group, organization: crm_organization2) }
let_it_be(:contact1_issue) { create(:issue, project: project) }
let_it_be(:contact2_issue) { create(:issue, project: project) }
@@ -24,14 +24,14 @@ RSpec.describe Issuables::CrmOrganizationFilter do
end
describe 'when an organization has issues' do
- it 'returns all organization1 issues' do
- params = { crm_organization_id: organization1.id }
+ it 'returns all crm_organization1 issues' do
+ params = { crm_organization_id: crm_organization1.id }
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact1_issue, contact2_issue)
end
- it 'returns all organization2 issues' do
- params = { crm_organization_id: organization2.id }
+ it 'returns all crm_organization2 issues' do
+ params = { crm_organization_id: crm_organization2.id }
expect(described_class.new(params: params).filter(issues)).to contain_exactly(contact3_issue)
end
@@ -39,8 +39,8 @@ RSpec.describe Issuables::CrmOrganizationFilter do
describe 'when an organization has no issues' do
it 'returns no issues' do
- organization3 = create(:organization, group: group)
- params = { crm_organization_id: organization3.id }
+ crm_organization3 = create(:crm_organization, group: group)
+ params = { crm_organization_id: crm_organization3.id }
expect(described_class.new(params: params).filter(issues)).to be_empty
end
diff --git a/spec/finders/members_finder_spec.rb b/spec/finders/members_finder_spec.rb
index c48a0271471..afab4514ce2 100644
--- a/spec/finders/members_finder_spec.rb
+++ b/spec/finders/members_finder_spec.rb
@@ -161,6 +161,37 @@ RSpec.describe MembersFinder, feature_category: :subgroups do
expect(result).to eq([member3, member2, member1])
end
+ context 'with :shared_into_ancestors' do
+ let_it_be(:invited_group) do
+ create(:group).tap do |invited_group|
+ create(:group_group_link, shared_group: nested_group, shared_with_group: invited_group)
+ end
+ end
+
+ let_it_be(:invited_group_member) { create(:group_member, :developer, group: invited_group, user: user1) }
+ let_it_be(:namespace_parent_member) { create(:group_member, :owner, group: group, user: user2) }
+ let_it_be(:namespace_member) { create(:group_member, :developer, group: nested_group, user: user3) }
+ let_it_be(:project_member) { create(:project_member, :developer, project: project, user: user4) }
+
+ subject(:result) { described_class.new(project, user4).execute(include_relations: include_relations) }
+
+ context 'when :shared_into_ancestors is included in the relations' do
+ let(:include_relations) { [:inherited, :direct, :invited_groups, :shared_into_ancestors] }
+
+ it "includes members of groups invited into ancestors of project's group" do
+ expect(result).to match_array([namespace_parent_member, namespace_member, invited_group_member, project_member])
+ end
+ end
+
+ context 'when :shared_into_ancestors is not included in the relations' do
+ let(:include_relations) { [:inherited, :direct, :invited_groups] }
+
+ it "does not include members of groups invited into ancestors of project's group" do
+ expect(result).to match_array([namespace_parent_member, namespace_member, project_member])
+ end
+ end
+ end
+
context 'when :invited_groups is passed' do
shared_examples 'with invited_groups param' do
subject { described_class.new(project, user2).execute(include_relations: [:inherited, :direct, :invited_groups]) }
@@ -207,12 +238,4 @@ RSpec.describe MembersFinder, feature_category: :subgroups do
end
it_behaves_like '#execute'
-
- context 'when project_members_index_by_project_namespace feature flag is disabled' do
- before do
- stub_feature_flags(project_members_index_by_project_namespace: false)
- end
-
- it_behaves_like '#execute'
- end
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index e8099924638..6d576bc8e38 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -493,6 +493,48 @@ RSpec.describe MergeRequestsFinder, feature_category: :code_review_workflow do
end
end
+ context 'filtering by approved' do
+ before do
+ create(:approval, merge_request: merge_request3, user: user2)
+ end
+
+ context 'when flag `mr_approved_filter` is disabled' do
+ before do
+ stub_feature_flags(mr_approved_filter: false)
+ end
+
+ it 'for approved' do
+ merge_requests = described_class.new(user, { approved: true }).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5)
+ end
+
+ it 'for not approved' do
+ merge_requests = described_class.new(user, { approved: false }).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request3, merge_request4, merge_request5)
+ end
+ end
+
+ context 'when flag `mr_approved_filter` is enabled' do
+ before do
+ stub_feature_flags(mr_approved_filter: true)
+ end
+
+ it 'for approved' do
+ merge_requests = described_class.new(user, { approved: true }).execute
+
+ expect(merge_requests).to contain_exactly(merge_request3)
+ end
+
+ it 'for not approved' do
+ merge_requests = described_class.new(user, { approved: false }).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request4, merge_request5)
+ end
+ end
+ end
+
context 'filtering by approved by username' do
let(:params) { { approved_by_usernames: user2.username } }
@@ -564,24 +606,28 @@ RSpec.describe MergeRequestsFinder, feature_category: :code_review_workflow do
let_it_be(:new_project) { create(:project, forked_from_project: project1) }
let!(:new_merge_request) do
- create(:merge_request,
- :simple,
- author: user,
- created_at: 1.week.from_now,
- updated_at: 1.week.from_now,
- source_project: new_project,
- target_project: new_project)
+ create(
+ :merge_request,
+ :simple,
+ author: user,
+ created_at: 1.week.from_now,
+ updated_at: 1.week.from_now,
+ source_project: new_project,
+ target_project: new_project
+ )
end
let!(:old_merge_request) do
- create(:merge_request,
- :simple,
- author: user,
- source_branch: 'feature_1',
- created_at: 1.week.ago,
- updated_at: 1.week.ago,
- source_project: new_project,
- target_project: new_project)
+ create(
+ :merge_request,
+ :simple,
+ author: user,
+ source_branch: 'feature_1',
+ created_at: 1.week.ago,
+ updated_at: 1.week.ago,
+ source_project: new_project,
+ target_project: new_project
+ )
end
before_all do
diff --git a/spec/finders/milestones_finder_spec.rb b/spec/finders/milestones_finder_spec.rb
index 8dd83df3a28..c4c62e21ad9 100644
--- a/spec/finders/milestones_finder_spec.rb
+++ b/spec/finders/milestones_finder_spec.rb
@@ -62,9 +62,31 @@ RSpec.describe MilestonesFinder do
end
context 'with filters' do
- let_it_be(:milestone_1) { create(:milestone, group: group, state: 'closed', title: 'one test', start_date: now - 1.day, due_date: now) }
- let_it_be(:milestone_3) { create(:milestone, project: project_1, state: 'closed', start_date: now + 2.days, due_date: now + 3.days) }
+ let_it_be(:milestone_1) do
+ create(
+ :milestone,
+ group: group,
+ state: 'closed',
+ title: 'one test',
+ start_date: now - 1.day,
+ due_date: now,
+ updated_at: now - 3.days
+ )
+ end
+
+ let_it_be(:milestone_3) do
+ create(
+ :milestone,
+ project: project_1,
+ state: 'closed',
+ description: 'three test',
+ start_date: now + 2.days,
+ due_date: now + 3.days,
+ updated_at: now - 5.days
+ )
+ end
+ let(:result) { described_class.new(params).execute }
let(:params) do
{
project_ids: [project_1.id, project_2.id],
@@ -76,62 +98,96 @@ RSpec.describe MilestonesFinder do
it 'filters by id' do
params[:ids] = [milestone_1.id, milestone_2.id]
- result = described_class.new(params).execute
-
expect(result).to contain_exactly(milestone_1, milestone_2)
end
it 'filters by active state' do
params[:state] = 'active'
- result = described_class.new(params).execute
expect(result).to contain_exactly(milestone_2, milestone_4)
end
it 'filters by closed state' do
params[:state] = 'closed'
- result = described_class.new(params).execute
expect(result).to contain_exactly(milestone_1, milestone_3)
end
it 'filters by title' do
- result = described_class.new(params.merge(title: 'one test')).execute
+ params[:title] = 'one test'
- expect(result.to_a).to contain_exactly(milestone_1)
+ expect(result).to contain_exactly(milestone_1)
end
it 'filters by search_title' do
- result = described_class.new(params.merge(search_title: 'one t')).execute
+ params[:search_title] = 'test'
+
+ expect(result).to contain_exactly(milestone_1)
+ end
+
+ it 'filters by search (title, description)' do
+ params[:search] = 'test'
- expect(result.to_a).to contain_exactly(milestone_1)
+ expect(result).to contain_exactly(milestone_1, milestone_3)
end
context 'by timeframe' do
it 'returns milestones with start_date and due_date between timeframe' do
params.merge!(start_date: now - 1.day, end_date: now + 3.days)
- milestones = described_class.new(params).execute
-
- expect(milestones).to match_array([milestone_1, milestone_2, milestone_3])
+ expect(result).to contain_exactly(milestone_1, milestone_2, milestone_3)
end
it 'returns milestones which starts before the timeframe' do
milestone = create(:milestone, project: project_2, start_date: now - 5.days)
params.merge!(start_date: now - 3.days, end_date: now - 2.days)
- milestones = described_class.new(params).execute
-
- expect(milestones).to match_array([milestone])
+ expect(result).to contain_exactly(milestone)
end
it 'returns milestones which ends after the timeframe' do
milestone = create(:milestone, project: project_2, due_date: now + 6.days)
params.merge!(start_date: now + 6.days, end_date: now + 7.days)
- milestones = described_class.new(params).execute
+ expect(result).to contain_exactly(milestone)
+ end
+ end
+
+ context 'by updated_at' do
+ it 'returns milestones updated before a given date' do
+ params[:updated_before] = 4.days.ago.iso8601
+
+ expect(result).to contain_exactly(milestone_3)
+ end
+
+ it 'returns milestones updated after a given date' do
+ params[:updated_after] = 4.days.ago.iso8601
+
+ expect(result).to contain_exactly(milestone_1, milestone_2, milestone_4)
+ end
+
+ it 'returns milestones updated between the given dates' do
+ params.merge!(updated_after: 6.days.ago.iso8601, updated_before: 4.days.ago.iso8601)
+
+ expect(result).to contain_exactly(milestone_3)
+ end
+ end
+
+ context 'by iids' do
+ before do
+ params[:iids] = 1
+ end
- expect(milestones).to match_array([milestone])
+ it 'returns milestone for the given iids' do
+ expect(result).to contain_exactly(milestone_2, milestone_3, milestone_4)
+ end
+
+ context 'when include_parent_milestones is true' do
+ it 'ignores the iid filter' do
+ params[:include_parent_milestones] = true
+
+ expect(result).to contain_exactly(milestone_1, milestone_2, milestone_3, milestone_4)
+ end
end
end
end
diff --git a/spec/finders/notes_finder_spec.rb b/spec/finders/notes_finder_spec.rb
index 1255a882114..e93c0c790c2 100644
--- a/spec/finders/notes_finder_spec.rb
+++ b/spec/finders/notes_finder_spec.rb
@@ -74,11 +74,13 @@ RSpec.describe NotesFinder do
context 'on restricted projects' do
let(:project) do
- create(:project,
- :public,
- :issues_private,
- :snippets_private,
- :merge_requests_private)
+ create(
+ :project,
+ :public,
+ :issues_private,
+ :snippets_private,
+ :merge_requests_private
+ )
end
it 'publicly excludes notes on merge requests' do
@@ -126,6 +128,51 @@ RSpec.describe NotesFinder do
end
end
+ context 'for notes from users who have been banned', :enable_admin_mode, feature_category: :instance_resiliency do
+ subject(:finder) { described_class.new(user, project: project).execute }
+
+ let_it_be(:banned_user) { create(:banned_user).user }
+ let!(:banned_note) { create(:note_on_issue, project: project, author: banned_user) }
+
+ context 'when :hidden_notes feature is not enabled' do
+ before do
+ stub_feature_flags(hidden_notes: false)
+ end
+
+ context 'when user is not an admin' do
+ it { is_expected.to include(banned_note) }
+ end
+
+ context 'when @current_user is nil' do
+ let(:user) { nil }
+
+ it { is_expected.to be_empty }
+ end
+ end
+
+ context 'when :hidden_notes feature is enabled' do
+ before do
+ stub_feature_flags(hidden_notes: true)
+ end
+
+ context 'when user is an admin' do
+ let(:user) { create(:admin) }
+
+ it { is_expected.to include(banned_note) }
+ end
+
+ context 'when user is not an admin' do
+ it { is_expected.not_to include(banned_note) }
+ end
+
+ context 'when @current_user is nil' do
+ let(:user) { nil }
+
+ it { is_expected.to be_empty }
+ end
+ end
+ end
+
context 'for target type' do
let(:project) { create(:project, :repository) }
let!(:note1) { create :note_on_issue, project: project }
diff --git a/spec/finders/packages/conan/package_finder_spec.rb b/spec/finders/packages/conan/package_finder_spec.rb
index f25a62225a8..787cb256486 100644
--- a/spec/finders/packages/conan/package_finder_spec.rb
+++ b/spec/finders/packages/conan/package_finder_spec.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
-RSpec.describe ::Packages::Conan::PackageFinder do
+RSpec.describe ::Packages::Conan::PackageFinder, feature_category: :package_registry do
using RSpec::Parameterized::TableSyntax
let_it_be_with_reload(:project) { create(:project) }
@@ -15,7 +15,8 @@ RSpec.describe ::Packages::Conan::PackageFinder do
describe '#execute' do
let(:query) { "#{conan_package.name.split('/').first[0, 3]}%" }
- let(:finder) { described_class.new(user, query: query) }
+ let(:finder) { described_class.new(user, params) }
+ let(:params) { { query: query } }
subject { finder.execute }
@@ -40,7 +41,7 @@ RSpec.describe ::Packages::Conan::PackageFinder do
end
with_them do
- let(:expected_packages) { packages_visible ? [conan_package, conan_package2] : [] }
+ let(:expected_packages) { packages_visible ? [conan_package2, conan_package] : [] }
let(:user) { role == :anonymous ? nil : super() }
before do
@@ -50,5 +51,23 @@ RSpec.describe ::Packages::Conan::PackageFinder do
it { is_expected.to eq(expected_packages) }
end
+
+ context 'with project' do
+ subject { described_class.new(user, params, project: project).execute }
+
+ it { is_expected.to match_array([conan_package2, conan_package]) }
+
+ it 'respects the limit' do
+ stub_const("#{described_class}::MAX_PACKAGES_COUNT", 1)
+
+ expect(subject).to match_array([conan_package2])
+ end
+
+ context 'with a different project' do
+ let_it_be(:project) { private_project }
+
+ it { is_expected.to match_array([private_package]) }
+ end
+ end
end
end
diff --git a/spec/finders/packages/group_packages_finder_spec.rb b/spec/finders/packages/group_packages_finder_spec.rb
index f78a356b13d..e4a944eb837 100644
--- a/spec/finders/packages/group_packages_finder_spec.rb
+++ b/spec/finders/packages/group_packages_finder_spec.rb
@@ -203,7 +203,9 @@ RSpec.describe Packages::GroupPackagesFinder do
end
context 'group has package of all types' do
- package_types.each { |pt| let_it_be("package_#{pt}") { create("#{pt}_package", project: project) } }
+ package_types.each do |pt| # rubocop:disable RSpec/UselessDynamicDefinition
+ let_it_be("package_#{pt}") { create("#{pt}_package", project: project) }
+ end
package_types.each do |package_type|
it_behaves_like 'with package type', package_type
diff --git a/spec/finders/packages/npm/package_finder_spec.rb b/spec/finders/packages/npm/package_finder_spec.rb
index 8c9149a5a2d..e11b33f71e9 100644
--- a/spec/finders/packages/npm/package_finder_spec.rb
+++ b/spec/finders/packages/npm/package_finder_spec.rb
@@ -71,6 +71,14 @@ RSpec.describe ::Packages::Npm::PackageFinder do
context 'enabled' do
it { is_expected.to contain_exactly(package2) }
end
+
+ context 'with npm_allow_packages_in_multiple_projects disabled' do
+ before do
+ stub_feature_flags(npm_allow_packages_in_multiple_projects: false)
+ end
+
+ it { is_expected.to contain_exactly(package2) }
+ end
end
context 'with a project' do
diff --git a/spec/finders/pending_todos_finder_spec.rb b/spec/finders/pending_todos_finder_spec.rb
index 4f4862852f4..0cf61a0958e 100644
--- a/spec/finders/pending_todos_finder_spec.rb
+++ b/spec/finders/pending_todos_finder_spec.rb
@@ -5,49 +5,60 @@ require 'spec_helper'
RSpec.describe PendingTodosFinder do
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
+ let_it_be(:user3) { create(:user) }
let_it_be(:issue) { create(:issue) }
+ let_it_be(:issue2) { create(:issue) }
+ let_it_be(:project) { create(:project) }
let_it_be(:note) { create(:note) }
+ let_it_be(:todo) { create(:todo, :pending, user: user, target: issue) }
+ let_it_be(:todo2) { create(:todo, :pending, user: user, target: issue2, project: project) }
+ let_it_be(:todo3) { create(:todo, :pending, user: user2, target: issue) }
+ let_it_be(:todo4) { create(:todo, :pending, user: user3, target: issue) }
+ let_it_be(:done_todo) { create(:todo, :done, user: user) }
let(:users) { [user, user2] }
describe '#execute' do
- it 'returns only pending todos' do
- create(:todo, :done, user: user)
+ it 'returns all pending todos if no params are passed' do
+ todos = described_class.new.execute
- todo = create(:todo, :pending, user: user)
- todos = described_class.new(users).execute
+ expect(todos).to match_array([todo, todo2, todo3, todo4])
+ end
- expect(todos).to eq([todo])
+ it 'supports retrieving only pending todos for chosen users' do
+ todos = described_class.new(users: users).execute
+
+ expect(todos).to match_array([todo, todo2, todo3])
end
it 'supports retrieving of todos for a specific project' do
- project1 = create(:project)
project2 = create(:project)
+ project2_todo = create(:todo, :pending, user: user, project: project2)
- create(:todo, :pending, user: user, project: project2)
+ todos = described_class.new(users: user, project_id: project.id).execute
+ expect(todos).to match_array([todo2])
- todo = create(:todo, :pending, user: user, project: project1)
- todos = described_class.new(users, project_id: project1.id).execute
-
- expect(todos).to eq([todo])
+ todos = described_class.new(users: user, project_id: project2.id).execute
+ expect(todos).to match_array([project2_todo])
end
it 'supports retrieving of todos for a specific todo target' do
- todo = create(:todo, :pending, user: user, target: issue)
+ todos = described_class.new(users: user, target_id: issue.id, target_type: 'Issue').execute
- create(:todo, :pending, user: user, target: note)
-
- todos = described_class.new(users, target_id: issue.id, target_type: 'Issue').execute
-
- expect(todos).to eq([todo])
+ expect(todos).to match_array([todo])
end
it 'supports retrieving of todos for a specific target type' do
- todo = create(:todo, :pending, user: user, target: issue)
+ todos = described_class.new(users: user, target_type: issue.class.name).execute
+
+ expect(todos).to match_array([todo, todo2])
+ end
- create(:todo, :pending, user: user, target: note)
+ it 'supports retrieving of todos from a specific author' do
+ todo = create(:todo, :pending, user: user, author: user2, target: issue)
+ create(:todo, :pending, user: user, author: user3, target: issue)
- todos = described_class.new(users, target_type: issue.class.name).execute
+ todos = described_class.new(users: users, author_id: user2.id).execute
expect(todos).to eq([todo])
end
@@ -56,7 +67,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, commit_id: '456')
todo = create(:todo, :pending, user: user, commit_id: '123')
- todos = described_class.new(users, commit_id: '123').execute
+ todos = described_class.new(users: users, commit_id: '123').execute
expect(todos).to eq([todo])
end
@@ -71,7 +82,7 @@ RSpec.describe PendingTodosFinder do
discussion = Discussion.lazy_find(first_discussion_note.discussion_id)
users = [note_2.author, note_3.author, user]
- todos = described_class.new(users, discussion: discussion).execute
+ todos = described_class.new(users: users, discussion: discussion).execute
expect(todos).to contain_exactly(todo1, todo2)
end
@@ -81,7 +92,7 @@ RSpec.describe PendingTodosFinder do
create(:todo, :pending, user: user, target: issue, action: Todo::ASSIGNED)
- todos = described_class.new(users, action: Todo::MENTIONED).execute
+ todos = described_class.new(users: users, action: Todo::MENTIONED).execute
expect(todos).to contain_exactly(todo)
end
diff --git a/spec/finders/personal_access_tokens_finder_spec.rb b/spec/finders/personal_access_tokens_finder_spec.rb
index bcd5aef84f9..d91b2c8f599 100644
--- a/spec/finders/personal_access_tokens_finder_spec.rb
+++ b/spec/finders/personal_access_tokens_finder_spec.rb
@@ -110,7 +110,7 @@ RSpec.describe PersonalAccessTokensFinder, :enable_admin_mode do
lazy { [user] } | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
lazy { [other_user] } | [:active_other]
lazy { [user, other_user] } | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
- [] | [] # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
+ [] | []
end
with_them do
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index 297c6f84cef..c68ae443231 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe ProjectsFinder do
end
let_it_be(:internal_project) do
- create(:project, :internal, :merge_requests_disabled, group: group, name: 'B', path: 'B')
+ create(:project, :internal, :merge_requests_disabled, group: group, name: 'B', path: 'B', updated_at: 4.days.ago)
end
let_it_be(:public_project) do
@@ -133,6 +133,52 @@ RSpec.describe ProjectsFinder do
end
end
+ describe 'filter by updated_at' do
+ context 'when updated_before is present' do
+ let(:params) { { updated_before: 2.days.ago } }
+
+ it { is_expected.to contain_exactly(internal_project) }
+ end
+
+ context 'when updated_after is present' do
+ let(:params) { { updated_after: 2.days.ago } }
+
+ it { is_expected.not_to include(internal_project) }
+ end
+
+ context 'when both updated_before and updated_after are present' do
+ let(:params) { { updated_before: 2.days.ago, updated_after: 6.days.ago } }
+
+ it { is_expected.to contain_exactly(internal_project) }
+
+ context 'when updated_after > updated_before' do
+ let(:params) { { updated_after: 2.days.ago, updated_before: 6.days.ago } }
+
+ it { is_expected.to be_empty }
+
+ it 'does not query the DB' do
+ expect { subject.to_a }.to make_queries(0)
+ end
+ end
+
+ context 'when updated_after equals updated_before', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/408387' do
+ let(:params) { { updated_after: internal_project.updated_at, updated_before: internal_project.updated_at } }
+
+ it 'allows an exact match' do
+ expect(subject).to contain_exactly(internal_project)
+ end
+ end
+
+ context 'when arguments are invalid datetimes' do
+ let(:params) { { updated_after: 'invalid', updated_before: 'inavlid' } }
+
+ it 'does not filter by updated_at' do
+ expect(subject).to contain_exactly(internal_project, public_project)
+ end
+ end
+ end
+ end
+
describe 'filter by tags (deprecated)' do
before do
public_project.reload
diff --git a/spec/finders/serverless_domain_finder_spec.rb b/spec/finders/serverless_domain_finder_spec.rb
deleted file mode 100644
index 4e6b9f07544..00000000000
--- a/spec/finders/serverless_domain_finder_spec.rb
+++ /dev/null
@@ -1,103 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe ServerlessDomainFinder do
- let(:function_name) { 'test-function' }
- let(:pages_domain_name) { 'serverless.gitlab.io' }
- let(:valid_cluster_uuid) { 'aba1cdef123456f278' }
- let(:invalid_cluster_uuid) { 'aba1cdef123456f178' }
- let!(:environment) { create(:environment, name: 'test') }
-
- let(:pages_domain) do
- create(
- :pages_domain,
- :instance_serverless,
- domain: pages_domain_name
- )
- end
-
- let(:knative_with_ingress) do
- create(
- :clusters_applications_knative,
- external_ip: '10.0.0.1'
- )
- end
-
- let!(:serverless_domain_cluster) do
- create(
- :serverless_domain_cluster,
- uuid: 'abcdef12345678',
- pages_domain: pages_domain,
- knative: knative_with_ingress
- )
- end
-
- let(:valid_uri) { "https://#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:valid_fqdn) { "#{function_name}-#{valid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
- let(:invalid_uri) { "https://#{function_name}-#{invalid_cluster_uuid}#{"%x" % environment.id}-#{environment.slug}.#{pages_domain_name}" }
-
- let(:valid_finder) { described_class.new(valid_uri) }
- let(:invalid_finder) { described_class.new(invalid_uri) }
-
- describe '#serverless?' do
- context 'with a valid URI' do
- subject { valid_finder.serverless? }
-
- it { is_expected.to be_truthy }
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.serverless? }
-
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#serverless_domain_cluster_uuid' do
- context 'with a valid URI' do
- subject { valid_finder.serverless_domain_cluster_uuid }
-
- it { is_expected.to eq serverless_domain_cluster.uuid }
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.serverless_domain_cluster_uuid }
-
- it { is_expected.to be_nil }
- end
- end
-
- describe '#execute' do
- context 'with a valid URI' do
- let(:serverless_domain) do
- create(
- :serverless_domain,
- function_name: function_name,
- serverless_domain_cluster: serverless_domain_cluster,
- environment: environment
- )
- end
-
- subject { valid_finder.execute }
-
- it 'has the correct function_name' do
- expect(subject.function_name).to eq function_name
- end
-
- it 'has the correct serverless_domain_cluster' do
- expect(subject.serverless_domain_cluster).to eq serverless_domain_cluster
- end
-
- it 'has the correct environment' do
- expect(subject.environment).to eq environment
- end
- end
-
- context 'with an invalid URI' do
- subject { invalid_finder.execute }
-
- it { is_expected.to be_nil }
- end
- end
-end
diff --git a/spec/finders/snippets_finder_spec.rb b/spec/finders/snippets_finder_spec.rb
index 48880ec2c1f..9f4b7612be5 100644
--- a/spec/finders/snippets_finder_spec.rb
+++ b/spec/finders/snippets_finder_spec.rb
@@ -237,25 +237,28 @@ RSpec.describe SnippetsFinder do
it 'returns all personal snippets for the admin' do
snippets = described_class.new(admin, only_personal: true).execute
- expect(snippets).to contain_exactly(admin_private_personal_snippet,
- private_personal_snippet,
- internal_personal_snippet,
- public_personal_snippet)
+ expect(snippets).to contain_exactly(
+ admin_private_personal_snippet,
+ private_personal_snippet,
+ internal_personal_snippet,
+ public_personal_snippet
+ )
end
it 'returns only personal snippets visible by user' do
snippets = described_class.new(user, only_personal: true).execute
- expect(snippets).to contain_exactly(private_personal_snippet,
- internal_personal_snippet,
- public_personal_snippet)
+ expect(snippets).to contain_exactly(
+ private_personal_snippet,
+ internal_personal_snippet,
+ public_personal_snippet
+ )
end
it 'returns only internal or public personal snippets for user without snippets' do
snippets = described_class.new(user_without_snippets, only_personal: true).execute
- expect(snippets).to contain_exactly(internal_personal_snippet,
- public_personal_snippet)
+ expect(snippets).to contain_exactly(internal_personal_snippet, public_personal_snippet)
end
end
end
diff --git a/spec/finders/template_finder_spec.rb b/spec/finders/template_finder_spec.rb
index 21fea7863ff..c466f533a61 100644
--- a/spec/finders/template_finder_spec.rb
+++ b/spec/finders/template_finder_spec.rb
@@ -103,6 +103,10 @@ RSpec.describe TemplateFinder do
describe '#build' do
let(:project) { build_stubbed(:project) }
+ before do
+ stub_feature_flags(remove_monitor_metrics: false)
+ end
+
where(:type, :expected_class) do
:dockerfiles | described_class
:gitignores | described_class
@@ -119,6 +123,16 @@ RSpec.describe TemplateFinder do
it { is_expected.to be_a(expected_class) }
it { expect(finder.project).to eq(project) }
end
+
+ context 'when metrics dashboard is unavailable' do
+ before do
+ stub_feature_flags(remove_monitor_metrics: true)
+ end
+
+ subject(:finder) { described_class.build(:metrics_dashboard_ymls, project) }
+
+ it { is_expected.to be_nil }
+ end
end
describe '#execute' do
diff --git a/spec/finders/users_finder_spec.rb b/spec/finders/users_finder_spec.rb
index 5cf845a87b2..2e94ca5757a 100644
--- a/spec/finders/users_finder_spec.rb
+++ b/spec/finders/users_finder_spec.rb
@@ -61,9 +61,11 @@ RSpec.describe UsersFinder do
filtered_user_before = create(:user, created_at: 3.days.ago)
filtered_user_after = create(:user, created_at: Time.now + 3.days)
- users = described_class.new(user,
- created_after: 2.days.ago,
- created_before: Time.now + 2.days).execute
+ users = described_class.new(
+ user,
+ created_after: 2.days.ago,
+ created_before: Time.now + 2.days
+ ).execute
expect(users.map(&:username)).not_to include([filtered_user_before.username, filtered_user_after.username])
end