diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
commit | 43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch) | |
tree | dceebdc68925362117480a5d672bcff122fb625b /spec/finders | |
parent | 20c84b99005abd1c82101dfeff264ac50d2df211 (diff) |
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'spec/finders')
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 |