Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-09-05 12:10:52 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-09-05 12:10:52 +0300
commit8934df30a36d16ac9de9aebb079e16f16fda6912 (patch)
tree0f958a8b95c021053cb819767ec5c2cdb6802606 /spec
parent24b8d0f8cd52b72cbfbb0cfde7ad7204f3469ee9 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/features/boards/sidebar_spec.rb2
-rw-r--r--spec/features/issues/user_sees_live_update_spec.rb22
-rw-r--r--spec/frontend/sentry/init_sentry_spec.js96
-rw-r--r--spec/lib/gitlab/background_migration/convert_credit_card_validation_data_to_hashes_spec.rb81
-rw-r--r--spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb115
-rw-r--r--spec/migrations/20230821081603_queue_convert_credit_card_validation_data_to_hashes_spec.rb26
-rw-r--r--spec/models/users/credit_card_validation_spec.rb143
-rw-r--r--spec/services/users/upsert_credit_card_validation_service_spec.rb11
-rw-r--r--spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb12
-rw-r--r--spec/support/shared_examples/lib/api/ai_workhorse_shared_examples.rb45
10 files changed, 457 insertions, 96 deletions
diff --git a/spec/features/boards/sidebar_spec.rb b/spec/features/boards/sidebar_spec.rb
index 4807b691e4f..358da1e1279 100644
--- a/spec/features/boards/sidebar_spec.rb
+++ b/spec/features/boards/sidebar_spec.rb
@@ -2,7 +2,7 @@
require 'spec_helper'
-RSpec.describe 'Project issue boards sidebar', :js, feature_category: :team_planning, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/416414' do
+RSpec.describe 'Project issue boards sidebar', :js, feature_category: :team_planning do
include BoardHelpers
let_it_be(:user) { create(:user) }
diff --git a/spec/features/issues/user_sees_live_update_spec.rb b/spec/features/issues/user_sees_live_update_spec.rb
index 860603ad546..0822542ca02 100644
--- a/spec/features/issues/user_sees_live_update_spec.rb
+++ b/spec/features/issues/user_sees_live_update_spec.rb
@@ -19,34 +19,32 @@ RSpec.describe 'Issues > User sees live update', :js, feature_category: :team_pl
expect(page).to have_text("new title")
issue.update!(title: "updated title")
-
wait_for_requests
+
expect(page).to have_text("updated title")
end
end
describe 'confidential issue#show' do
- it 'shows confidential sibebar information as confidential and can be turned off', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/254644' do
+ it 'shows confidential sidebar information as confidential and can be turned off' do
issue = create(:issue, :confidential, project: project)
visit project_issue_path(project, issue)
- expect(page).to have_css('.issuable-note-warning')
- expect(find('.issuable-sidebar-item.confidentiality')).to have_css('.is-active')
- expect(find('.issuable-sidebar-item.confidentiality')).not_to have_css('.not-active')
-
- find('.confidential-edit').click
- expect(page).to have_css('.sidebar-item-warning-message')
+ expect(page).to have_text('This is a confidential issue. People without permission will never get a notification.')
- within('.sidebar-item-warning-message') do
- find('[data-testid="confidential-toggle"]').click
+ within '.block.confidentiality' do
+ click_button 'Edit'
end
- wait_for_requests
+ expect(page).to have_text('You are going to turn off the confidentiality. This means everyone will be able to see and leave a comment on this issue.')
+
+ click_button 'Turn off'
visit project_issue_path(project, issue)
- expect(page).not_to have_css('.is-active')
+ expect(page).not_to have_css('.gl-badge', text: 'Confidential')
+ expect(page).not_to have_text('This is a confidential issue. People without permission will never get a notification.')
end
end
end
diff --git a/spec/frontend/sentry/init_sentry_spec.js b/spec/frontend/sentry/init_sentry_spec.js
index 8e46a63775b..8cfbcc1cfca 100644
--- a/spec/frontend/sentry/init_sentry_spec.js
+++ b/spec/frontend/sentry/init_sentry_spec.js
@@ -1,3 +1,15 @@
+import {
+ BrowserClient,
+ defaultStackParser,
+ makeFetchTransport,
+ defaultIntegrations,
+
+ // exports
+ captureException,
+ captureMessage,
+ withScope,
+ SDK_VERSION,
+} from 'sentrybrowser';
import * as Sentry from 'sentrybrowser';
import { initSentry } from '~/sentry/init_sentry';
@@ -11,9 +23,25 @@ const mockRevision = '00112233';
const mockFeatureCategory = 'my_feature_category';
const mockPage = 'index:page';
-jest.mock('sentrybrowser');
+jest.mock('sentrybrowser', () => {
+ return {
+ ...jest.createMockFromModule('sentrybrowser'),
+
+ // unmock actual configuration options
+ defaultStackParser: jest.requireActual('sentrybrowser').defaultStackParser,
+ makeFetchTransport: jest.requireActual('sentrybrowser').makeFetchTransport,
+ defaultIntegrations: jest.requireActual('sentrybrowser').defaultIntegrations,
+ };
+});
describe('SentryConfig', () => {
+ let mockBindClient;
+ let mockSetTags;
+ let mockSetUser;
+ let mockBrowserClient;
+ let mockStartSession;
+ let mockCaptureSession;
+
beforeEach(() => {
window.gon = {
sentry_dsn: mockDsn,
@@ -26,6 +54,21 @@ describe('SentryConfig', () => {
};
document.body.dataset.page = mockPage;
+
+ mockBindClient = jest.fn();
+ mockSetTags = jest.fn();
+ mockSetUser = jest.fn();
+ mockStartSession = jest.fn();
+ mockCaptureSession = jest.fn();
+ mockBrowserClient = jest.spyOn(Sentry, 'BrowserClient');
+
+ jest.spyOn(Sentry, 'getCurrentHub').mockReturnValue({
+ bindClient: mockBindClient,
+ setTags: mockSetTags,
+ setUser: mockSetUser,
+ startSession: mockStartSession,
+ captureSession: mockCaptureSession,
+ });
});
afterEach(() => {
@@ -39,19 +82,29 @@ describe('SentryConfig', () => {
initSentry();
});
- it('calls Sentry.init with gon values', () => {
- expect(Sentry.init).toHaveBeenCalledTimes(1);
- expect(Sentry.init).toHaveBeenCalledWith({
- dsn: mockDsn,
- release: mockVersion,
- allowUrls: [mockGitlabUrl, 'webpack-internal://'],
- environment: mockEnvironment,
- });
+ it('creates BrowserClient with gon values and configuration', () => {
+ expect(mockBrowserClient).toHaveBeenCalledWith(
+ expect.objectContaining({
+ dsn: mockDsn,
+ release: mockVersion,
+ allowUrls: [mockGitlabUrl, 'webpack-internal://'],
+ environment: mockEnvironment,
+
+ transport: makeFetchTransport,
+ stackParser: defaultStackParser,
+ integrations: defaultIntegrations,
+ }),
+ );
+ });
+
+ it('binds the BrowserClient to the hub', () => {
+ expect(mockBindClient).toHaveBeenCalledTimes(1);
+ expect(mockBindClient).toHaveBeenCalledWith(expect.any(BrowserClient));
});
it('calls Sentry.setTags with gon values', () => {
- expect(Sentry.setTags).toHaveBeenCalledTimes(1);
- expect(Sentry.setTags).toHaveBeenCalledWith({
+ expect(mockSetTags).toHaveBeenCalledTimes(1);
+ expect(mockSetTags).toHaveBeenCalledWith({
page: mockPage,
revision: mockRevision,
feature_category: mockFeatureCategory,
@@ -59,15 +112,20 @@ describe('SentryConfig', () => {
});
it('calls Sentry.setUser with gon values', () => {
- expect(Sentry.setUser).toHaveBeenCalledTimes(1);
- expect(Sentry.setUser).toHaveBeenCalledWith({
+ expect(mockSetUser).toHaveBeenCalledTimes(1);
+ expect(mockSetUser).toHaveBeenCalledWith({
id: mockCurrentUserId,
});
});
it('sets global sentry', () => {
// eslint-disable-next-line no-underscore-dangle
- expect(window._Sentry).toBe(Sentry);
+ expect(window._Sentry).toEqual({
+ captureException,
+ captureMessage,
+ withScope,
+ SDK_VERSION,
+ });
});
});
@@ -78,7 +136,7 @@ describe('SentryConfig', () => {
});
it('does not call Sentry.setUser', () => {
- expect(Sentry.setUser).not.toHaveBeenCalled();
+ expect(mockSetUser).not.toHaveBeenCalled();
});
});
@@ -89,7 +147,9 @@ describe('SentryConfig', () => {
});
it('Sentry.init is not called', () => {
- expect(Sentry.init).not.toHaveBeenCalled();
+ expect(mockBrowserClient).not.toHaveBeenCalled();
+ expect(mockBindClient).not.toHaveBeenCalled();
+
// eslint-disable-next-line no-underscore-dangle
expect(window._Sentry).toBe(undefined);
});
@@ -102,7 +162,9 @@ describe('SentryConfig', () => {
});
it('Sentry.init is not called', () => {
- expect(Sentry.init).not.toHaveBeenCalled();
+ expect(mockBrowserClient).not.toHaveBeenCalled();
+ expect(mockBindClient).not.toHaveBeenCalled();
+
// eslint-disable-next-line no-underscore-dangle
expect(window._Sentry).toBe(undefined);
});
diff --git a/spec/lib/gitlab/background_migration/convert_credit_card_validation_data_to_hashes_spec.rb b/spec/lib/gitlab/background_migration/convert_credit_card_validation_data_to_hashes_spec.rb
new file mode 100644
index 00000000000..97f69afca55
--- /dev/null
+++ b/spec/lib/gitlab/background_migration/convert_credit_card_validation_data_to_hashes_spec.rb
@@ -0,0 +1,81 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::BackgroundMigration::ConvertCreditCardValidationDataToHashes, schema: 20230821081603, feature_category: :user_profile do # rubocop:disable Layout/LineLength
+ let(:users_table) { table(:users) }
+ let(:credit_card_validations_table) { table(:user_credit_card_validations) }
+ let(:rows) { 5 }
+
+ describe '#perform' do
+ let(:network) { 'Visa' }
+ let(:holder_name) { 'John Smith' }
+ let(:last_digits) { 1111 }
+ let(:expiration_date) { 1.year.from_now.to_date }
+
+ subject(:perform_migration) do
+ described_class.new(
+ start_id: 1,
+ end_id: rows,
+ batch_table: :user_credit_card_validations,
+ batch_column: :user_id,
+ sub_batch_size: 2,
+ pause_ms: 0,
+ connection: ActiveRecord::Base.connection
+ ).perform
+ end
+
+ before do
+ (1..rows).each do |i|
+ users_table.create!(id: i, username: "John #{i}", email: "johndoe_#{i}@gitlab.com", projects_limit: 10)
+
+ credit_card_validations_table.create!(
+ id: i,
+ user_id: i,
+ network: network,
+ holder_name: holder_name,
+ last_digits: last_digits,
+ expiration_date: expiration_date,
+ credit_card_validated_at: Date.today
+ )
+ end
+ end
+
+ it 'updates values to hash for records in the specified batch', :aggregate_failures do
+ perform_migration
+
+ (1..rows).each do |i|
+ credit_card = credit_card_validations_table.find_by(user_id: i)
+
+ expect(credit_card.last_digits_hash).to eq(hashed_value(last_digits))
+ expect(credit_card.holder_name_hash).to eq(hashed_value(holder_name.downcase))
+ expect(credit_card.network_hash).to eq(hashed_value(network.downcase))
+ expect(credit_card.expiration_date_hash).to eq(hashed_value(expiration_date.to_s))
+ end
+ end
+
+ context 'with NULL columns' do
+ let(:network) { nil }
+ let(:holder_name) { nil }
+ let(:last_digits) { nil }
+ let(:expiration_date) { nil }
+
+ it 'does not update values for records in the specified batch', :aggregate_failures do
+ perform_migration
+
+ (1..rows).each do |i|
+ credit_card = credit_card_validations_table.find_by(user_id: i)
+
+ expect(credit_card.last_digits_hash).to eq(nil)
+ expect(credit_card.holder_name_hash).to eq(nil)
+ expect(credit_card.network_hash).to eq(nil)
+ expect(credit_card.expiration_date_hash).to eq(nil)
+ end
+ end
+ end
+ end
+
+ def hashed_value(value)
+ Gitlab::CryptoHelper.sha256(value)
+ end
+end
diff --git a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
index 789919d2a51..7a002c4b1d0 100644
--- a/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
+++ b/spec/lib/gitlab/database/load_balancing/service_discovery_spec.rb
@@ -15,7 +15,8 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery, feature_catego
load_balancer,
nameserver: 'localhost',
port: 8600,
- record: 'foo'
+ record: 'foo',
+ disconnect_timeout: 1 # Short disconnect timeout to keep tests fast
)
end
@@ -192,6 +193,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery, feature_catego
end
describe '#replace_hosts' do
+ before do
+ stub_env('LOAD_BALANCER_PARALLEL_DISCONNECT', 'true')
+ allow(service)
+ .to receive(:load_balancer)
+ .and_return(load_balancer)
+ end
+
let(:address_foo) { described_class::Address.new('foo') }
let(:address_bar) { described_class::Address.new('bar') }
@@ -202,19 +210,13 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery, feature_catego
)
end
- before do
- allow(service)
- .to receive(:load_balancer)
- .and_return(load_balancer)
- end
-
it 'replaces the hosts of the load balancer' do
service.replace_hosts([address_bar])
expect(load_balancer.host_list.host_names_and_ports).to eq([['bar', nil]])
end
- it 'disconnects the old connections' do
+ it 'disconnects the old connections gracefully if possible' do
host = load_balancer.host_list.hosts.first
allow(service)
@@ -222,11 +224,47 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery, feature_catego
.and_return(2)
expect(host)
- .to receive(:disconnect!)
- .with(timeout: 2)
+ .to receive(:try_disconnect).and_return(true)
+
+ expect(host).not_to receive(:force_disconnect!)
service.replace_hosts([address_bar])
end
+
+ it 'disconnects the old connections forcefully if necessary' do
+ host = load_balancer.host_list.hosts.first
+
+ allow(service)
+ .to receive(:disconnect_timeout)
+ .and_return(2)
+
+ expect(host)
+ .to receive(:try_disconnect).and_return(false)
+
+ expect(host).to receive(:force_disconnect!)
+
+ service.replace_hosts([address_bar])
+ end
+
+ context 'when LOAD_BALANCER_PARALLEL_DISCONNECT is false' do
+ before do
+ stub_env('LOAD_BALANCER_PARALLEL_DISCONNECT', 'false')
+ end
+
+ it 'disconnects them sequentially' do
+ host = load_balancer.host_list.hosts.first
+
+ allow(service)
+ .to receive(:disconnect_timeout)
+ .and_return(2)
+
+ expect(host)
+ .to receive(:disconnect!)
+ .with(timeout: 2)
+
+ service.replace_hosts([address_bar])
+ end
+ end
end
describe '#addresses_from_dns' do
@@ -475,4 +513,61 @@ RSpec.describe Gitlab::Database::LoadBalancing::ServiceDiscovery, feature_catego
end
end
end
+
+ context 'with service discovery connected to a real load balancer' do
+ let(:database_address) do
+ host, port = ApplicationRecord.connection_pool.db_config.configuration_hash.fetch(:host, :port)
+ described_class::Address.new(host, port)
+ end
+
+ before do
+ # set up the load balancer to point to the test postgres instance with three seperate conections
+ allow(service).to receive(:addresses_from_dns)
+ .and_return([Gitlab::Database::LoadBalancing::Resolver::FAR_FUTURE_TTL,
+ [database_address, database_address, database_address]])
+ .once
+
+ service.perform_service_discovery
+ end
+
+ it 'configures service discovery with three replicas' do
+ expect(service.load_balancer.host_list.hosts.count).to eq(3)
+ end
+
+ it 'swaps the hosts out gracefully when not contended' do
+ expect(service.load_balancer.host_list.hosts.count).to eq(3)
+
+ host = service.load_balancer.host_list.next
+
+ # Check out and use a connection from a host so that there is something to clean up
+ host.pool.with_connection do |connection|
+ expect { connection.execute('select 1') }.not_to raise_error
+ end
+
+ allow(service).to receive(:addresses_from_dns).and_return([Gitlab::Database::LoadBalancing::Resolver::FAR_FUTURE_TTL, []])
+
+ service.load_balancer.host_list.hosts.each do |h|
+ # Expect that the host gets gracefully disconnected
+ expect(h).not_to receive(:force_disconnect!)
+ end
+
+ expect { service.perform_service_discovery }.to change { host.pool.stat[:connections] }.from(1).to(0)
+ end
+
+ it 'swaps the hosts out forcefully when contended' do
+ host = service.load_balancer.host_list.next
+
+ # Check out a connection and leave it checked out (simulate a web request)
+ connection = host.pool.checkout
+ connection.execute('select 1')
+
+ # Expect that the connection is forcefully checked in
+ expect(host).to receive(:force_disconnect!).and_call_original
+ expect(connection).to receive(:steal!).and_call_original
+
+ allow(service).to receive(:addresses_from_dns).and_return([Gitlab::Database::LoadBalancing::Resolver::FAR_FUTURE_TTL, []])
+
+ service.perform_service_discovery
+ end
+ end
end
diff --git a/spec/migrations/20230821081603_queue_convert_credit_card_validation_data_to_hashes_spec.rb b/spec/migrations/20230821081603_queue_convert_credit_card_validation_data_to_hashes_spec.rb
new file mode 100644
index 00000000000..36ab25ffa3e
--- /dev/null
+++ b/spec/migrations/20230821081603_queue_convert_credit_card_validation_data_to_hashes_spec.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require_migration!
+
+RSpec.describe QueueConvertCreditCardValidationDataToHashes, feature_category: :user_profile do
+ let!(:batched_migration) { described_class::MIGRATION }
+
+ it 'schedules a new batched migration' do
+ reversible_migration do |migration|
+ migration.before -> {
+ expect(batched_migration).not_to have_scheduled_batched_migration
+ }
+
+ migration.after -> {
+ expect(batched_migration).to have_scheduled_batched_migration(
+ table_name: :user_credit_card_validations,
+ column_name: :user_id,
+ interval: described_class::DELAY_INTERVAL,
+ batch_size: described_class::BATCH_SIZE,
+ sub_batch_size: described_class::SUB_BATCH_SIZE
+ )
+ }
+ end
+ end
+end
diff --git a/spec/models/users/credit_card_validation_spec.rb b/spec/models/users/credit_card_validation_spec.rb
index 4db3683c057..486d1c6d3ea 100644
--- a/spec/models/users/credit_card_validation_spec.rb
+++ b/spec/models/users/credit_card_validation_spec.rb
@@ -2,14 +2,19 @@
require 'spec_helper'
-RSpec.describe Users::CreditCardValidation do
+RSpec.describe Users::CreditCardValidation, feature_category: :user_profile do
it { is_expected.to belong_to(:user) }
it { is_expected.to validate_length_of(:holder_name).is_at_most(50) }
it { is_expected.to validate_length_of(:network).is_at_most(32) }
it { is_expected.to validate_numericality_of(:last_digits).is_less_than_or_equal_to(9999) }
- describe '.similar_records' do
+ it { is_expected.to validate_length_of(:last_digits_hash).is_at_most(44) }
+ it { is_expected.to validate_length_of(:holder_name_hash).is_at_most(44) }
+ it { is_expected.to validate_length_of(:expiration_date_hash).is_at_most(44) }
+ 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)
end
@@ -53,6 +58,22 @@ RSpec.describe Users::CreditCardValidation do
end
describe 'scopes' do
+ describe '.find_or_initialize_by_user' do
+ subject(:find_or_initialize_by_user) { described_class.find_or_initialize_by_user(user.id) }
+
+ let_it_be(:user) { create(:user) }
+
+ context 'with no existing credit card record' do
+ it { is_expected.to be_a_new_record }
+ end
+
+ context 'with existing credit card record' do
+ let_it_be(:credit_card_validation) { create(:credit_card_validation, user: user) }
+
+ it { is_expected.to eq(credit_card_validation) }
+ end
+ end
+
describe '.by_banned_user' do
let(:banned_user) { create(:banned_user) }
let!(:credit_card) { create(:credit_card_validation) }
@@ -154,4 +175,122 @@ RSpec.describe Users::CreditCardValidation do
it { is_expected.not_to be_used_by_banned_user }
end
end
+
+ describe 'before_save' do
+ describe '#set_last_digits_hash' do
+ let(:credit_card_validation) { build(:credit_card_validation, last_digits: last_digits) }
+
+ subject(:save_credit_card_validation) { credit_card_validation.save! }
+
+ context 'when last_digits are nil' do
+ let(:last_digits) { nil }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.last_digits_hash } }
+ end
+
+ context 'when last_digits has a blank value' do
+ let(:last_digits) { ' ' }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.last_digits_hash } }
+ end
+
+ context 'when last_digits has a value' do
+ let(:last_digits) { 1111 }
+ let(:expected_last_digits_hash) { Gitlab::CryptoHelper.sha256(last_digits) }
+
+ it 'assigns correct last_digits_hash value' do
+ expect { save_credit_card_validation }.to change {
+ credit_card_validation.last_digits_hash
+ }.from(nil).to(expected_last_digits_hash)
+ end
+ end
+ end
+
+ describe '#set_holder_name_hash' do
+ let(:credit_card_validation) { build(:credit_card_validation, holder_name: holder_name) }
+
+ subject(:save_credit_card_validation) { credit_card_validation.save! }
+
+ context 'when holder_name is nil' do
+ let(:holder_name) { nil }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.holder_name_hash } }
+ end
+
+ context 'when holder_name has a blank value' do
+ let(:holder_name) { ' ' }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.holder_name_hash } }
+ end
+
+ context 'when holder_name has a value' do
+ let(:holder_name) { 'John Smith' }
+ let(:expected_holder_name_hash) { Gitlab::CryptoHelper.sha256(holder_name.downcase) }
+
+ it 'lowercases holder_name and assigns correct holder_name_hash value' do
+ expect { save_credit_card_validation }.to change {
+ credit_card_validation.holder_name_hash
+ }.from(nil).to(expected_holder_name_hash)
+ end
+ end
+ end
+
+ describe '#set_network_hash' do
+ let(:credit_card_validation) { build(:credit_card_validation, network: network) }
+
+ subject(:save_credit_card_validation) { credit_card_validation.save! }
+
+ context 'when network is nil' do
+ let(:network) { nil }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.network_hash } }
+ end
+
+ context 'when network has a blank value' do
+ let(:network) { ' ' }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.network_hash } }
+ end
+
+ context 'when network has a value' do
+ let(:network) { 'Visa' }
+ let(:expected_network_hash) { Gitlab::CryptoHelper.sha256(network.downcase) }
+
+ it 'lowercases network and assigns correct network_hash value' do
+ expect { save_credit_card_validation }.to change {
+ credit_card_validation.network_hash
+ }.from(nil).to(expected_network_hash)
+ end
+ end
+ end
+
+ describe '#set_expiration_date_hash' do
+ let(:credit_card_validation) { build(:credit_card_validation, expiration_date: expiration_date) }
+
+ subject(:save_credit_card_validation) { credit_card_validation.save! }
+
+ context 'when expiration_date is nil' do
+ let(:expiration_date) { nil }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.expiration_date_hash } }
+ end
+
+ context 'when expiration_date has a blank value' do
+ let(:expiration_date) { ' ' }
+
+ it { expect { save_credit_card_validation }.not_to change { credit_card_validation.expiration_date_hash } }
+ end
+
+ context 'when expiration_date has a value' do
+ let(:expiration_date) { 1.year.from_now.to_date }
+ let(:expected_expiration_date_hash) { Gitlab::CryptoHelper.sha256(expiration_date.to_s) }
+
+ it 'assigns correct expiration_date_hash value' do
+ expect { save_credit_card_validation }.to change {
+ credit_card_validation.expiration_date_hash
+ }.from(nil).to(expected_expiration_date_hash)
+ end
+ end
+ end
+ end
end
diff --git a/spec/services/users/upsert_credit_card_validation_service_spec.rb b/spec/services/users/upsert_credit_card_validation_service_spec.rb
index ebd2502398d..4e23b51cae2 100644
--- a/spec/services/users/upsert_credit_card_validation_service_spec.rb
+++ b/spec/services/users/upsert_credit_card_validation_service_spec.rb
@@ -101,6 +101,14 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
end
context 'when unexpected exception happen' do
+ let(:exception) { StandardError.new }
+
+ before do
+ allow_next_instance_of(::Users::CreditCardValidation) do |instance|
+ allow(instance).to receive(:save).and_raise(exception)
+ end
+ end
+
it 'tracks the exception and returns an error' do
logged_params = {
credit_card_validated_at: credit_card_validated_time,
@@ -111,8 +119,7 @@ RSpec.describe Users::UpsertCreditCardValidationService, feature_category: :user
user_id: user_id
}
- expect(::Users::CreditCardValidation).to receive(:upsert).and_raise(e = StandardError.new('My exception!'))
- expect(Gitlab::ErrorTracking).to receive(:track_exception).with(e, class: described_class.to_s, params: logged_params)
+ expect(Gitlab::ErrorTracking).to receive(:track_exception).with(exception, class: described_class.to_s, params: logged_params)
result = service.execute
diff --git a/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb b/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
index 8ebec19a884..d654a30d54a 100644
--- a/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
+++ b/spec/support/shared_examples/features/sidebar/sidebar_labels_shared_examples.rb
@@ -47,8 +47,7 @@ RSpec.shared_examples 'labels sidebar widget' do
end
end
- it 'adds first label by pressing enter when search',
- quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/414877' do
+ it 'adds first label by pressing enter when search' do
within(labels_widget) do
page.within('[data-testid="value-wrapper"]') do
expect(page).not_to have_content(development.name)
@@ -86,7 +85,7 @@ RSpec.shared_examples 'labels sidebar widget' do
context 'creating a label', :js do
before do
page.within(labels_widget) do
- page.find('[data-testid="create-label-button"]').click
+ click_button 'Create project label'
end
end
@@ -96,12 +95,11 @@ RSpec.shared_examples 'labels sidebar widget' do
end
end
- it 'creates new label', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/391240' do
+ it 'creates new label' do
page.within(labels_widget) do
fill_in 'Name new label', with: 'wontfix'
- page.find('.suggest-colors a', match: :first).click
- page.find('button', text: 'Create').click
- wait_for_requests
+ click_link 'Magenta-pink'
+ click_button 'Create'
expect(page).to have_content 'wontfix'
end
diff --git a/spec/support/shared_examples/lib/api/ai_workhorse_shared_examples.rb b/spec/support/shared_examples/lib/api/ai_workhorse_shared_examples.rb
deleted file mode 100644
index d4fe45a91a0..00000000000
--- a/spec/support/shared_examples/lib/api/ai_workhorse_shared_examples.rb
+++ /dev/null
@@ -1,45 +0,0 @@
-# frozen_string_literal: true
-
-RSpec.shared_examples 'behind AI related feature flags' do |provider_flag|
- context "when #{provider_flag} is disabled" do
- before do
- stub_feature_flags(provider_flag => false)
- end
-
- it 'responds as not found' do
- post api(url, current_user), params: input_params
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-
- context 'when ai_experimentation_api is disabled' do
- before do
- stub_feature_flags(ai_experimentation_api: false)
- end
-
- it 'responds as not found' do
- post api(url, current_user), params: input_params
-
- expect(response).to have_gitlab_http_status(:not_found)
- end
- end
-end
-
-RSpec.shared_examples 'delegates AI request to Workhorse' do
- it 'responds with Workhorse send-url headers' do
- post api(url, current_user), params: input_params
-
- expect(response.body).to eq('""')
- expect(response).to have_gitlab_http_status(:ok)
-
- send_url_prefix, encoded_data = response.headers['Gitlab-Workhorse-Send-Data'].split(':')
- data = Gitlab::Json.parse(Base64.urlsafe_decode64(encoded_data))
-
- expect(send_url_prefix).to eq('send-url')
- expect(data).to eq({
- 'AllowRedirects' => false,
- 'Method' => 'POST'
- }.merge(expected_params))
- end
-end