diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-02 15:17:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-02-02 15:17:50 +0000 |
commit | 65c71039ebe065a6c97e226f5743bd637680a14e (patch) | |
tree | a0c7a9d7f1fd65f290318cc7465cd3d07354a908 /spec | |
parent | 292384904c9d821acca2f92d2de2f0b2ed5216df (diff) | |
download | gitlab-ce-65c71039ebe065a6c97e226f5743bd637680a14e.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
22 files changed, 178 insertions, 419 deletions
diff --git a/spec/controllers/projects/commits_controller_spec.rb b/spec/controllers/projects/commits_controller_spec.rb index d84717f1124..c7f98406201 100644 --- a/spec/controllers/projects/commits_controller_spec.rb +++ b/spec/controllers/projects/commits_controller_spec.rb @@ -151,6 +151,20 @@ RSpec.describe Projects::CommitsController do expect(response.media_type).to eq('text/html') end end + + context 'when the ref does not exist' do + before do + get(:show, params: { + namespace_id: project.namespace, + project_id: project, + id: 'unknown.atom' + }) + end + + it 'returns 404 page' do + expect(response).to be_not_found + end + end end end diff --git a/spec/controllers/projects/merge_requests_controller_spec.rb b/spec/controllers/projects/merge_requests_controller_spec.rb index 3ac59d8e43a..88e60a5352a 100644 --- a/spec/controllers/projects/merge_requests_controller_spec.rb +++ b/spec/controllers/projects/merge_requests_controller_spec.rb @@ -443,7 +443,7 @@ RSpec.describe Projects::MergeRequestsController do context 'when the merge request is not mergeable' do before do - merge_request.update!(title: "WIP: #{merge_request.title}") + merge_request.update!(title: "Draft: #{merge_request.title}") post :merge, params: base_params end diff --git a/spec/features/merge_request/user_resolves_wip_mr_spec.rb b/spec/features/merge_request/user_resolves_wip_mr_spec.rb index fd405855cf8..92927b713f1 100644 --- a/spec/features/merge_request/user_resolves_wip_mr_spec.rb +++ b/spec/features/merge_request/user_resolves_wip_mr_spec.rb @@ -2,13 +2,13 @@ require 'spec_helper' -RSpec.describe 'Merge request > User resolves Work in Progress', :js do +RSpec.describe 'Merge request > User resolves Draft', :js do let(:project) { create(:project, :public, :repository) } let(:user) { project.creator } let(:merge_request) do create(:merge_request_with_diffs, source_project: project, author: user, - title: 'WIP: Bug NS-04', + title: 'Draft: Bug NS-04', merge_params: { force_remove_source_branch: '1' }) end diff --git a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js index a3a31ebc387..a2d37699387 100644 --- a/spec/frontend/cycle_analytics/value_stream_metrics_spec.js +++ b/spec/frontend/cycle_analytics/value_stream_metrics_spec.js @@ -5,6 +5,8 @@ import metricsData from 'test_fixtures/projects/analytics/value_stream_analytics import waitForPromises from 'helpers/wait_for_promises'; import { METRIC_TYPE_SUMMARY } from '~/api/analytics_api'; import ValueStreamMetrics from '~/cycle_analytics/components/value_stream_metrics.vue'; +import { METRICS_POPOVER_CONTENT } from '~/cycle_analytics/constants'; +import { prepareTimeMetricsData } from '~/cycle_analytics/utils'; import MetricTile from '~/cycle_analytics/components/metric_tile.vue'; import createFlash from '~/flash'; import { group } from './mock_data'; @@ -14,6 +16,7 @@ jest.mock('~/flash'); describe('ValueStreamMetrics', () => { let wrapper; let mockGetValueStreamSummaryMetrics; + let mockFilterFn; const { full_path: requestPath } = group; const fakeReqName = 'Mock metrics'; @@ -23,12 +26,13 @@ describe('ValueStreamMetrics', () => { name: fakeReqName, }); - const createComponent = ({ requestParams = {} } = {}) => { + const createComponent = (props = {}) => { return shallowMount(ValueStreamMetrics, { propsData: { requestPath, - requestParams, + requestParams: {}, requests: [metricsRequestFactory()], + ...props, }, }); }; @@ -104,6 +108,35 @@ describe('ValueStreamMetrics', () => { expect(wrapper.find(GlSkeletonLoading).exists()).toBe(false); }); + describe('filterFn', () => { + const transferedMetricsData = prepareTimeMetricsData(metricsData, METRICS_POPOVER_CONTENT); + + it('with a filter function, will call the function with the metrics data', async () => { + const filteredData = [ + { identifier: 'issues', value: '3', title: 'New Issues', description: 'foo' }, + ]; + mockFilterFn = jest.fn(() => filteredData); + + wrapper = createComponent({ + filterFn: mockFilterFn, + }); + + await waitForPromises(); + + expect(mockFilterFn).toHaveBeenCalledWith(transferedMetricsData); + expect(wrapper.vm.metrics).toEqual(filteredData); + }); + + it('without a filter function, it will only update the metrics', async () => { + wrapper = createComponent(); + + await waitForPromises(); + + expect(mockFilterFn).not.toHaveBeenCalled(); + expect(wrapper.vm.metrics).toEqual(transferedMetricsData); + }); + }); + describe('with additional params', () => { beforeEach(async () => { wrapper = createComponent({ diff --git a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js index 9adc6dba51e..cafb3f231bd 100644 --- a/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js +++ b/spec/frontend/projects/pipelines/charts/components/ci_cd_analytics_charts_spec.js @@ -1,6 +1,6 @@ -import { GlSegmentedControl } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; import { nextTick } from 'vue'; +import { GlSegmentedControl } from '@gitlab/ui'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import CiCdAnalyticsAreaChart from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_area_chart.vue'; import CiCdAnalyticsCharts from '~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue'; import { transformedAreaChartData, chartOptions } from '../mock_data'; @@ -29,12 +29,15 @@ const DEFAULT_PROPS = { describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', () => { let wrapper; - const createWrapper = (props = {}) => - shallowMount(CiCdAnalyticsCharts, { + const createWrapper = (props = {}, slots = {}) => + shallowMountExtended(CiCdAnalyticsCharts, { propsData: { ...DEFAULT_PROPS, ...props, }, + scopedSlots: { + ...slots, + }, }); afterEach(() => { @@ -44,20 +47,20 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( } }); - describe('segmented control', () => { - let segmentedControl; + const findMetricsSlot = () => wrapper.findByTestId('metrics-slot'); + const findSegmentedControl = () => wrapper.findComponent(GlSegmentedControl); + describe('segmented control', () => { beforeEach(() => { wrapper = createWrapper(); - segmentedControl = wrapper.find(GlSegmentedControl); }); it('should default to the first chart', () => { - expect(segmentedControl.props('checked')).toBe(0); + expect(findSegmentedControl().props('checked')).toBe(0); }); it('should use the title and index as values', () => { - const options = segmentedControl.props('options'); + const options = findSegmentedControl().props('options'); expect(options).toHaveLength(3); expect(options).toEqual([ { @@ -76,7 +79,7 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( }); it('should select a different chart on change', async () => { - segmentedControl.vm.$emit('input', 1); + findSegmentedControl().vm.$emit('input', 1); const chart = wrapper.find(CiCdAnalyticsAreaChart); @@ -91,4 +94,24 @@ describe('~/vue_shared/components/ci_cd_analytics/ci_cd_analytics_charts.vue', ( wrapper = createWrapper({ charts: [] }); expect(wrapper.find(CiCdAnalyticsAreaChart).exists()).toBe(false); }); + + describe('slots', () => { + beforeEach(() => { + wrapper = createWrapper( + {}, + { + metrics: '<div data-testid="metrics-slot">selected chart: {{props.selectedChart}}</div>', + }, + ); + }); + + it('renders a metrics slot', async () => { + const selectedChart = 1; + findSegmentedControl().vm.$emit('input', selectedChart); + + await nextTick(); + + expect(findMetricsSlot().text()).toBe(`selected chart: ${selectedChart}`); + }); + }); }); diff --git a/spec/lib/extracts_path_spec.rb b/spec/lib/extracts_path_spec.rb index 9b2bb024fa6..13b607452e1 100644 --- a/spec/lib/extracts_path_spec.rb +++ b/spec/lib/extracts_path_spec.rb @@ -209,8 +209,8 @@ RSpec.describe ExtractsPath do expect(extract_ref_without_atom('release/app/v1.0.0.atom')).to eq('release/app/v1.0.0') end - it 'returns nil if there are no matching refs' do - expect(extract_ref_without_atom('foo.atom')).to eq(nil) + it 'raises an error if there are no matching refs' do + expect { extract_ref_without_atom('foo.atom') }.to raise_error(ExtractsRef::InvalidPathError) end end end diff --git a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb deleted file mode 100644 index c4013d002b2..00000000000 --- a/spec/lib/gitlab/background_migration/backfill_legacy_project_repositories_spec.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::BackfillLegacyProjectRepositories do - it_behaves_like 'backfill migration for project repositories', :legacy -end diff --git a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb b/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb deleted file mode 100644 index ed44b819a97..00000000000 --- a/spec/lib/gitlab/background_migration/backfill_project_updated_at_after_repository_storage_move_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::BackfillProjectUpdatedAtAfterRepositoryStorageMove, :migration, schema: 20210301200959 do - let(:projects) { table(:projects) } - let(:project_repository_storage_moves) { table(:project_repository_storage_moves) } - let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') } - - subject { described_class.new } - - describe '#perform' do - it 'updates project updated_at column if they were moved to a different repository storage' do - freeze_time do - project_1 = projects.create!(id: 1, namespace_id: namespace.id, updated_at: 1.day.ago) - project_2 = projects.create!(id: 2, namespace_id: namespace.id, updated_at: Time.current) - original_project_3_updated_at = 2.minutes.from_now - project_3 = projects.create!(id: 3, namespace_id: namespace.id, updated_at: original_project_3_updated_at) - original_project_4_updated_at = 10.days.ago - project_4 = projects.create!(id: 4, namespace_id: namespace.id, updated_at: original_project_4_updated_at) - - repository_storage_move_1 = project_repository_storage_moves.create!(project_id: project_1.id, updated_at: 2.hours.ago, source_storage_name: 'default', destination_storage_name: 'default') - repository_storage_move_2 = project_repository_storage_moves.create!(project_id: project_2.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default') - project_repository_storage_moves.create!(project_id: project_3.id, updated_at: Time.current, source_storage_name: 'default', destination_storage_name: 'default') - - subject.perform([1, 2, 3, 4, non_existing_record_id]) - - expect(project_1.reload.updated_at).to eq(repository_storage_move_1.updated_at + 1.second) - expect(project_2.reload.updated_at).to eq(repository_storage_move_2.updated_at + 1.second) - expect(project_3.reload.updated_at).to eq(original_project_3_updated_at) - expect(project_4.reload.updated_at).to eq(original_project_4_updated_at) - end - end - end -end diff --git a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb b/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb deleted file mode 100644 index 68fe8f39f59..00000000000 --- a/spec/lib/gitlab/background_migration/populate_finding_uuid_for_vulnerability_feedback_spec.rb +++ /dev/null @@ -1,134 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::PopulateFindingUuidForVulnerabilityFeedback, schema: 20210301200959 do - let(:namespaces) { table(:namespaces) } - let(:projects) { table(:projects) } - let(:users) { table(:users) } - let(:scanners) { table(:vulnerability_scanners) } - let(:identifiers) { table(:vulnerability_identifiers) } - let(:findings) { table(:vulnerability_occurrences) } - let(:vulnerability_feedback) { table(:vulnerability_feedback) } - - let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') } - let(:project) { projects.create!(namespace_id: namespace.id, name: 'foo') } - let(:user) { users.create!(username: 'john.doe', projects_limit: 5) } - let(:scanner) { scanners.create!(project_id: project.id, external_id: 'foo', name: 'bar') } - let(:identifier) { identifiers.create!(project_id: project.id, fingerprint: 'foo', external_type: 'bar', external_id: 'zoo', name: 'baz') } - let(:sast_report) { 0 } - let(:dependency_scanning_report) { 1 } - let(:dast_report) { 3 } - let(:secret_detection_report) { 4 } - let(:project_fingerprint) { Digest::SHA1.hexdigest(SecureRandom.uuid) } - let(:location_fingerprint_1) { Digest::SHA1.hexdigest(SecureRandom.uuid) } - let(:location_fingerprint_2) { Digest::SHA1.hexdigest(SecureRandom.uuid) } - let(:location_fingerprint_3) { Digest::SHA1.hexdigest(SecureRandom.uuid) } - let(:finding_1) { finding_creator.call(sast_report, location_fingerprint_1) } - let(:finding_2) { finding_creator.call(dast_report, location_fingerprint_2) } - let(:finding_3) { finding_creator.call(secret_detection_report, location_fingerprint_3) } - let(:expected_uuid_1) do - Security::VulnerabilityUUID.generate( - report_type: 'sast', - primary_identifier_fingerprint: identifier.fingerprint, - location_fingerprint: location_fingerprint_1, - project_id: project.id - ) - end - - let(:expected_uuid_2) do - Security::VulnerabilityUUID.generate( - report_type: 'dast', - primary_identifier_fingerprint: identifier.fingerprint, - location_fingerprint: location_fingerprint_2, - project_id: project.id - ) - end - - let(:expected_uuid_3) do - Security::VulnerabilityUUID.generate( - report_type: 'secret_detection', - primary_identifier_fingerprint: identifier.fingerprint, - location_fingerprint: location_fingerprint_3, - project_id: project.id - ) - end - - let(:finding_creator) do - -> (report_type, location_fingerprint) do - findings.create!( - project_id: project.id, - primary_identifier_id: identifier.id, - scanner_id: scanner.id, - report_type: report_type, - uuid: SecureRandom.uuid, - name: 'Foo', - location_fingerprint: Gitlab::Database::ShaAttribute.serialize(location_fingerprint), - project_fingerprint: Gitlab::Database::ShaAttribute.serialize(project_fingerprint), - metadata_version: '1', - severity: 0, - confidence: 5, - raw_metadata: '{}' - ) - end - end - - let(:feedback_creator) do - -> (category, project_fingerprint) do - vulnerability_feedback.create!( - project_id: project.id, - author_id: user.id, - feedback_type: 0, - category: category, - project_fingerprint: project_fingerprint - ) - end - end - - let!(:feedback_1) { feedback_creator.call(finding_1.report_type, project_fingerprint) } - let!(:feedback_2) { feedback_creator.call(finding_2.report_type, project_fingerprint) } - let!(:feedback_3) { feedback_creator.call(finding_3.report_type, project_fingerprint) } - let!(:feedback_4) { feedback_creator.call(finding_1.report_type, 'foo') } - let!(:feedback_5) { feedback_creator.call(dependency_scanning_report, project_fingerprint) } - - subject(:populate_finding_uuids) { described_class.new.perform(feedback_1.id, feedback_5.id) } - - before do - allow(Gitlab::BackgroundMigration::Logger).to receive(:info) - end - - describe '#perform' do - it 'updates the `finding_uuid` attributes of the feedback records' do - expect { populate_finding_uuids }.to change { feedback_1.reload.finding_uuid }.from(nil).to(expected_uuid_1) - .and change { feedback_2.reload.finding_uuid }.from(nil).to(expected_uuid_2) - .and change { feedback_3.reload.finding_uuid }.from(nil).to(expected_uuid_3) - .and not_change { feedback_4.reload.finding_uuid } - .and not_change { feedback_5.reload.finding_uuid } - - expect(Gitlab::BackgroundMigration::Logger).to have_received(:info).once - end - - it 'preloads the finding and identifier records to prevent N+1 queries' do - # Load feedback records(1), load findings(2), load identifiers(3) and finally update feedback records one by one(6) - expect { populate_finding_uuids }.not_to exceed_query_limit(6) - end - - context 'when setting the `finding_uuid` attribute of a feedback record fails' do - let(:expected_error) { RuntimeError.new } - - before do - allow(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception) - - allow_next_found_instance_of(described_class::VulnerabilityFeedback) do |feedback| - allow(feedback).to receive(:update_column).and_raise(expected_error) - end - end - - it 'captures the errors and does not crash entirely' do - expect { populate_finding_uuids }.not_to raise_error - - expect(Gitlab::ErrorTracking).to have_received(:track_and_raise_for_dev_exception).with(expected_error).exactly(3).times - end - end - end -end diff --git a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb b/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb deleted file mode 100644 index b00eb185b34..00000000000 --- a/spec/lib/gitlab/background_migration/populate_issue_email_participants_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::PopulateIssueEmailParticipants, schema: 20210301200959 do - let!(:namespace) { table(:namespaces).create!(name: 'namespace', path: 'namespace') } - let!(:project) { table(:projects).create!(id: 1, namespace_id: namespace.id) } - let!(:issue1) { table(:issues).create!(id: 1, project_id: project.id, service_desk_reply_to: "a@gitlab.com") } - let!(:issue2) { table(:issues).create!(id: 2, project_id: project.id, service_desk_reply_to: "b@gitlab.com") } - let(:issue_email_participants) { table(:issue_email_participants) } - - describe '#perform' do - it 'migrates email addresses from service desk issues', :aggregate_failures do - expect { subject.perform(1, 2) }.to change { issue_email_participants.count }.by(2) - - expect(issue_email_participants.find_by(issue_id: 1).email).to eq("a@gitlab.com") - expect(issue_email_participants.find_by(issue_id: 2).email).to eq("b@gitlab.com") - end - end -end diff --git a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb b/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb deleted file mode 100644 index 17fe25c7f71..00000000000 --- a/spec/lib/gitlab/background_migration/wrongfully_confirmed_email_unconfirmer_spec.rb +++ /dev/null @@ -1,130 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::BackgroundMigration::WrongfullyConfirmedEmailUnconfirmer, schema: 20210301200959 do - let(:users) { table(:users) } - let(:emails) { table(:emails) } - let(:user_synced_attributes_metadata) { table(:user_synced_attributes_metadata) } - let(:confirmed_at_2_days_ago) { 2.days.ago } - let(:confirmed_at_3_days_ago) { 3.days.ago } - let(:one_year_ago) { 1.year.ago } - - let!(:user_needs_migration_1) { users.create!(name: 'user1', email: 'test1@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - let!(:user_needs_migration_2) { users.create!(name: 'user2', email: 'test2@test.com', unconfirmed_email: 'unconfirmed@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - let!(:user_does_not_need_migration) { users.create!(name: 'user3', email: 'test3@test.com', state: 'active', projects_limit: 1) } - let!(:inactive_user) { users.create!(name: 'user4', email: 'test4@test.com', state: 'blocked', projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - let!(:alert_bot_user) { users.create!(name: 'user5', email: 'test5@test.com', state: 'active', user_type: 2, projects_limit: 1, confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - let!(:user_has_synced_email) { users.create!(name: 'user6', email: 'test6@test.com', state: 'active', projects_limit: 1, confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - let!(:synced_attributes_metadata_for_user) { user_synced_attributes_metadata.create!(user_id: user_has_synced_email.id, email_synced: true) } - - let!(:bad_email_1) { emails.create!(user_id: user_needs_migration_1.id, email: 'other1@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - let!(:bad_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other2@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - let!(:bad_email_3_inactive_user) { emails.create!(user_id: inactive_user.id, email: 'other-inactive@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - let!(:bad_email_4_bot_user) { emails.create!(user_id: alert_bot_user.id, email: 'other-bot@test.com', confirmed_at: confirmed_at_3_days_ago, confirmation_sent_at: one_year_ago) } - - let!(:good_email_1) { emails.create!(user_id: user_needs_migration_2.id, email: 'other3@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - let!(:good_email_2) { emails.create!(user_id: user_needs_migration_2.id, email: 'other4@test.com', confirmed_at: nil) } - let!(:good_email_3) { emails.create!(user_id: user_does_not_need_migration.id, email: 'other5@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - - let!(:second_email_for_user_with_synced_email) { emails.create!(user_id: user_has_synced_email.id, email: 'other6@test.com', confirmed_at: confirmed_at_2_days_ago, confirmation_sent_at: one_year_ago) } - - subject do - email_ids = [bad_email_1, bad_email_2, good_email_1, good_email_2, good_email_3, second_email_for_user_with_synced_email].map(&:id) - - described_class.new.perform(email_ids.min, email_ids.max) - end - - it 'does not change irrelevant email records' do - subject - - expect(good_email_1.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago) - expect(good_email_2.reload.confirmed_at).to be_nil - expect(good_email_3.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago) - - expect(bad_email_3_inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago) - expect(bad_email_4_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago) - - expect(good_email_1.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - expect(good_email_2.reload.confirmation_sent_at).to be_nil - expect(good_email_3.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - - expect(bad_email_3_inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - expect(bad_email_4_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - end - - it 'clears the `unconfirmed_email` field' do - subject - - user_needs_migration_2.reload - expect(user_needs_migration_2.unconfirmed_email).to be_nil - end - - it 'does not change irrelevant user records' do - subject - - expect(user_does_not_need_migration.reload.confirmed_at).to be_nil - expect(inactive_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago) - expect(alert_bot_user.reload.confirmed_at).to be_within(1.second).of(confirmed_at_3_days_ago) - expect(user_has_synced_email.reload.confirmed_at).to be_within(1.second).of(confirmed_at_2_days_ago) - - expect(user_does_not_need_migration.reload.confirmation_sent_at).to be_nil - expect(inactive_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - expect(alert_bot_user.reload.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - expect(user_has_synced_email.confirmation_sent_at).to be_within(1.second).of(one_year_ago) - end - - it 'updates confirmation_sent_at column' do - subject - - expect(user_needs_migration_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now) - expect(user_needs_migration_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now) - - expect(bad_email_1.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now) - expect(bad_email_2.reload.confirmation_sent_at).to be_within(1.minute).of(Time.now) - end - - it 'unconfirms bad email records' do - subject - - expect(bad_email_1.reload.confirmed_at).to be_nil - expect(bad_email_2.reload.confirmed_at).to be_nil - - expect(bad_email_1.reload.confirmation_token).not_to be_nil - expect(bad_email_2.reload.confirmation_token).not_to be_nil - end - - it 'unconfirms user records' do - subject - - expect(user_needs_migration_1.reload.confirmed_at).to be_nil - expect(user_needs_migration_2.reload.confirmed_at).to be_nil - - expect(user_needs_migration_1.reload.confirmation_token).not_to be_nil - expect(user_needs_migration_2.reload.confirmation_token).not_to be_nil - end - - context 'enqueued jobs' do - let(:user_1) { User.find(user_needs_migration_1.id) } - let(:user_2) { User.find(user_needs_migration_2.id) } - - let(:email_1) { Email.find(bad_email_1.id) } - let(:email_2) { Email.find(bad_email_2.id) } - - it 'enqueues the email confirmation and the unconfirm notification mailer jobs' do - allow(DeviseMailer).to receive(:confirmation_instructions).and_call_original - allow(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to receive(:unconfirm_notification_email).and_call_original - - subject - - expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_1, email_1.confirmation_token) - expect(DeviseMailer).to have_received(:confirmation_instructions).with(email_2, email_2.confirmation_token) - - expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_1) - expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_1, user_1.confirmation_token) - - expect(Gitlab::BackgroundMigration::Mailers::UnconfirmMailer).to have_received(:unconfirm_notification_email).with(user_2) - expect(DeviseMailer).to have_received(:confirmation_instructions).with(user_2, user_2.confirmation_token) - end - end -end diff --git a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb index 902d8e13a63..fd8303c379c 100644 --- a/spec/lib/gitlab/database/migrations/instrumentation_spec.rb +++ b/spec/lib/gitlab/database/migrations/instrumentation_spec.rb @@ -66,55 +66,43 @@ RSpec.describe Gitlab::Database::Migrations::Instrumentation do context 'on successful execution' do subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) {} } - it 'records walltime' do + it 'records a valid observation', :aggregate_failures do expect(subject.walltime).not_to be_nil - end - - it 'records success' do expect(subject.success).to be_truthy - end - - it 'records the migration version' do expect(subject.version).to eq(migration_version) - end - - it 'records the migration name' do expect(subject.name).to eq(migration_name) end end context 'upon failure' do - subject { described_class.new(result_dir: result_dir).observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } } - - it 'raises the exception' do - expect { subject }.to raise_error(/something went wrong/) - end - - context 'retrieving observations' do - subject { instance.observations.first } - - before do - instance.observe(version: migration_version, name: migration_name, connection: connection) { raise 'something went wrong' } - rescue StandardError - # ignore - end + where(exception: ['something went wrong', SystemStackError, Interrupt]) + with_them do let(:instance) { described_class.new(result_dir: result_dir) } - it 'records walltime' do - expect(subject.walltime).not_to be_nil - end - - it 'records failure' do - expect(subject.success).to be_falsey - end + subject(:observe) { instance.observe(version: migration_version, name: migration_name, connection: connection) { raise exception } } - it 'records the migration version' do - expect(subject.version).to eq(migration_version) + it 'raises the exception' do + expect { observe }.to raise_error(exception) end - it 'records the migration name' do - expect(subject.name).to eq(migration_name) + context 'retrieving observations' do + subject { instance.observations.first } + + before do + observe + # rubocop:disable Lint/RescueException + rescue Exception + # rubocop:enable Lint/RescueException + # ignore (we expect this exception) + end + + it 'records a valid observation', :aggregate_failures do + expect(subject.walltime).not_to be_nil + expect(subject.success).to be_falsey + expect(subject.version).to eq(migration_version) + expect(subject.name).to eq(migration_name) + end end end end diff --git a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb index 5a19ae6581d..a757cac0a2a 100644 --- a/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb +++ b/spec/lib/gitlab/database/migrations/observers/query_details_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::QueryDetails do subject { described_class.new(observation, directory_path, connection) } let(:connection) { ActiveRecord::Migration.connection } - let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) } + let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) } let(:query) { "select date_trunc('day', $1::timestamptz) + $2 * (interval '1 hour')" } let(:query_binds) { [Time.current, 3] } let(:directory_path) { Dir.mktmpdir } diff --git a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb index 7b01e39f5f1..eb66972e5ab 100644 --- a/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb +++ b/spec/lib/gitlab/database/migrations/observers/query_log_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Gitlab::Database::Migrations::Observers::QueryLog do subject { described_class.new(observation, directory_path, connection) } - let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) } + let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) } let(:connection) { ActiveRecord::Migration.connection } let(:query) { 'select 1' } let(:directory_path) { Dir.mktmpdir } diff --git a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb index b26bb8fbe41..f433e25b2ba 100644 --- a/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb +++ b/spec/lib/gitlab/database/migrations/observers/transaction_duration_spec.rb @@ -5,7 +5,7 @@ RSpec.describe Gitlab::Database::Migrations::Observers::TransactionDuration do subject(:transaction_duration_observer) { described_class.new(observation, directory_path, connection) } let(:connection) { ActiveRecord::Migration.connection } - let(:observation) { Gitlab::Database::Migrations::Observation.new(migration_version, migration_name) } + let(:observation) { Gitlab::Database::Migrations::Observation.new(version: migration_version, name: migration_name) } let(:directory_path) { Dir.mktmpdir } let(:log_file) { "#{directory_path}/#{migration_version}_#{migration_name}-transaction-duration.json" } let(:transaction_duration) { Gitlab::Json.parse(File.read(log_file)) } diff --git a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb index 1a25824bc8a..6b3d18f20e9 100644 --- a/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb +++ b/spec/lib/gitlab/github_import/importer/releases_importer_spec.rb @@ -52,6 +52,12 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do expect { importer.execute }.to change { Release.count }.by(1) end + + it 'is idempotent' do + allow(importer).to receive(:each_release).and_return([github_release]) + expect { importer.execute }.to change { Release.count }.by(1) + expect { importer.execute }.to change { Release.count }.by(0) # Idempotency check + end end describe '#build_releases' do @@ -79,6 +85,24 @@ RSpec.describe Gitlab::GithubImport::Importer::ReleasesImporter do expect(release[:description]).to eq('Release for tag 1.0') end + + it 'does not create releases that have a NULL tag' do + null_tag_release = double( + name: 'NULL Test', + tag_name: nil + ) + + expect(importer).to receive(:each_release).and_return([null_tag_release]) + expect(importer.build_releases).to be_empty + end + + it 'does not create duplicate release tags' do + expect(importer).to receive(:each_release).and_return([github_release, github_release]) + + releases = importer.build_releases + expect(releases.length).to eq(1) + expect(releases[0][:description]).to eq('This is my release') + end end describe '#build' do diff --git a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb index 73b35d3a4e7..cbd1a30c417 100644 --- a/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb +++ b/spec/lib/gitlab/legacy_github_import/release_formatter_spec.rb @@ -63,5 +63,13 @@ RSpec.describe Gitlab::LegacyGithubImport::ReleaseFormatter do expect(release.valid?).to eq false end end + + context 'when release has NULL tag' do + let(:raw_data) { double(base_data.merge(tag_name: '')) } + + it 'returns false' do + expect(release.valid?).to eq false + end + end end end diff --git a/spec/models/merge_request_spec.rb b/spec/models/merge_request_spec.rb index 9da22e15a12..e1f3b36a2ba 100644 --- a/spec/models/merge_request_spec.rb +++ b/spec/models/merge_request_spec.rb @@ -1369,17 +1369,17 @@ RSpec.describe MergeRequest, factory_default: :keep do subject { build_stubbed(:merge_request) } [ - 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:', 'draft:', 'Draft: ', '[Draft]', '[DRAFT] ' - ].each do |wip_prefix| - it "detects the '#{wip_prefix}' prefix" do - subject.title = "#{wip_prefix}#{subject.title}" + ].each do |draft_prefix| + it "detects the '#{draft_prefix}' prefix" do + subject.title = "#{draft_prefix}#{subject.title}" expect(subject.work_in_progress?).to eq true end end [ + 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', ' [WIP] WIP: [WIP] WIP:', "WIP ", "(WIP)", "draft", "Draft", "Draft -", "draft - ", "Draft ", "draft " ].each do |draft_prefix| @@ -1390,10 +1390,10 @@ RSpec.describe MergeRequest, factory_default: :keep do end end - it "detects merge request title just saying 'wip'" do + it "doesn't detect merge request title just saying 'wip'" do subject.title = "wip" - expect(subject.work_in_progress?).to eq true + expect(subject.work_in_progress?).to eq false end it "does not detect merge request title just saying 'draft'" do @@ -1459,29 +1459,30 @@ RSpec.describe MergeRequest, factory_default: :keep do describe "#wipless_title" do subject { build_stubbed(:merge_request) } - [ - 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:', - 'draft:', 'Draft: ', '[Draft]', '[DRAFT] ' - ].each do |wip_prefix| - it "removes the '#{wip_prefix}' prefix" do + ['draft:', 'Draft: ', '[Draft]', '[DRAFT] '].each do |draft_prefix| + it "removes a '#{draft_prefix}' prefix" do wipless_title = subject.title - subject.title = "#{wip_prefix}#{subject.title}" + subject.title = "#{draft_prefix}#{subject.title}" expect(subject.wipless_title).to eq wipless_title end it "is satisfies the #work_in_progress? method" do - subject.title = "#{wip_prefix}#{subject.title}" + subject.title = "#{draft_prefix}#{subject.title}" subject.title = subject.wipless_title expect(subject.work_in_progress?).to eq false end end - it 'removes only WIP prefix from the MR title' do - subject.title = 'WIP: Implement feature called WIP' + [ + 'WIP:', 'WIP: ', '[WIP]', '[WIP] ', '[WIP] WIP: [WIP] WIP:' + ].each do |wip_prefix| + it "doesn't remove a '#{wip_prefix}' prefix" do + subject.title = "#{wip_prefix}#{subject.title}" - expect(subject.wipless_title).to eq 'Implement feature called WIP' + expect(subject.wipless_title).to eq subject.title + end end it 'removes only draft prefix from the MR title' do diff --git a/spec/services/merge_requests/create_service_spec.rb b/spec/services/merge_requests/create_service_spec.rb index da547716e1e..a196c944eda 100644 --- a/spec/services/merge_requests/create_service_spec.rb +++ b/spec/services/merge_requests/create_service_spec.rb @@ -61,19 +61,19 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do expect(merge_request.reload).to be_preparing end - describe 'when marked with /wip' do + describe 'when marked with /draft' do context 'in title and in description' do let(:opts) do { - title: 'WIP: Awesome merge_request', - description: "well this is not done yet\n/wip", + title: 'Draft: Awesome merge_request', + description: "well this is not done yet\n/draft", source_branch: 'feature', target_branch: 'master', assignees: [user2] } end - it 'sets MR to WIP' do + it 'sets MR to draft' do expect(merge_request.work_in_progress?).to be(true) end end @@ -89,7 +89,7 @@ RSpec.describe MergeRequests::CreateService, :clean_gitlab_redis_shared_state do } end - it 'sets MR to WIP' do + it 'sets MR to draft' do expect(merge_request.work_in_progress?).to be(true) end end diff --git a/spec/services/merge_requests/mergeability_check_service_spec.rb b/spec/services/merge_requests/mergeability_check_service_spec.rb index 65599b7e046..c24b83e21a6 100644 --- a/spec/services/merge_requests/mergeability_check_service_spec.rb +++ b/spec/services/merge_requests/mergeability_check_service_spec.rb @@ -73,12 +73,10 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar let(:merge_request) { create(:merge_request, merge_status: :unchecked, source_project: project, target_project: project) } describe '#async_execute' do - shared_examples_for 'no job is enqueued' do - it 'does not enqueue MergeRequestMergeabilityCheckWorker' do - expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async) + it 'updates merge status to checking' do + described_class.new(merge_request).async_execute - described_class.new(merge_request).async_execute - end + expect(merge_request).to be_checking end it 'enqueues MergeRequestMergeabilityCheckWorker' do @@ -92,15 +90,11 @@ RSpec.describe MergeRequests::MergeabilityCheckService, :clean_gitlab_redis_shar allow(Gitlab::Database).to receive(:read_only?) { true } end - it_behaves_like 'no job is enqueued' - end + it 'does not enqueue MergeRequestMergeabilityCheckWorker' do + expect(MergeRequestMergeabilityCheckWorker).not_to receive(:perform_async) - context 'when merge_status is already checking' do - before do - merge_request.mark_as_checking + described_class.new(merge_request).async_execute end - - it_behaves_like 'no job is enqueued' end end diff --git a/spec/services/merge_requests/update_service_spec.rb b/spec/services/merge_requests/update_service_spec.rb index 2925dad7f6b..48d9f019274 100644 --- a/spec/services/merge_requests/update_service_spec.rb +++ b/spec/services/merge_requests/update_service_spec.rb @@ -102,16 +102,16 @@ RSpec.describe MergeRequests::UpdateService, :mailer do MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2) end - it 'tracks Draft/WIP marking' do + it 'tracks Draft marking' do expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter) .to receive(:track_marked_as_draft_action).once.with(user: user) - opts[:title] = "WIP: #{opts[:title]}" + opts[:title] = "Draft: #{opts[:title]}" MergeRequests::UpdateService.new(project: project, current_user: user, params: opts).execute(merge_request2) end - it 'tracks Draft/WIP un-marking' do + it 'tracks Draft un-marking' do expect(Gitlab::UsageDataCounters::MergeRequestActivityUniqueCounter) .to receive(:track_unmarked_as_draft_action).once.with(user: user) diff --git a/spec/services/notes/create_service_spec.rb b/spec/services/notes/create_service_spec.rb index 1fb50b07b3b..babbd44a9f1 100644 --- a/spec/services/notes/create_service_spec.rb +++ b/spec/services/notes/create_service_spec.rb @@ -325,11 +325,11 @@ RSpec.describe Notes::CreateService do expect(issuable.work_in_progress?).to eq(can_use_quick_action) } ), - # Remove WIP status + # Remove draft status QuickAction.new( action_text: "/draft", before_action: -> { - issuable.reload.update!(title: "WIP: title") + issuable.reload.update!(title: "Draft: title") }, expectation: ->(noteable, can_use_quick_action) { expect(noteable.work_in_progress?).not_to eq(can_use_quick_action) |