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>2021-04-28 06:09:58 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-04-28 06:09:58 +0300
commit61ae9de492194653156cdd6e2b528e1dec5c99b6 (patch)
tree48d4cb8d8ce54253bd48a69f6e6ecbd165d0cc45 /spec
parent533d1ccc9875370e8f296c3de7dfb9c0e6a5c512 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r--spec/controllers/registrations_controller_spec.rb41
-rw-r--r--spec/features/invites_spec.rb43
-rw-r--r--spec/features/projects/blobs/blob_show_spec.rb22
-rw-r--r--spec/finders/deployments_finder_spec.rb57
-rw-r--r--spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb69
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_job_spec.rb51
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb9
-rw-r--r--spec/lib/gitlab/database/background_migration/batched_migration_spec.rb92
-rw-r--r--spec/services/users/registrations_build_service_spec.rb73
9 files changed, 420 insertions, 37 deletions
diff --git a/spec/controllers/registrations_controller_spec.rb b/spec/controllers/registrations_controller_spec.rb
index aac7c10d878..286c6b591f4 100644
--- a/spec/controllers/registrations_controller_spec.rb
+++ b/spec/controllers/registrations_controller_spec.rb
@@ -22,8 +22,9 @@ RSpec.describe RegistrationsController do
describe '#create' do
let(:base_user_params) { { first_name: 'first', last_name: 'last', username: 'new_username', email: 'new@user.com', password: 'Any_password' } }
let(:user_params) { { user: base_user_params } }
+ let(:session_params) { {} }
- subject { post(:create, params: user_params) }
+ subject { post(:create, params: user_params, session: session_params) }
context '`blocked_pending_approval` state' do
context 'when the `require_admin_approval_after_user_signup` setting is turned on' do
@@ -148,6 +149,26 @@ RSpec.describe RegistrationsController do
expect { subject }.to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
expect(controller.current_user).to be_nil
end
+
+ context 'when registration is triggered from an accepted invite' do
+ context 'when invite email matches email used on registration' do
+ let(:session_params) { { invite_email: user_params.dig(:user, :email) } }
+
+ it 'signs the user in without sending a confirmation email', :aggregate_failures do
+ expect { subject }.not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ expect(controller.current_user).to be_confirmed
+ end
+ end
+
+ context 'when invite email does not match the email used on registration' do
+ let(:session_params) { { invite_email: 'bogus@email.com' } }
+
+ it 'does not authenticate the user and sends a confirmation email', :aggregate_failures do
+ expect { subject }.to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ expect(controller.current_user).to be_nil
+ end
+ end
+ end
end
context 'when soft email confirmation is enabled' do
@@ -161,6 +182,24 @@ RSpec.describe RegistrationsController do
expect(controller.current_user).to be_present
expect(response).to redirect_to(users_sign_up_welcome_path)
end
+
+ context 'when invite email matches email used on registration' do
+ let(:session_params) { { invite_email: user_params.dig(:user, :email) } }
+
+ it 'signs the user in without sending a confirmation email', :aggregate_failures do
+ expect { subject }.not_to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ expect(controller.current_user).to be_confirmed
+ end
+ end
+
+ context 'when invite email does not match the email used on registration' do
+ let(:session_params) { { invite_email: 'bogus@email.com' } }
+
+ it 'authenticates the user and sends a confirmation email without confirming', :aggregate_failures do
+ expect { subject }.to have_enqueued_mail(DeviseMailer, :confirmation_instructions)
+ expect(controller.current_user).not_to be_confirmed
+ end
+ end
end
end
diff --git a/spec/features/invites_spec.rb b/spec/features/invites_spec.rb
index 014684c481c..cbbe99beb1f 100644
--- a/spec/features/invites_spec.rb
+++ b/spec/features/invites_spec.rb
@@ -90,7 +90,6 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
let(:new_user) { build_stubbed(:user) }
let(:invite_email) { new_user.email }
let(:group_invite) { create(:group_member, :invited, group: group, invite_email: invite_email, created_by: owner) }
- let!(:project_invite) { create(:project_member, :invited, project: project, invite_email: invite_email) }
context 'when registering using invitation email' do
before do
@@ -122,12 +121,6 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
expect(current_path).to eq(activity_group_path(group))
expect(page).to have_content('You have been granted Owner access to group Owned.')
-
- visit group_path(group)
- expect(page).to have_content(group.full_name)
-
- visit project_path(project)
- expect(page).to have_content(project.name)
end
context 'the user sign-up using a different email address' do
@@ -150,18 +143,11 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
end
- it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do
+ it 'signs up and redirects to the group activity page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
- confirm_email(new_user)
- fill_in_sign_in_form(new_user)
fill_in_welcome_form
- expect(current_path).to eq(root_path)
- expect(page).to have_content(project.full_name)
-
- visit group_path(group)
-
- expect(page).to have_content(group.full_name)
+ expect(current_path).to eq(activity_group_path(group))
end
end
@@ -170,29 +156,14 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
- it 'signs up and redirects to root page with all the project/groups invitation automatically accepted' do
+ it 'signs up and redirects to to the group activity page with all the project/groups invitation automatically accepted' do
fill_in_sign_up_form(new_user)
fill_in_welcome_form
- confirm_email(new_user)
-
- expect(current_path).to eq(root_path)
- expect(page).to have_content(project.full_name)
-
- visit group_path(group)
- expect(page).to have_content(group.full_name)
+ expect(current_path).to eq(activity_group_path(group))
end
end
- it "doesn't accept invitations until the user confirms their email" do
- fill_in_sign_up_form(new_user)
- fill_in_welcome_form
- sign_in(owner)
-
- visit project_project_members_path(project)
- expect(page).to have_content 'Invited'
- end
-
context 'the user sign-up using a different email address' do
let(:invite_email) { build_stubbed(:user).email }
@@ -202,7 +173,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 0
end
- it 'signs up and redirects to the invitation page' do
+ it 'signs up and redirects to the group activity page' do
fill_in_sign_up_form(new_user)
confirm_email(new_user)
fill_in_sign_in_form(new_user)
@@ -218,7 +189,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
allow(User).to receive(:allow_unconfirmed_access_for).and_return 2.days
end
- it 'signs up and redirects to the invitation page' do
+ it 'signs up and redirects to the group activity page' do
fill_in_sign_up_form(new_user)
fill_in_welcome_form
@@ -282,7 +253,7 @@ RSpec.describe 'Group or Project invitations', :aggregate_failures do
visit invite_path(group_invite.raw_invite_token)
end
- it 'grants access and redirects to group page' do
+ it 'grants access and redirects to the group activity page' do
expect(group.users.include?(user)).to be false
page.click_link 'Accept invitation'
diff --git a/spec/features/projects/blobs/blob_show_spec.rb b/spec/features/projects/blobs/blob_show_spec.rb
index 289088a3c87..3598aa2f423 100644
--- a/spec/features/projects/blobs/blob_show_spec.rb
+++ b/spec/features/projects/blobs/blob_show_spec.rb
@@ -125,6 +125,7 @@ RSpec.describe 'File blob', :js do
page.within '.project-refs-form' do
click_link ref_name
+ wait_for_requests
end
end
@@ -170,6 +171,27 @@ RSpec.describe 'File blob', :js do
expect(page).not_to have_css('.hll')
end
end
+
+ context 'sucessfully change ref of similar name' do
+ before do
+ project.repository.create_branch('dev')
+ project.repository.create_branch('development')
+ end
+
+ it 'switch ref from longer to shorter ref name' do
+ visit_blob('files/js/application.js', ref: 'development')
+ switch_ref_to('dev')
+
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ end
+
+ it 'switch ref from shorter to longer ref name' do
+ visit_blob('files/js/application.js', ref: 'dev')
+ switch_ref_to('development')
+
+ expect(page.find('.file-title-name').text).to eq('application.js')
+ end
+ end
end
context 'visiting with a line number anchor' do
diff --git a/spec/finders/deployments_finder_spec.rb b/spec/finders/deployments_finder_spec.rb
index 0f659fa1dab..3db3be0b64a 100644
--- a/spec/finders/deployments_finder_spec.rb
+++ b/spec/finders/deployments_finder_spec.rb
@@ -160,5 +160,62 @@ RSpec.describe DeploymentsFinder do
end
end
end
+
+ context 'at group scope' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:subgroup) { create(:group, parent: group) }
+
+ let_it_be(:group_project_1) { create(:project, :public, :test_repo, group: group) }
+ let_it_be(:group_project_2) { create(:project, :public, :test_repo, group: group) }
+ let_it_be(:subgroup_project_1) { create(:project, :public, :test_repo, group: subgroup) }
+ let(:base_params) { { group: group } }
+
+ describe 'ordering' do
+ using RSpec::Parameterized::TableSyntax
+
+ let(:params) { { **base_params, order_by: order_by, sort: sort } }
+
+ let!(:group_project_1_deployment) { create(:deployment, :success, project: group_project_1, iid: 11, ref: 'master', created_at: 2.days.ago, updated_at: Time.now, finished_at: Time.now) }
+ let!(:group_project_2_deployment) { create(:deployment, :success, project: group_project_2, iid: 12, ref: 'feature', created_at: 1.day.ago, updated_at: 2.hours.ago, finished_at: 2.hours.ago) }
+ let!(:subgroup_project_1_deployment) { create(:deployment, :success, project: subgroup_project_1, iid: 8, ref: 'video', created_at: Time.now, updated_at: 1.hour.ago, finished_at: 1.hour.ago) }
+
+ where(:order_by, :sort) do
+ 'created_at' | 'asc'
+ 'created_at' | 'desc'
+ 'id' | 'asc'
+ 'id' | 'desc'
+ 'iid' | 'asc'
+ 'iid' | 'desc'
+ 'ref' | 'asc'
+ 'ref' | 'desc'
+ 'updated_at' | 'asc'
+ 'updated_at' | 'desc'
+ 'finished_at' | 'asc'
+ 'finished_at' | 'desc'
+ 'invalid' | 'asc'
+ 'iid' | 'err'
+ end
+
+ with_them do
+ it 'returns the deployments unordered' do
+ expect(subject.to_a).to contain_exactly(group_project_1_deployment,
+ group_project_2_deployment,
+ subgroup_project_1_deployment)
+ end
+ end
+ end
+
+ it 'avoids N+1 queries' do
+ execute_queries = -> { described_class.new({ group: group }).execute.first }
+ control_count = ActiveRecord::QueryRecorder.new { execute_queries }.count
+
+ new_project = create(:project, :repository, group: group)
+ new_env = create(:environment, project: new_project, name: "production")
+ create_list(:deployment, 2, status: :success, project: new_project, environment: new_env)
+ group.reload
+
+ expect { execute_queries }.not_to exceed_query_limit(control_count)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb b/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb
new file mode 100644
index 00000000000..5386e5b0b1d
--- /dev/null
+++ b/spec/lib/gitlab/database/background_migration/batch_optimizer_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Gitlab::Database::BackgroundMigration::BatchOptimizer do
+ describe '#optimize' do
+ subject { described_class.new(migration, number_of_jobs: number_of_jobs).optimize! }
+
+ let(:migration) { create(:batched_background_migration, batch_size: batch_size, sub_batch_size: 100, interval: 120) }
+
+ let(:batch_size) { 10_000 }
+
+ let_it_be(:number_of_jobs) { 5 }
+
+ def mock_efficiency(eff)
+ expect(migration).to receive(:smoothed_time_efficiency).with(number_of_jobs: number_of_jobs).and_return(eff)
+ end
+
+ it 'with unknown time efficiency, it keeps the batch size' do
+ mock_efficiency(nil)
+
+ expect { subject }.not_to change { migration.reload.batch_size }
+ end
+
+ it 'with a time efficiency of 95%, it keeps the batch size' do
+ mock_efficiency(0.95)
+
+ expect { subject }.not_to change { migration.reload.batch_size }
+ end
+
+ it 'with a time efficiency of 90%, it keeps the batch size' do
+ mock_efficiency(0.9)
+
+ expect { subject }.not_to change { migration.reload.batch_size }
+ end
+
+ it 'with a time efficiency of 70%, it increases the batch size by 10%' do
+ mock_efficiency(0.7)
+
+ expect { subject }.to change { migration.reload.batch_size }.from(10_000).to(11_000)
+ end
+
+ it 'with a time efficiency of 110%, it decreases the batch size by 20%' do
+ mock_efficiency(1.1)
+
+ expect { subject }.to change { migration.reload.batch_size }.from(10_000).to(8_000)
+ end
+
+ context 'reaching the upper limit for the batch size' do
+ let(:batch_size) { 950_000 }
+
+ it 'caps the batch size at 10M' do
+ mock_efficiency(0.7)
+
+ expect { subject }.to change { migration.reload.batch_size }.to(1_000_000)
+ end
+ end
+
+ context 'reaching the lower limit for the batch size' do
+ let(:batch_size) { 1_050 }
+
+ it 'caps the batch size at 1k' do
+ mock_efficiency(1.1)
+
+ expect { subject }.to change { migration.reload.batch_size }.to(1_000)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
index 1020aafcf08..abee1fec80a 100644
--- a/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_job_spec.rb
@@ -47,4 +47,55 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedJob, type: :model d
end
end
end
+
+ describe '#time_efficiency' do
+ subject { job.time_efficiency }
+
+ let(:migration) { build(:batched_background_migration, interval: 120.seconds) }
+ let(:job) { build(:batched_background_migration_job, status: :succeeded, batched_migration: migration) }
+
+ context 'when job has not yet succeeded' do
+ let(:job) { build(:batched_background_migration_job, status: :running) }
+
+ it 'returns nil' do
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when finished_at is not set' do
+ it 'returns nil' do
+ job.started_at = Time.zone.now
+
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when started_at is not set' do
+ it 'returns nil' do
+ job.finished_at = Time.zone.now
+
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when job has finished' do
+ it 'returns ratio of duration to interval, here: 0.5' do
+ freeze_time do
+ job.started_at = Time.zone.now - migration.interval / 2
+ job.finished_at = Time.zone.now
+
+ expect(subject).to eq(0.5)
+ end
+ end
+
+ it 'returns ratio of duration to interval, here: 1' do
+ freeze_time do
+ job.started_at = Time.zone.now - migration.interval
+ job.finished_at = Time.zone.now
+
+ expect(subject).to eq(1)
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
index 7d0e10b62c6..79b21172dc6 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_runner_spec.rb
@@ -50,6 +50,15 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigrationRunner do
batch_size: migration.batch_size,
sub_batch_size: migration.sub_batch_size)
end
+
+ it 'optimizes the migration after executing the job' do
+ migration.update!(min_value: event1.id, max_value: event2.id)
+
+ expect(migration_wrapper).to receive(:perform).ordered
+ expect(migration).to receive(:optimize!).ordered
+
+ runner.run_migration_job(migration)
+ end
end
context 'when the batch maximum exceeds the migration maximum' do
diff --git a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
index cc3a96a793c..43e34325419 100644
--- a/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
+++ b/spec/lib/gitlab/database/background_migration/batched_migration_spec.rb
@@ -232,4 +232,96 @@ RSpec.describe Gitlab::Database::BackgroundMigration::BatchedMigration, type: :m
expect(batched_migration.prometheus_labels).to eq(labels)
end
end
+
+ describe '#smoothed_time_efficiency' do
+ let(:migration) { create(:batched_background_migration, interval: 120.seconds) }
+ let(:end_time) { Time.zone.now }
+
+ around do |example|
+ freeze_time do
+ example.run
+ end
+ end
+
+ let(:common_attrs) do
+ {
+ status: :succeeded,
+ batched_migration: migration,
+ finished_at: end_time
+ }
+ end
+
+ context 'when there are not enough jobs' do
+ subject { migration.smoothed_time_efficiency(number_of_jobs: 10) }
+
+ it 'returns nil' do
+ create_list(:batched_background_migration_job, 9, **common_attrs)
+
+ expect(subject).to be_nil
+ end
+ end
+
+ context 'when there are enough jobs' do
+ subject { migration.smoothed_time_efficiency(number_of_jobs: number_of_jobs) }
+
+ let!(:jobs) { create_list(:batched_background_migration_job, number_of_jobs, **common_attrs.merge(batched_migration: migration)) }
+ let(:number_of_jobs) { 10 }
+
+ before do
+ expect(migration).to receive_message_chain(:batched_jobs, :successful_in_execution_order, :reverse_order, :limit).with(no_args).with(no_args).with(number_of_jobs).and_return(jobs)
+ end
+
+ def mock_efficiencies(*effs)
+ effs.each_with_index do |eff, i|
+ expect(jobs[i]).to receive(:time_efficiency).and_return(eff)
+ end
+ end
+
+ context 'example 1: increasing trend, but only recently crossed threshold' do
+ it 'returns the smoothed time efficiency' do
+ mock_efficiencies(1.1, 1, 0.95, 0.9, 0.8, 0.95, 0.9, 0.8, 0.9, 0.95)
+
+ expect(subject).to be_within(0.05).of(0.95)
+ end
+ end
+
+ context 'example 2: increasing trend, crossed threshold a while ago' do
+ it 'returns the smoothed time efficiency' do
+ mock_efficiencies(1.2, 1.1, 1, 1, 1.1, 1, 0.95, 0.9, 0.95, 0.9)
+
+ expect(subject).to be_within(0.05).of(1.1)
+ end
+ end
+
+ context 'example 3: decreasing trend, but only recently crossed threshold' do
+ it 'returns the smoothed time efficiency' do
+ mock_efficiencies(0.9, 0.95, 1, 1.2, 1.1, 1.2, 1.1, 1.0, 1.1, 1.0)
+
+ expect(subject).to be_within(0.05).of(1.0)
+ end
+ end
+
+ context 'example 4: latest run spiked' do
+ it 'returns the smoothed time efficiency' do
+ mock_efficiencies(1.2, 0.9, 0.8, 0.9, 0.95, 0.9, 0.92, 0.9, 0.95, 0.9)
+
+ expect(subject).to be_within(0.02).of(0.96)
+ end
+ end
+ end
+ end
+
+ describe '#optimize!' do
+ subject { batched_migration.optimize! }
+
+ let(:batched_migration) { create(:batched_background_migration) }
+ let(:optimizer) { instance_double('Gitlab::Database::BackgroundMigration::BatchOptimizer') }
+
+ it 'calls the BatchOptimizer' do
+ expect(Gitlab::Database::BackgroundMigration::BatchOptimizer).to receive(:new).with(batched_migration).and_return(optimizer)
+ expect(optimizer).to receive(:optimize!)
+
+ subject
+ end
+ end
end
diff --git a/spec/services/users/registrations_build_service_spec.rb b/spec/services/users/registrations_build_service_spec.rb
new file mode 100644
index 00000000000..bc3718dbdb2
--- /dev/null
+++ b/spec/services/users/registrations_build_service_spec.rb
@@ -0,0 +1,73 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Users::RegistrationsBuildService do
+ describe '#execute' do
+ let(:base_params) { build_stubbed(:user).slice(:first_name, :last_name, :username, :email, :password) }
+ let(:skip_param) { {} }
+ let(:params) { base_params.merge(skip_param) }
+
+ subject(:service) { described_class.new(nil, params) }
+
+ before do
+ stub_application_setting(signup_enabled?: true)
+ end
+
+ context 'when automatic user confirmation is not enabled' do
+ before do
+ stub_application_setting(send_user_confirmation_email: true)
+ end
+
+ context 'when skip_confirmation is true' do
+ let(:skip_param) { { skip_confirmation: true } }
+
+ it 'confirms the user' do
+ expect(service.execute).to be_confirmed
+ end
+ end
+
+ context 'when skip_confirmation is not set' do
+ it 'does not confirm the user' do
+ expect(service.execute).not_to be_confirmed
+ end
+ end
+
+ context 'when skip_confirmation is false' do
+ let(:skip_param) { { skip_confirmation: false } }
+
+ it 'does not confirm the user' do
+ expect(service.execute).not_to be_confirmed
+ end
+ end
+ end
+
+ context 'when automatic user confirmation is enabled' do
+ before do
+ stub_application_setting(send_user_confirmation_email: false)
+ end
+
+ context 'when skip_confirmation is true' do
+ let(:skip_param) { { skip_confirmation: true } }
+
+ it 'confirms the user' do
+ expect(service.execute).to be_confirmed
+ end
+ end
+
+ context 'when skip_confirmation is not set the application setting takes precedence' do
+ it 'confirms the user' do
+ expect(service.execute).to be_confirmed
+ end
+ end
+
+ context 'when skip_confirmation is false the application setting takes precedence' do
+ let(:skip_param) { { skip_confirmation: false } }
+
+ it 'confirms the user' do
+ expect(service.execute).to be_confirmed
+ end
+ end
+ end
+ end
+end