summaryrefslogtreecommitdiff
path: root/spec/lib
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2020-05-13 13:21:06 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2020-05-13 13:21:06 +0000
commit6e0790501a8cd39791191de6312c0387d4a0ed3f (patch)
treeb988c8fd0c042de231b7221d500972bf51202be0 /spec/lib
parent91866438d75c3ee05b1a40b30f2b62e111a00fde (diff)
downloadgitlab-ce-6e0790501a8cd39791191de6312c0387d4a0ed3f.tar.gz
Add latest changes from gitlab-org/gitlab@13-0-stable-ee
Diffstat (limited to 'spec/lib')
-rw-r--r--spec/lib/api/entities/design_management/design_spec.rb19
-rw-r--r--spec/lib/banzai/filter/issue_reference_filter_spec.rb55
-rw-r--r--spec/lib/banzai/reference_parser/design_parser_spec.rb91
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb42
-rw-r--r--spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb2
-rw-r--r--spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb101
-rw-r--r--spec/lib/gitlab/ci/config/entry/reports_spec.rb1
-rw-r--r--spec/lib/gitlab/git/attributes_parser_spec.rb8
-rw-r--r--spec/lib/gitlab/git_access_snippet_spec.rb32
-rw-r--r--spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb31
-rw-r--r--spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_spec.rb14
-rw-r--r--spec/lib/gitlab/import_export/all_models.yml2
-rw-r--r--spec/lib/gitlab/import_export/design_repo_restorer_spec.rb42
-rw-r--r--spec/lib/gitlab/import_export/design_repo_saver_spec.rb37
-rw-r--r--spec/lib/gitlab/import_export/import_test_coverage_spec.rb13
-rw-r--r--spec/lib/gitlab/import_export/importer_spec.rb3
-rw-r--r--spec/lib/gitlab/import_export/project/tree_restorer_spec.rb64
-rw-r--r--spec/lib/gitlab/import_export/project/tree_saver_spec.rb25
-rw-r--r--spec/lib/gitlab/kubernetes/network_policy_spec.rb224
-rw-r--r--spec/lib/gitlab/logging/cloudflare_helper_spec.rb52
-rw-r--r--spec/lib/gitlab/lograge/custom_options_spec.rb12
-rw-r--r--spec/lib/gitlab/url_builder_spec.rb11
-rw-r--r--spec/lib/gitlab/usage_data_counters/designs_counter_spec.rb14
-rw-r--r--spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb9
-rw-r--r--spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb24
-rw-r--r--spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb24
26 files changed, 910 insertions, 42 deletions
diff --git a/spec/lib/api/entities/design_management/design_spec.rb b/spec/lib/api/entities/design_management/design_spec.rb
new file mode 100644
index 00000000000..50ca3b43c6a
--- /dev/null
+++ b/spec/lib/api/entities/design_management/design_spec.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe API::Entities::DesignManagement::Design do
+ let_it_be(:design) { create(:design) }
+ let(:entity) { described_class.new(design, request: double) }
+
+ subject { entity.as_json }
+
+ it 'has the correct attributes' do
+ expect(subject).to eq({
+ id: design.id,
+ project_id: design.project_id,
+ filename: design.filename,
+ image_url: ::Gitlab::UrlBuilder.build(design)
+ })
+ end
+end
diff --git a/spec/lib/banzai/filter/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
index 4a412da27a7..61c59162a30 100644
--- a/spec/lib/banzai/filter/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/issue_reference_filter_spec.rb
@@ -4,6 +4,7 @@ require 'spec_helper'
describe Banzai::Filter::IssueReferenceFilter do
include FilterSpecHelper
+ include DesignManagementTestHelpers
def helper
IssuesHelper
@@ -358,6 +359,23 @@ describe Banzai::Filter::IssueReferenceFilter do
end
end
+ context 'when processing a link to the designs tab' do
+ let(:designs_tab_url) { url_for_designs(issue) }
+ let(:input_text) { "See #{designs_tab_url}" }
+
+ subject(:link) { reference_filter(input_text).css('a').first }
+
+ before do
+ enable_design_management
+ end
+
+ it 'includes the word "designs" after the reference in the text content', :aggregate_failures do
+ expect(link.attr('title')).to eq(issue.title)
+ expect(link.attr('href')).to eq(designs_tab_url)
+ expect(link.text).to eq("#{issue.to_reference} (designs)")
+ end
+ end
+
context 'group context' do
let(:group) { create(:group) }
let(:context) { { project: nil, group: group } }
@@ -467,4 +485,41 @@ describe Banzai::Filter::IssueReferenceFilter do
end.not_to yield_control
end
end
+
+ describe '#object_link_text_extras' do
+ before do
+ enable_design_management(enabled)
+ end
+
+ let(:current_user) { project.owner }
+ let(:enabled) { true }
+ let(:matches) { Issue.link_reference_pattern.match(input_text) }
+ let(:extras) { subject.object_link_text_extras(issue, matches) }
+
+ subject { filter_instance }
+
+ context 'the link does not go to the designs tab' do
+ let(:input_text) { Gitlab::Routing.url_helpers.project_issue_url(issue.project, issue) }
+
+ it 'does not include designs' do
+ expect(extras).not_to include('designs')
+ end
+ end
+
+ context 'the link goes to the designs tab' do
+ let(:input_text) { url_for_designs(issue) }
+
+ it 'includes designs' do
+ expect(extras).to include('designs')
+ end
+
+ context 'design management is disabled' do
+ let(:enabled) { false }
+
+ it 'does not include designs in the extras' do
+ expect(extras).not_to include('designs')
+ end
+ end
+ end
+ end
end
diff --git a/spec/lib/banzai/reference_parser/design_parser_spec.rb b/spec/lib/banzai/reference_parser/design_parser_spec.rb
new file mode 100644
index 00000000000..76708acf887
--- /dev/null
+++ b/spec/lib/banzai/reference_parser/design_parser_spec.rb
@@ -0,0 +1,91 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Banzai::ReferenceParser::DesignParser do
+ include ReferenceParserHelpers
+ include DesignManagementTestHelpers
+
+ let_it_be(:issue) { create(:issue) }
+ let_it_be(:design) { create(:design, :with_versions, issue: issue) }
+ let_it_be(:user) { create(:user, developer_projects: [issue.project]) }
+
+ subject(:instance) { described_class.new(Banzai::RenderContext.new(issue.project, user)) }
+
+ let(:link) { design_link(design) }
+
+ before do
+ enable_design_management
+ end
+
+ describe '#nodes_visible_to_user' do
+ it_behaves_like 'referenced feature visibility', 'issues' do
+ let(:project) { issue.project }
+ end
+
+ describe 'specific states' do
+ let_it_be(:public_project) { create(:project, :public) }
+
+ let_it_be(:other_project_link) do
+ design_link(create(:design, :with_versions))
+ end
+ let_it_be(:public_link) do
+ design_link(create(:design, :with_versions, issue: create(:issue, project: public_project)))
+ end
+ let_it_be(:public_but_confidential_link) do
+ design_link(create(:design, :with_versions, issue: create(:issue, :confidential, project: public_project)))
+ end
+
+ subject(:visible_nodes) do
+ nodes = [link,
+ other_project_link,
+ public_link,
+ public_but_confidential_link]
+
+ instance.nodes_visible_to_user(user, nodes)
+ end
+
+ it 'redacts links we should not have access to' do
+ expect(visible_nodes).to contain_exactly(link, public_link)
+ end
+
+ context 'design management is not available' do
+ before do
+ enable_design_management(false)
+ end
+
+ it 'redacts all nodes' do
+ expect(visible_nodes).to be_empty
+ end
+ end
+ end
+ end
+
+ describe '#process' do
+ it 'returns the correct designs' do
+ frag = document([design, create(:design, :with_versions)])
+
+ expect(subject.process([frag])[:visible]).to contain_exactly(design)
+ end
+ end
+
+ def design_link(design)
+ node = empty_html_link
+ node['class'] = 'gfm'
+ node['data-reference-type'] = 'design'
+ node['data-project'] = design.project.id.to_s
+ node['data-issue'] = design.issue.id.to_s
+ node['data-design'] = design.id.to_s
+
+ node
+ end
+
+ def document(designs)
+ frag = Nokogiri::HTML.fragment('')
+ designs.each do |design|
+ frag.add_child(design_link(design))
+ end
+
+ frag
+ end
+end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
new file mode 100644
index 00000000000..92ecec350ae
--- /dev/null
+++ b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Analytics::CycleAnalytics::Median do
+ let_it_be(:project) { create(:project, :repository) }
+ let(:query) { Project.joins(merge_requests: :metrics) }
+
+ let(:stage) do
+ build(
+ :cycle_analytics_project_stage,
+ start_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestCreated.identifier,
+ end_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestMerged.identifier,
+ project: project
+ )
+ end
+
+ subject { described_class.new(stage: stage, query: query).seconds }
+
+ around do |example|
+ Timecop.freeze { example.run }
+ end
+
+ it 'retruns nil when no results' do
+ expect(subject).to eq(nil)
+ end
+
+ it 'returns median duration seconds as float' do
+ merge_request1 = create(:merge_request, source_branch: '1', target_project: project, source_project: project)
+ merge_request2 = create(:merge_request, source_branch: '2', target_project: project, source_project: project)
+
+ Timecop.travel(5.minutes.from_now) do
+ merge_request1.metrics.update!(merged_at: Time.zone.now)
+ end
+
+ Timecop.travel(10.minutes.from_now) do
+ merge_request2.metrics.update!(merged_at: Time.zone.now)
+ end
+
+ expect(subject).to be_within(0.5).of(7.5.minutes.seconds)
+ end
+end
diff --git a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
index c3bb975727b..34ac70071bb 100644
--- a/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_environment_id_deployment_merge_requests_spec.rb
@@ -32,7 +32,7 @@ describe Gitlab::BackgroundMigration::BackfillEnvironmentIdDeploymentMergeReques
expect(deployment_merge_requests.where(environment_id: nil).count).to eq(3)
- migration.perform(1, mr.id)
+ migration.backfill_range(1, mr.id)
expect(deployment_merge_requests.where(environment_id: nil).count).to be_zero
expect(deployment_merge_requests.count).to eq(2)
diff --git a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
index dcbf8d12f35..27ae60eb278 100644
--- a/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
+++ b/spec/lib/gitlab/background_migration/backfill_snippet_repositories_spec.rb
@@ -11,13 +11,14 @@ describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, s
let(:user_state) { 'active' }
let(:ghost) { false }
let(:user_type) { nil }
+ let(:user_name) { 'Test' }
let!(:user) do
users.create(id: 1,
email: 'user@example.com',
projects_limit: 10,
username: 'test',
- name: 'Test',
+ name: user_name,
state: user_state,
ghost: ghost,
last_activity_on: 1.minute.ago,
@@ -70,6 +71,17 @@ describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, s
end
end
+ shared_examples 'migration_bot user commits files' do
+ it do
+ subject
+
+ last_commit = raw_repository(snippet).commit
+
+ expect(last_commit.author_name).to eq migration_bot.name
+ expect(last_commit.author_email).to eq migration_bot.email
+ end
+ end
+
shared_examples 'commits the file to the repository' do
context 'when author can update snippet and use git' do
it 'creates the repository and commit the file' do
@@ -88,17 +100,6 @@ describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, s
end
context 'when author cannot update snippet or use git' do
- shared_examples 'migration_bot user commits files' do
- it do
- subject
-
- last_commit = raw_repository(snippet).commit
-
- expect(last_commit.author_name).to eq migration_bot.name
- expect(last_commit.author_email).to eq migration_bot.email
- end
- end
-
context 'when user is blocked' do
let(:user_state) { 'blocked' }
@@ -219,6 +220,82 @@ describe Gitlab::BackgroundMigration::BackfillSnippetRepositories, :migration, s
end
end
end
+
+ context 'when snippet content size is higher than the existing limit' do
+ let(:limit) { 15 }
+ let(:content) { 'a' * (limit + 1) }
+ let(:snippet) { snippet_without_repo }
+ let(:ids) { [snippet.id, snippet.id] }
+
+ before do
+ allow(Gitlab::CurrentSettings).to receive(:snippet_size_limit).and_return(limit)
+ end
+
+ it_behaves_like 'migration_bot user commits files'
+ end
+
+ context 'when user name is invalid' do
+ let(:user_name) { '.' }
+ let!(:snippet) { snippets.create(id: 4, type: 'PersonalSnippet', author_id: user.id, file_name: file_name, content: content) }
+ let(:ids) { [4, 4] }
+
+ after do
+ raw_repository(snippet).remove
+ end
+
+ it_behaves_like 'migration_bot user commits files'
+ end
+
+ context 'when both user name and snippet file_name are invalid' do
+ let(:user_name) { '.' }
+ let!(:other_user) do
+ users.create(id: 2,
+ email: 'user2@example.com',
+ projects_limit: 10,
+ username: 'test2',
+ name: 'Test2',
+ state: user_state,
+ ghost: ghost,
+ last_activity_on: 1.minute.ago,
+ user_type: user_type,
+ confirmed_at: 1.day.ago)
+ end
+ let!(:invalid_snippet) { snippets.create(id: 4, type: 'PersonalSnippet', author_id: user.id, file_name: '.', content: content) }
+ let!(:snippet) { snippets.create(id: 5, type: 'PersonalSnippet', author_id: other_user.id, file_name: file_name, content: content) }
+ let(:ids) { [4, 5] }
+
+ after do
+ raw_repository(snippet).remove
+ raw_repository(invalid_snippet).remove
+ end
+
+ it 'updates the file_name only when it is invalid' do
+ subject
+
+ expect(blob_at(invalid_snippet, 'snippetfile1.txt')).to be
+ expect(blob_at(snippet, file_name)).to be
+ end
+
+ it_behaves_like 'migration_bot user commits files' do
+ let(:snippet) { invalid_snippet }
+ end
+
+ it 'does not alter the commit author in subsequent migrations' do
+ subject
+
+ last_commit = raw_repository(snippet).commit
+
+ expect(last_commit.author_name).to eq other_user.name
+ expect(last_commit.author_email).to eq other_user.email
+ end
+
+ it "increases the number of retries temporarily from #{described_class::MAX_RETRIES} to #{described_class::MAX_RETRIES + 1}" do
+ expect(service).to receive(:create_commit).with(Snippet.find(invalid_snippet.id)).exactly(described_class::MAX_RETRIES + 1).times.and_call_original
+ expect(service).to receive(:create_commit).with(Snippet.find(snippet.id)).once.and_call_original
+
+ subject
+ end
+ end
end
def blob_at(snippet, path)
diff --git a/spec/lib/gitlab/ci/config/entry/reports_spec.rb b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
index b2dbbbf59ac..8c6c91d919e 100644
--- a/spec/lib/gitlab/ci/config/entry/reports_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/reports_spec.rb
@@ -48,6 +48,7 @@ describe Gitlab::Ci::Config::Entry::Reports do
:cobertura | 'cobertura-coverage.xml'
:terraform | 'tfplan.json'
:accessibility | 'gl-accessibility.json'
+ :cluster_applications | 'gl-cluster-applications.json'
end
with_them do
diff --git a/spec/lib/gitlab/git/attributes_parser_spec.rb b/spec/lib/gitlab/git/attributes_parser_spec.rb
index 94b7a086e59..45db4acd3ac 100644
--- a/spec/lib/gitlab/git/attributes_parser_spec.rb
+++ b/spec/lib/gitlab/git/attributes_parser_spec.rb
@@ -75,6 +75,14 @@ describe Gitlab::Git::AttributesParser, :seed_helper do
expect(subject.attributes('test.foo')).to eq({})
end
end
+
+ context 'when attributes data has binary data' do
+ let(:data) { "\xFF\xFE*\u0000.\u0000c\u0000s".b }
+
+ it 'returns an empty Hash' do
+ expect(subject.attributes('test.foo')).to eq({})
+ end
+ end
end
describe '#patterns' do
diff --git a/spec/lib/gitlab/git_access_snippet_spec.rb b/spec/lib/gitlab/git_access_snippet_spec.rb
index fb2a7d16665..7ecfa4e519d 100644
--- a/spec/lib/gitlab/git_access_snippet_spec.rb
+++ b/spec/lib/gitlab/git_access_snippet_spec.rb
@@ -298,6 +298,16 @@ describe Gitlab::GitAccessSnippet do
let(:ref) { "refs/heads/snippet/edit-file" }
let(:changes) { "#{oldrev} #{newrev} #{ref}" }
+ shared_examples 'migration bot does not err' do
+ let(:actor) { migration_bot }
+
+ it 'does not err' do
+ expect(snippet.repository_size_checker).not_to receive(:above_size_limit?)
+
+ expect { push_access_check }.not_to raise_error
+ end
+ end
+
shared_examples_for 'a push to repository already over the limit' do
it 'errs' do
expect(snippet.repository_size_checker).to receive(:above_size_limit?).and_return(true)
@@ -306,6 +316,8 @@ describe Gitlab::GitAccessSnippet do
push_access_check
end.to raise_error(described_class::ForbiddenError, /Your push has been rejected/)
end
+
+ it_behaves_like 'migration bot does not err'
end
shared_examples_for 'a push to repository below the limit' do
@@ -318,6 +330,8 @@ describe Gitlab::GitAccessSnippet do
expect { push_access_check }.not_to raise_error
end
+
+ it_behaves_like 'migration bot does not err'
end
shared_examples_for 'a push to repository to make it over the limit' do
@@ -332,6 +346,8 @@ describe Gitlab::GitAccessSnippet do
push_access_check
end.to raise_error(described_class::ForbiddenError, /Your push to this repository would cause it to exceed the size limit/)
end
+
+ it_behaves_like 'migration bot does not err'
end
context 'when GIT_OBJECT_DIRECTORY_RELATIVE env var is set' do
@@ -350,14 +366,6 @@ describe Gitlab::GitAccessSnippet do
it_behaves_like 'a push to repository already over the limit'
it_behaves_like 'a push to repository below the limit'
it_behaves_like 'a push to repository to make it over the limit'
-
- context 'when user is migration bot' do
- let(:actor) { migration_bot }
-
- it_behaves_like 'a push to repository already over the limit'
- it_behaves_like 'a push to repository below the limit'
- it_behaves_like 'a push to repository to make it over the limit'
- end
end
context 'when GIT_OBJECT_DIRECTORY_RELATIVE env var is not set' do
@@ -372,14 +380,6 @@ describe Gitlab::GitAccessSnippet do
it_behaves_like 'a push to repository already over the limit'
it_behaves_like 'a push to repository below the limit'
it_behaves_like 'a push to repository to make it over the limit'
-
- context 'when user is migration bot' do
- let(:actor) { migration_bot }
-
- it_behaves_like 'a push to repository already over the limit'
- it_behaves_like 'a push to repository below the limit'
- it_behaves_like 'a push to repository to make it over the limit'
- end
end
end
diff --git a/spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb b/spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb
new file mode 100644
index 00000000000..922a433d7ac
--- /dev/null
+++ b/spec/lib/gitlab/grape_logging/loggers/cloudflare_logger_spec.rb
@@ -0,0 +1,31 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::GrapeLogging::Loggers::CloudflareLogger do
+ subject { described_class.new }
+
+ describe "#parameters" do
+ let(:mock_request) { ActionDispatch::Request.new({}) }
+ let(:start_time) { Time.new(2018, 01, 01) }
+
+ describe 'with no Cloudflare headers' do
+ it 'returns an empty hash' do
+ expect(subject.parameters(mock_request, nil)).to eq({})
+ end
+ end
+
+ describe 'with Cloudflare headers' do
+ before do
+ mock_request.headers['Cf-Ray'] = SecureRandom.hex
+ mock_request.headers['Cf-Request-Id'] = SecureRandom.hex
+ end
+
+ it 'returns the correct duration in seconds' do
+ data = subject.parameters(mock_request, nil)
+
+ expect(data.keys).to contain_exactly(:cf_ray, :cf_request_id)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_spec.rb b/spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_spec.rb
index 85a5b1dacc7..11cf14523c2 100644
--- a/spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_spec.rb
+++ b/spec/lib/gitlab/graphql/pagination/externally_paginated_array_connection_spec.rb
@@ -19,6 +19,20 @@ describe Gitlab::Graphql::Pagination::ExternallyPaginatedArrayConnection do
it_behaves_like 'connection with paged nodes' do
let(:paged_nodes_size) { values.size }
end
+
+ context 'when after or before is specified, they are ignored' do
+ # after and before are not used to filter the array, as they
+ # were already used to directly fetch the external array
+ it_behaves_like 'connection with paged nodes' do
+ let(:arguments) { { after: next_cursor } }
+ let(:paged_nodes_size) { values.size }
+ end
+
+ it_behaves_like 'connection with paged nodes' do
+ let(:arguments) { { before: prev_cursor } }
+ let(:paged_nodes_size) { values.size }
+ end
+ end
end
describe '#start_cursor' do
diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml
index ead71631e33..9e822ad51c2 100644
--- a/spec/lib/gitlab/import_export/all_models.yml
+++ b/spec/lib/gitlab/import_export/all_models.yml
@@ -11,6 +11,7 @@ issues:
- resource_label_events
- resource_weight_events
- resource_milestone_events
+- resource_state_events
- sent_notifications
- sentry_issue
- label_links
@@ -119,6 +120,7 @@ merge_requests:
- notes
- resource_label_events
- resource_milestone_events
+- resource_state_events
- label_links
- labels
- last_edited_by
diff --git a/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb b/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
new file mode 100644
index 00000000000..5662b8af280
--- /dev/null
+++ b/spec/lib/gitlab/import_export/design_repo_restorer_spec.rb
@@ -0,0 +1,42 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::DesignRepoRestorer do
+ include GitHelpers
+
+ describe 'bundle a design Git repo' do
+ let(:user) { create(:user) }
+ let!(:project_with_design_repo) { create(:project, :design_repo) }
+ let!(:project) { create(:project) }
+ let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
+ let(:shared) { project.import_export_shared }
+ let(:bundler) { Gitlab::ImportExport::DesignRepoSaver.new(project: project_with_design_repo, shared: shared) }
+ let(:bundle_path) { File.join(shared.export_path, Gitlab::ImportExport.design_repo_bundle_filename) }
+ let(:restorer) do
+ described_class.new(path_to_bundle: bundle_path,
+ shared: shared,
+ project: project)
+ end
+
+ before do
+ allow_next_instance_of(Gitlab::ImportExport) do |instance|
+ allow(instance).to receive(:storage_path).and_return(export_path)
+ end
+
+ bundler.save
+ end
+
+ after do
+ FileUtils.rm_rf(export_path)
+ Gitlab::GitalyClient::StorageSettings.allow_disk_access do
+ FileUtils.rm_rf(project_with_design_repo.design_repository.path_to_repo)
+ FileUtils.rm_rf(project.design_repository.path_to_repo)
+ end
+ end
+
+ it 'restores the repo successfully' do
+ expect(restorer.restore).to eq(true)
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/design_repo_saver_spec.rb b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
new file mode 100644
index 00000000000..bff48e8b52a
--- /dev/null
+++ b/spec/lib/gitlab/import_export/design_repo_saver_spec.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::ImportExport::DesignRepoSaver do
+ describe 'bundle a design Git repo' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:design) { create(:design, :with_file, versions_count: 1) }
+ let!(:project) { create(:project, :design_repo) }
+ let(:export_path) { "#{Dir.tmpdir}/project_tree_saver_spec" }
+ let(:shared) { project.import_export_shared }
+ let(:design_bundler) { described_class.new(project: project, shared: shared) }
+
+ before do
+ project.add_maintainer(user)
+ allow_next_instance_of(Gitlab::ImportExport) do |instance|
+ allow(instance).to receive(:storage_path).and_return(export_path)
+ end
+ end
+
+ after do
+ FileUtils.rm_rf(export_path)
+ end
+
+ it 'bundles the repo successfully' do
+ expect(design_bundler.save).to be true
+ end
+
+ context 'when the repo is empty' do
+ let!(:project) { create(:project) }
+
+ it 'bundles the repo successfully' do
+ expect(design_bundler.save).to be true
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
index 335b0031147..038b95809b4 100644
--- a/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
+++ b/spec/lib/gitlab/import_export/import_test_coverage_spec.rb
@@ -53,22 +53,15 @@ describe 'Test coverage of the Project Import' do
].freeze
# A list of JSON fixture files we use to test Import.
- # Note that we use separate fixture to test ee-only features.
# Most of the relations are present in `complex/project.json`
# which is our main fixture.
- PROJECT_JSON_FIXTURES_EE =
- if Gitlab.ee?
- ['ee/spec/fixtures/lib/gitlab/import_export/designs/project.json'].freeze
- else
- []
- end
-
PROJECT_JSON_FIXTURES = [
'spec/fixtures/lib/gitlab/import_export/complex/project.json',
'spec/fixtures/lib/gitlab/import_export/group/project.json',
'spec/fixtures/lib/gitlab/import_export/light/project.json',
- 'spec/fixtures/lib/gitlab/import_export/milestone-iid/project.json'
- ].freeze + PROJECT_JSON_FIXTURES_EE
+ 'spec/fixtures/lib/gitlab/import_export/milestone-iid/project.json',
+ 'spec/fixtures/lib/gitlab/import_export/designs/project.json'
+ ].freeze
it 'ensures that all imported/exported relations are present in test JSONs' do
not_tested_relations = (relations_from_config - tested_relations) - MUTED_RELATIONS
diff --git a/spec/lib/gitlab/import_export/importer_spec.rb b/spec/lib/gitlab/import_export/importer_spec.rb
index 14e643f86c0..60179146416 100644
--- a/spec/lib/gitlab/import_export/importer_spec.rb
+++ b/spec/lib/gitlab/import_export/importer_spec.rb
@@ -51,7 +51,8 @@ describe Gitlab::ImportExport::Importer do
Gitlab::ImportExport::UploadsRestorer,
Gitlab::ImportExport::LfsRestorer,
Gitlab::ImportExport::StatisticsRestorer,
- Gitlab::ImportExport::SnippetsRepoRestorer
+ Gitlab::ImportExport::SnippetsRepoRestorer,
+ Gitlab::ImportExport::DesignRepoRestorer
].each do |restorer|
it "calls the #{restorer}" do
fake_restorer = double(restorer.to_s)
diff --git a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
index ecb1ed08260..58589a7bbbe 100644
--- a/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_restorer_spec.rb
@@ -8,6 +8,7 @@ end
describe Gitlab::ImportExport::Project::TreeRestorer do
include ImportExport::CommonUtil
+ using RSpec::Parameterized::TableSyntax
let(:shared) { project.import_export_shared }
@@ -987,6 +988,69 @@ describe Gitlab::ImportExport::Project::TreeRestorer do
end
end
end
+
+ context 'JSON with design management data' do
+ let_it_be(:user) { create(:admin, email: 'user_1@gitlabexample.com') }
+ let_it_be(:second_user) { create(:user, email: 'user_2@gitlabexample.com') }
+ let_it_be(:project) do
+ create(:project, :builds_disabled, :issues_disabled,
+ { name: 'project', path: 'project' })
+ end
+ let(:shared) { project.import_export_shared }
+ let(:project_tree_restorer) { described_class.new(user: user, shared: shared, project: project) }
+
+ subject(:restored_project_json) { project_tree_restorer.restore }
+
+ before do
+ setup_import_export_config('designs')
+ restored_project_json
+ end
+
+ it_behaves_like 'restores project successfully', issues: 2
+
+ it 'restores project associations correctly' do
+ expect(project.designs.size).to eq(7)
+ end
+
+ describe 'restores issue associations correctly' do
+ let(:issue) { project.issues.offset(index).first }
+
+ where(:index, :design_filenames, :version_shas, :events, :author_emails) do
+ 0 | %w[chirrido3.jpg jonathan_richman.jpg mariavontrap.jpeg] | %w[27702d08f5ee021ae938737f84e8fe7c38599e85 9358d1bac8ff300d3d2597adaa2572a20f7f8703 e1a4a501bcb42f291f84e5d04c8f927821542fb6] | %w[creation creation creation modification modification deletion] | %w[user_1@gitlabexample.com user_1@gitlabexample.com user_2@gitlabexample.com]
+ 1 | ['1 (1).jpeg', '2099743.jpg', 'a screenshot (1).jpg', 'chirrido3.jpg'] | %w[73f871b4c8c1d65c62c460635e023179fb53abc4 8587e78ab6bda3bc820a9f014c3be4a21ad4fcc8 c9b5f067f3e892122a4b12b0a25a8089192f3ac8] | %w[creation creation creation creation modification] | %w[user_1@gitlabexample.com user_2@gitlabexample.com user_2@gitlabexample.com]
+ end
+
+ with_them do
+ it do
+ expect(issue.designs.pluck(:filename)).to contain_exactly(*design_filenames)
+ expect(issue.design_versions.pluck(:sha)).to contain_exactly(*version_shas)
+ expect(issue.design_versions.flat_map(&:actions).map(&:event)).to contain_exactly(*events)
+ expect(issue.design_versions.map(&:author).map(&:email)).to contain_exactly(*author_emails)
+ end
+ end
+ end
+
+ describe 'restores design version associations correctly' do
+ let(:project_designs) { project.designs.reorder(:filename, :issue_id) }
+ let(:design) { project_designs.offset(index).first }
+
+ where(:index, :version_shas) do
+ 0 | %w[73f871b4c8c1d65c62c460635e023179fb53abc4 c9b5f067f3e892122a4b12b0a25a8089192f3ac8]
+ 1 | %w[73f871b4c8c1d65c62c460635e023179fb53abc4]
+ 2 | %w[c9b5f067f3e892122a4b12b0a25a8089192f3ac8]
+ 3 | %w[27702d08f5ee021ae938737f84e8fe7c38599e85 9358d1bac8ff300d3d2597adaa2572a20f7f8703 e1a4a501bcb42f291f84e5d04c8f927821542fb6]
+ 4 | %w[8587e78ab6bda3bc820a9f014c3be4a21ad4fcc8]
+ 5 | %w[27702d08f5ee021ae938737f84e8fe7c38599e85 e1a4a501bcb42f291f84e5d04c8f927821542fb6]
+ 6 | %w[27702d08f5ee021ae938737f84e8fe7c38599e85]
+ end
+
+ with_them do
+ it do
+ expect(design.versions.pluck(:sha)).to contain_exactly(*version_shas)
+ end
+ end
+ end
+ end
end
context 'enable ndjson import' do
diff --git a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
index 8adc360026d..b9bfe253f10 100644
--- a/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
+++ b/spec/lib/gitlab/import_export/project/tree_saver_spec.rb
@@ -168,6 +168,28 @@ describe Gitlab::ImportExport::Project::TreeSaver do
it 'has issue resource label events' do
expect(subject.first['resource_label_events']).not_to be_empty
end
+
+ it 'saves the issue designs correctly' do
+ expect(subject.first['designs'].size).to eq(1)
+ end
+
+ it 'saves the issue design notes correctly' do
+ expect(subject.first['designs'].first['notes']).not_to be_empty
+ end
+
+ it 'saves the issue design versions correctly' do
+ issue_json = subject.first
+ actions = issue_json['design_versions'].flat_map { |v| v['actions'] }
+
+ expect(issue_json['design_versions'].size).to eq(2)
+ issue_json['design_versions'].each do |version|
+ expect(version['author_id']).to be_kind_of(Integer)
+ end
+ expect(actions.size).to eq(2)
+ actions.each do |action|
+ expect(action['design']).to be_present
+ end
+ end
end
context 'with ci_pipelines' do
@@ -442,6 +464,9 @@ describe Gitlab::ImportExport::Project::TreeSaver do
board = create(:board, project: project, name: 'TestBoard')
create(:list, board: board, position: 0, label: project_label)
+ design = create(:design, :with_file, versions_count: 2, issue: issue)
+ create(:diff_note_on_design, noteable: design, project: project, author: user)
+
project
end
end
diff --git a/spec/lib/gitlab/kubernetes/network_policy_spec.rb b/spec/lib/gitlab/kubernetes/network_policy_spec.rb
new file mode 100644
index 00000000000..87ed922e099
--- /dev/null
+++ b/spec/lib/gitlab/kubernetes/network_policy_spec.rb
@@ -0,0 +1,224 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Kubernetes::NetworkPolicy do
+ let(:policy) do
+ described_class.new(
+ name: name,
+ namespace: namespace,
+ creation_timestamp: '2020-04-14T00:08:30Z',
+ pod_selector: pod_selector,
+ policy_types: %w(Ingress Egress),
+ ingress: ingress,
+ egress: egress
+ )
+ end
+
+ let(:name) { 'example-name' }
+ let(:namespace) { 'example-namespace' }
+ let(:pod_selector) { { matchLabels: { role: 'db' } } }
+
+ let(:ingress) do
+ [
+ {
+ from: [
+ { namespaceSelector: { matchLabels: { project: 'myproject' } } }
+ ]
+ }
+ ]
+ end
+
+ let(:egress) do
+ [
+ {
+ ports: [{ port: 5978 }]
+ }
+ ]
+ end
+
+ describe '.from_yaml' do
+ let(:manifest) do
+ <<-POLICY
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: example-name
+ namespace: example-namespace
+spec:
+ podSelector:
+ matchLabels:
+ role: db
+ policyTypes:
+ - Ingress
+ ingress:
+ - from:
+ - namespaceSelector:
+ matchLabels:
+ project: myproject
+ POLICY
+ end
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, namespace: namespace },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ )
+ end
+
+ subject { Gitlab::Kubernetes::NetworkPolicy.from_yaml(manifest)&.generate }
+
+ it { is_expected.to eq(resource) }
+
+ context 'with nil manifest' do
+ let(:manifest) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with invalid manifest' do
+ let(:manifest) { "\tfoo: bar" }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with manifest without metadata' do
+ let(:manifest) do
+ <<-POLICY
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+spec:
+ podSelector:
+ matchLabels:
+ role: db
+ policyTypes:
+ - Ingress
+ ingress:
+ - from:
+ - namespaceSelector:
+ matchLabels:
+ project: myproject
+ POLICY
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with manifest without spec' do
+ let(:manifest) do
+ <<-POLICY
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: example-name
+ namespace: example-namespace
+ POLICY
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with disallowed class' do
+ let(:manifest) do
+ <<-POLICY
+apiVersion: networking.k8s.io/v1
+kind: NetworkPolicy
+metadata:
+ name: example-name
+ namespace: example-namespace
+ creationTimestamp: 2020-04-14T00:08:30Z
+spec:
+ podSelector:
+ matchLabels:
+ role: db
+ policyTypes:
+ - Ingress
+ ingress:
+ - from:
+ - namespaceSelector:
+ matchLabels:
+ project: myproject
+ POLICY
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '.from_resource' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, namespace: namespace, creationTimestamp: '2020-04-14T00:08:30Z', resourceVersion: '4990' },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ )
+ end
+ let(:generated_resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, namespace: namespace },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ )
+ end
+
+ subject { Gitlab::Kubernetes::NetworkPolicy.from_resource(resource)&.generate }
+
+ it { is_expected.to eq(generated_resource) }
+
+ context 'with nil resource' do
+ let(:resource) { nil }
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with resource without metadata' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress), ingress: ingress, egress: nil }
+ )
+ end
+
+ it { is_expected.to be_nil }
+ end
+
+ context 'with resource without spec' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, namespace: namespace, uid: '128cf288-7de4-11ea-aceb-42010a800089', resourceVersion: '4990' }
+ )
+ end
+
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '#generate' do
+ let(:resource) do
+ ::Kubeclient::Resource.new(
+ metadata: { name: name, namespace: namespace },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress Egress), ingress: ingress, egress: egress }
+ )
+ end
+
+ subject { policy.generate }
+
+ it { is_expected.to eq(resource) }
+ end
+
+ describe '#as_json' do
+ let(:json_policy) do
+ {
+ name: name,
+ namespace: namespace,
+ creation_timestamp: '2020-04-14T00:08:30Z',
+ manifest: YAML.dump(
+ {
+ metadata: { name: name, namespace: namespace },
+ spec: { podSelector: pod_selector, policyTypes: %w(Ingress Egress), ingress: ingress, egress: egress }
+ }
+ )
+ }
+ end
+
+ subject { policy.as_json }
+
+ it { is_expected.to eq(json_policy) }
+ end
+end
diff --git a/spec/lib/gitlab/logging/cloudflare_helper_spec.rb b/spec/lib/gitlab/logging/cloudflare_helper_spec.rb
new file mode 100644
index 00000000000..8585943be3a
--- /dev/null
+++ b/spec/lib/gitlab/logging/cloudflare_helper_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::Logging::CloudflareHelper do
+ let(:helper) do
+ Class.new do
+ include Gitlab::Logging::CloudflareHelper
+ end.new
+ end
+
+ describe '#store_cloudflare_headers!' do
+ let(:payload) { {} }
+ let(:env) { {} }
+ let(:request) { ActionDispatch::Request.new(env) }
+
+ before do
+ request.headers.merge!(headers)
+ end
+
+ context 'with normal headers' do
+ let(:headers) { { 'Cf-Ray' => SecureRandom.hex, 'Cf-Request-Id' => SecureRandom.hex } }
+
+ it 'adds Cf-Ray-Id and Cf-Request-Id' do
+ helper.store_cloudflare_headers!(payload, request)
+
+ expect(payload[:cf_ray]).to eq(headers['Cf-Ray'])
+ expect(payload[:cf_request_id]).to eq(headers['Cf-Request-Id'])
+ end
+ end
+
+ context 'with header values with long strings' do
+ let(:headers) { { 'Cf-Ray' => SecureRandom.hex(33), 'Cf-Request-Id' => SecureRandom.hex(33) } }
+
+ it 'filters invalid header values' do
+ helper.store_cloudflare_headers!(payload, request)
+
+ expect(payload.keys).not_to include(:cf_ray, :cf_request_id)
+ end
+ end
+
+ context 'with header values with non-alphanumeric characters' do
+ let(:headers) { { 'Cf-Ray' => "Bad\u0000ray", 'Cf-Request-Id' => "Bad\u0000req" } }
+
+ it 'filters invalid header values' do
+ helper.store_cloudflare_headers!(payload, request)
+
+ expect(payload.keys).not_to include(:cf_ray, :cf_request_id)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/lograge/custom_options_spec.rb b/spec/lib/gitlab/lograge/custom_options_spec.rb
index 48d06283b7a..3c014ae618b 100644
--- a/spec/lib/gitlab/lograge/custom_options_spec.rb
+++ b/spec/lib/gitlab/lograge/custom_options_spec.rb
@@ -19,7 +19,12 @@ describe Gitlab::Lograge::CustomOptions do
1,
2,
'transaction_id',
- { params: params, user_id: 'test' }
+ {
+ params: params,
+ user_id: 'test',
+ cf_ray: SecureRandom.hex,
+ cf_request_id: SecureRandom.hex
+ }
)
end
@@ -46,5 +51,10 @@ describe Gitlab::Lograge::CustomOptions do
it 'adds the user id' do
expect(subject[:user_id]).to eq('test')
end
+
+ it 'adds Cloudflare headers' do
+ expect(subject[:cf_ray]).to eq(event.payload[:cf_ray])
+ expect(subject[:cf_request_id]).to eq(event.payload[:cf_request_id])
+ end
end
end
diff --git a/spec/lib/gitlab/url_builder_spec.rb b/spec/lib/gitlab/url_builder_spec.rb
index 71ffa4a00a1..66826bcb3b1 100644
--- a/spec/lib/gitlab/url_builder_spec.rb
+++ b/spec/lib/gitlab/url_builder_spec.rb
@@ -25,6 +25,7 @@ describe Gitlab::UrlBuilder do
:project_snippet | ->(snippet) { "/#{snippet.project.full_path}/snippets/#{snippet.id}" }
:project_wiki | ->(wiki) { "/#{wiki.container.full_path}/-/wikis/home" }
:ci_build | ->(build) { "/#{build.project.full_path}/-/jobs/#{build.id}" }
+ :design | ->(design) { "/#{design.project.full_path}/-/design_management/designs/#{design.id}/raw_image" }
:group | ->(group) { "/groups/#{group.full_path}" }
:group_milestone | ->(milestone) { "/groups/#{milestone.group.full_path}/-/milestones/#{milestone.iid}" }
@@ -95,6 +96,16 @@ describe Gitlab::UrlBuilder do
end
end
+ context 'when passing a DesignManagement::Design' do
+ let(:design) { build_stubbed(:design) }
+
+ it 'uses the given ref and size in the URL' do
+ url = subject.build(design, ref: 'feature', size: 'small')
+
+ expect(url).to eq "#{Settings.gitlab['url']}/#{design.project.full_path}/-/design_management/designs/#{design.id}/feature/resized_image/small"
+ end
+ end
+
context 'when passing an unsupported class' do
let(:object) { Object.new }
diff --git a/spec/lib/gitlab/usage_data_counters/designs_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/designs_counter_spec.rb
new file mode 100644
index 00000000000..deaf7ebc7f3
--- /dev/null
+++ b/spec/lib/gitlab/usage_data_counters/designs_counter_spec.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe Gitlab::UsageDataCounters::DesignsCounter do
+ it_behaves_like 'a redis usage counter', 'Designs', :create
+ it_behaves_like 'a redis usage counter', 'Designs', :update
+ it_behaves_like 'a redis usage counter', 'Designs', :delete
+
+ it_behaves_like 'a redis usage counter with totals', :design_management_designs,
+ create: 5,
+ update: 3,
+ delete: 2
+end
diff --git a/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb b/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb
index 920d1d23567..ee6224eca68 100644
--- a/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb
+++ b/spec/lib/gitlab/usage_data_counters/web_ide_counter_spec.rb
@@ -26,6 +26,10 @@ describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_shared_st
it_behaves_like 'counter examples', 'views'
end
+ describe 'terminals counter' do
+ it_behaves_like 'counter examples', 'terminals'
+ end
+
describe 'previews counter' do
let(:setting_enabled) { true }
@@ -56,6 +60,7 @@ describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_shared_st
merge_requests = 3
views = 2
previews = 4
+ terminals = 1
before do
stub_application_setting(web_ide_clientside_preview_enabled: true)
@@ -64,6 +69,7 @@ describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_shared_st
merge_requests.times { described_class.increment_merge_requests_count }
views.times { described_class.increment_views_count }
previews.times { described_class.increment_previews_count }
+ terminals.times { described_class.increment_terminals_count }
end
it 'can report all totals' do
@@ -71,7 +77,8 @@ describe Gitlab::UsageDataCounters::WebIdeCounter, :clean_gitlab_redis_shared_st
web_ide_commits: commits,
web_ide_views: views,
web_ide_merge_requests: merge_requests,
- web_ide_previews: previews
+ web_ide_previews: previews,
+ web_ide_terminals: terminals
)
end
end
diff --git a/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb b/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb
new file mode 100644
index 00000000000..e5e7f6a4450
--- /dev/null
+++ b/spec/lib/system_check/app/hashed_storage_all_projects_check_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rake_helper'
+
+describe SystemCheck::App::HashedStorageAllProjectsCheck do
+ before do
+ silence_output
+ end
+
+ describe '#check?' do
+ it 'fails when at least one project is in legacy storage' do
+ create(:project, :legacy_storage)
+
+ expect(subject.check?).to be_falsey
+ end
+
+ it 'succeeds when all projects are in hashed storage' do
+ create(:project)
+
+ expect(subject.check?).to be_truthy
+ end
+ end
+end
diff --git a/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb b/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb
new file mode 100644
index 00000000000..d5a0014b791
--- /dev/null
+++ b/spec/lib/system_check/app/hashed_storage_enabled_check_spec.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+require 'rake_helper'
+
+describe SystemCheck::App::HashedStorageEnabledCheck do
+ before do
+ silence_output
+ end
+
+ describe '#check?' do
+ it 'fails when hashed storage is disabled' do
+ stub_application_setting(hashed_storage_enabled: false)
+
+ expect(subject.check?).to be_falsey
+ end
+
+ it 'succeeds when hashed storage is enabled' do
+ stub_application_setting(hashed_storage_enabled: true)
+
+ expect(subject.check?).to be_truthy
+ end
+ end
+end