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
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-10-20 11:43:02 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-10-20 11:43:02 +0300
commitd9ab72d6080f594d0b3cae15f14b3ef2c6c638cb (patch)
tree2341ef426af70ad1e289c38036737e04b0aa5007 /spec/support/shared_examples
parentd6e514dd13db8947884cd58fe2a9c2a063400a9b (diff)
Add latest changes from gitlab-org/gitlab@14-4-stable-eev14.4.0-rc42
Diffstat (limited to 'spec/support/shared_examples')
-rw-r--r--spec/support/shared_examples/ci/stuck_builds_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/features/container_registry_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/features/discussion_comments_shared_example.rb30
-rw-r--r--spec/support/shared_examples/features/project_upload_files_shared_examples.rb50
-rw-r--r--spec/support/shared_examples/graphql/connection_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb18
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb22
-rw-r--r--spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb35
-rw-r--r--spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb40
-rw-r--r--spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb36
-rw-r--r--spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb68
-rw-r--r--spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb51
-rw-r--r--spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb36
-rw-r--r--spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb11
-rw-r--r--spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb37
-rw-r--r--spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb7
-rw-r--r--spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb10
-rw-r--r--spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb36
-rw-r--r--spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb16
-rw-r--r--spec/support/shared_examples/requests/rack_attack_shared_examples.rb5
-rw-r--r--spec/support/shared_examples/services/dependency_proxy_settings_shared_examples.rb8
-rw-r--r--spec/support/shared_examples/workers/concerns/dependency_proxy/cleanup_worker_shared_examples.rb53
-rw-r--r--spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb24
24 files changed, 527 insertions, 114 deletions
diff --git a/spec/support/shared_examples/ci/stuck_builds_shared_examples.rb b/spec/support/shared_examples/ci/stuck_builds_shared_examples.rb
new file mode 100644
index 00000000000..4fcea18393c
--- /dev/null
+++ b/spec/support/shared_examples/ci/stuck_builds_shared_examples.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'job is dropped with failure reason' do |failure_reason|
+ it 'changes status' do
+ service.execute
+ job.reload
+
+ expect(job).to be_failed
+ expect(job.failure_reason).to eq(failure_reason)
+ end
+
+ context 'when job has data integrity problem' do
+ it 'drops the job and logs the reason' do
+ job.update_columns(yaml_variables: '[{"key" => "value"}]')
+
+ expect(Gitlab::ErrorTracking)
+ .to receive(:track_exception)
+ .with(anything, a_hash_including(build_id: job.id))
+ .once
+ .and_call_original
+
+ service.execute
+ job.reload
+
+ expect(job).to be_failed
+ expect(job.failure_reason).to eq('data_integrity_failure')
+ end
+ end
+end
+
+RSpec.shared_examples 'job is unchanged' do
+ it 'does not change status' do
+ expect { service.execute }.not_to change(job, :status)
+ end
+end
diff --git a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
index e8f7e62d0d7..30710e43357 100644
--- a/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
+++ b/spec/support/shared_examples/controllers/wiki_actions_shared_examples.rb
@@ -299,7 +299,7 @@ RSpec.shared_examples 'wiki controller actions' do
expect(response.headers['Content-Disposition']).to match(/^inline/)
expect(response.headers[Gitlab::Workhorse::DETECT_HEADER]).to eq('true')
expect(response.cache_control[:public]).to be(false)
- expect(response.headers['Cache-Control']).to eq('no-store')
+ expect(response.headers['Cache-Control']).to eq('private, no-store')
end
end
end
diff --git a/spec/support/shared_examples/features/container_registry_shared_examples.rb b/spec/support/shared_examples/features/container_registry_shared_examples.rb
new file mode 100644
index 00000000000..06b2b8c621c
--- /dev/null
+++ b/spec/support/shared_examples/features/container_registry_shared_examples.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'handling feature network errors with the container registry' do
+ it 'displays the error message' do
+ visit_container_registry
+
+ expect(page).to have_content 'We are having trouble connecting to the Container Registry'
+ end
+end
diff --git a/spec/support/shared_examples/features/discussion_comments_shared_example.rb b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
index 318ba67b9e9..6c06cbf9082 100644
--- a/spec/support/shared_examples/features/discussion_comments_shared_example.rb
+++ b/spec/support/shared_examples/features/discussion_comments_shared_example.rb
@@ -3,9 +3,9 @@
RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name|
let(:form_selector) { '.js-main-target-form' }
let(:dropdown_selector) { "#{form_selector} .comment-type-dropdown" }
- let(:toggle_selector) { "#{dropdown_selector} .dropdown-toggle" }
+ let(:toggle_selector) { "#{dropdown_selector} .gl-dropdown-toggle" }
let(:menu_selector) { "#{dropdown_selector} .dropdown-menu" }
- let(:submit_selector) { "#{form_selector} .js-comment-submit-button" }
+ let(:submit_selector) { "#{form_selector} .js-comment-submit-button > button:first-child" }
let(:close_selector) { "#{form_selector} .btn-comment-and-close" }
let(:comments_selector) { '.timeline > .note.timeline-entry:not(.being-posted)' }
let(:comment) { 'My comment' }
@@ -43,13 +43,11 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
expect(items.first).to have_content 'Comment'
expect(items.first).to have_content "Add a general comment to this #{resource_name}."
- expect(items.first).to have_selector '[data-testid="check-icon"]'
- expect(items.first['class']).to match 'droplab-item-selected'
+ expect(items.first).to have_selector '[data-testid="dropdown-item-checkbox"]'
expect(items.last).to have_content 'Start thread'
expect(items.last).to have_content "Discuss a specific suggestion or question#{' that needs to be resolved' if resource_name == 'merge request'}."
- expect(items.last).not_to have_selector '[data-testid="check-icon"]'
- expect(items.last['class']).not_to match 'droplab-item-selected'
+ expect(items.last).not_to have_selector '[data-testid="dropdown-item-checkbox"]'
end
it 'closes the menu when clicking the toggle or body' do
@@ -75,14 +73,14 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
expect(find(dropdown_selector)).to have_content 'Comment'
find(toggle_selector).click
- execute_script("document.querySelector('#{menu_selector} .divider').click()")
+ execute_script("document.querySelector('#{menu_selector} .dropdown-divider').click()")
else
execute_script("document.querySelector('#{menu_selector}').click()")
expect(page).to have_selector menu_selector
expect(find(dropdown_selector)).to have_content 'Comment'
- execute_script("document.querySelector('#{menu_selector} .divider').click()")
+ execute_script("document.querySelector('#{menu_selector} .dropdown-divider').click()")
expect(page).to have_selector menu_selector
end
@@ -97,7 +95,7 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
end
it 'updates the submit button text and closes the dropdown' do
- expect(find(submit_selector).value).to eq 'Start thread'
+ expect(find(submit_selector).text).to eq 'Start thread'
expect(page).not_to have_selector menu_selector
end
@@ -137,12 +135,10 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
items = all("#{menu_selector} li")
expect(items.first).to have_content 'Comment'
- expect(items.first).not_to have_selector '[data-testid="check-icon"]'
- expect(items.first['class']).not_to match 'droplab-item-selected'
+ expect(items.first).not_to have_selector '[data-testid="dropdown-item-checkbox"]'
expect(items.last).to have_content 'Start thread'
- expect(items.last).to have_selector '[data-testid="check-icon"]'
- expect(items.last['class']).to match 'droplab-item-selected'
+ expect(items.last).to have_selector '[data-testid="dropdown-item-checkbox"]'
end
describe 'when selecting "Comment"' do
@@ -153,7 +149,7 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
it 'updates the submit button text and closes the dropdown' do
button = find(submit_selector)
- expect(button.value).to eq 'Comment'
+ expect(button.text).to eq 'Comment'
expect(page).not_to have_selector menu_selector
end
@@ -166,12 +162,10 @@ RSpec.shared_examples 'thread comments for commit and snippet' do |resource_name
aggregate_failures do
expect(items.first).to have_content 'Comment'
- expect(items.first).to have_selector '[data-testid="check-icon"]'
- expect(items.first['class']).to match 'droplab-item-selected'
+ expect(items.first).to have_selector '[data-testid="dropdown-item-checkbox"]'
expect(items.last).to have_content 'Start thread'
- expect(items.last).not_to have_selector '[data-testid="check-icon"]'
- expect(items.last['class']).not_to match 'droplab-item-selected'
+ expect(items.last).not_to have_selector '[data-testid="dropdown-item-checkbox"]'
end
end
end
diff --git a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
index 7adf303bde4..85434ba7afd 100644
--- a/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
+++ b/spec/support/shared_examples/features/project_upload_files_shared_examples.rb
@@ -1,6 +1,6 @@
# frozen_string_literal: true
-RSpec.shared_examples 'it uploads and commits a new text file' do
+RSpec.shared_examples 'it uploads and commits a new text file' do |drop: false|
it 'uploads and commits a new text file', :js do
find('.add-to-tree').click
@@ -10,7 +10,11 @@ RSpec.shared_examples 'it uploads and commits a new text file' do
wait_for_requests
end
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ end
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -32,7 +36,7 @@ RSpec.shared_examples 'it uploads and commits a new text file' do
end
end
-RSpec.shared_examples 'it uploads and commits a new image file' do
+RSpec.shared_examples 'it uploads and commits a new image file' do |drop: false|
it 'uploads and commits a new image file', :js do
find('.add-to-tree').click
@@ -42,7 +46,11 @@ RSpec.shared_examples 'it uploads and commits a new image file' do
wait_for_requests
end
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'), make_visible: true)
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'logo_sample.svg'), make_visible: true)
+ end
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -58,7 +66,7 @@ RSpec.shared_examples 'it uploads and commits a new image file' do
end
end
-RSpec.shared_examples 'it uploads and commits a new pdf file' do
+RSpec.shared_examples 'it uploads and commits a new pdf file' do |drop: false|
it 'uploads and commits a new pdf file', :js do
find('.add-to-tree').click
@@ -68,7 +76,11 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do
wait_for_requests
end
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true)
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'git-cheat-sheet.pdf'), make_visible: true)
+ end
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -84,7 +96,7 @@ RSpec.shared_examples 'it uploads and commits a new pdf file' do
end
end
-RSpec.shared_examples 'it uploads and commits a new file to a forked project' do
+RSpec.shared_examples 'it uploads and commits a new file to a forked project' do |drop: false|
let(:fork_message) do
"You're not allowed to make changes to this project directly. "\
"A fork of this project has been created that you can make changes in, so you can submit a merge request."
@@ -100,7 +112,12 @@ RSpec.shared_examples 'it uploads and commits a new file to a forked project' do
find('.add-to-tree').click
click_link('Upload file')
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ end
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -123,7 +140,7 @@ RSpec.shared_examples 'it uploads and commits a new file to a forked project' do
end
end
-RSpec.shared_examples 'it uploads a file to a sub-directory' do
+RSpec.shared_examples 'it uploads a file to a sub-directory' do |drop: false|
it 'uploads a file to a sub-directory', :js do
click_link 'files'
@@ -133,7 +150,12 @@ RSpec.shared_examples 'it uploads a file to a sub-directory' do
find('.add-to-tree').click
click_link('Upload file')
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ end
page.within('#modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
@@ -150,11 +172,15 @@ RSpec.shared_examples 'it uploads a file to a sub-directory' do
end
end
-RSpec.shared_examples 'uploads and commits a new text file via "upload file" button' do
+RSpec.shared_examples 'uploads and commits a new text file via "upload file" button' do |drop: false|
it 'uploads and commits a new text file via "upload file" button', :js do
find('[data-testid="upload-file-button"]').click
- attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ if drop
+ find(".upload-dropzone-card").drop(File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'))
+ else
+ attach_file('upload_file', File.join(Rails.root, 'spec', 'fixtures', 'doc_sample.txt'), make_visible: true)
+ end
page.within('#details-modal-upload-blob') do
fill_in(:commit_message, with: 'New commit message')
diff --git a/spec/support/shared_examples/graphql/connection_shared_examples.rb b/spec/support/shared_examples/graphql/connection_shared_examples.rb
index 4cba5b5a69d..895bab1f51a 100644
--- a/spec/support/shared_examples/graphql/connection_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/connection_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
RSpec.shared_examples 'a connection with collection methods' do
- %i[to_a size include? empty?].each do |method_name|
+ %i[to_a size map include? empty?].each do |method_name|
it "responds to #{method_name}" do
expect(connection).to respond_to(method_name)
end
diff --git a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
index eaeb5faee3b..37a805902a9 100644
--- a/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
+++ b/spec/support/shared_examples/graphql/sorted_paginated_query_shared_examples.rb
@@ -9,7 +9,7 @@
# data_path: the keys necessary to dig into the return GraphQL data to get the
# returned results
# first_param: number of items expected (like a page size)
-# expected_results: array of comparison data of all items sorted correctly
+# all_records: array of comparison data of all items sorted correctly
# pagination_query: method that specifies the GraphQL query
# pagination_results_data: method that extracts the sorted data used to compare against
# the expected results
@@ -38,9 +38,9 @@
# let(:ordered_issues) { issues.sort_by(&:weight) }
#
# it_behaves_like 'sorted paginated query' do
-# let(:sort_param) { :WEIGHT_ASC }
-# let(:first_param) { 2 }
-# let(:expected_results) { ordered_issues.map(&:iid) }
+# let(:sort_param) { :WEIGHT_ASC }
+# let(:first_param) { 2 }
+# let(:all_records) { ordered_issues.map(&:iid) }
# end
# end
#
@@ -51,7 +51,7 @@ RSpec.shared_examples 'sorted paginated query' do |conditions = {}|
let(:node_path) { ['id'] }
it_behaves_like 'requires variables' do
- let(:required_variables) { [:sort_param, :first_param, :expected_results, :data_path, :current_user] }
+ let(:required_variables) { [:sort_param, :first_param, :all_records, :data_path, :current_user] }
end
describe do
@@ -101,13 +101,13 @@ RSpec.shared_examples 'sorted paginated query' do |conditions = {}|
context 'when sorting' do
it 'sorts correctly' do
- expect(results).to eq expected_results
+ expect(results).to eq all_records
end
context 'when paginating' do
let(:params) { sort_argument.merge(first: first_param) }
- let(:first_page) { expected_results.first(first_param) }
- let(:rest) { expected_results.drop(first_param) }
+ let(:first_page) { all_records.first(first_param) }
+ let(:rest) { all_records.drop(first_param) }
it 'paginates correctly' do
expect(results).to eq first_page
@@ -130,7 +130,7 @@ RSpec.shared_examples 'sorted paginated query' do |conditions = {}|
it 'fetches last elements without error' do
post_graphql(pagination_query(params), current_user: current_user)
- expect(results.first).to eq(expected_results.last)
+ expect(results.first).to eq(all_records.last)
end
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index 3760325675a..8b4ecd7d5ae 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -35,8 +35,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
end
- it 'calls ::Gitlab::Database::LoadBalancing::Sticking.unstick_or_continue_sticking' do
- expect(::Gitlab::Database::LoadBalancing::Sticking).to receive(:unstick_or_continue_sticking)
+ it 'calls ::ApplicationRecord.sticking.unstick_or_continue_sticking' do
+ expect(::ApplicationRecord.sticking).to receive(:unstick_or_continue_sticking)
.with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
.and_call_original
@@ -49,8 +49,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
end
- it 'does not call ::Gitlab::Database::LoadBalancing::Sticking.unstick_or_continue_sticking' do
- expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:unstick_or_continue_sticking)
+ it 'does not call ::ApplicationRecord.sticking.unstick_or_continue_sticking' do
+ expect(::ApplicationRecord.sticking).not_to receive(:unstick_or_continue_sticking)
trace.read { |stream| stream }
end
@@ -305,8 +305,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: trace.job.project)
end
- it 'calls ::Gitlab::Database::LoadBalancing::Sticking.stick' do
- expect(::Gitlab::Database::LoadBalancing::Sticking).to receive(:stick)
+ it 'calls ::ApplicationRecord.sticking.stick' do
+ expect(::ApplicationRecord.sticking).to receive(:stick)
.with(described_class::LOAD_BALANCING_STICKING_NAMESPACE, trace.job.id)
.and_call_original
@@ -319,8 +319,8 @@ RSpec.shared_examples 'common trace features' do
stub_feature_flags(gitlab_ci_archived_trace_consistent_reads: false)
end
- it 'does not call ::Gitlab::Database::LoadBalancing::Sticking.stick' do
- expect(::Gitlab::Database::LoadBalancing::Sticking).not_to receive(:stick)
+ it 'does not call ::ApplicationRecord.sticking.stick' do
+ expect(::ApplicationRecord.sticking).not_to receive(:stick)
subject
end
@@ -497,7 +497,7 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(build.job_artifacts_trace.file.filename).to eq('job.log')
expect(File.exist?(src_path)).to be_falsy
expect(src_checksum)
- .to eq(described_class.hexdigest(build.job_artifacts_trace.file.path))
+ .to eq(described_class.sha256_hexdigest(build.job_artifacts_trace.file.path))
expect(build.job_artifacts_trace.file_sha256).to eq(src_checksum)
end
end
@@ -523,7 +523,7 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(build.job_artifacts_trace.file.filename).to eq('job.log')
expect(build.old_trace).to be_nil
expect(src_checksum)
- .to eq(described_class.hexdigest(build.job_artifacts_trace.file.path))
+ .to eq(described_class.sha256_hexdigest(build.job_artifacts_trace.file.path))
expect(build.job_artifacts_trace.file_sha256).to eq(src_checksum)
end
end
@@ -861,7 +861,7 @@ RSpec.shared_examples 'trace with enabled live trace feature' do
expect(build.job_artifacts_trace.file.filename).to eq('job.log')
expect(Ci::BuildTraceChunk.where(build: build)).not_to be_exist
expect(src_checksum)
- .to eq(described_class.hexdigest(build.job_artifacts_trace.file.path))
+ .to eq(described_class.sha256_hexdigest(build.job_artifacts_trace.file.path))
expect(build.job_artifacts_trace.file_sha256).to eq(src_checksum)
end
end
diff --git a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
index 6e12b5a0e85..bd8bdd70ce5 100644
--- a/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/cycle_analytics/event_shared_examples.rb
@@ -33,3 +33,38 @@ RSpec.shared_examples_for 'value stream analytics event' do
end
end
end
+
+RSpec.shared_examples_for 'LEFT JOIN-able value stream analytics event' do
+ let(:params) { {} }
+ let(:instance) { described_class.new(params) }
+ let(:record_with_data) { nil }
+ let(:record_without_data) { nil }
+ let(:scope) { instance.object_type.all }
+
+ let(:records) do
+ scope_with_left_join = instance.include_in(scope)
+ scope_with_left_join.select(scope.model.arel_table[:id], instance.timestamp_projection.as('timestamp_column_data')).to_a
+ end
+
+ it 'can use the event as LEFT JOIN' do
+ expected_record_count = record_without_data.nil? ? 1 : 2
+
+ expect(records.count).to eq(expected_record_count)
+ end
+
+ context 'when looking at the record with data' do
+ subject(:record) { records.to_a.find { |r| r.id == record_with_data.id } }
+
+ it 'contains the timestamp expression' do
+ expect(record.timestamp_column_data).not_to eq(nil)
+ end
+ end
+
+ context 'when looking at the record without data' do
+ subject(:record) { records.to_a.find { |r| r.id == record_without_data.id } }
+
+ it 'returns nil for the timestamp expression' do
+ expect(record.timestamp_column_data).to eq(nil) if record_without_data
+ end
+ end
+end
diff --git a/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
new file mode 100644
index 00000000000..5ce698c4701
--- /dev/null
+++ b/spec/support/shared_examples/lib/gitlab/import_export/attributes_permitter_shared_examples.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+RSpec.shared_examples 'a permitted attribute' do |relation_sym, permitted_attributes|
+ let(:prohibited_attributes) { %i[remote_url my_attributes my_ids token my_id test] }
+
+ let(:import_export_config) { Gitlab::ImportExport::Config.new.to_h }
+ let(:project_relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
+
+ let(:relation_hash) { (permitted_attributes + prohibited_attributes).map(&:to_s).zip([]).to_h }
+ let(:relation_name) { project_relation_factory.overrides[relation_sym]&.to_sym || relation_sym }
+ let(:relation_class) { project_relation_factory.relation_class(relation_name) }
+ let(:excluded_keys) { import_export_config.dig(:excluded_keys, relation_sym) || [] }
+
+ let(:cleaned_hash) do
+ Gitlab::ImportExport::AttributeCleaner.new(
+ relation_hash: relation_hash,
+ relation_class: relation_class,
+ excluded_keys: excluded_keys
+ ).clean
+ end
+
+ let(:permitted_hash) { subject.permit(relation_sym, relation_hash) }
+
+ if described_class.new.permitted_attributes_defined?(relation_sym)
+ it 'contains only attributes that are defined as permitted in the import/export config' do
+ expect(permitted_hash.keys).to contain_exactly(*permitted_attributes.map(&:to_s))
+ end
+
+ it 'does not contain attributes that would be cleaned with AttributeCleaner' do
+ expect(cleaned_hash.keys).to include(*permitted_hash.keys)
+ end
+
+ it 'does not contain prohibited attributes that are not related to given relation' do
+ expect(permitted_hash.keys).not_to include(*prohibited_attributes.map(&:to_s))
+ end
+ else
+ it 'is disabled' do
+ expect(subject).not_to be_permitted_attributes_defined(relation_sym)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
index c6d6ff6bc1d..c06083ba952 100644
--- a/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
+++ b/spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb
@@ -4,14 +4,20 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
let(:db_config_name) { ::Gitlab::Database.db_config_names.first }
let(:expected_payload_defaults) do
+ result = {}
metrics =
::Gitlab::Metrics::Subscribers::ActiveRecord.load_balancing_metric_counter_keys +
- ::Gitlab::Metrics::Subscribers::ActiveRecord.load_balancing_metric_duration_keys +
::Gitlab::Metrics::Subscribers::ActiveRecord.db_counter_keys
- metrics.each_with_object({}) do |key, result|
+ metrics.each do |key|
result[key] = 0
end
+
+ ::Gitlab::Metrics::Subscribers::ActiveRecord.load_balancing_metric_duration_keys.each do |key|
+ result[key] = 0.0
+ end
+
+ result
end
def transform_hash(hash, another_hash)
@@ -36,8 +42,8 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
"db_primary_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
db_primary_count: record_query ? 1 : 0,
"db_primary_#{db_config_name}_count": record_query ? 1 : 0,
- db_primary_duration_s: record_query ? 0.002 : 0,
- "db_primary_#{db_config_name}_duration_s": record_query ? 0.002 : 0,
+ db_primary_duration_s: record_query ? 0.002 : 0.0,
+ "db_primary_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
db_primary_wal_count: record_wal_query ? 1 : 0,
"db_primary_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
db_primary_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0,
@@ -52,19 +58,29 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
"db_replica_#{db_config_name}_cached_count": record_cached_query ? 1 : 0,
db_replica_count: record_query ? 1 : 0,
"db_replica_#{db_config_name}_count": record_query ? 1 : 0,
- db_replica_duration_s: record_query ? 0.002 : 0,
- "db_replica_#{db_config_name}_duration_s": record_query ? 0.002 : 0,
+ db_replica_duration_s: record_query ? 0.002 : 0.0,
+ "db_replica_#{db_config_name}_duration_s": record_query ? 0.002 : 0.0,
db_replica_wal_count: record_wal_query ? 1 : 0,
"db_replica_#{db_config_name}_wal_count": record_wal_query ? 1 : 0,
db_replica_wal_cached_count: record_wal_query && record_cached_query ? 1 : 0,
"db_replica_#{db_config_name}_wal_cached_count": record_wal_query && record_cached_query ? 1 : 0
})
else
- {
+ transform_hash(expected_payload_defaults, {
db_count: record_query ? 1 : 0,
db_write_count: record_write_query ? 1 : 0,
- db_cached_count: record_cached_query ? 1 : 0
- }
+ db_cached_count: record_cached_query ? 1 : 0,
+ db_primary_cached_count: 0,
+ "db_primary_#{db_config_name}_cached_count": 0,
+ db_primary_count: 0,
+ "db_primary_#{db_config_name}_count": 0,
+ db_primary_duration_s: 0.0,
+ "db_primary_#{db_config_name}_duration_s": 0.0,
+ db_primary_wal_count: 0,
+ "db_primary_#{db_config_name}_wal_count": 0,
+ db_primary_wal_cached_count: 0,
+ "db_primary_#{db_config_name}_wal_cached_count": 0
+ })
end
expect(described_class.db_counter_payload).to eq(expected)
@@ -89,7 +105,7 @@ RSpec.shared_examples 'store ActiveRecord info in RequestStore' do |db_role|
end
RSpec.shared_examples 'record ActiveRecord metrics in a metrics transaction' do |db_role|
- let(:db_config_name) { ::Gitlab::Database.db_config_name(ApplicationRecord.connection) }
+ let(:db_config_name) { ::Gitlab::Database.db_config_name(ApplicationRecord.retrieve_connection) }
it 'increments only db counters' do
if record_query
diff --git a/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
new file mode 100644
index 00000000000..f928fb1eb43
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/analytics/cycle_analytics/stage_event_model_examples.rb
@@ -0,0 +1,68 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'StageEventModel' do
+ describe '.upsert_data' do
+ let(:time) { Time.parse(Time.current.to_s(:db)) } # truncating the timestamp so we can compare it with the timestamp loaded from the DB
+ let(:input_data) do
+ [
+ {
+ stage_event_hash_id: 1,
+ issuable_id: 2,
+ group_id: 3,
+ project_id: 4,
+ author_id: 5,
+ milestone_id: 6,
+ start_event_timestamp: time,
+ end_event_timestamp: time
+ },
+ {
+ stage_event_hash_id: 7,
+ issuable_id: 8,
+ group_id: 10,
+ project_id: 11,
+ author_id: 12,
+ milestone_id: 13,
+ start_event_timestamp: time,
+ end_event_timestamp: time
+ }
+ ]
+ end
+
+ let(:column_order) do
+ [
+ :stage_event_hash_id,
+ described_class.issuable_id_column,
+ :group_id,
+ :project_id,
+ :milestone_id,
+ :author_id,
+ :start_event_timestamp,
+ :end_event_timestamp
+ ]
+ end
+
+ subject(:upsert_data) { described_class.upsert_data(input_data) }
+
+ it 'inserts the data' do
+ upsert_data
+
+ expect(described_class.count).to eq(input_data.count)
+ end
+
+ it 'does not produce duplicate rows' do
+ 2.times { upsert_data }
+
+ expect(described_class.count).to eq(input_data.count)
+ end
+
+ it 'inserts the data correctly' do
+ upsert_data
+
+ output_data = described_class.all.map do |record|
+ column_order.map { |column| record[column] }
+ end.sort
+
+ expect(input_data.map(&:values).sort).to eq(output_data)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb
new file mode 100644
index 00000000000..a4e0d6c871e
--- /dev/null
+++ b/spec/support/shared_examples/models/concerns/ttl_expirable_shared_examples.rb
@@ -0,0 +1,51 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.shared_examples 'ttl_expirable' do
+ let_it_be(:class_symbol) { described_class.model_name.param_key.to_sym }
+
+ it_behaves_like 'having unique enum values'
+
+ describe 'validations' do
+ it { is_expected.to validate_presence_of(:status) }
+ end
+
+ describe '.updated_before' do
+ # rubocop:disable Rails/SaveBang
+ let_it_be_with_reload(:item1) { create(class_symbol) }
+ let_it_be(:item2) { create(class_symbol) }
+ # rubocop:enable Rails/SaveBang
+
+ before do
+ item1.update_column(:updated_at, 1.month.ago)
+ end
+
+ it 'returns items with created at older than the supplied number of days' do
+ expect(described_class.updated_before(10)).to contain_exactly(item1)
+ end
+ end
+
+ describe '.active' do
+ # rubocop:disable Rails/SaveBang
+ let_it_be(:item1) { create(class_symbol) }
+ let_it_be(:item2) { create(class_symbol, :expired) }
+ let_it_be(:item3) { create(class_symbol, status: :error) }
+ # rubocop:enable Rails/SaveBang
+
+ it 'returns only active items' do
+ expect(described_class.active).to contain_exactly(item1)
+ end
+ end
+
+ describe '.lock_next_by' do
+ let_it_be(:item1) { create(class_symbol, created_at: 1.month.ago, updated_at: 1.day.ago) }
+ let_it_be(:item2) { create(class_symbol, created_at: 1.year.ago, updated_at: 1.year.ago) }
+ let_it_be(:item3) { create(class_symbol, created_at: 2.years.ago, updated_at: 1.month.ago) }
+
+ it 'returns the first item sorted by the argument' do
+ expect(described_class.lock_next_by(:updated_at)).to contain_exactly(item2)
+ expect(described_class.lock_next_by(:created_at)).to contain_exactly(item3)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
index 274fbae3dfd..750d3dd11e3 100644
--- a/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
+++ b/spec/support/shared_examples/models/packages/debian/distribution_shared_examples.rb
@@ -193,42 +193,6 @@ RSpec.shared_examples 'Debian Distribution' do |factory, container, can_freeze|
end
end
- describe '#needs_update?' do
- subject { distribution.needs_update? }
-
- context 'with new distribution' do
- let(:distribution) { create(factory, container: distribution_with_suite.container) }
-
- it { is_expected.to be_truthy }
- end
-
- context 'with file' do
- context 'without valid_time_duration_seconds' do
- let(:distribution) { create(factory, :with_file, container: distribution_with_suite.container) }
-
- it { is_expected.to be_falsey }
- end
-
- context 'with valid_time_duration_seconds' do
- let(:distribution) { create(factory, :with_file, container: distribution_with_suite.container, valid_time_duration_seconds: 2.days.to_i) }
-
- context 'when not yet expired' do
- it { is_expected.to be_falsey }
- end
-
- context 'when expired' do
- it do
- distribution
-
- travel_to(4.days.from_now) do
- is_expected.to be_truthy
- end
- end
- end
- end
- end
- end
-
if container == :project
describe 'project distribution specifics' do
describe 'relationships' do
diff --git a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
index b86c0529338..e45be21f152 100644
--- a/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/composer_packages_shared_examples.rb
@@ -85,7 +85,18 @@ RSpec.shared_examples 'Composer package creation' do |user_type, status, add_mem
expect(response).to have_gitlab_http_status(status)
end
+
it_behaves_like 'a package tracking event', described_class.name, 'push_package'
+
+ context 'when package creation fails' do
+ before do
+ allow_next_instance_of(::Packages::Composer::CreatePackageService) do |create_package_service|
+ allow(create_package_service).to receive(:execute).and_raise(StandardError)
+ end
+ end
+
+ it_behaves_like 'not a package tracking event'
+ end
end
end
diff --git a/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb b/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
index e776cf13217..e1e75be2494 100644
--- a/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/container_repositories_shared_examples.rb
@@ -79,3 +79,40 @@ RSpec.shared_examples 'returns repositories for allowed users' do |user_type, sc
end
end
end
+
+RSpec.shared_examples 'handling network errors with the container registry' do
+ before do
+ stub_container_registry_network_error(client_method: :repository_tags)
+ end
+
+ it 'returns a connection error' do
+ subject
+
+ expect(response).to have_gitlab_http_status(:service_unavailable)
+ expect(json_response['message']).to include('We are having trouble connecting to the Container Registry')
+ end
+end
+
+RSpec.shared_examples 'handling graphql network errors with the container registry' do
+ before do
+ stub_container_registry_network_error(client_method: :repository_tags)
+ end
+
+ it 'returns a connection error' do
+ subject
+
+ expect_graphql_errors_to_include('We are having trouble connecting to the Container Registry')
+ end
+end
+
+RSpec.shared_examples 'not hitting graphql network errors with the container registry' do
+ before do
+ stub_container_registry_network_error(client_method: :repository_tags)
+ end
+
+ it 'does not return any error' do
+ subject
+
+ expect_graphql_errors_to_be_empty
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
index 274516cd87b..01ed6c26576 100644
--- a/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/group_and_project_boards_query_shared_examples.rb
@@ -62,9 +62,10 @@ RSpec.shared_examples 'group and project boards query' do
context 'when ascending' do
it_behaves_like 'sorted paginated query' do
- let(:sort_param) { }
- let(:first_param) { 2 }
- let(:expected_results) do
+ let(:sort_param) { }
+ let(:first_param) { 2 }
+
+ let(:all_records) do
if board_parent.multiple_issue_boards_available?
boards.map { |board| global_id_of(board) }
else
diff --git a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
index af4c9286e7c..367c6d4fa3a 100644
--- a/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/graphql/packages/group_and_project_packages_list_shared_examples.rb
@@ -17,9 +17,11 @@ RSpec.shared_examples 'group and project packages query' do
let(:package_names) { graphql_data_at(resource_type, :packages, :nodes, :name) }
let(:target_shas) { graphql_data_at(resource_type, :packages, :nodes, :metadata, :target_sha) }
let(:packages) { graphql_data_at(resource_type, :packages, :nodes) }
+ let(:packages_count) { graphql_data_at(resource_type, :packages, :count) }
let(:fields) do
<<~QUERY
+ count
nodes {
#{all_graphql_fields_for('packages'.classify, excluded: ['project'])}
metadata { #{query_graphql_fragment('ComposerMetadata')} }
@@ -55,6 +57,10 @@ RSpec.shared_examples 'group and project packages query' do
it 'deals with metadata' do
expect(target_shas).to contain_exactly(composer_metadatum.target_sha)
end
+
+ it 'returns the count of the packages' do
+ expect(packages_count).to eq(4)
+ end
end
context 'when the user does not have access to the resource' do
@@ -95,7 +101,7 @@ RSpec.shared_examples 'group and project packages query' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { order }
let(:first_param) { 4 }
- let(:expected_results) { ascending_packages }
+ let(:all_records) { ascending_packages }
end
end
end
@@ -105,7 +111,7 @@ RSpec.shared_examples 'group and project packages query' do
it_behaves_like 'sorted paginated query' do
let(:sort_param) { order }
let(:first_param) { 4 }
- let(:expected_results) { ascending_packages.reverse }
+ let(:all_records) { ascending_packages.reverse }
end
end
end
diff --git a/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb b/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb
new file mode 100644
index 00000000000..9f67bd69560
--- /dev/null
+++ b/spec/support/shared_examples/requests/api/issuable_search_shared_examples.rb
@@ -0,0 +1,36 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'issuable anonymous search' do
+ context 'with anonymous user' do
+ context 'with disable_anonymous_search disabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: false)
+ end
+
+ it 'returns issuables matching given search string for title' do
+ get api(url), params: { scope: 'all', search: issuable.title }
+
+ expect_paginated_array_response(result)
+ end
+
+ it 'returns issuables matching given search string for description' do
+ get api(url), params: { scope: 'all', search: issuable.description }
+
+ expect_paginated_array_response(result)
+ end
+ end
+
+ context 'with disable_anonymous_search enabled' do
+ before do
+ stub_feature_flags(disable_anonymous_search: true)
+ end
+
+ it "returns 422 error" do
+ get api(url), params: { scope: 'all', search: issuable.title }
+
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response['message']).to eq('User must be authenticated to use search')
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
index cb06c9fa596..3e9c4a5eb68 100644
--- a/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/logging_application_context_shared_examples.rb
@@ -15,6 +15,22 @@ RSpec.shared_examples 'storing arguments in the application context' do
end
end
+# For the API we need a slightly different approach as `client_id` is
+# calculated in API logging code.
+RSpec.shared_examples 'storing arguments in the application context for the API' do
+ it 'places the expected params in the application context' do
+ expect(::API::API::LOG_FORMATTER).to receive(:call) do
+ expect(Gitlab::ApplicationContext.current).to include(log_hash(expected_params))
+ end
+
+ subject
+ end
+
+ def log_hash(hash)
+ hash.transform_keys! { |key| "meta.#{key}" }
+ end
+end
+
RSpec.shared_examples 'not executing any extra queries for the application context' do |expected_extra_queries = 0|
it 'does not execute more queries than without adding anything to the application context' do
# Call the subject once to memoize all factories being used for the spec, so they won't
diff --git a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
index 2a19ff6f590..b294467d482 100644
--- a/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
+++ b/spec/support/shared_examples/requests/rack_attack_shared_examples.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
#
# Requires let variables:
-# * throttle_setting_prefix: "throttle_authenticated_api", "throttle_authenticated_web", "throttle_protected_paths", "throttle_authenticated_packages_api", "throttle_authenticated_git_lfs", "throttle_authenticated_files_api"
+# * throttle_setting_prefix: "throttle_authenticated_api", "throttle_authenticated_web", "throttle_protected_paths", "throttle_authenticated_packages_api", "throttle_authenticated_git_lfs", "throttle_authenticated_files_api", "throttle_authenticated_deprecated_api"
# * request_method
# * request_args
# * other_user_request_args
@@ -16,7 +16,8 @@ RSpec.shared_examples 'rate-limited token-authenticated requests' do
"throttle_authenticated_web" => "throttle_authenticated_web",
"throttle_authenticated_packages_api" => "throttle_authenticated_packages_api",
"throttle_authenticated_git_lfs" => "throttle_authenticated_git_lfs",
- "throttle_authenticated_files_api" => "throttle_authenticated_files_api"
+ "throttle_authenticated_files_api" => "throttle_authenticated_files_api",
+ "throttle_authenticated_deprecated_api" => "throttle_authenticated_deprecated_api"
}
end
diff --git a/spec/support/shared_examples/services/dependency_proxy_settings_shared_examples.rb b/spec/support/shared_examples/services/dependency_proxy_settings_shared_examples.rb
new file mode 100644
index 00000000000..2c1dc2da560
--- /dev/null
+++ b/spec/support/shared_examples/services/dependency_proxy_settings_shared_examples.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'updating the dependency proxy group settings attributes' do |from: {}, to: {}|
+ it 'updates the dependency proxy settings' do
+ expect { subject }
+ .to change { group_settings.reload.enabled }.from(from[:enabled]).to(to[:enabled])
+ end
+end
diff --git a/spec/support/shared_examples/workers/concerns/dependency_proxy/cleanup_worker_shared_examples.rb b/spec/support/shared_examples/workers/concerns/dependency_proxy/cleanup_worker_shared_examples.rb
new file mode 100644
index 00000000000..c9014ad549c
--- /dev/null
+++ b/spec/support/shared_examples/workers/concerns/dependency_proxy/cleanup_worker_shared_examples.rb
@@ -0,0 +1,53 @@
+# frozen_string_literal: true
+
+RSpec.shared_examples 'dependency_proxy_cleanup_worker' do
+ let_it_be(:group) { create(:group) }
+
+ let(:worker) { described_class.new }
+
+ describe '#perform_work' do
+ subject(:perform_work) { worker.perform_work }
+
+ context 'with no work to do' do
+ it { is_expected.to be_nil }
+ end
+
+ context 'with work to do' do
+ let_it_be(:artifact1) { create(factory_type, :expired, group: group) }
+ let_it_be(:artifact2) { create(factory_type, :expired, group: group, updated_at: 6.months.ago, created_at: 2.years.ago) }
+ let_it_be_with_reload(:artifact3) { create(factory_type, :expired, group: group, updated_at: 1.year.ago, created_at: 1.year.ago) }
+ let_it_be(:artifact4) { create(factory_type, group: group, updated_at: 2.years.ago, created_at: 2.years.ago) }
+
+ it 'deletes the oldest expired artifact based on updated_at', :aggregate_failures do
+ expect(worker).to receive(:log_extra_metadata_on_done).with("#{factory_type}_id".to_sym, artifact3.id)
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:group_id, group.id)
+
+ expect { perform_work }.to change { artifact1.class.count }.by(-1)
+ end
+ end
+ end
+
+ describe '#max_running_jobs' do
+ let(:capacity) { 5 }
+
+ subject { worker.max_running_jobs }
+
+ before do
+ stub_application_setting(dependency_proxy_ttl_group_policy_worker_capacity: capacity)
+ end
+
+ it { is_expected.to eq(capacity) }
+ end
+
+ describe '#remaining_work_count' do
+ let_it_be(:expired_artifacts) do
+ (1..3).map do |_|
+ create(factory_type, :expired, group: group)
+ end
+ end
+
+ subject { worker.remaining_work_count }
+
+ it { is_expected.to eq(3) }
+ end
+end
diff --git a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
index 1b09b5fe613..d6e96ef37d6 100644
--- a/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
+++ b/spec/support/shared_examples/workers/concerns/reenqueuer_shared_examples.rb
@@ -1,11 +1,14 @@
# frozen_string_literal: true
-# Expects `subject` to be a job/worker instance
+# Expects `subject` to be a job/worker instance and
+# `job_args` to be arguments to #perform if it takes arguments
RSpec.shared_examples 'reenqueuer' do
before do
allow(subject).to receive(:sleep) # faster tests
end
+ let(:subject_perform) { defined?(job_args) ? subject.perform(job_args) : subject.perform }
+
it 'implements lease_timeout' do
expect(subject.lease_timeout).to be_a(ActiveSupport::Duration)
end
@@ -18,12 +21,13 @@ RSpec.shared_examples 'reenqueuer' do
it 'tries to obtain a lease' do
expect_to_obtain_exclusive_lease(subject.lease_key)
- subject.perform
+ subject_perform
end
end
end
-# Expects `subject` to be a job/worker instance
+# Expects `subject` to be a job/worker instance and
+# `job_args` to be arguments to #perform if it takes arguments
RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_duration|
before do
# Allow Timecop freeze and travel without the block form
@@ -38,13 +42,15 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
Timecop.safe_mode = true
end
+ let(:subject_perform) { defined?(job_args) ? subject.perform(job_args) : subject.perform }
+
context 'when the work finishes in 0 seconds' do
let(:actual_duration) { 0 }
it 'sleeps exactly the minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(minimum_duration))
- subject.perform
+ subject_perform
end
end
@@ -54,7 +60,7 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
it 'sleeps 90% of minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(0.9 * minimum_duration))
- subject.perform
+ subject_perform
end
end
@@ -64,7 +70,7 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
it 'sleeps 10% of minimum duration' do
expect(subject).to receive(:sleep).with(a_value_within(0.01).of(0.1 * minimum_duration))
- subject.perform
+ subject_perform
end
end
@@ -74,7 +80,7 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- subject.perform
+ subject_perform
end
end
@@ -84,7 +90,7 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- subject.perform
+ subject_perform
end
end
@@ -94,7 +100,7 @@ RSpec.shared_examples '#perform is rate limited to 1 call per' do |minimum_durat
it 'does not sleep' do
expect(subject).not_to receive(:sleep)
- subject.perform
+ subject_perform
end
end