diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-18 00:13:54 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-10-18 00:13:54 +0300 |
commit | c766b837cfcba1a652b781f1f725ae034c9755e1 (patch) | |
tree | a97ee56aa9ce37e51e5b5d40f586bed2ed4647a7 /spec | |
parent | 5cbf24858edb03505b16474e3b7b41a49b677ff6 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
23 files changed, 297 insertions, 137 deletions
diff --git a/spec/factories/integrations.rb b/spec/factories/integrations.rb index 0f61558e203..68751e68f05 100644 --- a/spec/factories/integrations.rb +++ b/spec/factories/integrations.rb @@ -39,7 +39,7 @@ FactoryBot.define do recipients { 'foo@bar.com' } disable_diffs { true } send_from_committer_email { true } - branches_to_be_notified { nil } + branches_to_be_notified { 'all' } end factory :gitlab_slack_application_integration, class: 'Integrations::GitlabSlackApplication' do diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb index b1e7866f9ce..fcba413e802 100644 --- a/spec/factories/notes.rb +++ b/spec/factories/notes.rb @@ -18,7 +18,8 @@ FactoryBot.define do factory :note_on_personal_snippet, traits: [:on_personal_snippet] factory :note_on_design, traits: [:on_design] factory :note_on_alert, traits: [:on_alert] - factory :system_note, traits: [:system] + factory :note_on_abuse_report, traits: [:on_abuse_report] + factory :system_note, traits: [:system] factory :discussion_note, class: 'DiscussionNote' @@ -39,6 +40,8 @@ FactoryBot.define do factory :discussion_note_on_project_snippet, traits: [:on_project_snippet], class: 'DiscussionNote' + factory :discussion_note_on_abuse_report, traits: [:on_abuse_report], class: 'DiscussionNote' + factory :legacy_diff_note_on_commit, traits: [:on_commit, :legacy_diff_note], class: 'LegacyDiffNote' factory :legacy_diff_note_on_merge_request, traits: [:on_merge_request, :legacy_diff_note], class: 'LegacyDiffNote' do @@ -166,6 +169,11 @@ FactoryBot.define do noteable { association(:alert_management_alert, project: project) } end + trait :on_abuse_report do + noteable { association(:abuse_report) } + project { nil } + end + trait :resolved do resolved_at { Time.now } resolved_by { association(:user) } diff --git a/spec/factories/users/credit_card_validations.rb b/spec/factories/users/credit_card_validations.rb index 509e86e7bd3..fac53a54c12 100644 --- a/spec/factories/users/credit_card_validations.rb +++ b/spec/factories/users/credit_card_validations.rb @@ -4,7 +4,7 @@ FactoryBot.define do factory :credit_card_validation, class: 'Users::CreditCardValidation' do user sequence(:credit_card_validated_at) { |n| Time.current + n } - expiration_date { 1.year.from_now.end_of_month } + expiration_date { 1.year.from_now.to_date } last_digits { 10 } holder_name { 'John Smith' } network { 'AmericanExpress' } diff --git a/spec/frontend/admin/abuse_report/components/user_details_spec.js b/spec/frontend/admin/abuse_report/components/user_details_spec.js index f3d8d5bb610..24ec0cdb1b2 100644 --- a/spec/frontend/admin/abuse_report/components/user_details_spec.js +++ b/spec/frontend/admin/abuse_report/components/user_details_spec.js @@ -70,14 +70,6 @@ describe('UserDetails', () => { expect(findUserDetailLabel('credit-card-verification')).toBe(USER_DETAILS_I18N.creditCard); }); - it('renders the users name', () => { - expect(findUserDetail('credit-card-verification').text()).toContain( - sprintf(USER_DETAILS_I18N.registeredWith, { ...user.creditCard }), - ); - - expect(findUserDetail('credit-card-verification').text()).toContain(user.creditCard.name); - }); - describe('similar credit cards', () => { it('renders the number of similar records', () => { expect(findUserDetail('credit-card-verification').text()).toContain( diff --git a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js index 0ed2e51e8c3..7c8cc1bb38d 100644 --- a/spec/frontend/projects/settings/components/new_access_dropdown_spec.js +++ b/spec/frontend/projects/settings/components/new_access_dropdown_spec.js @@ -14,11 +14,13 @@ import AccessDropdown, { i18n } from '~/projects/settings/components/access_drop import { ACCESS_LEVELS, LEVEL_TYPES } from '~/projects/settings/constants'; jest.mock('~/projects/settings/api/access_dropdown_api', () => ({ - getGroups: jest.fn().mockResolvedValue([ - { id: 4, name: 'group4' }, - { id: 5, name: 'group5' }, - { id: 6, name: 'group6' }, - ]), + getGroups: jest.fn().mockResolvedValue({ + data: [ + { id: 4, name: 'group4' }, + { id: 5, name: 'group5' }, + { id: 6, name: 'group6' }, + ], + }), getUsers: jest.fn().mockResolvedValue({ data: [ { id: 7, name: 'user7' }, diff --git a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js index 46a1c18f16f..b4c90fe49d1 100644 --- a/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js +++ b/spec/frontend/vue_shared/components/markdown/markdown_editor_spec.js @@ -7,6 +7,8 @@ import { EDITING_MODE_MARKDOWN_FIELD, EDITING_MODE_CONTENT_EDITOR, CLEAR_AUTOSAVE_ENTRY_EVENT, + CONTENT_EDITOR_READY_EVENT, + MARKDOWN_EDITOR_READY_EVENT, } from '~/vue_shared/constants'; import markdownEditorEventHub from '~/vue_shared/components/markdown/eventhub'; import MarkdownEditor from '~/vue_shared/components/markdown/markdown_editor.vue'; @@ -83,22 +85,23 @@ describe('vue_shared/component/markdown/markdown_editor', () => { const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync); const findContentEditor = () => { const result = wrapper.findComponent(ContentEditor); - // In Vue.js 3 there are nuances stubbing component with custom stub on mount // So we try to search for stub also return result.exists() ? result : wrapper.findComponent(ContentEditorStub); }; - const enableContentEditor = async () => { - findMarkdownField().vm.$emit('enableContentEditor'); - await nextTick(); - await waitForPromises(); + const enableContentEditor = () => { + return new Promise((resolve) => { + markdownEditorEventHub.$once(CONTENT_EDITOR_READY_EVENT, resolve); + findMarkdownField().vm.$emit('enableContentEditor'); + }); }; - const enableMarkdownEditor = async () => { - findContentEditor().vm.$emit('enableMarkdownEditor'); - await nextTick(); - await waitForPromises(); + const enableMarkdownEditor = () => { + return new Promise((resolve) => { + markdownEditorEventHub.$once(MARKDOWN_EDITOR_READY_EVENT, resolve); + findContentEditor().vm.$emit('enableMarkdownEditor'); + }); }; beforeEach(() => { @@ -128,9 +131,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => { }); }); - // quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/412618 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('passes render_quick_actions param to renderMarkdownPath if quick actions are enabled', async () => { + it('passes render_quick_actions param to renderMarkdownPath if quick actions are enabled', async () => { buildWrapper({ propsData: { supportsQuickActions: true } }); await enableContentEditor(); @@ -139,9 +140,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => { expect(mock.history.post[0].url).toContain(`render_quick_actions=true`); }); - // quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/411565 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('does not pass render_quick_actions param to renderMarkdownPath if quick actions are disabled', async () => { + it('does not pass render_quick_actions param to renderMarkdownPath if quick actions are disabled', async () => { buildWrapper({ propsData: { supportsQuickActions: false } }); await enableContentEditor(); @@ -213,9 +212,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => { expect(findMarkdownField().find('textarea').attributes('disabled')).toBe(undefined); }); - // quarantine: https://gitlab.com/gitlab-org/gitlab/-/issues/404734 - // eslint-disable-next-line jest/no-disabled-tests - it.skip('disables content editor when disabled prop is true', async () => { + it('disables content editor when disabled prop is true', async () => { buildWrapper({ propsData: { disabled: true } }); await enableContentEditor(); @@ -358,9 +355,7 @@ describe('vue_shared/component/markdown/markdown_editor', () => { }); it(`emits ${EDITING_MODE_MARKDOWN_FIELD} event when enableMarkdownEditor emitted from content editor`, async () => { - buildWrapper({ - stubs: { ContentEditor: ContentEditorStub }, - }); + buildWrapper(); await enableContentEditor(); await enableMarkdownEditor(); diff --git a/spec/frontend/work_items/mock_data.js b/spec/frontend/work_items/mock_data.js index fc405f626c6..bd210a03b21 100644 --- a/spec/frontend/work_items/mock_data.js +++ b/spec/frontend/work_items/mock_data.js @@ -194,6 +194,7 @@ export const workItemQueryResponse = { confidential: false, title: '123', state: 'OPEN', + webUrl: '/gitlab-org/gitlab-test/-/work_items/4', workItemType: { id: '1', name: 'Task', @@ -271,6 +272,7 @@ export const updateWorkItemMutationResponse = { confidential: false, title: '123', state: 'OPEN', + webUrl: '/gitlab-org/gitlab-test/-/work_items/4', workItemType: { id: '1', name: 'Task', @@ -381,6 +383,7 @@ export const convertWorkItemMutationResponse = { confidential: false, title: '123', state: 'OPEN', + webUrl: '/gitlab-org/gitlab-test/-/work_items/4', workItemType: { id: '1', name: 'Task', @@ -765,6 +768,7 @@ export const workItemResponseFactory = ({ confidential: false, title: '123', state: 'OPEN', + webUrl: '/gitlab-org/gitlab-test/-/work_items/5', workItemType: { id: '1', name: 'Task', @@ -1092,6 +1096,7 @@ export const workItemHierarchyNoUpdatePermissionResponse = { confidential: false, createdAt: '2022-08-03T12:41:54Z', closedAt: null, + webUrl: '/gitlab-org/gitlab-test/-/work_items/2', widgets: [ { type: 'HIERARCHY', @@ -1144,6 +1149,7 @@ export const confidentialWorkItemTask = { confidential: true, createdAt: '2022-08-03T12:41:54Z', closedAt: null, + webUrl: '/gitlab-org/gitlab-test/-/work_items/2', widgets: [], __typename: 'WorkItem', }; @@ -1162,6 +1168,7 @@ export const closedWorkItemTask = { confidential: false, createdAt: '2022-08-03T12:41:54Z', closedAt: '2022-08-12T13:07:52Z', + webUrl: '/gitlab-org/gitlab-test/-/work_items/3', widgets: [], __typename: 'WorkItem', }; @@ -1184,6 +1191,7 @@ export const childrenWorkItems = [ confidential: false, createdAt: '2022-08-03T12:41:54Z', closedAt: null, + webUrl: '/gitlab-org/gitlab-test/-/work_items/5', widgets: [], __typename: 'WorkItem', }, @@ -1422,6 +1430,7 @@ export const workItemHierarchyTreeResponse = { confidential: false, createdAt: '2022-08-03T12:41:54Z', closedAt: null, + webUrl: '/gitlab-org/gitlab-test/-/work_items/13', widgets: [ { type: 'HIERARCHY', diff --git a/spec/lib/gitlab/checks/global_file_size_check_spec.rb b/spec/lib/gitlab/checks/global_file_size_check_spec.rb index a2b3ee0f761..9e25af30707 100644 --- a/spec/lib/gitlab/checks/global_file_size_check_spec.rb +++ b/spec/lib/gitlab/checks/global_file_size_check_spec.rb @@ -34,7 +34,10 @@ RSpec.describe Gitlab::Checks::GlobalFileSizeCheck, feature_category: :source_co end context 'when there are oversized blobs' do - let(:blob_double) { instance_double(Gitlab::Git::Blob, size: 10) } + mock_blob_id = "88acbfafb1b8fdb7c51db870babce21bd861ac4f" + mock_blob_size = 300 * 1024 * 1024 # 300 MiB + size_msg = (mock_blob_size / 1024.0 / 1024.0).round(2).to_s + let(:blob_double) { instance_double(Gitlab::Git::Blob, size: mock_blob_size, id: mock_blob_id) } before do allow_next_instance_of(Gitlab::Checks::FileSizeCheck::HookEnvironmentAwareAnyOversizedBlobs, @@ -48,8 +51,15 @@ RSpec.describe Gitlab::Checks::GlobalFileSizeCheck, feature_category: :source_co it 'logs a message with blob size and raises an exception' do expect(Gitlab::AppJsonLogger).to receive(:info).with('Checking for blobs over the file size limit') - expect(Gitlab::AppJsonLogger).to receive(:info).with(message: 'Found blob over global limit', blob_sizes: [10]) - expect { subject.validate! }.to raise_exception(Gitlab::GitAccess::ForbiddenError) + expect(Gitlab::AppJsonLogger).to receive(:info).with( + message: 'Found blob over global limit', + blob_sizes: [mock_blob_size], + blob_details: { mock_blob_id => { "size" => mock_blob_size } } + ) + expect do + subject.validate! + end.to raise_exception(Gitlab::GitAccess::ForbiddenError, + /- #{mock_blob_id} \(#{size_msg} MiB\)/) end context 'when the enforce_global_file_size_limit feature flag is disabled' do diff --git a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb index b807f6cd784..c6cd5e55754 100644 --- a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb +++ b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb @@ -23,8 +23,6 @@ RSpec.describe 'cross-database foreign keys' do 'merge_requests.merge_user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/422080 'merge_requests.author_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/422080 'project_authorizations.user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/422044 - 'projects.creator_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/421844 - 'projects.marked_for_deletion_by_user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/421844 'user_group_callouts.user_id' # https://gitlab.com/gitlab-org/gitlab/-/issues/421287 ] end diff --git a/spec/lib/gitlab/diff/position_tracer_spec.rb b/spec/lib/gitlab/diff/position_tracer_spec.rb index 4aa4f160fc9..059058c5499 100644 --- a/spec/lib/gitlab/diff/position_tracer_spec.rb +++ b/spec/lib/gitlab/diff/position_tracer_spec.rb @@ -116,5 +116,71 @@ RSpec.describe Gitlab::Diff::PositionTracer do expect(diff_refs.head_sha).to eq(new_diff_refs.head_sha) end end + + describe 'when requesting diffs' do + shared_examples 'it does not call diff stats' do + it 'does not call diff stats' do + expect_next_instance_of(Gitlab::GitalyClient::CommitService) do |instance| + expect(instance).not_to receive(:diff_stats) + end + + diff_files + end + end + + shared_examples 'it calls diff stats' do + it 'calls diff stats' do + expect_next_instance_of(Gitlab::GitalyClient::CommitService) do |instance| + expect(instance).to receive(:diff_stats).and_call_original + end + + diff_files + end + end + + context 'when remove_request_stats_for_tracing is true' do + context 'ac diffs' do + let(:diff_files) { subject.ac_diffs.diff_files } + + it_behaves_like 'it does not call diff stats' + end + + context 'bd diffs' do + let(:diff_files) { subject.bd_diffs.diff_files } + + it_behaves_like 'it does not call diff stats' + end + + context 'cd diffs' do + let(:diff_files) { subject.cd_diffs.diff_files } + + it_behaves_like 'it does not call diff stats' + end + end + + context 'when remove_request_stats_for_tracing is false' do + before do + stub_feature_flags(remove_request_stats_for_tracing: false) + end + + context 'ac diffs' do + let(:diff_files) { subject.ac_diffs.diff_files } + + it_behaves_like 'it calls diff stats' + end + + context 'bd diffs' do + let(:diff_files) { subject.bd_diffs.diff_files } + + it_behaves_like 'it calls diff stats' + end + + context 'cd diffs' do + let(:diff_files) { subject.cd_diffs.diff_files } + + it_behaves_like 'it calls diff stats' + end + end + end end end diff --git a/spec/lib/gitlab/i18n_spec.rb b/spec/lib/gitlab/i18n_spec.rb index ee92831922d..fdd868acbb1 100644 --- a/spec/lib/gitlab/i18n_spec.rb +++ b/spec/lib/gitlab/i18n_spec.rb @@ -62,4 +62,18 @@ RSpec.describe Gitlab::I18n, feature_category: :internationalization do end end end + + describe '.trimmed_language_name' do + it 'trims the language name', :aggregate_failures do + expect(described_class.trimmed_language_name('en')).to eq('English') + expect(described_class.trimmed_language_name('bg')).to eq('Bulgarian') + expect(described_class.trimmed_language_name('id_ID')).to eq('Indonesian') + expect(described_class.trimmed_language_name('nb_NO')).to eq('Norwegian (Bokmål)') + expect(described_class.trimmed_language_name('zh_HK')).to eq('Chinese, Traditional (Hong Kong)') + end + + it 'return nil for unknown language code' do + expect(described_class.trimmed_language_name('_invalid_code_')).to be_nil + end + end end diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb index e2e7e042ebc..68eb38a1335 100644 --- a/spec/lib/gitlab/url_builder_spec.rb +++ b/spec/lib/gitlab/url_builder_spec.rb @@ -60,7 +60,8 @@ RSpec.describe Gitlab::UrlBuilder do :discussion_note_on_project_snippet | ->(note) { "/#{note.project.full_path}/-/snippets/#{note.noteable_id}#note_#{note.id}" } :discussion_note_on_personal_snippet | ->(note) { "/-/snippets/#{note.noteable_id}#note_#{note.id}" } :note_on_personal_snippet | ->(note) { "/-/snippets/#{note.noteable_id}#note_#{note.id}" } - :package | ->(package) { "/#{package.project.full_path}/-/packages/#{package.id}" } + :note_on_abuse_report | ->(note) { "/admin/abuse_reports/#{note.noteable_id}#note_#{note.id}" } + :package | ->(package) { "/#{package.project.full_path}/-/packages/#{package.id}" } end with_them do diff --git a/spec/models/abuse/reports/user_mention_spec.rb b/spec/models/abuse/reports/user_mention_spec.rb new file mode 100644 index 00000000000..c5048134382 --- /dev/null +++ b/spec/models/abuse/reports/user_mention_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Abuse::Reports::UserMention, feature_category: :insider_threat do + describe 'associations' do + it { is_expected.to belong_to(:abuse_report).optional(false) } + it { is_expected.to belong_to(:note).optional(false) } + end + + it_behaves_like 'has user mentions' +end diff --git a/spec/models/abuse_report_spec.rb b/spec/models/abuse_report_spec.rb index 1bfe9517447..6500e5fac02 100644 --- a/spec/models/abuse_report_spec.rb +++ b/spec/models/abuse_report_spec.rb @@ -18,6 +18,8 @@ RSpec.describe AbuseReport, feature_category: :insider_threat do it { is_expected.to belong_to(:assignee).class_name('User').inverse_of(:assigned_abuse_reports) } it { is_expected.to belong_to(:user).inverse_of(:abuse_reports) } it { is_expected.to have_many(:events).class_name('ResourceEvents::AbuseReportEvent').inverse_of(:abuse_report) } + it { is_expected.to have_many(:notes) } + it { is_expected.to have_many(:user_mentions).class_name('Abuse::Reports::UserMention') } it "aliases reporter to author" do expect(subject.author).to be(subject.reporter) diff --git a/spec/models/concerns/noteable_spec.rb b/spec/models/concerns/noteable_spec.rb index dd180749e94..82c63eea33a 100644 --- a/spec/models/concerns/noteable_spec.rb +++ b/spec/models/concerns/noteable_spec.rb @@ -493,4 +493,24 @@ RSpec.describe Noteable, feature_category: :code_review_workflow do end end end + + describe '#supports_resolvable_notes' do + context 'when noteable is an abuse report' do + let(:abuse_report) { build(:abuse_report) } + + it 'returns true' do + expect(abuse_report.supports_resolvable_notes?).to be(true) + end + end + end + + describe '#supports_replying_to_individual_notes' do + context 'when noteable is an abuse report' do + let(:abuse_report) { build(:abuse_report) } + + it 'returns true' do + expect(abuse_report.supports_replying_to_individual_notes?).to be(true) + end + end + end end diff --git a/spec/models/discussion_note_spec.rb b/spec/models/discussion_note_spec.rb index 6e1b39cc438..09adf4a95b5 100644 --- a/spec/models/discussion_note_spec.rb +++ b/spec/models/discussion_note_spec.rb @@ -8,4 +8,12 @@ RSpec.describe DiscussionNote do it { is_expected.to eq('note') } end + + describe 'validations' do + context 'when noteable is an abuse report' do + subject { build(:discussion_note, noteable: build_stubbed(:abuse_report)) } + + it { is_expected.to be_valid } + end + end end diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb index 331acc5dedb..5aa3ac3a2ea 100644 --- a/spec/models/note_spec.rb +++ b/spec/models/note_spec.rb @@ -81,6 +81,14 @@ RSpec.describe Note, feature_category: :team_planning do end end + context 'when noteable is an abuse report' do + subject { build(:note, noteable: build_stubbed(:abuse_report), project: nil, namespace: nil) } + + it 'is valid without project or namespace' do + is_expected.to be_valid + end + end + describe 'max notes limit' do let_it_be(:noteable) { create(:issue) } let_it_be(:existing_note) { create(:note, project: noteable.project, noteable: noteable) } @@ -1350,6 +1358,20 @@ RSpec.describe Note, feature_category: :team_planning do end end + describe '#for_abuse_report' do + it 'is true when the noteable is an abuse report' do + note = build(:note, noteable: build(:abuse_report)) + + expect(note).to be_for_abuse_report + end + + it 'is not true when the noteable is not an abuse report' do + note = build(:note, noteable: build(:design)) + + expect(note).not_to be_for_abuse_report + end + end + describe '#to_ability_name' do it 'returns note' do expect(build(:note).to_ability_name).to eq('note') diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 1a0fc34a1cd..c27ed2cc82c 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -9168,4 +9168,11 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr name: name ) end + + context 'with loose foreign key on projects.creator_id' do + it_behaves_like 'cleanup by a loose foreign key' do + let_it_be(:parent) { create(:user) } + let_it_be(:model) { create(:project, creator: parent) } + end + end end diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb index 486d1c6d3ea..7faddb2384c 100644 --- a/spec/models/users/credit_card_validation_spec.rb +++ b/spec/models/users/credit_card_validation_spec.rb @@ -15,41 +15,43 @@ RSpec.describe Users::CreditCardValidation, feature_category: :user_profile do it { is_expected.to validate_length_of(:network_hash).is_at_most(44) } describe '#similar_records' do - let(:card_details) do - subject.attributes.with_indifferent_access.slice(:expiration_date, :last_digits, :network, :holder_name) + let_it_be(:credit_card_validation) { create(:credit_card_validation) } + + let_it_be(:card_details) do + credit_card_validation.attributes.with_indifferent_access.slice( + :expiration_date, :last_digits, :network, :holder_name + ) end - subject!(:credit_card_validation) { create(:credit_card_validation, holder_name: 'Alice') } + let_it_be(:match_1) { create(:credit_card_validation, card_details) } + let_it_be(:match_2) { create(:credit_card_validation, card_details.merge(holder_name: 'Bob')) } - let!(:match1) { create(:credit_card_validation, card_details) } - let!(:match2) { create(:credit_card_validation, card_details.merge(holder_name: 'Bob')) } - let!(:non_match1) { create(:credit_card_validation, card_details.merge(last_digits: 9)) } - let!(:non_match2) { create(:credit_card_validation, card_details.merge(network: 'unknown')) } - let!(:non_match3) do - create(:credit_card_validation, card_details.dup.tap { |h| h[:expiration_date] += 1.year }) + let_it_be(:non_match_1) { create(:credit_card_validation, card_details.merge(last_digits: 9999)) } + let_it_be(:non_match_2) { create(:credit_card_validation, card_details.merge(network: 'Mastercard')) } + let_it_be(:non_match_3) do + create(:credit_card_validation, card_details.merge(expiration_date: 2.years.from_now.to_date)) end it 'returns matches with the same last_digits, expiration and network, ordered by credit_card_validated_at' do - expect(subject.similar_records).to eq([match2, match1, subject]) + # eq is used instead of match_array because rows are sorted by credit_card_validated_at in desc order + expect(credit_card_validation.similar_records).to eq([match_2, match_1, credit_card_validation]) end end describe '#similar_holder_names_count' do - subject!(:credit_card_validation) { create(:credit_card_validation, holder_name: holder_name) } - context 'when holder_name is present' do - let(:holder_name) { 'ALICE M SMITH' } + let_it_be(:credit_card_validation) { create(:credit_card_validation, holder_name: 'ALICE M SMITH') } - let!(:match) { create(:credit_card_validation, holder_name: 'Alice M Smith') } - let!(:non_match) { create(:credit_card_validation, holder_name: 'Bob B Brown') } + let_it_be(:match) { create(:credit_card_validation, holder_name: 'Alice M Smith') } + let_it_be(:non_match) { create(:credit_card_validation, holder_name: 'Bob B Brown') } it 'returns the count of cards with similar case insensitive holder names' do - expect(subject.similar_holder_names_count).to eq(2) + expect(credit_card_validation.similar_holder_names_count).to eq(2) end end context 'when holder_name is nil' do - let(:holder_name) { nil } + let_it_be(:credit_card_validation) { create(:credit_card_validation, holder_name: nil) } it 'returns 0' do expect(subject.similar_holder_names_count).to eq(0) @@ -75,104 +77,117 @@ RSpec.describe Users::CreditCardValidation, feature_category: :user_profile do end describe '.by_banned_user' do - let(:banned_user) { create(:banned_user) } - let!(:credit_card) { create(:credit_card_validation) } - let!(:banned_user_credit_card) { create(:credit_card_validation, user: banned_user.user) } + subject(:by_banned_user) { described_class.by_banned_user } + + let_it_be(:banned_user) { create(:banned_user) } + let_it_be(:credit_card) { create(:credit_card_validation) } + let_it_be(:banned_user_credit_card) { create(:credit_card_validation, user: banned_user.user) } it 'returns only records associated to banned users' do - expect(described_class.by_banned_user).to match_array([banned_user_credit_card]) + expect(by_banned_user).to match_array([banned_user_credit_card]) end end describe '.similar_by_holder_name' do - let!(:credit_card) { create(:credit_card_validation, holder_name: 'CARD MCHODLER') } - let!(:credit_card2) { create(:credit_card_validation, holder_name: 'RICHIE RICH') } + subject(:similar_by_holder_name) { described_class.similar_by_holder_name(holder_name_hash) } - it 'returns only records that case-insensitive match the given holder name' do - expect(described_class.similar_by_holder_name('card mchodler')).to match_array([credit_card]) - end + let_it_be(:credit_card_validation) { create(:credit_card_validation, holder_name: 'Alice M Smith') } + let_it_be(:match) { create(:credit_card_validation, holder_name: 'ALICE M SMITH') } + + context 'when holder_name_hash is present' do + let_it_be(:holder_name_hash) { credit_card_validation.holder_name_hash } - context 'when given holder name is falsey' do - it 'returns [] when given holder name is ""' do - expect(described_class.similar_by_holder_name('')).to match_array([]) + it 'returns records with similar holder names case-insensitively' do + expect(similar_by_holder_name).to match_array([credit_card_validation, match]) end + end + + context 'when holder_name_hash is nil' do + let_it_be(:holder_name_hash) { nil } - it 'returns [] when given holder name is nil' do - expect(described_class.similar_by_holder_name(nil)).to match_array([]) + it 'returns an empty array' do + expect(similar_by_holder_name).to match_array([]) end end end describe '.similar_to' do - let(:credit_card) { create(:credit_card_validation) } + subject(:similar_to) { described_class.similar_to(credit_card_validation) } + + let_it_be(:credit_card_validation) { create(:credit_card_validation) } - let!(:credit_card2) do + let_it_be(:match) do create(:credit_card_validation, - expiration_date: credit_card.expiration_date, - last_digits: credit_card.last_digits, - network: credit_card.network + expiration_date: credit_card_validation.expiration_date, + last_digits: credit_card_validation.last_digits, + network: credit_card_validation.network ) end - let!(:credit_card3) do + let_it_be(:non_match) do create(:credit_card_validation, - expiration_date: credit_card.expiration_date, - last_digits: credit_card.last_digits, - network: 'UnknownCCNetwork' + expiration_date: credit_card_validation.expiration_date, + last_digits: credit_card_validation.last_digits, + network: 'Mastercard' ) end it 'returns only records with similar expiration_date, last_digits, and network attribute values' do - expect(described_class.similar_to(credit_card)).to match_array([credit_card, credit_card2]) + expect(similar_to).to match_array([credit_card_validation, match]) end end end describe '#used_by_banned_user?' do - let(:credit_card_details) do - { - holder_name: 'Christ McLovin', - expiration_date: 2.years.from_now.end_of_month, - last_digits: 4242, - network: 'Visa' - } - end - - let!(:credit_card) { create(:credit_card_validation, credit_card_details) } + subject(:used_by_banned_user) { credit_card_validation.used_by_banned_user? } - subject { credit_card } + let_it_be(:credit_card_validation) { create(:credit_card_validation) } - context 'when there is a similar credit card associated to a banned user' do - let_it_be(:banned_user) { create(:banned_user) } - - let(:attrs) { credit_card_details.merge({ user: banned_user.user }) } - let!(:similar_credit_card) { create(:credit_card_validation, attrs) } + let_it_be(:card_details) do + credit_card_validation.attributes.with_indifferent_access.slice( + :expiration_date, :last_digits, :network, :holder_name + ) + end - it { is_expected.to be_used_by_banned_user } + let_it_be(:banned_user) { create(:banned_user) } - context 'when holder names do not match' do - let!(:similar_credit_card) do - create(:credit_card_validation, attrs.merge({ holder_name: 'Mary Goody' })) + context 'when there is a similar credit card associated to a banned user' do + context 'when holder names match exactly' do + before do + create(:credit_card_validation, card_details.merge(user: banned_user.user)) end - it { is_expected.not_to be_used_by_banned_user } + it { is_expected.to be(true) } end - context 'when .similar_to returns nothing' do - let!(:similar_credit_card) do - create(:credit_card_validation, attrs.merge({ network: 'DifferentNetwork' })) + context 'when holder names do not match exactly' do + before do + create(:credit_card_validation, card_details.merge(user: banned_user.user, holder_name: 'John M Smith')) end - it { is_expected.not_to be_used_by_banned_user } + it { is_expected.to be(false) } end end - context 'when there is a similar credit card not associated to a banned user' do - let!(:similar_credit_card) do - create(:credit_card_validation, credit_card_details) + context 'when there are no similar credit cards associated to a banned user' do + before do + create(:credit_card_validation, + user: banned_user.user, + network: 'Mastercard', + last_digits: 1111, + holder_name: 'Jane Smith' + ) + end + + it { is_expected.to be(false) } + end + + context 'when there is a similar credit card but it is not associated to a banned user' do + before do + create(:credit_card_validation, card_details) end - it { is_expected.not_to be_used_by_banned_user } + it { is_expected.to be(false) } end end diff --git a/spec/requests/api/integrations_spec.rb b/spec/requests/api/integrations_spec.rb index d9b90ed516f..d8ac9d5abf7 100644 --- a/spec/requests/api/integrations_spec.rb +++ b/spec/requests/api/integrations_spec.rb @@ -63,28 +63,8 @@ RSpec.describe API::Integrations, feature_category: :integrations do describe "PUT /projects/:id/#{endpoint}/#{integration.dasherize}" do include_context 'with integration' - # NOTE: Some attributes are not supported for PUT requests, even though they probably should be. - # We can fix these manually, or with a generic approach like https://gitlab.com/gitlab-org/gitlab/-/issues/348208 - let(:missing_attributes) do - { - datadog: %i[archive_trace_events], - emails_on_push: %i[branches_to_be_notified], - hangouts_chat: %i[notify_only_broken_pipelines], - jira: %i[issues_enabled project_key jira_issue_regex jira_issue_prefix vulnerabilities_enabled vulnerabilities_issuetype], - mattermost: %i[labels_to_be_notified], - mock_ci: %i[enable_ssl_verification], - prometheus: %i[manual_configuration], - pumble: %i[branches_to_be_notified notify_only_broken_pipelines], - slack: %i[labels_to_be_notified], - unify_circuit: %i[branches_to_be_notified notify_only_broken_pipelines], - webex_teams: %i[branches_to_be_notified notify_only_broken_pipelines] - } - end - it "updates #{integration} settings and returns the correct fields" do - supported_attrs = attributes_for(integration_factory) - .without(:active, :type) - .without(missing_attributes.fetch(integration.to_sym, [])) + supported_attrs = attributes_for(integration_factory).without(:active, :type) put api("/projects/#{project.id}/#{endpoint}/#{dashed_integration}", user), params: supported_attrs diff --git a/spec/serializers/admin/abuse_report_details_entity_spec.rb b/spec/serializers/admin/abuse_report_details_entity_spec.rb index bed9775ac8c..47904a4e7e5 100644 --- a/spec/serializers/admin/abuse_report_details_entity_spec.rb +++ b/spec/serializers/admin/abuse_report_details_entity_spec.rb @@ -158,7 +158,6 @@ RSpec.describe Admin::AbuseReportDetailsEntity, feature_category: :insider_threa it 'exposes the credit card' do expect(credit_card_hash.keys).to match_array([ - :name, :similar_records_count, :card_matches_link ]) diff --git a/spec/serializers/integrations/field_entity_spec.rb b/spec/serializers/integrations/field_entity_spec.rb index 25ac0aa4911..aa503bdfcc8 100644 --- a/spec/serializers/integrations/field_entity_spec.rb +++ b/spec/serializers/integrations/field_entity_spec.rb @@ -103,7 +103,7 @@ RSpec.describe Integrations::FieldEntity, feature_category: :integrations do ['Default branch and protected branches', 'default_and_protected'] ], help: nil, - value: nil, + value: 'all', checkbox_label: nil } diff --git a/spec/services/draft_notes/publish_service_spec.rb b/spec/services/draft_notes/publish_service_spec.rb index 48959baeaa5..e087f2ffc7e 100644 --- a/spec/services/draft_notes/publish_service_spec.rb +++ b/spec/services/draft_notes/publish_service_spec.rb @@ -181,7 +181,7 @@ RSpec.describe DraftNotes::PublishService, feature_category: :code_review_workfl # NOTE: This should be reduced as we work on reducing Gitaly calls. # Gitaly requests shouldn't go above this threshold as much as possible # as it may add more to the Gitaly N+1 issue we are experiencing. - expect { publish }.to change { Gitlab::GitalyClient.get_request_count }.by(20) + expect { publish }.to change { Gitlab::GitalyClient.get_request_count }.by(19) end end |