diff options
Diffstat (limited to 'spec')
28 files changed, 519 insertions, 94 deletions
diff --git a/spec/controllers/concerns/redis_tracking_spec.rb b/spec/controllers/concerns/redis_tracking_spec.rb index 09ea9bd726f..3795fca5576 100644 --- a/spec/controllers/concerns/redis_tracking_spec.rb +++ b/spec/controllers/concerns/redis_tracking_spec.rb @@ -11,7 +11,7 @@ RSpec.describe RedisTracking do include RedisTracking skip_before_action :authenticate_user!, only: :show - track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :g_compliance_dashboard_feature + track_redis_hll_event :index, :show, name: 'i_analytics_dev_ops_score', feature: :g_compliance_dashboard_feature, feature_default_enabled: true def index render html: 'index' @@ -61,6 +61,14 @@ RSpec.describe RedisTracking do get :index end + + it 'passes default_enabled flag' do + sign_in(user) + + expect(controller).to receive(:metric_feature_enabled?).with(feature.to_sym, true) + + get :index + end end context 'when user is not logged in and there is a visitor_id' do diff --git a/spec/factories/audit_events.rb b/spec/factories/audit_events.rb index 9a450797df7..5497648273c 100644 --- a/spec/factories/audit_events.rb +++ b/spec/factories/audit_events.rb @@ -36,7 +36,7 @@ FactoryBot.define do ip_address { IPAddr.new '127.0.0.1' } details do { - change: 'packges_enabled', + change: 'packages_enabled', from: true, to: false, author_name: user.name, diff --git a/spec/factories/packages.rb b/spec/factories/packages.rb index ee9079579e0..52b2a32cd3b 100644 --- a/spec/factories/packages.rb +++ b/spec/factories/packages.rb @@ -2,6 +2,7 @@ FactoryBot.define do factory :package, class: 'Packages::Package' do project + creator { project&.creator } name { 'my/company/app/my-app' } sequence(:version) { |n| "1.#{n}-SNAPSHOT" } package_type { :maven } diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb index 9879703c8bf..1c8da227412 100644 --- a/spec/features/issues/issue_detail_spec.rb +++ b/spec/features/issues/issue_detail_spec.rb @@ -20,6 +20,19 @@ RSpec.describe 'Issue Detail', :js do end end + context 'when user displays the issue as an incident' do + let(:issue) { create(:incident, project: project, author: user) } + + before do + visit project_issue_path(project, issue) + wait_for_requests + end + + it 'does not show design management' do + expect(page).not_to have_selector('.js-design-management') + end + end + context 'when issue description has xss snippet' do before do issue.update!(description: '![xss" onload=alert(1);//](a)') diff --git a/spec/frontend/boards/stores/mutations_spec.js b/spec/frontend/boards/stores/mutations_spec.js index 5a4f703f72e..f80236afacd 100644 --- a/spec/frontend/boards/stores/mutations_spec.js +++ b/spec/frontend/boards/stores/mutations_spec.js @@ -190,6 +190,48 @@ describe('Board Store Mutations', () => { }); }); + describe('UPDATE_ISSUE_BY_ID', () => { + const issueId = '1'; + const prop = 'id'; + const value = '2'; + const issue = { [issueId]: { id: 1, title: 'Issue' } }; + + beforeEach(() => { + state = { + ...state, + isLoadingIssues: true, + error: undefined, + issues: { + ...issue, + }, + }; + }); + + describe('when the issue is in state', () => { + it('updates the property of the correct issue', () => { + mutations.UPDATE_ISSUE_BY_ID(state, { + issueId, + prop, + value, + }); + + expect(state.issues[issueId]).toEqual({ ...issue[issueId], id: '2' }); + }); + }); + + describe('when the issue is not in state', () => { + it('throws an error', () => { + expect(() => { + mutations.UPDATE_ISSUE_BY_ID(state, { + issueId: '3', + prop, + value, + }); + }).toThrow(new Error('No issue found.')); + }); + }); + }); + describe('RECEIVE_ADD_ISSUE_SUCCESS', () => { expectNotImplemented(mutations.RECEIVE_ADD_ISSUE_SUCCESS); }); diff --git a/spec/frontend/environments/environment_rollback_spec.js b/spec/frontend/environments/environment_rollback_spec.js index f25e05f9cd8..fb62a096c3d 100644 --- a/spec/frontend/environments/environment_rollback_spec.js +++ b/spec/frontend/environments/environment_rollback_spec.js @@ -1,5 +1,5 @@ import { shallowMount, mount } from '@vue/test-utils'; -import { GlDeprecatedButton } from '@gitlab/ui'; +import { GlButton } from '@gitlab/ui'; import eventHub from '~/environments/event_hub'; import RollbackComponent from '~/environments/components/environment_rollback.vue'; @@ -40,7 +40,7 @@ describe('Rollback Component', () => { }, }, }); - const button = wrapper.find(GlDeprecatedButton); + const button = wrapper.find(GlButton); button.vm.$emit('click'); diff --git a/spec/frontend/packages/mock_data.js b/spec/frontend/packages/mock_data.js index 86205b0744c..b95d06428ff 100644 --- a/spec/frontend/packages/mock_data.js +++ b/spec/frontend/packages/mock_data.js @@ -30,6 +30,7 @@ export const mavenPackage = { name: 'Test package', package_type: 'maven', project_path: 'foo/bar/baz', + projectPathName: 'foo/bar/baz', project_id: 1, updated_at: '2015-12-10', version: '1.0.0', @@ -59,6 +60,7 @@ export const npmPackage = { name: '@Test/package', package_type: 'npm', project_path: 'foo/bar/baz', + projectPathName: 'foo/bar/baz', project_id: 1, updated_at: '2015-12-10', version: '', @@ -86,6 +88,7 @@ export const conanPackage = { id: 3, name: 'conan-package', project_path: 'foo/bar/baz', + projectPathName: 'foo/bar/baz', package_files: [], package_type: 'conan', project_id: 1, diff --git a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap index eb9d4faa964..4b1346925cc 100644 --- a/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap +++ b/spec/frontend/packages/shared/components/__snapshots__/package_list_row_spec.js.snap @@ -14,22 +14,23 @@ exports[`packages_list_row renders 1`] = ` class="gl-display-flex gl-xs-flex-direction-column gl-justify-content-space-between gl-align-items-stretch gl-flex-fill-1" > <div - class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3" + class="gl-display-flex gl-flex-direction-column gl-justify-content-space-between gl-xs-mb-3 gl-min-w-0 gl-flex-grow-1" > <div - class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6" + class="gl-display-flex gl-align-items-center gl-text-body gl-font-weight-bold gl-min-h-6 gl-min-w-0" > <div - class="gl-display-flex gl-align-items-center gl-mr-3" + class="gl-display-flex gl-align-items-center gl-mr-3 gl-min-w-0" > <gl-link-stub - class="gl-text-body" + class="gl-text-body gl-min-w-0" data-qa-selector="package_link" href="foo" > - - Test package - + <gl-truncate-stub + position="end" + text="Test package" + /> </gl-link-stub> <!----> @@ -39,7 +40,7 @@ exports[`packages_list_row renders 1`] = ` </div> <div - class="gl-text-gray-500 gl-mt-1 gl-min-h-6" + class="gl-text-gray-500 gl-mt-1 gl-min-h-6 gl-min-w-0 gl-flex-fill-1" > <div class="gl-display-flex" @@ -54,19 +55,20 @@ exports[`packages_list_row renders 1`] = ` class="gl-display-flex gl-align-items-center" > <gl-icon-stub - class="gl-ml-3 gl-mr-2" + class="gl-ml-3 gl-mr-2 gl-min-w-0" name="review-list" size="16" /> <gl-link-stub - class="gl-text-body" + class="gl-text-body gl-min-w-0" data-testid="packages-row-project" href="/foo/bar/baz" > - - - + <gl-truncate-stub + position="end" + text="foo/bar/baz" + /> </gl-link-stub> </div> @@ -89,7 +91,7 @@ exports[`packages_list_row renders 1`] = ` </div> <div - class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500" + class="gl-display-flex gl-flex-direction-column gl-sm-align-items-flex-end gl-justify-content-space-between gl-text-gray-500 gl-flex-shrink-0" > <div class="gl-sm-text-body gl-sm-font-weight-bold gl-min-h-6" diff --git a/spec/frontend/packages/shared/components/packages_list_loader_spec.js b/spec/frontend/packages/shared/components/packages_list_loader_spec.js index c8c2e2a4ba4..115a3a7095d 100644 --- a/spec/frontend/packages/shared/components/packages_list_loader_spec.js +++ b/spec/frontend/packages/shared/components/packages_list_loader_spec.js @@ -12,8 +12,8 @@ describe('PackagesListLoader', () => { }); }; - const getShapes = () => wrapper.vm.desktopShapes; - const findSquareButton = () => wrapper.find({ ref: 'button-loader' }); + const findDesktopShapes = () => wrapper.find('[data-testid="desktop-loader"]'); + const findMobileShapes = () => wrapper.find('[data-testid="mobile-loader"]'); beforeEach(createComponent); @@ -22,21 +22,30 @@ describe('PackagesListLoader', () => { wrapper = null; }); - describe('when used for projects', () => { - it('should return 5 rects with last one being a square', () => { - expect(getShapes()).toHaveLength(5); - expect(findSquareButton().exists()).toBe(true); + describe('desktop loader', () => { + it('produces the right loader', () => { + expect(findDesktopShapes().findAll('rect[width="1000"]')).toHaveLength(20); + }); + + it('has the correct classes', () => { + expect(findDesktopShapes().classes()).toEqual([ + 'gl-display-none', + 'gl-display-sm-flex', + 'gl-flex-direction-column', + ]); }); }); - describe('when used for groups', () => { - beforeEach(() => { - createComponent({ isGroup: true }); + describe('mobile loader', () => { + it('produces the right loader', () => { + expect(findMobileShapes().findAll('rect[height="170"]')).toHaveLength(5); }); - it('should return 5 rects with no square', () => { - expect(getShapes()).toHaveLength(5); - expect(findSquareButton().exists()).toBe(false); + it('has the correct classes', () => { + expect(findMobileShapes().classes()).toEqual([ + 'gl-flex-direction-column', + 'gl-display-sm-none', + ]); }); }); }); diff --git a/spec/frontend/repository/log_tree_spec.js b/spec/frontend/repository/log_tree_spec.js index 5637d0be957..47f02db5f91 100644 --- a/spec/frontend/repository/log_tree_spec.js +++ b/spec/frontend/repository/log_tree_spec.js @@ -100,24 +100,28 @@ describe('fetchLogsTree', () => { ); })); - it('writes query to client', () => - fetchLogsTree(client, '', '0', resolver).then(() => { - expect(client.writeQuery).toHaveBeenCalledWith({ - query: expect.anything(), - data: { - commits: [ - expect.objectContaining({ - __typename: 'LogTreeCommit', - commitPath: 'https://test.com', - committedDate: '2019-01-01', - fileName: 'index.js', - filePath: '/index.js', - message: 'testing message', - sha: '123', - type: 'blob', - }), - ], - }, - }); - })); + it('writes query to client', async () => { + await fetchLogsTree(client, '', '0', resolver); + expect(client.writeQuery).toHaveBeenCalledWith({ + query: expect.anything(), + data: { + projectPath: 'gitlab-org/gitlab-foss', + escapedRef: 'master', + commits: [ + expect.objectContaining({ + __typename: 'LogTreeCommit', + commitPath: 'https://test.com', + committedDate: '2019-01-01', + fileName: 'index.js', + filePath: '/index.js', + lockLabel: false, + message: 'testing message', + sha: '123', + titleHtml: undefined, + type: 'blob', + }), + ], + }, + }); + }); }); diff --git a/spec/graphql/types/user_type_spec.rb b/spec/graphql/types/user_type_spec.rb index 7710b8efefe..1d5af24b3d9 100644 --- a/spec/graphql/types/user_type_spec.rb +++ b/spec/graphql/types/user_type_spec.rb @@ -25,6 +25,7 @@ RSpec.describe GitlabSchema.types['User'] do assignedMergeRequests groupMemberships projectMemberships + starredProjects ] expect(described_class).to have_graphql_fields(*expected_fields) diff --git a/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb b/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb new file mode 100644 index 00000000000..31c373d14d3 --- /dev/null +++ b/spec/lib/gitlab/ci/pipeline_object_hierarchy_spec.rb @@ -0,0 +1,111 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Ci::PipelineObjectHierarchy do + let_it_be(:project) { create_default(:project, :repository) } + let_it_be(:pipeline) { create(:ci_empty_pipeline, status: :created, project: project) } + let_it_be(:ancestor) { create(:ci_pipeline, project: pipeline.project) } + let_it_be(:parent) { create(:ci_pipeline, project: pipeline.project) } + let_it_be(:child) { create(:ci_pipeline, project: pipeline.project) } + let_it_be(:cousin_parent) { create(:ci_pipeline, project: pipeline.project) } + let_it_be(:cousin) { create(:ci_pipeline, project: pipeline.project) } + + before_all do + create_source_relation(ancestor, parent) + create_source_relation(ancestor, cousin_parent) + create_source_relation(parent, child) + create_source_relation(cousin_parent, cousin) + end + + describe '#base_and_ancestors' do + it 'includes the base and its ancestors' do + relation = described_class.new(::Ci::Pipeline.where(id: parent.id)).base_and_ancestors + + expect(relation).to contain_exactly(ancestor, parent) + end + + it 'can find ancestors upto a certain level' do + relation = described_class.new(::Ci::Pipeline.where(id: child.id)).base_and_ancestors(upto: ancestor.id) + + expect(relation).to contain_exactly(parent, child) + end + + describe 'hierarchy_order option' do + let(:relation) do + described_class.new(::Ci::Pipeline.where(id: child.id)).base_and_ancestors(hierarchy_order: hierarchy_order) + end + + context ':asc' do + let(:hierarchy_order) { :asc } + + it 'orders by child to ancestor' do + expect(relation).to eq([child, parent, ancestor]) + end + end + + context ':desc' do + let(:hierarchy_order) { :desc } + + it 'orders by ancestor to child' do + expect(relation).to eq([ancestor, parent, child]) + end + end + end + end + + describe '#base_and_descendants' do + it 'includes the base and its descendants' do + relation = described_class.new(::Ci::Pipeline.where(id: parent.id)).base_and_descendants + + expect(relation).to contain_exactly(parent, child) + end + + context 'when with_depth is true' do + let(:relation) do + described_class.new(::Ci::Pipeline.where(id: ancestor.id)).base_and_descendants(with_depth: true) + end + + it 'includes depth in the results' do + object_depths = { + ancestor.id => 1, + parent.id => 2, + cousin_parent.id => 2, + child.id => 3, + cousin.id => 3 + } + + relation.each do |object| + expect(object.depth).to eq(object_depths[object.id]) + end + end + end + end + + describe '#all_objects' do + it 'includes its ancestors and descendants' do + relation = described_class.new(::Ci::Pipeline.where(id: parent.id)).all_objects + + expect(relation).to contain_exactly(ancestor, parent, child) + end + + it 'returns all family tree' do + relation = described_class.new( + ::Ci::Pipeline.where(id: child.id), + described_class.new(::Ci::Pipeline.where(id: child.id)).base_and_ancestors + ).all_objects + + expect(relation).to contain_exactly(ancestor, parent, cousin_parent, child, cousin) + end + end + + private + + def create_source_relation(parent, child) + create(:ci_sources_pipeline, + source_job: create(:ci_build, pipeline: parent), + source_project: parent.project, + pipeline: child, + project: child.project) + end +end diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index d0ffda61cc1..de538c6c263 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -539,6 +539,7 @@ timelogs: - issue - merge_request - user +- note push_event_payload: - event issue_assignees: diff --git a/spec/models/ci/pipeline_spec.rb b/spec/models/ci/pipeline_spec.rb index 58ceaad1063..955f146270e 100644 --- a/spec/models/ci/pipeline_spec.rb +++ b/spec/models/ci/pipeline_spec.rb @@ -2616,11 +2616,11 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end describe '#same_family_pipeline_ids' do - subject(:same_family_pipeline_ids) { pipeline.same_family_pipeline_ids } + subject { pipeline.same_family_pipeline_ids.map(&:id) } context 'when pipeline is not child nor parent' do it 'returns just the pipeline id' do - expect(same_family_pipeline_ids).to contain_exactly(pipeline.id) + expect(subject).to contain_exactly(pipeline.id) end end @@ -2643,7 +2643,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it 'returns parent sibling and self ids' do - expect(same_family_pipeline_ids).to contain_exactly(parent.id, pipeline.id, sibling.id) + expect(subject).to contain_exactly(parent.id, pipeline.id, sibling.id) end end @@ -2659,7 +2659,46 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do end it 'returns self and child ids' do - expect(same_family_pipeline_ids).to contain_exactly(pipeline.id, child.id) + expect(subject).to contain_exactly(pipeline.id, child.id) + end + end + + context 'when pipeline is a child of a child pipeline' do + let(:ancestor) { create(:ci_pipeline, project: pipeline.project) } + let(:parent) { create(:ci_pipeline, project: pipeline.project) } + let(:cousin_parent) { create(:ci_pipeline, project: pipeline.project) } + let(:cousin) { create(:ci_pipeline, project: pipeline.project) } + + before do + create(:ci_sources_pipeline, + source_job: create(:ci_build, pipeline: ancestor), + source_project: ancestor.project, + pipeline: parent, + project: parent.project) + + create(:ci_sources_pipeline, + source_job: create(:ci_build, pipeline: ancestor), + source_project: ancestor.project, + pipeline: cousin_parent, + project: cousin_parent.project) + + create(:ci_sources_pipeline, + source_job: create(:ci_build, pipeline: parent), + source_project: parent.project, + pipeline: pipeline, + project: pipeline.project) + + create(:ci_sources_pipeline, + source_job: create(:ci_build, pipeline: cousin_parent), + source_project: cousin_parent.project, + pipeline: cousin, + project: cousin.project) + end + + it 'returns all family ids' do + expect(subject).to contain_exactly( + ancestor.id, parent.id, cousin_parent.id, cousin.id, pipeline.id + ) end end end diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb index 7fb6e6d63c6..ea1f75d04e7 100644 --- a/spec/models/packages/package_spec.rb +++ b/spec/models/packages/package_spec.rb @@ -6,6 +6,7 @@ RSpec.describe Packages::Package, type: :model do describe 'relationships' do it { is_expected.to belong_to(:project) } + it { is_expected.to belong_to(:creator) } it { is_expected.to have_many(:package_files).dependent(:destroy) } it { is_expected.to have_many(:dependency_links).inverse_of(:package) } it { is_expected.to have_many(:tags).inverse_of(:package) } diff --git a/spec/requests/api/graphql/user/starred_projects_query_spec.rb b/spec/requests/api/graphql/user/starred_projects_query_spec.rb new file mode 100644 index 00000000000..8a1bd3d172f --- /dev/null +++ b/spec/requests/api/graphql/user/starred_projects_query_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Getting starredProjects of the user' do + include GraphqlHelpers + + let(:query) do + graphql_query_for(:user, user_params, user_fields) + end + + let(:user_params) { { username: user.username } } + + let_it_be(:project_a) { create(:project, :public) } + let_it_be(:project_b) { create(:project, :private) } + let_it_be(:project_c) { create(:project, :private) } + let_it_be(:user, reload: true) { create(:user) } + + let(:user_fields) { 'starredProjects { nodes { id } }' } + let(:starred_projects) { graphql_data_at(:user, :starred_projects, :nodes) } + + before do + project_b.add_reporter(user) + project_c.add_reporter(user) + + user.toggle_star(project_a) + user.toggle_star(project_b) + user.toggle_star(project_c) + + post_graphql(query) + end + + it_behaves_like 'a working graphql query' + + it 'found only public project' do + expect(starred_projects).to contain_exactly( + a_hash_including('id' => global_id_of(project_a)) + ) + end + + context 'the current user is the user' do + let(:current_user) { user } + + before do + post_graphql(query, current_user: current_user) + end + + it 'found all projects' do + expect(starred_projects).to contain_exactly( + a_hash_including('id' => global_id_of(project_a)), + a_hash_including('id' => global_id_of(project_b)), + a_hash_including('id' => global_id_of(project_c)) + ) + end + end + + context 'the current user is a member of a private project the user starred' do + let_it_be(:other_user) { create(:user) } + + before do + project_b.add_reporter(other_user) + + post_graphql(query, current_user: other_user) + end + + it 'finds public and member projects' do + expect(starred_projects).to contain_exactly( + a_hash_including('id' => global_id_of(project_a)), + a_hash_including('id' => global_id_of(project_b)) + ) + end + end +end diff --git a/spec/services/projects/propagate_service_template_spec.rb b/spec/services/admin/propagate_service_template_spec.rb index 8f206046b0a..15654653095 100644 --- a/spec/services/projects/propagate_service_template_spec.rb +++ b/spec/services/admin/propagate_service_template_spec.rb @@ -2,10 +2,10 @@ require 'spec_helper' -RSpec.describe Projects::PropagateServiceTemplate do +RSpec.describe Admin::PropagateServiceTemplate do describe '.propagate' do let!(:service_template) do - PushoverService.create( + PushoverService.create!( template: true, active: true, push_events: false, @@ -31,8 +31,7 @@ RSpec.describe Projects::PropagateServiceTemplate do end it 'creates services for a project that has another service' do - BambooService.create( - template: true, + BambooService.create!( active: true, project: project, properties: { @@ -51,7 +50,7 @@ RSpec.describe Projects::PropagateServiceTemplate do end it 'does not create the service if it exists already' do - other_service = BambooService.create( + other_service = BambooService.create!( template: true, active: true, properties: { @@ -110,7 +109,7 @@ RSpec.describe Projects::PropagateServiceTemplate do let(:project_total) { 5 } before do - stub_const 'Projects::PropagateServiceTemplate::BATCH_SIZE', 3 + stub_const('Admin::PropagateServiceTemplate::BATCH_SIZE', 3) project_total.times { create(:project) } diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb index f26f9eeb6f0..69f44724ce0 100644 --- a/spec/services/ci/create_downstream_pipeline_service_spec.rb +++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb @@ -311,7 +311,7 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do end end - context 'when upstream pipeline is a child pipeline' do + context 'when upstream pipeline is a first descendant pipeline' do let!(:pipeline_source) do create(:ci_sources_pipeline, source_pipeline: create(:ci_pipeline, project: upstream_pipeline.project), @@ -323,12 +323,53 @@ RSpec.describe Ci::CreateDownstreamPipelineService, '#execute' do upstream_pipeline.update!(source: :parent_pipeline) end - it 'does not create a further child pipeline' do + it 'creates the pipeline' do + expect { service.execute(bridge) } + .to change { Ci::Pipeline.count }.by(1) + + expect(bridge.reload).to be_success + end + + context 'when FF ci_child_of_child_pipeline is disabled' do + before do + stub_feature_flags(ci_child_of_child_pipeline: false) + end + + it 'does not create a further child pipeline' do + expect { service.execute(bridge) } + .not_to change { Ci::Pipeline.count } + + expect(bridge.reload).to be_failed + expect(bridge.failure_reason).to eq 'bridge_pipeline_is_child_pipeline' + end + end + end + + context 'when upstream pipeline is a second descendant pipeline' do + let!(:pipeline_source) do + parent_of_upstream_pipeline = create(:ci_pipeline, project: upstream_pipeline.project) + + create(:ci_sources_pipeline, + source_pipeline: create(:ci_pipeline, project: upstream_pipeline.project), + pipeline: parent_of_upstream_pipeline + ) + + create(:ci_sources_pipeline, + source_pipeline: parent_of_upstream_pipeline, + pipeline: upstream_pipeline + ) + end + + before do + upstream_pipeline.update!(source: :parent_pipeline) + end + + it 'does not create a second descendant pipeline' do expect { service.execute(bridge) } .not_to change { Ci::Pipeline.count } expect(bridge.reload).to be_failed - expect(bridge.failure_reason).to eq 'bridge_pipeline_is_child_pipeline' + expect(bridge.failure_reason).to eq 'reached_max_descendant_pipelines_depth' end end end diff --git a/spec/services/packages/composer/create_package_service_spec.rb b/spec/services/packages/composer/create_package_service_spec.rb index 3f9da31cf6e..a1fe9a1b918 100644 --- a/spec/services/packages/composer/create_package_service_spec.rb +++ b/spec/services/packages/composer/create_package_service_spec.rb @@ -37,12 +37,16 @@ RSpec.describe Packages::Composer::CreatePackageService do expect(created_package.composer_metadatum.target_sha).to eq branch.target expect(created_package.composer_metadatum.composer_json.to_json).to eq json end + + it_behaves_like 'assigns the package creator' do + let(:package) { created_package } + end end context 'with a tag' do let(:tag) { project.repository.find_tag('v1.2.3') } - before do + before(:all) do project.repository.add_tag(user, 'v1.2.3', 'master') end @@ -54,6 +58,10 @@ RSpec.describe Packages::Composer::CreatePackageService do expect(created_package.name).to eq package_name expect(created_package.version).to eq '1.2.3' end + + it_behaves_like 'assigns the package creator' do + let(:package) { created_package } + end end end diff --git a/spec/services/packages/conan/create_package_service_spec.rb b/spec/services/packages/conan/create_package_service_spec.rb index f8068f6e57b..b217e570aba 100644 --- a/spec/services/packages/conan/create_package_service_spec.rb +++ b/spec/services/packages/conan/create_package_service_spec.rb @@ -5,9 +5,11 @@ RSpec.describe Packages::Conan::CreatePackageService do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } - subject { described_class.new(project, user, params) } + subject(:service) { described_class.new(project, user, params) } describe '#execute' do + subject(:package) { service.execute } + context 'valid params' do let(:params) do { @@ -19,8 +21,6 @@ RSpec.describe Packages::Conan::CreatePackageService do end it 'creates a new package' do - package = subject.execute - expect(package).to be_valid expect(package.name).to eq(params[:package_name]) expect(package.version).to eq(params[:package_version]) @@ -28,6 +28,8 @@ RSpec.describe Packages::Conan::CreatePackageService do expect(package.conan_metadatum.package_username).to eq(params[:package_username]) expect(package.conan_metadatum.package_channel).to eq(params[:package_channel]) end + + it_behaves_like 'assigns the package creator' end context 'invalid params' do @@ -41,7 +43,7 @@ RSpec.describe Packages::Conan::CreatePackageService do end it 'fails' do - expect { subject.execute }.to raise_exception(ActiveRecord::RecordInvalid) + expect { package }.to raise_exception(ActiveRecord::RecordInvalid) end end end diff --git a/spec/services/packages/maven/create_package_service_spec.rb b/spec/services/packages/maven/create_package_service_spec.rb index bfdf62008ba..7ec368aa00f 100644 --- a/spec/services/packages/maven/create_package_service_spec.rb +++ b/spec/services/packages/maven/create_package_service_spec.rb @@ -34,6 +34,8 @@ RSpec.describe Packages::Maven::CreatePackageService do end it_behaves_like 'assigns build to package' + + it_behaves_like 'assigns the package creator' end context 'without version' do @@ -57,6 +59,8 @@ RSpec.describe Packages::Maven::CreatePackageService do expect(package.maven_metadatum.app_name).to eq(app_name) expect(package.maven_metadatum.app_version).to be nil end + + it_behaves_like 'assigns the package creator' end context 'path is missing' do diff --git a/spec/services/packages/npm/create_package_service_spec.rb b/spec/services/packages/npm/create_package_service_spec.rb index 895c46735ed..c8431c640da 100644 --- a/spec/services/packages/npm/create_package_service_spec.rb +++ b/spec/services/packages/npm/create_package_service_spec.rb @@ -27,6 +27,10 @@ RSpec.describe Packages::Npm::CreatePackageService do .and change { Packages::Tag.count }.by(1) end + it_behaves_like 'assigns the package creator' do + let(:package) { subject } + end + it { is_expected.to be_valid } it 'creates a package with name and version' do diff --git a/spec/services/packages/nuget/create_package_service_spec.rb b/spec/services/packages/nuget/create_package_service_spec.rb index 1579b42d9ad..e51bc03f311 100644 --- a/spec/services/packages/nuget/create_package_service_spec.rb +++ b/spec/services/packages/nuget/create_package_service_spec.rb @@ -9,9 +9,10 @@ RSpec.describe Packages::Nuget::CreatePackageService do describe '#execute' do subject { described_class.new(project, user, params).execute } + let(:package) { Packages::Package.last } + it 'creates the package' do expect { subject }.to change { Packages::Package.count }.by(1) - package = Packages::Package.last expect(package).to be_valid expect(package.name).to eq(Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) @@ -23,12 +24,12 @@ RSpec.describe Packages::Nuget::CreatePackageService do expect { subject }.to change { Packages::Package.count }.by(1) expect { described_class.new(project, user, params).execute }.to change { Packages::Package.count }.by(1) - package = Packages::Package.last - expect(package).to be_valid expect(package.name).to eq(Packages::Nuget::CreatePackageService::TEMPORARY_PACKAGE_NAME) expect(package.version).to start_with(Packages::Nuget::CreatePackageService::PACKAGE_VERSION) expect(package.package_type).to eq('nuget') end + + it_behaves_like 'assigns the package creator' end end diff --git a/spec/services/packages/pypi/create_package_service_spec.rb b/spec/services/packages/pypi/create_package_service_spec.rb index 69905478879..fa1af1e3f3d 100644 --- a/spec/services/packages/pypi/create_package_service_spec.rb +++ b/spec/services/packages/pypi/create_package_service_spec.rb @@ -47,6 +47,10 @@ RSpec.describe Packages::Pypi::CreatePackageService do end end + it_behaves_like 'assigns the package creator' do + let(:package) { created_package } + end + context 'with an existing package' do before do described_class.new(project, user, params).execute diff --git a/spec/support/shared_examples/services/packages_shared_examples.rb b/spec/support/shared_examples/services/packages_shared_examples.rb index 836997e78f5..7fd59c3d963 100644 --- a/spec/support/shared_examples/services/packages_shared_examples.rb +++ b/spec/support/shared_examples/services/packages_shared_examples.rb @@ -14,6 +14,14 @@ RSpec.shared_examples 'assigns build to package' do end end +RSpec.shared_examples 'assigns the package creator' do + it 'assigns the package creator' do + subject + + expect(package.creator).to eq user + end +end + RSpec.shared_examples 'returns packages' do |container_type, user_type| context "for #{user_type}" do before do diff --git a/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb b/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb new file mode 100644 index 00000000000..3508ba8cca9 --- /dev/null +++ b/spec/views/shared/deploy_tokens/_form.html.haml_spec.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'shared/deploy_tokens/_form.html.haml' do + using RSpec::Parameterized::TableSyntax + + let_it_be(:user) { create(:user) } + let_it_be(:token) { build(:deploy_token) } + + RSpec.shared_examples "display deploy token settings" do |role, shows_package_registry_permissions| + before do + subject.add_user(user, role) + allow(view).to receive(:current_user).and_return(user) + stub_config(packages: { enabled: packages_enabled }) + end + + it "correctly renders the form" do + render 'shared/deploy_tokens/form', token: token, group_or_project: subject + + if shows_package_registry_permissions + expect(rendered).to have_content('Allows read access to the package registry') + else + expect(rendered).not_to have_content('Allows read access to the package registry') + end + end + end + + context "when the subject is a project" do + let_it_be(:subject, refind: true) { create(:project, :private) } + + where(:packages_enabled, :feature_enabled, :role, :shows_package_registry_permissions) do + true | true | :maintainer | true + false | true | :maintainer | false + true | false | :maintainer | false + false | false | :maintainer | false + end + + with_them do + before do + subject.update!(packages_enabled: feature_enabled) + end + + it_behaves_like 'display deploy token settings', params[:role], params[:shows_package_registry_permissions] + end + end + + context "when the subject is a group" do + let_it_be(:subject, refind: true) { create(:group, :private) } + + where(:packages_enabled, :role, :shows_package_registry_permissions) do + true | :owner | true + false | :owner | false + true | :maintainer | true + false | :maintainer | false + end + + with_them do + it_behaves_like 'display deploy token settings', params[:role], params[:shows_package_registry_permissions] + end + end +end diff --git a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb index 676a419553f..3ff67f47523 100644 --- a/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb +++ b/spec/workers/personal_access_tokens/expired_notification_worker_spec.rb @@ -9,32 +9,16 @@ RSpec.describe PersonalAccessTokens::ExpiredNotificationWorker, type: :worker do context 'when a token has expired' do let(:expired_today) { create(:personal_access_token, expires_at: Date.current) } - context 'when feature is enabled' do - it 'uses notification service to send email to the user' do - expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).to receive(:access_token_expired).with(expired_today.user) - end - - worker.perform + it 'uses notification service to send email to the user' do + expect_next_instance_of(NotificationService) do |notification_service| + expect(notification_service).to receive(:access_token_expired).with(expired_today.user) end - it 'updates notified column' do - expect { worker.perform }.to change { expired_today.reload.after_expiry_notification_delivered }.from(false).to(true) - end + worker.perform end - context 'when feature is disabled' do - before do - stub_feature_flags(expired_pat_email_notification: false) - end - - it 'does not update notified column' do - expect { worker.perform }.not_to change { expired_today.reload.after_expiry_notification_delivered } - end - - it 'does not trigger email' do - expect { worker.perform }.not_to change { ActionMailer::Base.deliveries.count } - end + it 'updates notified column' do + expect { worker.perform }.to change { expired_today.reload.after_expiry_notification_delivered }.from(false).to(true) end end diff --git a/spec/workers/propagate_service_template_worker_spec.rb b/spec/workers/propagate_service_template_worker_spec.rb index 48151b25d4b..793f0b9b08c 100644 --- a/spec/workers/propagate_service_template_worker_spec.rb +++ b/spec/workers/propagate_service_template_worker_spec.rb @@ -21,7 +21,7 @@ RSpec.describe PropagateServiceTemplateWorker do stub_exclusive_lease("propagate_service_template_worker:#{template.id}", timeout: PropagateServiceTemplateWorker::LEASE_TIMEOUT) - expect(Projects::PropagateServiceTemplate) + expect(Admin::PropagateServiceTemplate) .to receive(:propagate) .with(template) |