diff options
Diffstat (limited to 'spec/workers')
30 files changed, 778 insertions, 84 deletions
diff --git a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb index c7de8553d86..da0cbe37400 100644 --- a/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb +++ b/spec/workers/analytics/instance_statistics/count_job_trigger_worker_spec.rb @@ -6,12 +6,12 @@ RSpec.describe Analytics::InstanceStatistics::CountJobTriggerWorker do it_behaves_like 'an idempotent worker' context 'triggers a job for each measurement identifiers' do - let(:expected_count) { Analytics::InstanceStatistics::Measurement.identifier_query_mapping.keys.size } + let(:expected_count) { Analytics::UsageTrends::Measurement.identifier_query_mapping.keys.size } it 'triggers CounterJobWorker jobs' do subject.perform - expect(Analytics::InstanceStatistics::CounterJobWorker.jobs.count).to eq(expected_count) + expect(Analytics::UsageTrends::CounterJobWorker.jobs.count).to eq(expected_count) end end end diff --git a/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb b/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb index 667ec0bcb75..4994fec44ab 100644 --- a/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb +++ b/spec/workers/analytics/instance_statistics/counter_job_worker_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do let_it_be(:user_1) { create(:user) } let_it_be(:user_2) { create(:user) } - let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:users) } + let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:users) } let(:recorded_at) { Time.zone.now } let(:job_args) { [users_measurement_identifier, user_1.id, user_2.id, recorded_at] } @@ -18,7 +18,7 @@ RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do it 'counts a scope and stores the result' do subject - measurement = Analytics::InstanceStatistics::Measurement.users.first + measurement = Analytics::UsageTrends::Measurement.users.first expect(measurement.recorded_at).to be_like_time(recorded_at) expect(measurement.identifier).to eq('users') expect(measurement.count).to eq(2) @@ -26,14 +26,14 @@ RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do end context 'when no records are in the database' do - let(:users_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:groups) } + let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:groups) } subject { described_class.new.perform(users_measurement_identifier, nil, nil, recorded_at) } it 'sets 0 as the count' do subject - measurement = Analytics::InstanceStatistics::Measurement.groups.first + measurement = Analytics::UsageTrends::Measurement.groups.first expect(measurement.recorded_at).to be_like_time(recorded_at) expect(measurement.identifier).to eq('groups') expect(measurement.count).to eq(0) @@ -49,19 +49,19 @@ RSpec.describe Analytics::InstanceStatistics::CounterJobWorker do it 'does not insert anything when BatchCount returns error' do allow(Gitlab::Database::BatchCount).to receive(:batch_count).and_return(Gitlab::Database::BatchCounter::FALLBACK) - expect { subject }.not_to change { Analytics::InstanceStatistics::Measurement.count } + expect { subject }.not_to change { Analytics::UsageTrends::Measurement.count } end context 'when pipelines_succeeded identifier is passed' do let_it_be(:pipeline) { create(:ci_pipeline, :success) } - let(:successful_pipelines_measurement_identifier) { ::Analytics::InstanceStatistics::Measurement.identifiers.fetch(:pipelines_succeeded) } + let(:successful_pipelines_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:pipelines_succeeded) } let(:job_args) { [successful_pipelines_measurement_identifier, pipeline.id, pipeline.id, recorded_at] } it 'counts successful pipelines' do subject - measurement = Analytics::InstanceStatistics::Measurement.pipelines_succeeded.first + measurement = Analytics::UsageTrends::Measurement.pipelines_succeeded.first expect(measurement.recorded_at).to be_like_time(recorded_at) expect(measurement.identifier).to eq('pipelines_succeeded') expect(measurement.count).to eq(1) diff --git a/spec/workers/analytics/usage_trends/count_job_trigger_worker_spec.rb b/spec/workers/analytics/usage_trends/count_job_trigger_worker_spec.rb new file mode 100644 index 00000000000..735e4a214a9 --- /dev/null +++ b/spec/workers/analytics/usage_trends/count_job_trigger_worker_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Analytics::UsageTrends::CountJobTriggerWorker do + it_behaves_like 'an idempotent worker' + + context 'triggers a job for each measurement identifiers' do + let(:expected_count) { Analytics::UsageTrends::Measurement.identifier_query_mapping.keys.size } + + it 'triggers CounterJobWorker jobs' do + subject.perform + + expect(Analytics::UsageTrends::CounterJobWorker.jobs.count).to eq(expected_count) + end + end +end diff --git a/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb b/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb new file mode 100644 index 00000000000..9e4c82ee981 --- /dev/null +++ b/spec/workers/analytics/usage_trends/counter_job_worker_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Analytics::UsageTrends::CounterJobWorker do + let_it_be(:user_1) { create(:user) } + let_it_be(:user_2) { create(:user) } + + let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:users) } + let(:recorded_at) { Time.zone.now } + let(:job_args) { [users_measurement_identifier, user_1.id, user_2.id, recorded_at] } + + before do + allow(ActiveRecord::Base.connection).to receive(:transaction_open?).and_return(false) + end + + include_examples 'an idempotent worker' do + it 'counts a scope and stores the result' do + subject + + measurement = Analytics::UsageTrends::Measurement.users.first + expect(measurement.recorded_at).to be_like_time(recorded_at) + expect(measurement.identifier).to eq('users') + expect(measurement.count).to eq(2) + end + end + + context 'when no records are in the database' do + let(:users_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:groups) } + + subject { described_class.new.perform(users_measurement_identifier, nil, nil, recorded_at) } + + it 'sets 0 as the count' do + subject + + measurement = Analytics::UsageTrends::Measurement.groups.first + expect(measurement.recorded_at).to be_like_time(recorded_at) + expect(measurement.identifier).to eq('groups') + expect(measurement.count).to eq(0) + end + end + + it 'does not raise error when inserting duplicated measurement' do + subject + + expect { subject }.not_to raise_error + end + + it 'does not insert anything when BatchCount returns error' do + allow(Gitlab::Database::BatchCount).to receive(:batch_count).and_return(Gitlab::Database::BatchCounter::FALLBACK) + + expect { subject }.not_to change { Analytics::UsageTrends::Measurement.count } + end + + context 'when pipelines_succeeded identifier is passed' do + let_it_be(:pipeline) { create(:ci_pipeline, :success) } + + let(:successful_pipelines_measurement_identifier) { ::Analytics::UsageTrends::Measurement.identifiers.fetch(:pipelines_succeeded) } + let(:job_args) { [successful_pipelines_measurement_identifier, pipeline.id, pipeline.id, recorded_at] } + + it 'counts successful pipelines' do + subject + + measurement = Analytics::UsageTrends::Measurement.pipelines_succeeded.first + expect(measurement.recorded_at).to be_like_time(recorded_at) + expect(measurement.identifier).to eq('pipelines_succeeded') + expect(measurement.count).to eq(1) + end + end +end diff --git a/spec/workers/emails_on_push_worker_spec.rb b/spec/workers/emails_on_push_worker_spec.rb index fac463b4dd4..6c37c422aed 100644 --- a/spec/workers/emails_on_push_worker_spec.rb +++ b/spec/workers/emails_on_push_worker_spec.rb @@ -97,7 +97,7 @@ RSpec.describe EmailsOnPushWorker, :mailer do end it "gracefully handles an input SMTP error" do - expect(ActionMailer::Base.deliveries.count).to eq(0) + expect(ActionMailer::Base.deliveries).to be_empty end end @@ -112,6 +112,16 @@ RSpec.describe EmailsOnPushWorker, :mailer do end end + context "with mixed-case recipient" do + let(:recipients) { user.email.upcase } + + it "retains the case" do + perform + + expect(email_recipients).to contain_exactly(recipients) + end + end + context "when the recipient addresses are a list of email addresses" do let(:recipients) do 1.upto(5).map { |i| user.email.sub('@', "+#{i}@") }.join("\n") @@ -120,7 +130,6 @@ RSpec.describe EmailsOnPushWorker, :mailer do it "sends the mail to each of the recipients" do perform - expect(ActionMailer::Base.deliveries.count).to eq(5) expect(email_recipients).to contain_exactly(*recipients.split) end @@ -132,13 +141,22 @@ RSpec.describe EmailsOnPushWorker, :mailer do end end + context "when recipients are invalid" do + let(:recipients) { "invalid\n\nrecipients" } + + it "ignores them" do + perform + + expect(ActionMailer::Base.deliveries).to be_empty + end + end + context "when the recipient addresses contains angle brackets and are separated by spaces" do let(:recipients) { "John Doe <johndoe@example.com> Jane Doe <janedoe@example.com>" } it "accepts emails separated by whitespace" do perform - expect(ActionMailer::Base.deliveries.count).to eq(2) expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com") end end @@ -149,7 +167,6 @@ RSpec.describe EmailsOnPushWorker, :mailer do it "accepts both kind of emails" do perform - expect(ActionMailer::Base.deliveries.count).to eq(2) expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com") end end @@ -160,10 +177,19 @@ RSpec.describe EmailsOnPushWorker, :mailer do it "accepts emails separated by newlines" do perform - expect(ActionMailer::Base.deliveries.count).to eq(2) expect(email_recipients).to contain_exactly("johndoe@example.com", "janedoe@example.com") end end + + context 'when the recipient addresses contains duplicates' do + let(:recipients) { 'non@dubplicate.com Duplic@te.com duplic@te.com Duplic@te.com duplic@Te.com' } + + it 'deduplicates recipients while treating the domain part as case-insensitive' do + perform + + expect(email_recipients).to contain_exactly('non@dubplicate.com', 'Duplic@te.com') + end + end end end end diff --git a/spec/workers/error_tracking_issue_link_worker_spec.rb b/spec/workers/error_tracking_issue_link_worker_spec.rb index 5be568c2dad..90e747c8788 100644 --- a/spec/workers/error_tracking_issue_link_worker_spec.rb +++ b/spec/workers/error_tracking_issue_link_worker_spec.rb @@ -20,7 +20,7 @@ RSpec.describe ErrorTrackingIssueLinkWorker do describe '#perform' do it 'creates a link between an issue and a Sentry issue in Sentry' do - expect_next_instance_of(Sentry::Client) do |client| + expect_next_instance_of(ErrorTracking::SentryClient) do |client| expect(client).to receive(:repos).with('sentry-org').and_return([repo]) expect(client) .to receive(:create_issue_link) @@ -33,8 +33,8 @@ RSpec.describe ErrorTrackingIssueLinkWorker do shared_examples_for 'makes no external API requests' do it 'takes no action' do - expect_any_instance_of(Sentry::Client).not_to receive(:repos) - expect_any_instance_of(Sentry::Client).not_to receive(:create_issue_link) + expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:repos) + expect_any_instance_of(ErrorTracking::SentryClient).not_to receive(:create_issue_link) expect(subject).to be nil end @@ -42,7 +42,7 @@ RSpec.describe ErrorTrackingIssueLinkWorker do shared_examples_for 'attempts to create a link via plugin' do it 'takes no action' do - expect_next_instance_of(Sentry::Client) do |client| + expect_next_instance_of(ErrorTracking::SentryClient) do |client| expect(client).to receive(:repos).with('sentry-org').and_return([repo]) expect(client) .to receive(:create_issue_link) @@ -98,8 +98,8 @@ RSpec.describe ErrorTrackingIssueLinkWorker do context 'when Sentry repos request errors' do it 'falls back to creating a link via plugin' do - expect_next_instance_of(Sentry::Client) do |client| - expect(client).to receive(:repos).with('sentry-org').and_raise(Sentry::Client::Error) + expect_next_instance_of(ErrorTracking::SentryClient) do |client| + expect(client).to receive(:repos).with('sentry-org').and_raise(ErrorTracking::SentryClient::Error) expect(client) .to receive(:create_issue_link) .with(nil, sentry_issue.sentry_issue_identifier, issue) diff --git a/spec/workers/expire_job_cache_worker_spec.rb b/spec/workers/expire_job_cache_worker_spec.rb index b4f8f56563b..95c54a762a4 100644 --- a/spec/workers/expire_job_cache_worker_spec.rb +++ b/spec/workers/expire_job_cache_worker_spec.rb @@ -13,7 +13,6 @@ RSpec.describe ExpireJobCacheWorker do include_examples 'an idempotent worker' do it 'invalidates Etag caching for the job path' do - pipeline_path = "/#{project.full_path}/-/pipelines/#{pipeline.id}.json" job_path = "/#{project.full_path}/builds/#{job.id}.json" spy_store = Gitlab::EtagCaching::Store.new @@ -22,13 +21,12 @@ RSpec.describe ExpireJobCacheWorker do expect(spy_store).to receive(:touch) .exactly(worker_exec_times).times - .with(pipeline_path) + .with(job_path) .and_call_original - expect(spy_store).to receive(:touch) + expect(ExpirePipelineCacheWorker).to receive(:perform_async) + .with(pipeline.id) .exactly(worker_exec_times).times - .with(job_path) - .and_call_original subject end diff --git a/spec/workers/expire_pipeline_cache_worker_spec.rb b/spec/workers/expire_pipeline_cache_worker_spec.rb index fb6ee67311c..a8c21aa9f83 100644 --- a/spec/workers/expire_pipeline_cache_worker_spec.rb +++ b/spec/workers/expire_pipeline_cache_worker_spec.rb @@ -25,15 +25,6 @@ RSpec.describe ExpirePipelineCacheWorker do subject.perform(617748) end - it "doesn't do anything if the pipeline cannot be cached" do - allow_any_instance_of(Ci::Pipeline).to receive(:cacheable?).and_return(false) - - expect_any_instance_of(Ci::ExpirePipelineCacheService).not_to receive(:execute) - expect_any_instance_of(Gitlab::EtagCaching::Store).not_to receive(:touch) - - subject.perform(pipeline.id) - end - it_behaves_like 'an idempotent worker' do let(:job_args) { [pipeline.id] } end diff --git a/spec/workers/jira_connect/sync_project_worker_spec.rb b/spec/workers/jira_connect/sync_project_worker_spec.rb index f7fa565d534..04cc3bec3af 100644 --- a/spec/workers/jira_connect/sync_project_worker_spec.rb +++ b/spec/workers/jira_connect/sync_project_worker_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe JiraConnect::SyncProjectWorker, factory_default: :keep do describe '#perform' do - let_it_be(:project) { create_default(:project) } + let_it_be(:project) { create_default(:project).freeze } let!(:mr_with_jira_title) { create(:merge_request, :unique_branches, title: 'TEST-123') } let!(:mr_with_jira_description) { create(:merge_request, :unique_branches, description: 'TEST-323') } let!(:mr_with_other_title) { create(:merge_request, :unique_branches) } diff --git a/spec/workers/merge_requests/delete_source_branch_worker_spec.rb b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb new file mode 100644 index 00000000000..957adbbbd6e --- /dev/null +++ b/spec/workers/merge_requests/delete_source_branch_worker_spec.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe MergeRequests::DeleteSourceBranchWorker do + let_it_be(:merge_request) { create(:merge_request) } + let_it_be(:user) { create(:user) } + + let(:sha) { merge_request.source_branch_sha } + let(:worker) { described_class.new } + + describe '#perform' do + context 'with a non-existing merge request' do + it 'does nothing' do + expect(::Branches::DeleteService).not_to receive(:new) + expect(::MergeRequests::RetargetChainService).not_to receive(:new) + + worker.perform(non_existing_record_id, sha, user.id) + end + end + + context 'with a non-existing user' do + it 'does nothing' do + expect(::Branches::DeleteService).not_to receive(:new) + expect(::MergeRequests::RetargetChainService).not_to receive(:new) + + worker.perform(merge_request.id, sha, non_existing_record_id) + end + end + + context 'with existing user and merge request' do + it 'calls service to delete source branch' do + expect_next_instance_of(::Branches::DeleteService) do |instance| + expect(instance).to receive(:execute).with(merge_request.source_branch) + end + + worker.perform(merge_request.id, sha, user.id) + end + + it 'calls service to try retarget merge requests' do + expect_next_instance_of(::MergeRequests::RetargetChainService) do |instance| + expect(instance).to receive(:execute).with(merge_request) + end + + worker.perform(merge_request.id, sha, user.id) + end + + context 'source branch sha does not match' do + it 'does nothing' do + expect(::Branches::DeleteService).not_to receive(:new) + expect(::MergeRequests::RetargetChainService).not_to receive(:new) + + worker.perform(merge_request.id, 'new-source-branch-sha', user.id) + end + end + end + + it_behaves_like 'an idempotent worker' do + let(:merge_request) { create(:merge_request) } + let(:job_args) { [merge_request.id, sha, user.id] } + end + end +end diff --git a/spec/workers/merge_worker_spec.rb b/spec/workers/merge_worker_spec.rb index 97e8aeb616e..417e6edce96 100644 --- a/spec/workers/merge_worker_spec.rb +++ b/spec/workers/merge_worker_spec.rb @@ -14,7 +14,7 @@ RSpec.describe MergeWorker do source_project.repository.expire_branches_cache end - it 'clears cache of source repo after removing source branch' do + it 'clears cache of source repo after removing source branch', :sidekiq_inline do expect(source_project.repository.branch_names).to include('markdown') described_class.new.perform( diff --git a/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb index 722ecfc1dec..24143e8cf8a 100644 --- a/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb +++ b/spec/workers/namespaces/in_product_marketing_emails_worker_spec.rb @@ -3,25 +3,43 @@ require 'spec_helper' RSpec.describe Namespaces::InProductMarketingEmailsWorker, '#perform' do - context 'when the experiment is inactive' do + context 'when the application setting is enabled' do before do - stub_experiment(in_product_marketing_emails: false) + stub_application_setting(in_product_marketing_emails_enabled: true) end - it 'does not execute the in product marketing emails service' do - expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals) + context 'when the experiment is inactive' do + before do + stub_experiment(in_product_marketing_emails: false) + end - subject.perform + it 'does not execute the in product marketing emails service' do + expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals) + + subject.perform + end + end + + context 'when the experiment is active' do + before do + stub_experiment(in_product_marketing_emails: true) + end + + it 'calls the send_for_all_tracks_and_intervals method on the in product marketing emails service' do + expect(Namespaces::InProductMarketingEmailsService).to receive(:send_for_all_tracks_and_intervals) + + subject.perform + end end end - context 'when the experiment is active' do + context 'when the application setting is disabled' do before do - stub_experiment(in_product_marketing_emails: true) + stub_application_setting(in_product_marketing_emails_enabled: false) end - it 'calls the send_for_all_tracks_and_intervals method on the in product marketing emails service' do - expect(Namespaces::InProductMarketingEmailsService).to receive(:send_for_all_tracks_and_intervals) + it 'does not execute the in product marketing emails service' do + expect(Namespaces::InProductMarketingEmailsService).not_to receive(:send_for_all_tracks_and_intervals) subject.perform end diff --git a/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb b/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb new file mode 100644 index 00000000000..459e4f953d0 --- /dev/null +++ b/spec/workers/namespaces/onboarding_issue_created_worker_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Namespaces::OnboardingIssueCreatedWorker, '#perform' do + let_it_be(:issue) { create(:issue) } + let(:namespace) { issue.namespace } + + it_behaves_like 'records an onboarding progress action', :issue_created do + subject { described_class.new.perform(namespace.id) } + end + + it_behaves_like 'does not record an onboarding progress action' do + subject { described_class.new.perform(nil) } + end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { [namespace.id] } + + it 'sets the onboarding progress action' do + OnboardingProgress.onboard(namespace) + + subject + + expect(OnboardingProgress.completed?(namespace, :issue_created)).to eq(true) + end + end +end diff --git a/spec/workers/namespaces/onboarding_progress_worker_spec.rb b/spec/workers/namespaces/onboarding_progress_worker_spec.rb new file mode 100644 index 00000000000..76ac078ddcf --- /dev/null +++ b/spec/workers/namespaces/onboarding_progress_worker_spec.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Namespaces::OnboardingProgressWorker, '#perform' do + let_it_be(:namespace) { create(:namespace) } + let_it_be(:action) { 'git_pull' } + + it_behaves_like 'records an onboarding progress action', :git_pull do + include_examples 'an idempotent worker' do + subject { described_class.new.perform(namespace.id, action) } + end + end + + it_behaves_like 'does not record an onboarding progress action' do + subject { described_class.new.perform(namespace.id, nil) } + end + + it_behaves_like 'does not record an onboarding progress action' do + subject { described_class.new.perform(nil, action) } + end +end diff --git a/spec/workers/new_issue_worker_spec.rb b/spec/workers/new_issue_worker_spec.rb index 7cba3487603..ec129ad3380 100644 --- a/spec/workers/new_issue_worker_spec.rb +++ b/spec/workers/new_issue_worker_spec.rb @@ -38,21 +38,48 @@ RSpec.describe NewIssueWorker do end end - context 'when everything is ok' do - let_it_be(:user) { create_default(:user) } + context 'with a user' do let_it_be(:project) { create(:project, :public) } let_it_be(:mentioned) { create(:user) } + let_it_be(:user) { nil } let_it_be(:issue) { create(:issue, project: project, description: "issue for #{mentioned.to_reference}") } - it 'creates a new event record' do - expect { worker.perform(issue.id, user.id) }.to change { Event.count }.from(0).to(1) + shared_examples 'a new issue where the current_user cannot trigger notifications' do + it 'does not create a notification for the mentioned user' do + expect(Notify).not_to receive(:new_issue_email) + .with(mentioned.id, issue.id, NotificationReason::MENTIONED) + + expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: issue.class, object_id: issue.id) + + worker.perform(issue.id, user.id) + end + end + + context 'when the new issue author is blocked' do + let_it_be(:user) { create_default(:user, :blocked) } + + it_behaves_like 'a new issue where the current_user cannot trigger notifications' end - it 'creates a notification for the mentioned user' do - expect(Notify).to receive(:new_issue_email).with(mentioned.id, issue.id, NotificationReason::MENTIONED) - .and_return(double(deliver_later: true)) + context 'when the new issue author is a ghost' do + let_it_be(:user) { create_default(:user, :ghost) } + + it_behaves_like 'a new issue where the current_user cannot trigger notifications' + end + + context 'when everything is ok' do + let_it_be(:user) { create_default(:user) } + + it 'creates a new event record' do + expect { worker.perform(issue.id, user.id) }.to change { Event.count }.from(0).to(1) + end + + it 'creates a notification for the mentioned user' do + expect(Notify).to receive(:new_issue_email).with(mentioned.id, issue.id, NotificationReason::MENTIONED) + .and_return(double(deliver_later: true)) - worker.perform(issue.id, user.id) + worker.perform(issue.id, user.id) + end end end end diff --git a/spec/workers/new_merge_request_worker_spec.rb b/spec/workers/new_merge_request_worker_spec.rb index 310fde4c7e1..0d64973b0fa 100644 --- a/spec/workers/new_merge_request_worker_spec.rb +++ b/spec/workers/new_merge_request_worker_spec.rb @@ -40,24 +40,51 @@ RSpec.describe NewMergeRequestWorker do end end - context 'when everything is ok' do + context 'with a user' do let(:project) { create(:project, :public) } let(:mentioned) { create(:user) } - let(:user) { create(:user) } + let(:user) { nil } let(:merge_request) do create(:merge_request, source_project: project, description: "mr for #{mentioned.to_reference}") end - it 'creates a new event record' do - expect { worker.perform(merge_request.id, user.id) }.to change { Event.count }.from(0).to(1) + shared_examples 'a new merge request where the author cannot trigger notifications' do + it 'does not create a notification for the mentioned user' do + expect(Notify).not_to receive(:new_merge_request_email) + .with(mentioned.id, merge_request.id, NotificationReason::MENTIONED) + + expect(Gitlab::AppLogger).to receive(:warn).with(message: 'Skipping sending notifications', user: user.id, klass: merge_request.class, object_id: merge_request.id) + + worker.perform(merge_request.id, user.id) + end + end + + context 'when the merge request author is blocked' do + let(:user) { create(:user, :blocked) } + + it_behaves_like 'a new merge request where the author cannot trigger notifications' end - it 'creates a notification for the mentioned user' do - expect(Notify).to receive(:new_merge_request_email) - .with(mentioned.id, merge_request.id, NotificationReason::MENTIONED) - .and_return(double(deliver_later: true)) + context 'when the merge request author is a ghost' do + let(:user) { create(:user, :ghost) } + + it_behaves_like 'a new merge request where the author cannot trigger notifications' + end + + context 'when everything is ok' do + let(:user) { create(:user) } + + it 'creates a new event record' do + expect { worker.perform(merge_request.id, user.id) }.to change { Event.count }.from(0).to(1) + end + + it 'creates a notification for the mentioned user' do + expect(Notify).to receive(:new_merge_request_email) + .with(mentioned.id, merge_request.id, NotificationReason::MENTIONED) + .and_return(double(deliver_later: true)) - worker.perform(merge_request.id, user.id) + worker.perform(merge_request.id, user.id) + end end end end diff --git a/spec/workers/packages/composer/cache_update_worker_spec.rb b/spec/workers/packages/composer/cache_update_worker_spec.rb new file mode 100644 index 00000000000..cc6b48c80eb --- /dev/null +++ b/spec/workers/packages/composer/cache_update_worker_spec.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Composer::CacheUpdateWorker, type: :worker do + describe '#perform' do + let_it_be(:package_name) { 'sample-project' } + let_it_be(:json) { { 'name' => package_name } } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, :custom_repo, files: { 'composer.json' => json.to_json }, group: group) } + let(:last_sha) { nil } + let!(:package) { create(:composer_package, :with_metadatum, project: project, name: package_name, version: '1.0.0', json: json) } + let(:job_args) { [project.id, package_name, last_sha] } + + subject { described_class.new.perform(*job_args) } + + before do + stub_composer_cache_object_storage + end + + include_examples 'an idempotent worker' do + context 'creating a package' do + it 'updates the cache' do + expect { subject }.to change { Packages::Composer::CacheFile.count }.by(1) + end + end + + context 'deleting a package' do + let!(:last_sha) do + Gitlab::Composer::Cache.new(project: project, name: package_name).execute + package.reload.composer_metadatum.version_cache_sha + end + + before do + package.destroy! + end + + it 'marks the file for deletion' do + expect { subject }.not_to change { Packages::Composer::CacheFile.count } + + cache_file = Packages::Composer::CacheFile.last + + expect(cache_file.reload.delete_at).not_to be_nil + end + end + end + end +end diff --git a/spec/workers/packages/maven/metadata/sync_worker_spec.rb b/spec/workers/packages/maven/metadata/sync_worker_spec.rb new file mode 100644 index 00000000000..7e0f3616491 --- /dev/null +++ b/spec/workers/packages/maven/metadata/sync_worker_spec.rb @@ -0,0 +1,253 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Packages::Maven::Metadata::SyncWorker, type: :worker do + let_it_be(:versionless_package_for_versions) { create(:maven_package, name: 'MyDummyMavenPkg', version: nil) } + let_it_be(:metadata_package_file) { create(:package_file, :xml, package: versionless_package_for_versions) } + + let(:versions) { %w[1.2 1.1 2.1 3.0-SNAPSHOT] } + let(:worker) { described_class.new } + + describe '#perform' do + let(:user) { create(:user) } + let(:project) { versionless_package_for_versions.project } + let(:package_name) { versionless_package_for_versions.name } + let(:role) { :maintainer } + let(:most_recent_metadata_file_for_versions) { versionless_package_for_versions.package_files.recent.with_file_name(Packages::Maven::Metadata.filename).first } + + before do + project.send("add_#{role}", user) + end + + subject { worker.perform(user.id, project.id, package_name) } + + context 'with a jar' do + context 'with a valid package name' do + before do + metadata_package_file.update!( + file: CarrierWaveStringFile.new_file( + file_content: versions_xml_content, + filename: 'maven-metadata.xml', + content_type: 'application/xml' + ) + ) + + versions.each do |version| + create(:maven_package, name: versionless_package_for_versions.name, version: version, project: versionless_package_for_versions.project) + end + end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { [user.id, project.id, package_name] } + + it 'creates the updated metadata files', :aggregate_failures do + expect { subject }.to change { ::Packages::PackageFile.count }.by(5) + + most_recent_versions = versions_from(most_recent_metadata_file_for_versions.file.read) + expect(most_recent_versions.latest).to eq('3.0-SNAPSHOT') + expect(most_recent_versions.release).to eq('2.1') + expect(most_recent_versions.versions).to match_array(versions) + end + end + + it 'logs the message from the service' do + expect(worker).to receive(:log_extra_metadata_on_done).with(:message, 'New metadata package file created') + + subject + end + + context 'not in the passed project' do + let(:project) { create(:project) } + + it 'does not create the updated metadata files' do + expect { subject } + .to change { ::Packages::PackageFile.count }.by(0) + .and raise_error(described_class::SyncError, 'Non existing versionless package') + end + end + + context 'with a user with not enough permissions' do + let(:role) { :guest } + + it 'does not create the updated metadata files' do + expect { subject } + .to change { ::Packages::PackageFile.count }.by(0) + .and raise_error(described_class::SyncError, 'Not allowed') + end + end + end + end + + context 'with a maven plugin' do + let_it_be(:versionless_package_name_for_plugins) { versionless_package_for_versions.maven_metadatum.app_group.tr('.', '/') } + let_it_be(:versionless_package_for_versions) { create(:maven_package, name: "#{versionless_package_name_for_plugins}/one-maven-plugin", version: nil) } + let_it_be(:metadata_package_file) { create(:package_file, :xml, package: versionless_package_for_versions) } + + let_it_be(:versionless_package_for_plugins) { create(:maven_package, name: versionless_package_name_for_plugins, version: nil, project: versionless_package_for_versions.project) } + let_it_be(:metadata_package_file_for_plugins) { create(:package_file, :xml, package: versionless_package_for_plugins) } + + let_it_be(:addtional_maven_package_for_same_group_id) { create(:maven_package, name: "#{versionless_package_name_for_plugins}/maven-package", project: versionless_package_for_versions.project) } + + let(:plugins) { %w[one-maven-plugin three-maven-plugin] } + let(:most_recent_metadata_file_for_plugins) { versionless_package_for_plugins.package_files.recent.with_file_name(Packages::Maven::Metadata.filename).first } + + context 'with a valid package name' do + before do + versionless_package_for_versions.update!(name: package_name) + + metadata_package_file.update!( + file: CarrierWaveStringFile.new_file( + file_content: versions_xml_content, + filename: 'maven-metadata.xml', + content_type: 'application/xml' + ) + ) + + metadata_package_file_for_plugins.update!( + file: CarrierWaveStringFile.new_file( + file_content: plugins_xml_content, + filename: 'maven-metadata.xml', + content_type: 'application/xml' + ) + ) + + plugins.each do |plugin| + versions.each do |version| + pkg = create(:maven_package, name: "#{versionless_package_name_for_plugins}/#{plugin}", version: version, project: versionless_package_for_versions.project) + pkg.maven_metadatum.update!(app_name: plugin) + end + end + end + + it_behaves_like 'an idempotent worker' do + let(:job_args) { [user.id, project.id, package_name] } + + it 'creates the updated metadata files', :aggregate_failures do + expect { subject }.to change { ::Packages::PackageFile.count }.by(5 * 2) # the two xml files are updated + + most_recent_versions = versions_from(most_recent_metadata_file_for_versions.file.read) + expect(most_recent_versions.latest).to eq('3.0-SNAPSHOT') + expect(most_recent_versions.release).to eq('2.1') + expect(most_recent_versions.versions).to match_array(versions) + + plugins_from_xml = plugins_from(most_recent_metadata_file_for_plugins.file.read) + expect(plugins_from_xml).to match_array(plugins) + end + end + + it 'logs the message from the service' do + expect(worker).to receive(:log_extra_metadata_on_done).with(:message, 'New metadata package file created') + + subject + end + + context 'not in the passed project' do + let(:project) { create(:project) } + + it 'does not create the updated metadata files' do + expect { subject } + .to change { ::Packages::PackageFile.count }.by(0) + .and raise_error(described_class::SyncError, 'Non existing versionless package') + end + end + + context 'with a user with not enough permissions' do + let(:role) { :guest } + + it 'does not create the updated metadata files' do + expect { subject } + .to change { ::Packages::PackageFile.count }.by(0) + .and raise_error(described_class::SyncError, 'Not allowed') + end + end + end + end + + context 'with no package name' do + subject { worker.perform(user.id, project.id, nil) } + + it 'does not run' do + expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new) + expect { subject }.not_to change { ::Packages::PackageFile.count } + end + end + + context 'with no user id' do + subject { worker.perform(nil, project.id, package_name) } + + it 'does not run' do + expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new) + expect { subject }.not_to change { ::Packages::PackageFile.count } + end + end + + context 'with no project id' do + subject { worker.perform(user.id, nil, package_name) } + + it 'does not run' do + expect(::Packages::Maven::Metadata::SyncService).not_to receive(:new) + expect { subject }.not_to change { ::Packages::PackageFile.count } + end + end + end + + def versions_from(xml_content) + xml_doc = Nokogiri::XML(xml_content) + + OpenStruct.new( + release: xml_doc.xpath('//metadata/versioning/release').first.content, + latest: xml_doc.xpath('//metadata/versioning/latest').first.content, + versions: xml_doc.xpath('//metadata/versioning/versions/version').map(&:content) + ) + end + + def plugins_from(xml_content) + xml_doc = Nokogiri::XML(xml_content) + + xml_doc.xpath('//metadata/plugins/plugin/name').map(&:content) + end + + def versions_xml_content + Nokogiri::XML::Builder.new do |xml| + xml.metadata do + xml.groupId(versionless_package_for_versions.maven_metadatum.app_group) + xml.artifactId(versionless_package_for_versions.maven_metadatum.app_name) + xml.versioning do + xml.release('1.3') + xml.latest('1.3') + xml.lastUpdated('20210113130531') + xml.versions do + xml.version('1.1') + xml.version('1.2') + xml.version('1.3') + end + end + end + end.to_xml + end + + def plugins_xml_content + Nokogiri::XML::Builder.new do |xml| + xml.metadata do + xml.plugins do + xml.plugin do + xml.name('one-maven-plugin') + xml.prefix('one') + xml.artifactId('one-maven-plugin') + end + xml.plugin do + xml.name('two-maven-plugin') + xml.prefix('two') + xml.artifactId('two-maven-plugin') + end + xml.plugin do + xml.name('three-maven-plugin') + xml.prefix('three') + xml.artifactId('three-maven-plugin') + end + end + end + end.to_xml + end +end diff --git a/spec/workers/pages_update_configuration_worker_spec.rb b/spec/workers/pages_update_configuration_worker_spec.rb index 87bbff1a28b..ff3727646c7 100644 --- a/spec/workers/pages_update_configuration_worker_spec.rb +++ b/spec/workers/pages_update_configuration_worker_spec.rb @@ -2,9 +2,9 @@ require "spec_helper" RSpec.describe PagesUpdateConfigurationWorker do - describe "#perform" do - let_it_be(:project) { create(:project) } + let_it_be(:project) { create(:project) } + describe "#perform" do it "does not break if the project doesn't exist" do expect { subject.perform(-1) }.not_to raise_error end @@ -42,4 +42,22 @@ RSpec.describe PagesUpdateConfigurationWorker do end end end + + describe '#perform_async' do + it "calls the correct service", :sidekiq_inline do + expect_next_instance_of(Projects::UpdatePagesConfigurationService, project) do |service| + expect(service).to receive(:execute).and_return(status: :success) + end + + described_class.perform_async(project.id) + end + + it "doesn't schedule a worker if updates on legacy storage are disabled", :sidekiq_inline do + stub_feature_flags(pages_update_legacy_storage: false) + + expect(Projects::UpdatePagesConfigurationService).not_to receive(:new) + + described_class.perform_async(project.id) + end + end end diff --git a/spec/workers/personal_access_tokens/expiring_worker_spec.rb b/spec/workers/personal_access_tokens/expiring_worker_spec.rb index c8bdf02f4d3..7fa777b911a 100644 --- a/spec/workers/personal_access_tokens/expiring_worker_spec.rb +++ b/spec/workers/personal_access_tokens/expiring_worker_spec.rb @@ -7,18 +7,23 @@ RSpec.describe PersonalAccessTokens::ExpiringWorker, type: :worker do describe '#perform' do context 'when a token needs to be notified' do - let_it_be(:pat) { create(:personal_access_token, expires_at: 5.days.from_now) } + let_it_be(:user) { create(:user) } + let_it_be(:expiring_token) { create(:personal_access_token, user: user, expires_at: 5.days.from_now) } + let_it_be(:expiring_token2) { create(:personal_access_token, user: user, expires_at: 3.days.from_now) } + let_it_be(:notified_token) { create(:personal_access_token, user: user, expires_at: 5.days.from_now, expire_notification_delivered: true) } + let_it_be(:not_expiring_token) { create(:personal_access_token, user: user, expires_at: 1.month.from_now) } + let_it_be(:impersonation_token) { create(:personal_access_token, user: user, expires_at: 5.days.from_now, impersonation: true) } it 'uses notification service to send the email' do expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).to receive(:access_token_about_to_expire).with(pat.user) + expect(notification_service).to receive(:access_token_about_to_expire).with(user, match_array([expiring_token.name, expiring_token2.name])) end worker.perform end it 'marks the notification as delivered' do - expect { worker.perform }.to change { pat.reload.expire_notification_delivered }.from(false).to(true) + expect { worker.perform }.to change { expiring_token.reload.expire_notification_delivered }.from(false).to(true) end end @@ -27,7 +32,7 @@ RSpec.describe PersonalAccessTokens::ExpiringWorker, type: :worker do it "doesn't use notification service to send the email" do expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).not_to receive(:access_token_about_to_expire).with(pat.user) + expect(notification_service).not_to receive(:access_token_about_to_expire).with(pat.user, [pat.name]) end worker.perform @@ -43,7 +48,7 @@ RSpec.describe PersonalAccessTokens::ExpiringWorker, type: :worker do it "doesn't use notification service to send the email" do expect_next_instance_of(NotificationService) do |notification_service| - expect(notification_service).not_to receive(:access_token_about_to_expire).with(pat.user) + expect(notification_service).not_to receive(:access_token_about_to_expire).with(pat.user, [pat.name]) end worker.perform diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb index aaae0988602..be501318920 100644 --- a/spec/workers/post_receive_spec.rb +++ b/spec/workers/post_receive_spec.rb @@ -93,6 +93,29 @@ RSpec.describe PostReceive do perform end + + it 'tracks an event for the empty_repo_upload experiment', :snowplow do + allow_next_instance_of(ApplicationExperiment) do |e| + allow(e).to receive(:should_track?).and_return(true) + allow(e).to receive(:track_initial_writes) + end + + perform + + expect_snowplow_event(category: 'empty_repo_upload', action: 'initial_write', context: [{ schema: 'iglu:com.gitlab/gitlab_experiment/jsonschema/0-3-0', data: anything }]) + end + + it 'does not track an event for the empty_repo_upload experiment when project is not empty', :snowplow do + allow(empty_project).to receive(:empty_repo?).and_return(false) + allow_next_instance_of(ApplicationExperiment) do |e| + allow(e).to receive(:should_track?).and_return(true) + allow(e).to receive(:track_initial_writes) + end + + perform + + expect_no_snowplow_event + end end shared_examples 'not updating remote mirrors' do @@ -159,7 +182,7 @@ RSpec.describe PostReceive do end it 'expires the status cache' do - expect(project.repository).to receive(:empty?).and_return(true) + expect(project.repository).to receive(:empty?).at_least(:once).and_return(true) expect(project.repository).to receive(:expire_status_cache) perform diff --git a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb index fb762593d75..f284e1ab8c6 100644 --- a/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb +++ b/spec/workers/project_schedule_bulk_repository_shard_moves_worker_spec.rb @@ -6,7 +6,7 @@ RSpec.describe ProjectScheduleBulkRepositoryShardMovesWorker do it_behaves_like 'schedules bulk repository shard moves' do let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } } - let(:move_service_klass) { ProjectRepositoryStorageMove } - let(:worker_klass) { ProjectUpdateRepositoryStorageWorker } + let(:move_service_klass) { Projects::RepositoryStorageMove } + let(:worker_klass) { Projects::UpdateRepositoryStorageWorker } end end diff --git a/spec/workers/project_update_repository_storage_worker_spec.rb b/spec/workers/project_update_repository_storage_worker_spec.rb index 490f1f5a2ad..6924e8a93a3 100644 --- a/spec/workers/project_update_repository_storage_worker_spec.rb +++ b/spec/workers/project_update_repository_storage_worker_spec.rb @@ -10,6 +10,6 @@ RSpec.describe ProjectUpdateRepositoryStorageWorker do let_it_be(:repository_storage_move) { create(:project_repository_storage_move) } let(:service_klass) { Projects::UpdateRepositoryStorageService } - let(:repository_storage_move_klass) { ProjectRepositoryStorageMove } + let(:repository_storage_move_klass) { Projects::RepositoryStorageMove } end end diff --git a/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb new file mode 100644 index 00000000000..24957a35b72 --- /dev/null +++ b/spec/workers/projects/schedule_bulk_repository_shard_moves_worker_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::ScheduleBulkRepositoryShardMovesWorker do + it_behaves_like 'schedules bulk repository shard moves' do + let_it_be_with_reload(:container) { create(:project, :repository).tap { |project| project.track_project_repository } } + + let(:move_service_klass) { Projects::RepositoryStorageMove } + let(:worker_klass) { Projects::UpdateRepositoryStorageWorker } + end +end diff --git a/spec/workers/projects/update_repository_storage_worker_spec.rb b/spec/workers/projects/update_repository_storage_worker_spec.rb new file mode 100644 index 00000000000..7570d706325 --- /dev/null +++ b/spec/workers/projects/update_repository_storage_worker_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Projects::UpdateRepositoryStorageWorker do + subject { described_class.new } + + it_behaves_like 'an update storage move worker' do + let_it_be_with_refind(:container) { create(:project, :repository) } + let_it_be(:repository_storage_move) { create(:project_repository_storage_move) } + + let(:service_klass) { Projects::UpdateRepositoryStorageService } + let(:repository_storage_move_klass) { Projects::RepositoryStorageMove } + end +end diff --git a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb index 8379b11af8f..53f8d1bf5ba 100644 --- a/spec/workers/purge_dependency_proxy_cache_worker_spec.rb +++ b/spec/workers/purge_dependency_proxy_cache_worker_spec.rb @@ -26,19 +26,25 @@ RSpec.describe PurgeDependencyProxyCacheWorker do end context 'an admin user' do - include_examples 'an idempotent worker' do - let(:job_args) { [user.id, group_id] } + context 'when admin mode is enabled', :enable_admin_mode do + include_examples 'an idempotent worker' do + let(:job_args) { [user.id, group_id] } - it 'deletes the blobs and returns ok', :aggregate_failures do - expect(group.dependency_proxy_blobs.size).to eq(1) - expect(group.dependency_proxy_manifests.size).to eq(1) + it 'deletes the blobs and returns ok', :aggregate_failures do + expect(group.dependency_proxy_blobs.size).to eq(1) + expect(group.dependency_proxy_manifests.size).to eq(1) - subject + subject - expect(group.dependency_proxy_blobs.size).to eq(0) - expect(group.dependency_proxy_manifests.size).to eq(0) + expect(group.dependency_proxy_blobs.size).to eq(0) + expect(group.dependency_proxy_manifests.size).to eq(0) + end end end + + context 'when admin mode is disabled' do + it_behaves_like 'returns nil' + end end context 'a non-admin user' do diff --git a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb index 3a09b6ce449..a5f1c6b7b3d 100644 --- a/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb +++ b/spec/workers/snippet_schedule_bulk_repository_shard_moves_worker_spec.rb @@ -6,7 +6,7 @@ RSpec.describe SnippetScheduleBulkRepositoryShardMovesWorker do it_behaves_like 'schedules bulk repository shard moves' do let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } } - let(:move_service_klass) { SnippetRepositoryStorageMove } - let(:worker_klass) { SnippetUpdateRepositoryStorageWorker } + let(:move_service_klass) { Snippets::RepositoryStorageMove } + let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker } end end diff --git a/spec/workers/snippet_update_repository_storage_worker_spec.rb b/spec/workers/snippet_update_repository_storage_worker_spec.rb index a48abe4abf7..205cb2e432f 100644 --- a/spec/workers/snippet_update_repository_storage_worker_spec.rb +++ b/spec/workers/snippet_update_repository_storage_worker_spec.rb @@ -10,6 +10,6 @@ RSpec.describe SnippetUpdateRepositoryStorageWorker do let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) } let(:service_klass) { Snippets::UpdateRepositoryStorageService } - let(:repository_storage_move_klass) { SnippetRepositoryStorageMove } + let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove } end end diff --git a/spec/workers/snippets/schedule_bulk_repository_shard_moves_worker_spec.rb b/spec/workers/snippets/schedule_bulk_repository_shard_moves_worker_spec.rb new file mode 100644 index 00000000000..be7d8ebe2d3 --- /dev/null +++ b/spec/workers/snippets/schedule_bulk_repository_shard_moves_worker_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Snippets::ScheduleBulkRepositoryShardMovesWorker do + it_behaves_like 'schedules bulk repository shard moves' do + let_it_be_with_reload(:container) { create(:snippet, :repository).tap { |snippet| snippet.create_repository } } + + let(:move_service_klass) { Snippets::RepositoryStorageMove } + let(:worker_klass) { Snippets::UpdateRepositoryStorageWorker } + end +end diff --git a/spec/workers/snippets/update_repository_storage_worker_spec.rb b/spec/workers/snippets/update_repository_storage_worker_spec.rb new file mode 100644 index 00000000000..38e9012e9c5 --- /dev/null +++ b/spec/workers/snippets/update_repository_storage_worker_spec.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Snippets::UpdateRepositoryStorageWorker do + subject { described_class.new } + + it_behaves_like 'an update storage move worker' do + let_it_be_with_refind(:container) { create(:snippet, :repository) } + let_it_be(:repository_storage_move) { create(:snippet_repository_storage_move) } + + let(:service_klass) { Snippets::UpdateRepositoryStorageService } + let(:repository_storage_move_klass) { Snippets::RepositoryStorageMove } + end +end |