diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-19 14:01:45 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-19 14:01:45 +0300 |
commit | 9297025d0b7ddf095eb618dfaaab2ff8f2018d8b (patch) | |
tree | 865198c01d1824a9b098127baa3ab980c9cd2c06 /spec/models/ci/catalog/listing_spec.rb | |
parent | 6372471f43ee03c05a7c1f8b0c6ac6b8a7431dbe (diff) |
Add latest changes from gitlab-org/gitlab@16-7-stable-eev16.7.0-rc42
Diffstat (limited to 'spec/models/ci/catalog/listing_spec.rb')
-rw-r--r-- | spec/models/ci/catalog/listing_spec.rb | 292 |
1 files changed, 187 insertions, 105 deletions
diff --git a/spec/models/ci/catalog/listing_spec.rb b/spec/models/ci/catalog/listing_spec.rb index 7a1e12165ac..2ffffb9112c 100644 --- a/spec/models/ci/catalog/listing_spec.rb +++ b/spec/models/ci/catalog/listing_spec.rb @@ -3,59 +3,61 @@ require 'spec_helper' RSpec.describe Ci::Catalog::Listing, feature_category: :pipeline_composition do - let_it_be(:namespace) { create(:group) } - let_it_be(:project_x) { create(:project, namespace: namespace, name: 'X Project') } - let_it_be(:project_a) { create(:project, :public, namespace: namespace, name: 'A Project') } - let_it_be(:project_noaccess) { create(:project, namespace: namespace, name: 'C Project') } - let_it_be(:project_ext) { create(:project, :public, name: 'TestProject') } let_it_be(:user) { create(:user) } + let_it_be(:namespace) { create(:group) } + let_it_be(:public_namespace_project) do + create(:project, :public, namespace: namespace, name: 'A public namespace project') + end - let_it_be(:project_b) do + let_it_be(:public_project) { create(:project, :public, name: 'B public test project') } + let_it_be(:namespace_project_a) { create(:project, namespace: namespace, name: 'Test namespace project') } + let_it_be(:namespace_project_b) { create(:project, namespace: namespace, name: 'X namespace Project') } + let_it_be(:project_noaccess) { create(:project, namespace: namespace, name: 'Project with no access') } + let_it_be(:internal_project) { create(:project, :internal, name: 'Internal project') } + + let_it_be(:private_project) do create(:project, namespace: namespace, name: 'B Project', description: 'Rspec test framework') end let(:list) { described_class.new(user) } before_all do - project_x.add_reporter(user) - project_b.add_reporter(user) - project_a.add_reporter(user) - project_ext.add_reporter(user) + namespace_project_a.add_reporter(user) + namespace_project_b.add_reporter(user) + public_namespace_project.add_reporter(user) + public_project.add_reporter(user) + internal_project.add_owner(user) end describe '#resources' do subject(:resources) { list.resources(**params) } - context 'when user is anonymous' do - let(:user) { nil } - let(:params) { {} } + let(:params) { {} } - let!(:resource_1) { create(:ci_catalog_resource, project: project_a) } - let!(:resource_2) { create(:ci_catalog_resource, project: project_ext) } - let!(:resource_3) { create(:ci_catalog_resource, project: project_b) } + let_it_be(:public_resource_a) { create(:ci_catalog_resource, :published, project: public_namespace_project) } + let_it_be(:public_resource_b) { create(:ci_catalog_resource, :published, project: public_project) } + let_it_be(:internal_resource) { create(:ci_catalog_resource, :published, project: internal_project) } + let_it_be(:private_namespace_resource) { create(:ci_catalog_resource, :published, project: namespace_project_a) } + let_it_be(:unpublished_resource) { create(:ci_catalog_resource, project: namespace_project_b) } - it 'returns only resources for public projects' do - is_expected.to contain_exactly(resource_1, resource_2) - end + it 'by default returns all resources visible to the current user' do + is_expected.to contain_exactly(public_resource_a, public_resource_b, private_namespace_resource, + internal_resource) + end - context 'when sorting is provided' do - let(:params) { { sort: :name_desc } } + context 'when user is anonymous' do + let(:user) { nil } - it 'returns only resources for public projects sorted by name DESC' do - is_expected.to contain_exactly(resource_2, resource_1) - end + it 'returns only published resources for public projects' do + is_expected.to contain_exactly(public_resource_a, public_resource_b) end end context 'when search params are provided' do let(:params) { { search: 'test' } } - let!(:resource_1) { create(:ci_catalog_resource, project: project_a) } - let!(:resource_2) { create(:ci_catalog_resource, project: project_ext) } - let!(:resource_3) { create(:ci_catalog_resource, project: project_b) } - it 'returns the resources that match the search params' do - is_expected.to contain_exactly(resource_2, resource_3) + is_expected.to contain_exactly(public_resource_b, private_namespace_resource) end context 'when search term is too small' do @@ -65,117 +67,197 @@ RSpec.describe Ci::Catalog::Listing, feature_category: :pipeline_composition do end end - context 'when namespace is provided' do - let(:params) { { namespace: namespace } } + context 'when the scope is :namespaces' do + let_it_be(:public_resource_no_namespace) do + create(:ci_catalog_resource, project: create(:project, :public, name: 'public')) + end - context 'when namespace is not a root namespace' do - let(:namespace) { create(:group, :nested) } + let(:params) { { scope: :namespaces } } - it 'raises an exception' do - expect { resources }.to raise_error(ArgumentError, 'Namespace is not a root namespace') + context 'when the `ci_guard_query_for_catalog_resource_scope` ff is enabled' do + it "returns the catalog resources belonging to the user's authorized namespaces" do + is_expected.to contain_exactly(public_resource_a, public_resource_b, internal_resource, + private_namespace_resource) end end - context 'when the user has access to all projects in the namespace' do - context 'when the namespace has no catalog resources' do - it { is_expected.to be_empty } + context 'when the `ci_guard_query_for_catalog_resource_scope` ff is disabled' do + before do + stub_feature_flags(ci_guard_for_catalog_resource_scope: false) end - context 'when the namespace has catalog resources' do - let_it_be(:today) { Time.zone.now } - let_it_be(:yesterday) { today - 1.day } - let_it_be(:tomorrow) { today + 1.day } + it 'returns all resources visible to the current user' do + is_expected.to contain_exactly( + public_resource_a, public_resource_b, private_namespace_resource, + internal_resource) + end + end + end - let_it_be(:resource_1) do - create(:ci_catalog_resource, project: project_x, latest_released_at: yesterday, created_at: today) - end + context 'with a sort parameter' do + let_it_be(:today) { Time.zone.now } + let_it_be(:yesterday) { today - 1.day } + let_it_be(:tomorrow) { today + 1.day } - let_it_be(:resource_2) do - create(:ci_catalog_resource, project: project_b, latest_released_at: today, created_at: yesterday) - end + let(:params) { { sort: sort } } - let_it_be(:resource_3) do - create(:ci_catalog_resource, project: project_a, latest_released_at: nil, created_at: tomorrow) - end + before_all do + public_resource_a.update!(created_at: today, latest_released_at: yesterday) + public_resource_b.update!(created_at: yesterday, latest_released_at: today) + private_namespace_resource.update!(created_at: tomorrow, latest_released_at: tomorrow) + internal_resource.update!(created_at: tomorrow + 1) + end - let_it_be(:other_namespace_resource) do - create(:ci_catalog_resource, project: project_ext, latest_released_at: tomorrow) - end + context 'when the sort is created_at ascending' do + let_it_be(:sort) { :created_at_asc } + + it 'contains catalog resources sorted by created_at ascending' do + is_expected.to eq([public_resource_b, public_resource_a, private_namespace_resource, internal_resource]) + end + end + + context 'when the sort is created_at descending' do + let_it_be(:sort) { :created_at_desc } + + it 'contains catalog resources sorted by created_at descending' do + is_expected.to eq([internal_resource, private_namespace_resource, public_resource_a, public_resource_b]) + end + end + + context 'when the sort is name ascending' do + let_it_be(:sort) { :name_asc } + + it 'contains catalog resources for projects sorted by name ascending' do + is_expected.to eq([public_resource_a, public_resource_b, internal_resource, private_namespace_resource]) + end + end + + context 'when the sort is name descending' do + let_it_be(:sort) { :name_desc } + + it 'contains catalog resources for projects sorted by name descending' do + is_expected.to eq([private_namespace_resource, internal_resource, public_resource_b, public_resource_a]) + end + end - it 'contains only catalog resources for projects in that namespace' do - is_expected.to contain_exactly(resource_1, resource_2, resource_3) + context 'when the sort is latest_released_at ascending' do + let_it_be(:sort) { :latest_released_at_asc } + + it 'contains catalog resources sorted by latest_released_at ascending with nulls last' do + is_expected.to eq([public_resource_a, public_resource_b, private_namespace_resource, internal_resource]) + end + end + + context 'when the sort is latest_released_at descending' do + let_it_be(:sort) { :latest_released_at_desc } + + it 'contains catalog resources sorted by latest_released_at descending with nulls last' do + is_expected.to eq([private_namespace_resource, public_resource_b, public_resource_a, internal_resource]) + end + end + end + + context 'when namespace is provided' do + let(:params) { { namespace: namespace } } + + context 'when it is a root namespace' do + context 'when it has catalog resources' do + it 'returns resources in the namespace visible to the user' do + is_expected.to contain_exactly(public_resource_a, private_namespace_resource) end + end - context 'with a sort parameter' do - let(:params) { { namespace: namespace, sort: sort } } + context 'when the namespace has no catalog resources' do + let(:namespace) { build(:namespace) } - context 'when the sort is created_at ascending' do - let_it_be(:sort) { :created_at_asc } + it { is_expected.to be_empty } + end + end - it 'contains catalog resources sorted by created_at ascending' do - is_expected.to eq([resource_2, resource_1, resource_3]) - end - end + context 'when namespace is not a root namespace' do + let_it_be(:namespace) { create(:group, :nested) } - context 'when the sort is created_at descending' do - let_it_be(:sort) { :created_at_desc } + it 'raises an exception' do + expect { resources }.to raise_error(ArgumentError, 'Namespace is not a root namespace') + end + end + end + end - it 'contains catalog resources sorted by created_at descending' do - is_expected.to eq([resource_3, resource_1, resource_2]) - end - end + describe '#find_resource' do + let_it_be(:accessible_resource) { create(:ci_catalog_resource, :published, project: public_project) } + let_it_be(:inaccessible_resource) { create(:ci_catalog_resource, :published, project: project_noaccess) } + let_it_be(:draft_resource) { create(:ci_catalog_resource, project: public_namespace_project, state: :draft) } - context 'when the sort is name ascending' do - let_it_be(:sort) { :name_asc } + context 'when using the ID argument' do + subject { list.find_resource(id: id) } - it 'contains catalog resources for projects sorted by name ascending' do - is_expected.to eq([resource_3, resource_2, resource_1]) - end - end + context 'when the resource is published and visible to the user' do + let(:id) { accessible_resource.id } - context 'when the sort is name descending' do - let_it_be(:sort) { :name_desc } + it 'fetches the resource' do + is_expected.to eq(accessible_resource) + end + end - it 'contains catalog resources for projects sorted by name descending' do - is_expected.to eq([resource_1, resource_2, resource_3]) - end - end + context 'when the resource is not found' do + let(:id) { 'not-an-id' } - context 'when the sort is latest_released_at ascending' do - let_it_be(:sort) { :latest_released_at_asc } + it 'returns nil' do + is_expected.to be_nil + end + end - it 'contains catalog resources sorted by latest_released_at ascending with nulls last' do - is_expected.to eq([resource_1, resource_2, resource_3]) - end - end + context 'when the resource is not published' do + let(:id) { draft_resource.id } - context 'when the sort is latest_released_at descending' do - let_it_be(:sort) { :latest_released_at_desc } + it 'returns nil' do + is_expected.to be_nil + end + end - it 'contains catalog resources sorted by latest_released_at descending with nulls last' do - is_expected.to eq([resource_2, resource_1, resource_3]) - end - end - end + context "when the current user cannot read code on the resource's project" do + let(:id) { inaccessible_resource.id } + + it 'returns nil' do + is_expected.to be_nil end end + end - context 'when the user only has access to some projects in the namespace' do - let!(:accessible_resource) { create(:ci_catalog_resource, project: project_x) } - let!(:inaccessible_resource) { create(:ci_catalog_resource, project: project_noaccess) } + context 'when using the full_path argument' do + subject { list.find_resource(full_path: full_path) } - it 'only returns catalog resources for projects the user has access to' do - is_expected.to contain_exactly(accessible_resource) + context 'when the resource is published and visible to the user' do + let(:full_path) { accessible_resource.project.full_path } + + it 'fetches the resource' do + is_expected.to eq(accessible_resource) end end - context 'when the user does not have access to the namespace' do - let!(:project) { create(:project) } - let!(:resource) { create(:ci_catalog_resource, project: project) } + context 'when the resource is not found' do + let(:full_path) { 'not-a-path' } - let(:namespace) { project.namespace } + it 'returns nil' do + is_expected.to be_nil + end + end - it { is_expected.to be_empty } + context 'when the resource is not published' do + let(:full_path) { draft_resource.project.full_path } + + it 'returns nil' do + is_expected.to be_nil + end + end + + context "when the current user cannot read code on the resource's project" do + let(:full_path) { inaccessible_resource.project.full_path } + + it 'returns nil' do + is_expected.to be_nil + end end end end |