diff options
Diffstat (limited to 'spec')
34 files changed, 384 insertions, 88 deletions
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 24ec5467c86..74267874eeb 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -50,6 +50,7 @@ RSpec.describe 'Database schema', feature_category: :database do ci_namespace_monthly_usages: %w[namespace_id], ci_pipeline_artifacts: %w[partition_id], ci_pipeline_chat_data: %w[partition_id], + ci_pipelines_config: %w[partition_id], ci_pipeline_metadata: %w[partition_id], ci_pipeline_variables: %w[partition_id], ci_pipelines: %w[partition_id], diff --git a/spec/factories/ci/pipeline_config.rb b/spec/factories/ci/pipeline_config.rb new file mode 100644 index 00000000000..a415efaf185 --- /dev/null +++ b/spec/factories/ci/pipeline_config.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :ci_pipeline_config, class: 'Ci::PipelineConfig' do + pipeline factory: :ci_empty_pipeline + content { "content" } + end +end diff --git a/spec/frontend/custom_emoji/components/__snapshots__/list_spec.js.snap b/spec/frontend/custom_emoji/components/__snapshots__/list_spec.js.snap index c69547deb1c..a43b4aae586 100644 --- a/spec/frontend/custom_emoji/components/__snapshots__/list_spec.js.snap +++ b/spec/frontend/custom_emoji/components/__snapshots__/list_spec.js.snap @@ -141,7 +141,7 @@ exports[`Custom emoji settings list component renders table of custom emoji 1`] class="gl-vertical-align-middle!" role="cell" > - <gl-emoji + <div data-fallback-src="https://gitlab.com/custom_emoji/custom_emoji/-/raw/main/img/confused_husky.gif" data-name="confused_husky" data-unicode-version="custom" diff --git a/spec/frontend/custom_emoji/components/list_spec.js b/spec/frontend/custom_emoji/components/list_spec.js index b5729d59464..4177aea2d33 100644 --- a/spec/frontend/custom_emoji/components/list_spec.js +++ b/spec/frontend/custom_emoji/components/list_spec.js @@ -21,6 +21,9 @@ function createComponent(propsData = {}) { userPermissions: { createCustomEmoji: true }, ...propsData, }, + stubs: { + GlEmoji: { template: '<div/>' }, + }, }); } diff --git a/spec/frontend/emoji/components/emoji_group_spec.js b/spec/frontend/emoji/components/emoji_group_spec.js index a2a46bedd7b..a2e3643356f 100644 --- a/spec/frontend/emoji/components/emoji_group_spec.js +++ b/spec/frontend/emoji/components/emoji_group_spec.js @@ -13,6 +13,7 @@ function factory(propsData = {}) { propsData, stubs: { GlButton, + GlEmoji: { template: '<div/>' }, }, }), ); diff --git a/spec/frontend/kubernetes_dashboard/components/workload_table_spec.js b/spec/frontend/kubernetes_dashboard/components/workload_table_spec.js index 369b8f32c2d..e873da07a2a 100644 --- a/spec/frontend/kubernetes_dashboard/components/workload_table_spec.js +++ b/spec/frontend/kubernetes_dashboard/components/workload_table_spec.js @@ -1,7 +1,7 @@ import { mount } from '@vue/test-utils'; import { GlTable, GlBadge, GlPagination } from '@gitlab/ui'; import WorkloadTable from '~/kubernetes_dashboard/components/workload_table.vue'; -import { TABLE_HEADING_CLASSES, PAGE_SIZE } from '~/kubernetes_dashboard/constants'; +import { PAGE_SIZE } from '~/kubernetes_dashboard/constants'; import { mockPodsTableItems } from '../graphql/mock_data'; let wrapper; @@ -26,25 +26,24 @@ describe('Workload table component', () => { { key: 'name', label: 'Name', - thClass: TABLE_HEADING_CLASSES, sortable: true, + tdClass: 'gl-md-w-half gl-lg-w-40p gl-word-break-word', }, { key: 'status', label: 'Status', - thClass: TABLE_HEADING_CLASSES, sortable: true, + tdClass: 'gl-md-w-15', }, { key: 'namespace', label: 'Namespace', - thClass: TABLE_HEADING_CLASSES, sortable: true, + tdClass: 'gl-md-w-30p gl-lg-w-40p gl-word-break-word', }, { key: 'age', label: 'Age', - thClass: TABLE_HEADING_CLASSES, sortable: true, }, ]; @@ -57,13 +56,11 @@ describe('Workload table component', () => { { key: 'field-1', label: 'Field-1', - thClass: TABLE_HEADING_CLASSES, sortable: true, }, { key: 'field-2', label: 'Field-2', - thClass: TABLE_HEADING_CLASSES, sortable: true, }, ]; diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap index cbf2184d879..78d7f4183b7 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap +++ b/spec/frontend/packages_and_registries/package_registry/components/list/__snapshots__/package_list_row_spec.js.snap @@ -28,19 +28,15 @@ exports[`packages_list_row renders 1`] = ` <div class="gl-align-items-center gl-display-flex gl-min-w-0 gl-mr-3" > - <router-link-stub - ariacurrentvalue="page" + <a class="gl-min-w-0 gl-text-body" data-testid="details-link" - event="click" - tag="a" - to="[object Object]" > <gl-truncate-stub position="end" text="@gitlab-org/package-15" /> - </router-link-stub> + </a> </div> </div> <div diff --git a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js index 9f8fd4e28e7..afcb1798878 100644 --- a/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js +++ b/spec/frontend/packages_and_registries/package_registry/components/list/package_list_row_spec.js @@ -1,6 +1,7 @@ import { GlFormCheckbox, GlSprintf, GlTruncate } from '@gitlab/ui'; import Vue from 'vue'; import VueRouter from 'vue-router'; +import { RouterLinkStub } from '@vue/test-utils'; import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import { createMockDirective, getBinding } from 'helpers/vue_mock_directive'; @@ -58,6 +59,7 @@ describe('packages_list_row', () => { ListItem, GlSprintf, TimeagoTooltip, + RouterLink: RouterLinkStub, }, propsData: { packageEntity, diff --git a/spec/frontend/releases/components/app_edit_new_spec.js b/spec/frontend/releases/components/app_edit_new_spec.js index 15436832be8..90f31dca232 100644 --- a/spec/frontend/releases/components/app_edit_new_spec.js +++ b/spec/frontend/releases/components/app_edit_new_spec.js @@ -319,6 +319,25 @@ describe('Release edit/new component', () => { expect(actions.saveRelease).not.toHaveBeenCalled(); }); }); + + describe('when tag notes are loading', () => { + beforeEach(async () => { + await factory({ + store: { + modules: { + editNew: { + state: { + isFetchingTagNotes: true, + }, + }, + }, + }, + }); + }); + it('renders the submit button as disabled', () => { + expect(findSubmitButton().attributes('disabled')).toBeDefined(); + }); + }); }); describe('delete', () => { diff --git a/spec/frontend/releases/stores/modules/detail/actions_spec.js b/spec/frontend/releases/stores/modules/detail/actions_spec.js index a55b6cdef92..4dc55c12464 100644 --- a/spec/frontend/releases/stores/modules/detail/actions_spec.js +++ b/spec/frontend/releases/stores/modules/detail/actions_spec.js @@ -4,6 +4,7 @@ import testAction from 'helpers/vuex_action_helper'; import { useLocalStorageSpy } from 'helpers/local_storage_helper'; import { getTag } from '~/api/tags_api'; import { createAlert } from '~/alert'; +import { HTTP_STATUS_NOT_FOUND } from '~/lib/utils/http_status'; import { redirectTo } from '~/lib/utils/url_utility'; // eslint-disable-line import/no-deprecated import AccessorUtilities from '~/lib/utils/accessor'; import { s__ } from '~/locale'; @@ -128,6 +129,38 @@ describe('Release edit/new actions', () => { { type: types.INITIALIZE_RELEASE, payload: release }, { type: types.UPDATE_CREATE_FROM, payload: createFrom }, ], + expectedActions: [{ type: 'fetchTagNotes', payload: release.tagName }], + }); + }); + + it('with no tag name, does not fetch tag information', () => { + const release = { + tagName: '', + tagMessage: 'hello', + name: '', + description: '', + milestones: [], + groupMilestones: [], + releasedAt: new Date(), + assets: { + links: [], + }, + }; + const createFrom = 'main'; + + window.localStorage.setItem(`${state.projectPath}/release/new`, JSON.stringify(release)); + window.localStorage.setItem( + `${state.projectPath}/release/new/createFrom`, + JSON.stringify(createFrom), + ); + + return testAction({ + action: actions.loadDraftRelease, + state, + expectedMutations: [ + { type: types.INITIALIZE_RELEASE, payload: release }, + { type: types.UPDATE_CREATE_FROM, payload: createFrom }, + ], }); }); }); @@ -988,6 +1021,7 @@ describe('Release edit/new actions', () => { expect(getTag).toHaveBeenCalledWith(state.projectId, tagName); }); + it('creates an alert on error', async () => { error = new Error(); getTag.mockRejectedValue(error); @@ -1007,5 +1041,23 @@ describe('Release edit/new actions', () => { }); expect(getTag).toHaveBeenCalledWith(state.projectId, tagName); }); + + it('assumes creating a tag on 404', async () => { + error = { response: { status: HTTP_STATUS_NOT_FOUND } }; + getTag.mockRejectedValue(error); + + await testAction({ + action: actions.fetchTagNotes, + payload: tagName, + state, + expectedMutations: [ + { type: types.REQUEST_TAG_NOTES }, + { type: types.RECEIVE_TAG_NOTES_SUCCESS, payload: {} }, + ], + expectedActions: [{ type: 'setNewTag' }, { type: 'setCreating' }], + }); + + expect(getTag).toHaveBeenCalledWith(state.projectId, tagName); + }); }); }); diff --git a/spec/frontend/releases/stores/modules/detail/getters_spec.js b/spec/frontend/releases/stores/modules/detail/getters_spec.js index 24490e19296..30a3c78641c 100644 --- a/spec/frontend/releases/stores/modules/detail/getters_spec.js +++ b/spec/frontend/releases/stores/modules/detail/getters_spec.js @@ -424,7 +424,7 @@ describe('Release edit/new getters', () => { describe('formattedReleaseNotes', () => { it.each` - description | includeTagNotes | tagNotes | included | showCreateFrom + description | includeTagNotes | tagNotes | included | isNewTag ${'release notes'} | ${true} | ${'tag notes'} | ${true} | ${false} ${'release notes'} | ${true} | ${''} | ${false} | ${false} ${'release notes'} | ${false} | ${'tag notes'} | ${false} | ${false} @@ -432,25 +432,24 @@ describe('Release edit/new getters', () => { ${'release notes'} | ${true} | ${''} | ${false} | ${true} ${'release notes'} | ${false} | ${'tag notes'} | ${false} | ${true} `( - 'should include tag notes=$included when includeTagNotes=$includeTagNotes and tagNotes=$tagNotes and showCreateFrom=$showCreateFrom', - ({ description, includeTagNotes, tagNotes, included, showCreateFrom }) => { + 'should include tag notes=$included when includeTagNotes=$includeTagNotes and tagNotes=$tagNotes and isNewTag=$isNewTag', + ({ description, includeTagNotes, tagNotes, included, isNewTag }) => { let state; - if (showCreateFrom) { + if (isNewTag) { state = { release: { description, tagMessage: tagNotes }, includeTagNotes, - showCreateFrom, }; } else { - state = { release: { description }, includeTagNotes, tagNotes, showCreateFrom }; + state = { release: { description }, includeTagNotes, tagNotes }; } const text = `### ${s__('Releases|Tag message')}\n\n${tagNotes}\n`; if (included) { - expect(getters.formattedReleaseNotes(state)).toContain(text); + expect(getters.formattedReleaseNotes(state, { isNewTag })).toContain(text); } else { - expect(getters.formattedReleaseNotes(state)).not.toContain(text); + expect(getters.formattedReleaseNotes(state, { isNewTag })).not.toContain(text); } }, ); diff --git a/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_config_spec.rb b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_config_spec.rb new file mode 100644 index 00000000000..fad3e277888 --- /dev/null +++ b/spec/lib/gitlab/background_migration/backfill_partition_id_ci_pipeline_config_spec.rb @@ -0,0 +1,73 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::BackgroundMigration::BackfillPartitionIdCiPipelineConfig, + feature_category: :continuous_integration do + let(:ci_pipelines_table) { table(:ci_pipelines, database: :ci) } + let(:ci_pipeline_config_table) { table(:ci_pipelines_config, database: :ci) } + let!(:pipeline_1) { ci_pipelines_table.create!(id: 1, partition_id: 100) } + let!(:pipeline_2) { ci_pipelines_table.create!(id: 2, partition_id: 101) } + let!(:pipeline_3) { ci_pipelines_table.create!(id: 3, partition_id: 101) } + let!(:ci_pipeline_config_100) do + ci_pipeline_config_table.create!( + pipeline_id: pipeline_1.id, + content: "content", + partition_id: pipeline_1.partition_id + ) + end + + let!(:ci_pipeline_config_101) do + ci_pipeline_config_table.create!( + pipeline_id: pipeline_2.id, + content: "content", + partition_id: pipeline_2.partition_id + ) + end + + let!(:invalid_ci_pipeline_config) do + ci_pipeline_config_table.create!( + pipeline_id: pipeline_3.id, + content: "content", + partition_id: pipeline_1.partition_id + ) + end + + let(:migration_attrs) do + { + start_id: ci_pipeline_config_table.minimum(:pipeline_id), + end_id: ci_pipeline_config_table.maximum(:pipeline_id), + batch_table: :ci_pipelines_config, + batch_column: :pipeline_id, + sub_batch_size: 1, + pause_ms: 0, + connection: Ci::ApplicationRecord.connection + } + end + + let!(:migration) { described_class.new(**migration_attrs) } + + describe '#perform' do + context 'when second partition does not exist' do + before do + pipeline_3.update!(partition_id: 100) + end + + it 'does not execute the migration' do + expect { migration.perform } + .not_to change { invalid_ci_pipeline_config.reload.partition_id } + end + end + + context 'when second partition exists' do + it 'fixes invalid records in the wrong the partition' do + expect { migration.perform } + .to not_change { ci_pipeline_config_100.reload.partition_id } + .and not_change { ci_pipeline_config_101.reload.partition_id } + .and change { invalid_ci_pipeline_config.reload.partition_id } + .from(100) + .to(101) + end + end + end +end diff --git a/spec/lib/gitlab/github_import/importer/replay_events_importer_spec.rb b/spec/lib/gitlab/github_import/importer/replay_events_importer_spec.rb index a2233ffe8cc..2b21232c642 100644 --- a/spec/lib/gitlab/github_import/importer/replay_events_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/replay_events_importer_spec.rb @@ -16,37 +16,39 @@ RSpec.describe Gitlab::GithubImport::Importer::ReplayEventsImporter, feature_cat ) end - let(:importer) { described_class.new(representation, project, client) } + let(:events) do + [ + { + requested_reviewer: { id: 1, login: 'user1' }, + event: 'review_requested' + }, + { + requested_reviewer: { id: 1, login: 'user1' }, + event: 'review_request_removed' + }, + { + requested_reviewer: { id: 2, login: 'user2' }, + event: 'review_requested' + }, + { + requested_reviewer: { id: 2, login: 'user2' }, + event: 'review_request_removed' + }, + { + requested_reviewer: { id: 2, login: 'user2' }, + event: 'review_requested' + }, + { + requested_reviewer: { id: 3, login: 'user3' }, + event: 'review_requested' + } + ] + end + + subject(:importer) { described_class.new(representation, project, client) } describe '#execute' do before do - events = [ - { - requested_reviewer: { id: 1, login: 'user1' }, - event: 'review_requested' - }, - { - requested_reviewer: { id: 1, login: 'user1' }, - event: 'review_request_removed' - }, - { - requested_reviewer: { id: 2, login: 'user2' }, - event: 'review_requested' - }, - { - requested_reviewer: { id: 2, login: 'user2' }, - event: 'review_request_removed' - }, - { - requested_reviewer: { id: 2, login: 'user2' }, - event: 'review_requested' - }, - { - requested_reviewer: { id: 3, login: 'user3' }, - event: 'review_requested' - } - ] - representations = events.map { |e| Gitlab::GithubImport::Representation::IssueEvent.from_json_hash(e) } allow_next_instance_of(Gitlab::GithubImport::EventsCache) do |events_cache| @@ -75,6 +77,35 @@ RSpec.describe Gitlab::GithubImport::Importer::ReplayEventsImporter, feature_cat importer.execute end + + context 'when reviewer is a team' do + let(:events) do + [ + { + event: 'review_requested', + requested_team: { name: 'backend-team' } + }, + { + event: 'review_requested', + requested_team: { name: 'frontend-team' } + }, + { + event: 'review_request_removed', + requested_team: { name: 'frontend-team' } + } + ] + end + + it 'ignores the events and do not assign the reviewers' do + expect(Gitlab::GithubImport::Representation::PullRequests::ReviewRequests).to receive(:from_json_hash).with( + merge_request_id: association.id, + merge_request_iid: association.iid, + users: [] + ).and_call_original + + importer.execute + end + end end context 'when association is not found' do diff --git a/spec/migrations/20240110090352_queue_backfill_partition_id_ci_pipeline_config_spec.rb b/spec/migrations/20240110090352_queue_backfill_partition_id_ci_pipeline_config_spec.rb new file mode 100644 index 00000000000..9d64708eb29 --- /dev/null +++ b/spec/migrations/20240110090352_queue_backfill_partition_id_ci_pipeline_config_spec.rb @@ -0,0 +1,56 @@ +# frozen_string_literal: true + +require 'spec_helper' +require_migration! + +RSpec.describe QueueBackfillPartitionIdCiPipelineConfig, migration: :gitlab_ci, feature_category: :continuous_integration do + let!(:batched_migrations) { table(:batched_background_migrations) } + let!(:migration) { described_class::MIGRATION } + + describe '#up' do + context 'with migration present' do + let!(:ci_backfill_partition_id_ci_pipeline_config_migration) do + batched_migrations.create!( + job_class_name: 'QueueBackfillPartitionIdCiPipelineConfig', + table_name: :ci_pipelines_config, + column_name: :pipeline_id, + job_arguments: [], + interval: 2.minutes, + min_value: 1, + max_value: 2, + batch_size: 1000, + sub_batch_size: 100, + gitlab_schema: :gitlab_ci, + status: 3 # finished + ) + end + + context 'when migration finished successfully' do + it 'does not raise exception' do + expect { migrate! }.not_to raise_error + end + + it 'schedules background jobs for each batch of ci_pipelines_config' do + migrate! + + expect(migration).to have_scheduled_batched_migration( + gitlab_schema: :gitlab_ci, + table_name: :ci_pipelines_config, + column_name: :pipeline_id, + batch_size: described_class::BATCH_SIZE, + sub_batch_size: described_class::SUB_BATCH_SIZE + ) + end + end + end + end + + describe '#down' do + it 'deletes all batched migration records' do + migrate! + schema_migrate_down! + + expect(migration).not_to have_scheduled_batched_migration + end + end +end diff --git a/spec/models/ci/pipeline_config_spec.rb b/spec/models/ci/pipeline_config_spec.rb index 3d033d33df3..3368c40fb57 100644 --- a/spec/models/ci/pipeline_config_spec.rb +++ b/spec/models/ci/pipeline_config_spec.rb @@ -2,9 +2,24 @@ require 'spec_helper' -RSpec.describe Ci::PipelineConfig, type: :model do +RSpec.describe Ci::PipelineConfig, type: :model, feature_category: :continuous_integration do it { is_expected.to belong_to(:pipeline) } it { is_expected.to validate_presence_of(:pipeline) } it { is_expected.to validate_presence_of(:content) } + + describe 'partitioning', :ci_partitionable do + include Ci::PartitioningHelpers + + let(:pipeline) { create(:ci_pipeline) } + let(:pipeline_config) { create(:ci_pipeline_config, pipeline: pipeline) } + + before do + stub_current_partition_id + end + + it 'assigns the same partition id as the one that pipeline has' do + expect(pipeline_config.partition_id).to eq(ci_testing_partition_id) + end + end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index 118d6050174..26a9a364ea6 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -2511,9 +2511,15 @@ RSpec.describe Group, feature_category: :groups_and_projects do subject(:highest_group_member) { nested_group_2.highest_group_member(user) } context 'when the user is not a member of any group in the hierarchy' do - it 'returns nil' do - expect(highest_group_member).to be_nil + it { is_expected.to be_nil } + end + + context 'when access request to group is pending' do + before do + create(:group_member, requested_at: Time.current.utc, source: nested_group, user: user) end + + it { is_expected.to be_nil } end context 'when the user is only a member of one group in the hierarchy' do diff --git a/spec/requests/projects/google_cloud/databases_controller_spec.rb b/spec/requests/projects/google_cloud/databases_controller_spec.rb index fa978a3921f..46f6d27644c 100644 --- a/spec/requests/projects/google_cloud/databases_controller_spec.rb +++ b/spec/requests/projects/google_cloud/databases_controller_spec.rb @@ -96,7 +96,7 @@ RSpec.describe Projects::GoogleCloud::DatabasesController, :snowplow, feature_ca context 'when EnableCloudsqlService fails' do before do - allow_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::EnableCloudsqlService) do |service| allow(service).to receive(:execute) .and_return({ status: :error, message: 'error' }) end @@ -125,7 +125,7 @@ RSpec.describe Projects::GoogleCloud::DatabasesController, :snowplow, feature_ca context 'when EnableCloudsqlService is successful' do before do - allow_next_instance_of(::GoogleCloud::EnableCloudsqlService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::EnableCloudsqlService) do |service| allow(service).to receive(:execute) .and_return({ status: :success, message: 'success' }) end @@ -133,7 +133,7 @@ RSpec.describe Projects::GoogleCloud::DatabasesController, :snowplow, feature_ca context 'when CreateCloudsqlInstanceService fails' do before do - allow_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::CreateCloudsqlInstanceService) do |service| allow(service).to receive(:execute) .and_return({ status: :error, message: 'error' }) end @@ -162,7 +162,7 @@ RSpec.describe Projects::GoogleCloud::DatabasesController, :snowplow, feature_ca context 'when CreateCloudsqlInstanceService is successful' do before do - allow_next_instance_of(::GoogleCloud::CreateCloudsqlInstanceService) do |service| + allow_next_instance_of(::CloudSeed::GoogleCloud::CreateCloudsqlInstanceService) do |service| allow(service).to receive(:execute) .and_return({ status: :success, message: 'success' }) end diff --git a/spec/requests/projects/google_cloud/deployments_controller_spec.rb b/spec/requests/projects/google_cloud/deployments_controller_spec.rb index e9eac1e7ecd..1a6482477ef 100644 --- a/spec/requests/projects/google_cloud/deployments_controller_spec.rb +++ b/spec/requests/projects/google_cloud/deployments_controller_spec.rb @@ -110,7 +110,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController, feature_category: : context 'when enable service fails' do before do - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |service| allow(service) .to receive(:execute) .and_return( @@ -146,7 +146,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController, feature_category: : before do mock_gcp_error = Google::Apis::ClientError.new('some_error') - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |service| allow(service).to receive(:execute).and_raise(mock_gcp_error) end end @@ -173,14 +173,14 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController, feature_category: : context 'GCP_PROJECT_IDs are defined' do before do - allow_next_instance_of(GoogleCloud::EnableCloudRunService) do |enable_cloud_run_service| + allow_next_instance_of(CloudSeed::GoogleCloud::EnableCloudRunService) do |enable_cloud_run_service| allow(enable_cloud_run_service).to receive(:execute).and_return({ status: :success }) end end context 'when generate pipeline service fails' do before do - allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |generate_pipeline_service| + allow_next_instance_of(CloudSeed::GoogleCloud::GeneratePipelineService) do |generate_pipeline_service| allow(generate_pipeline_service).to receive(:execute).and_return({ status: :error }) end end @@ -206,7 +206,7 @@ RSpec.describe Projects::GoogleCloud::DeploymentsController, feature_category: : end it 'redirects to create merge request form' do - allow_next_instance_of(GoogleCloud::GeneratePipelineService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::GeneratePipelineService) do |service| allow(service).to receive(:execute).and_return({ status: :success }) end diff --git a/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb b/spec/services/cloud_seed/google_cloud/create_cloudsql_instance_service_spec.rb index c31e76170d5..f6f1206e753 100644 --- a/spec/services/google_cloud/create_cloudsql_instance_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/create_cloudsql_instance_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::CreateCloudsqlInstanceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::CreateCloudsqlInstanceService, feature_category: :deployment_management do let(:project) { create(:project) } let(:user) { create(:user) } let(:gcp_project_id) { 'gcp_project_120' } diff --git a/spec/services/google_cloud/create_service_accounts_service_spec.rb b/spec/services/cloud_seed/google_cloud/create_service_accounts_service_spec.rb index 3b57f2a9e5f..da30037963b 100644 --- a/spec/services/google_cloud/create_service_accounts_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/create_service_accounts_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::CreateServiceAccountsService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::CreateServiceAccountsService, feature_category: :deployment_management do describe '#execute' do before do mock_google_oauth2_creds = Struct.new(:app_id, :app_secret) diff --git a/spec/services/google_cloud/enable_cloud_run_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb index 3de9e7fcd5c..09f1b3460cc 100644 --- a/spec/services/google_cloud/enable_cloud_run_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_cloud_run_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableCloudRunService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableCloudRunService, feature_category: :deployment_management do describe 'when a project does not have any gcp projects' do let_it_be(:project) { create(:project) } diff --git a/spec/services/google_cloud/enable_cloudsql_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb index b14b827e8b8..137393e4544 100644 --- a/spec/services/google_cloud/enable_cloudsql_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_cloudsql_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableCloudsqlService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableCloudsqlService, feature_category: :deployment_management do let_it_be(:project) { create(:project) } let_it_be(:user) { create(:user) } let_it_be(:params) do diff --git a/spec/services/google_cloud/enable_vision_ai_service_spec.rb b/spec/services/cloud_seed/google_cloud/enable_vision_ai_service_spec.rb index 5adafcffe69..c37b5681a4b 100644 --- a/spec/services/google_cloud/enable_vision_ai_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/enable_vision_ai_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::EnableVisionAiService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::EnableVisionAiService, feature_category: :deployment_management do describe 'when a project does not have any gcp projects' do let_it_be(:project) { create(:project) } diff --git a/spec/services/google_cloud/fetch_google_ip_list_service_spec.rb b/spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb index f8d5ba99bf6..c4a0be78213 100644 --- a/spec/services/google_cloud/fetch_google_ip_list_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/fetch_google_ip_list_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::FetchGoogleIpListService, :use_clean_rails_memory_store_caching, +RSpec.describe CloudSeed::GoogleCloud::FetchGoogleIpListService, :use_clean_rails_memory_store_caching, :clean_gitlab_redis_rate_limiting, feature_category: :build_artifacts do include StubRequests diff --git a/spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb b/spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb index a748fed7134..2af03291484 100644 --- a/spec/services/google_cloud/gcp_region_add_or_replace_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/gcp_region_add_or_replace_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GcpRegionAddOrReplaceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GcpRegionAddOrReplaceService, feature_category: :deployment_management do it 'adds and replaces GCP region vars' do project = create(:project, :public) service = described_class.new(project) diff --git a/spec/services/google_cloud/generate_pipeline_service_spec.rb b/spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb index 8f49e1af901..14c1e6bae7f 100644 --- a/spec/services/google_cloud/generate_pipeline_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/generate_pipeline_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GeneratePipelineService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GeneratePipelineService, feature_category: :deployment_management do describe 'for cloud-run' do describe 'when there is no existing pipeline' do let_it_be(:project) { create(:project, :repository) } @@ -64,7 +64,10 @@ RSpec.describe GoogleCloud::GeneratePipelineService, feature_category: :deployme describe 'when there is an existing pipeline without `deploy` stage' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before_all do @@ -119,7 +122,10 @@ EOF describe 'when there is an existing pipeline with `deploy` stage' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do @@ -166,7 +172,10 @@ EOF describe 'when there is an existing pipeline with `includes`' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_RUN } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do @@ -210,7 +219,10 @@ EOF describe 'when there is no existing pipeline' do let_it_be(:project) { create(:project, :repository) } let_it_be(:maintainer) { create(:user) } - let_it_be(:service_params) { { action: GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_STORAGE } } + let_it_be(:service_params) do + { action: CloudSeed::GoogleCloud::GeneratePipelineService::ACTION_DEPLOY_TO_CLOUD_STORAGE } + end + let_it_be(:service) { described_class.new(project, maintainer, service_params) } before do diff --git a/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb b/spec/services/cloud_seed/google_cloud/get_cloudsql_instances_service_spec.rb index cd2ad00ac3f..fb17d578af7 100644 --- a/spec/services/google_cloud/get_cloudsql_instances_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/get_cloudsql_instances_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::GetCloudsqlInstancesService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::GetCloudsqlInstancesService, feature_category: :deployment_management do let(:service) { described_class.new(project) } let(:project) { create(:project) } diff --git a/spec/services/google_cloud/service_accounts_service_spec.rb b/spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb index c900bf7d300..62d58b3198a 100644 --- a/spec/services/google_cloud/service_accounts_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/service_accounts_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::ServiceAccountsService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::ServiceAccountsService, feature_category: :deployment_management do let(:service) { described_class.new(project) } describe 'find_for_project' do diff --git a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb b/spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb index 5095277f61a..ce02672e3fa 100644 --- a/spec/services/google_cloud/setup_cloudsql_instance_service_spec.rb +++ b/spec/services/cloud_seed/google_cloud/setup_cloudsql_instance_service_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe GoogleCloud::SetupCloudsqlInstanceService, feature_category: :deployment_management do +RSpec.describe CloudSeed::GoogleCloud::SetupCloudsqlInstanceService, feature_category: :deployment_management do let(:random_user) { create(:user) } let(:project) { create(:project) } let(:list_databases_empty) { Google::Apis::SqladminV1beta4::ListDatabasesResponse.new(items: []) } diff --git a/spec/support/helpers/database/duplicate_indexes.yml b/spec/support/helpers/database/duplicate_indexes.yml index acfda313020..80d409f233d 100644 --- a/spec/support/helpers/database/duplicate_indexes.yml +++ b/spec/support/helpers/database/duplicate_indexes.yml @@ -37,9 +37,6 @@ ci_job_artifacts: - index_ci_job_artifacts_on_project_id index_ci_job_artifacts_on_project_id_and_id: - index_ci_job_artifacts_on_project_id -ci_job_artifact_states: - index_ci_job_artifact_states_on_job_artifact_id: - - index_ci_job_artifact_states_on_job_artifact_id_partition_id ci_pipeline_artifacts: index_ci_pipeline_artifacts_on_pipeline_id_and_file_type: - index_ci_pipeline_artifacts_on_pipeline_id diff --git a/spec/support/shared_examples/models/member_shared_examples.rb b/spec/support/shared_examples/models/member_shared_examples.rb index 6f00a5485a2..01d6642e814 100644 --- a/spec/support/shared_examples/models/member_shared_examples.rb +++ b/spec/support/shared_examples/models/member_shared_examples.rb @@ -54,6 +54,25 @@ RSpec.shared_examples 'inherited access level as a member of entity' do expect { non_member.update!(access_level: Gitlab::Access::GUEST) } .to change { non_member.reload.access_level } end + + context 'when access request to entity is pending' do + before do + parent_entity.members.where(user: user).update!(requested_at: Time.current) + end + + it 'is allowed to be a reporter of the entity' do + entity.add_reporter(user) + + expect(member.access_level).to eq(Gitlab::Access::REPORTER) + end + + it 'is allowed to change to be a guest of the entity' do + entity.add_maintainer(user) + + expect { member.update!(access_level: Gitlab::Access::GUEST) } + .to change { member.reload.access_level }.from(Gitlab::Access::MAINTAINER).to(Gitlab::Access::GUEST) + end + end end end @@ -63,10 +82,9 @@ RSpec.shared_examples '#valid_level_roles' do |entity_name| let(:entity) { create(entity_name) } # rubocop:disable Rails/SaveBang let(:entity_member) { create("#{entity_name}_member", :developer, source: entity, user: member_user) } let(:presenter) { described_class.new(entity_member, current_user: member_user) } + let(:all_permissible_roles) { entity_member.class.permissible_access_level_roles(member_user, entity) } context 'when no parent member is present' do - let(:all_permissible_roles) { entity_member.class.permissible_access_level_roles(member_user, entity) } - it 'returns all permissible roles' do expect(presenter.valid_level_roles).to eq(all_permissible_roles) end @@ -80,6 +98,16 @@ RSpec.shared_examples '#valid_level_roles' do |entity_name| it 'returns higher roles when a parent member is present' do expect(presenter.valid_level_roles).to eq(expected_roles) end + + context 'when access request to parent is pending' do + before do + group.members.with_user(member_user).update!(requested_at: Time.current) + end + + it 'returns all permissible roles' do + expect(presenter.valid_level_roles).to eq(all_permissible_roles) + end + end end end diff --git a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb index 96413f622e8..04c6cf4bde9 100644 --- a/spec/uploaders/object_storage/cdn/google_cdn_spec.rb +++ b/spec/uploaders/object_storage/cdn/google_cdn_spec.rb @@ -19,7 +19,7 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN, subject { described_class.new(options) } before do - WebMock.stub_request(:get, GoogleCloud::FetchGoogleIpListService::GOOGLE_IP_RANGES_URL) + WebMock.stub_request(:get, CloudSeed::GoogleCloud::FetchGoogleIpListService::GOOGLE_IP_RANGES_URL) .to_return(status: 200, body: google_cloud_ips, headers: headers) end diff --git a/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb b/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb index 7aea40807e8..e86d6771386 100644 --- a/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb +++ b/spec/workers/google_cloud/create_cloudsql_instance_worker_spec.rb @@ -23,15 +23,15 @@ RSpec.describe GoogleCloud::CreateCloudsqlInstanceWorker, feature_category: :sha described_class.new.perform(user_id, project_id, worker_options) end - it 'calls GoogleCloud::SetupCloudsqlInstanceService' do - allow_next_instance_of(GoogleCloud::SetupCloudsqlInstanceService) do |service| + it 'calls CloudSeed::GoogleCloud::SetupCloudsqlInstanceService' do + allow_next_instance_of(CloudSeed::GoogleCloud::SetupCloudsqlInstanceService) do |service| expect(service).to receive(:execute).and_return({ status: :success }) end subject end - context 'when GoogleCloud::SetupCloudsqlInstanceService fails' do + context 'when CloudSeed::GoogleCloud::SetupCloudsqlInstanceService fails' do subject do user_id = random_user.id project_id = project.id @@ -39,7 +39,7 @@ RSpec.describe GoogleCloud::CreateCloudsqlInstanceWorker, feature_category: :sha end it 'raises error' do - allow_next_instance_of(GoogleCloud::SetupCloudsqlInstanceService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::SetupCloudsqlInstanceService) do |service| expect(service).to receive(:execute).and_return({ status: :error }) end diff --git a/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb b/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb index bdafc076465..2a7d52d987f 100644 --- a/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb +++ b/spec/workers/google_cloud/fetch_google_ip_list_worker_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe GoogleCloud::FetchGoogleIpListWorker, feature_category: :build_artifacts do describe '#perform' do it 'returns success' do - allow_next_instance_of(GoogleCloud::FetchGoogleIpListService) do |service| + allow_next_instance_of(CloudSeed::GoogleCloud::FetchGoogleIpListService) do |service| expect(service).to receive(:execute).and_return({ status: :success }) end |