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:
Diffstat (limited to 'spec/support/helpers')
-rw-r--r--spec/support/helpers/database/migration_testing_helpers.rb43
-rw-r--r--spec/support/helpers/features/snippet_helpers.rb9
-rw-r--r--spec/support/helpers/features/sorting_helpers.rb8
-rw-r--r--spec/support/helpers/filtered_search_helpers.rb112
-rw-r--r--spec/support/helpers/gitaly_setup.rb66
-rw-r--r--spec/support/helpers/graphql_helpers.rb119
-rw-r--r--spec/support/helpers/migrations_helpers.rb21
-rw-r--r--spec/support/helpers/namespaces_test_helper.rb13
-rw-r--r--spec/support/helpers/navbar_structure_helper.rb8
-rw-r--r--spec/support/helpers/next_instance_of.rb8
-rw-r--r--spec/support/helpers/project_helpers.rb16
-rw-r--r--spec/support/helpers/query_recorder.rb10
-rw-r--r--spec/support/helpers/rendered_helpers.rb12
-rw-r--r--spec/support/helpers/saas_test_helper.rb9
-rw-r--r--spec/support/helpers/stub_feature_flags.rb14
-rw-r--r--spec/support/helpers/stub_object_storage.rb5
-rw-r--r--spec/support/helpers/test_env.rb2
-rw-r--r--spec/support/helpers/trial_status_widget_test_helper.rb9
-rw-r--r--spec/support/helpers/workhorse_helpers.rb6
-rw-r--r--spec/support/helpers/workhorse_lfs_helpers.rb45
20 files changed, 490 insertions, 45 deletions
diff --git a/spec/support/helpers/database/migration_testing_helpers.rb b/spec/support/helpers/database/migration_testing_helpers.rb
new file mode 100644
index 00000000000..916446e66b7
--- /dev/null
+++ b/spec/support/helpers/database/migration_testing_helpers.rb
@@ -0,0 +1,43 @@
+# frozen_string_literal: true
+
+module Database
+ module MigrationTestingHelpers
+ def define_background_migration(name)
+ klass = Class.new do
+ # Can't simply def perform here as we won't have access to the block,
+ # similarly can't define_method(:perform, &block) here as it would change the block receiver
+ define_method(:perform) { |*args| yield(*args) }
+ end
+ stub_const("Gitlab::BackgroundMigration::#{name}", klass)
+ klass
+ end
+
+ def expect_migration_call_counts(migrations_to_calls)
+ migrations_to_calls.each do |migration, calls|
+ expect_next_instances_of(migration, calls) do |m|
+ expect(m).to receive(:perform).and_call_original
+ end
+ end
+ end
+
+ def expect_recorded_migration_runs(migrations_to_runs)
+ migrations_to_runs.each do |migration, runs|
+ path = File.join(result_dir, migration.name.demodulize)
+ if runs.zero?
+ expect(Pathname(path)).not_to be_exist
+ else
+ num_subdirs = Pathname(path).children.count(&:directory?)
+ expect(num_subdirs).to eq(runs)
+ end
+ end
+ end
+
+ def expect_migration_runs(migrations_to_run_counts)
+ expect_migration_call_counts(migrations_to_run_counts)
+
+ yield
+
+ expect_recorded_migration_runs(migrations_to_run_counts)
+ end
+ end
+end
diff --git a/spec/support/helpers/features/snippet_helpers.rb b/spec/support/helpers/features/snippet_helpers.rb
index dc718b1b212..3e32b0e4c67 100644
--- a/spec/support/helpers/features/snippet_helpers.rb
+++ b/spec/support/helpers/features/snippet_helpers.rb
@@ -67,14 +67,19 @@ module Spec
end
def snippet_fill_in_form(title: nil, content: nil, file_name: nil, description: nil, visibility: nil)
+ if content
+ snippet_fill_in_content(content)
+ # It takes some time after sending keys for the vue component to
+ # update so let Capybara wait for the content before proceeding
+ expect(page).to have_content(content)
+ end
+
snippet_fill_in_title(title) if title
snippet_fill_in_description(description) if description
snippet_fill_in_file_name(file_name) if file_name
- snippet_fill_in_content(content) if content
-
snippet_fill_in_visibility(visibility) if visibility
end
end
diff --git a/spec/support/helpers/features/sorting_helpers.rb b/spec/support/helpers/features/sorting_helpers.rb
index a6428bf8573..50b8083ebb3 100644
--- a/spec/support/helpers/features/sorting_helpers.rb
+++ b/spec/support/helpers/features/sorting_helpers.rb
@@ -21,6 +21,14 @@ module Spec
click_link(value)
end
end
+
+ # pajamas_sort_by is used to sort new pajamas dropdowns. When
+ # all of the dropdowns are converted, pajamas_sort_by can be renamed to sort_by
+ # https://gitlab.com/groups/gitlab-org/-/epics/7551
+ def pajamas_sort_by(value)
+ find('.filter-dropdown-container .dropdown').click
+ find('.dropdown-item', text: value).click
+ end
end
end
end
diff --git a/spec/support/helpers/filtered_search_helpers.rb b/spec/support/helpers/filtered_search_helpers.rb
index b6cf78b9046..93122ca3d0c 100644
--- a/spec/support/helpers/filtered_search_helpers.rb
+++ b/spec/support/helpers/filtered_search_helpers.rb
@@ -187,4 +187,116 @@ module FilteredSearchHelpers
toggle.click if toggle.visible?
end
end
+
+ ##
+ # For use with gl-filtered-search
+ def select_tokens(*args, submit: false)
+ within '[data-testid="filtered-search-input"]' do
+ find_field('Search').click
+
+ args.each do |token|
+ # Move mouse away to prevent invoking tooltips on usernames, which blocks the search input
+ find_button('Search').hover
+
+ if token == '='
+ click_on '= is'
+ else
+ click_on token
+ end
+
+ wait_for_requests
+ end
+ end
+
+ if submit
+ send_keys :enter
+ end
+ end
+
+ def get_suggestion_count
+ all('.gl-filtered-search-suggestion').size
+ end
+
+ def submit_search_term(value)
+ click_filtered_search_bar
+ send_keys(value, :enter)
+ end
+
+ def click_filtered_search_bar
+ find('.gl-filtered-search-last-item').click
+ end
+
+ def click_token_segment(value)
+ find('.gl-filtered-search-token-segment', text: value).click
+ end
+
+ def expect_visible_suggestions_list
+ expect(page).to have_css('.gl-filtered-search-suggestion-list')
+ end
+
+ def expect_hidden_suggestions_list
+ expect(page).not_to have_css('.gl-filtered-search-suggestion-list')
+ end
+
+ def expect_suggestion(value)
+ expect(page).to have_css('.gl-filtered-search-suggestion', text: value)
+ end
+
+ def expect_no_suggestion(value)
+ expect(page).not_to have_css('.gl-filtered-search-suggestion', text: value)
+ end
+
+ def expect_suggestion_count(count)
+ expect(page).to have_css('.gl-filtered-search-suggestion', count: count)
+ end
+
+ def expect_assignee_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Assignee = #{value}"
+ end
+
+ def expect_author_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Author = #{value}"
+ end
+
+ def expect_label_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Label = ~#{value}"
+ end
+
+ def expect_negated_label_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Label != ~#{value}"
+ end
+
+ def expect_milestone_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Milestone = %#{value}"
+ end
+
+ def expect_negated_milestone_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Milestone != %#{value}"
+ end
+
+ def expect_epic_token(value)
+ expect(page).to have_css '.gl-filtered-search-token', text: "Epic = #{value}"
+ end
+
+ def expect_search_term(value)
+ value.split(' ').each do |term|
+ expect(page).to have_css '.gl-filtered-search-term', text: term
+ end
+ end
+
+ def expect_empty_search_term
+ expect(page).to have_css '.gl-filtered-search-term', text: ''
+ end
+
+ def expect_token_segment(value)
+ expect(page).to have_css '.gl-filtered-search-token-segment', text: value
+ end
+
+ def expect_recent_searches_history_item(value)
+ expect(page).to have_css '.gl-search-box-by-click-history-item', text: value
+ end
+
+ def expect_recent_searches_history_item_count(count)
+ expect(page).to have_css '.gl-search-box-by-click-history-item', count: count
+ end
end
diff --git a/spec/support/helpers/gitaly_setup.rb b/spec/support/helpers/gitaly_setup.rb
index 0ad83bdeeb2..264281ef94a 100644
--- a/spec/support/helpers/gitaly_setup.rb
+++ b/spec/support/helpers/gitaly_setup.rb
@@ -31,6 +31,10 @@ module GitalySetup
expand_path('tmp/tests/gitaly')
end
+ def runtime_dir
+ expand_path('tmp/run')
+ end
+
def tmp_tests_gitaly_bin_dir
File.join(tmp_tests_gitaly_dir, '_build', 'bin')
end
@@ -102,12 +106,14 @@ module GitalySetup
Gitlab.config.repositories.storages[REPOS_STORAGE].legacy_disk_path
end
- def service_binary(service)
+ def service_cmd(service, toml = nil)
+ toml ||= config_path(service)
+
case service
when :gitaly, :gitaly2
- 'gitaly'
+ [File.join(tmp_tests_gitaly_bin_dir, 'gitaly'), toml]
when :praefect
- 'praefect'
+ [File.join(tmp_tests_gitaly_bin_dir, 'praefect'), '-config', toml]
end
end
@@ -132,14 +138,18 @@ module GitalySetup
end
def start_praefect
- start(:praefect)
+ if ENV['GITALY_PRAEFECT_WITH_DB']
+ LOGGER.debug 'Starting Praefect with database election strategy'
+ start(:praefect, File.join(tmp_tests_gitaly_dir, 'praefect-db.config.toml'))
+ else
+ LOGGER.debug 'Starting Praefect with in-memory election strategy'
+ start(:praefect)
+ end
end
def start(service, toml = nil)
toml ||= config_path(service)
- args = ["#{tmp_tests_gitaly_bin_dir}/#{service_binary(service)}"]
- args.push("-config") if service == :praefect
- args.push(toml)
+ args = service_cmd(service, toml)
# Ensure user configuration does not affect Git
# Context: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58776#note_547613780
@@ -259,6 +269,7 @@ module GitalySetup
{ 'default' => repos_path },
force: true,
options: {
+ runtime_dir: runtime_dir,
prometheus_listen_addr: 'localhost:9236'
}
)
@@ -267,12 +278,47 @@ module GitalySetup
{ 'default' => repos_path },
force: true,
options: {
- runtime_dir: File.join(gitaly_dir, "run2"),
+ runtime_dir: runtime_dir,
gitaly_socket: "gitaly2.socket",
config_filename: "gitaly2.config.toml"
}
)
- Gitlab::SetupHelper::Praefect.create_configuration(gitaly_dir, { 'praefect' => repos_path }, force: true)
+
+ # In CI we need to pre-generate both config files.
+ # For local testing we'll create the correct file on-demand.
+ if ENV['CI'] || ENV['GITALY_PRAEFECT_WITH_DB'].nil?
+ Gitlab::SetupHelper::Praefect.create_configuration(
+ gitaly_dir,
+ { 'praefect' => repos_path },
+ force: true
+ )
+ end
+
+ if ENV['CI'] || ENV['GITALY_PRAEFECT_WITH_DB']
+ Gitlab::SetupHelper::Praefect.create_configuration(
+ gitaly_dir,
+ { 'praefect' => repos_path },
+ force: true,
+ options: {
+ per_repository: true,
+ config_filename: 'praefect-db.config.toml',
+ pghost: ENV['CI'] ? 'postgres' : ENV.fetch('PGHOST'),
+ pgport: ENV['CI'] ? 5432 : ENV.fetch('PGPORT').to_i,
+ pguser: ENV['CI'] ? 'postgres' : ENV.fetch('USER')
+ }
+ )
+ end
+
+ # In CI no database is running when Gitaly is set up
+ # so scripts/gitaly-test-spawn will take care of it instead.
+ setup_praefect unless ENV['CI']
+ end
+
+ def setup_praefect
+ return unless ENV['GITALY_PRAEFECT_WITH_DB']
+
+ migrate_cmd = service_cmd(:praefect, File.join(tmp_tests_gitaly_dir, 'praefect-db.config.toml')) + ['sql-migrate']
+ system(env, *migrate_cmd, [:out, :err] => 'log/praefect-test.log')
end
def socket_path(service)
@@ -325,7 +371,7 @@ module GitalySetup
message += "- The `praefect` binary does not exist: #{praefect_binary}\n" unless File.exist?(praefect_binary)
message += "- The `git` binary does not exist: #{git_binary}\n" unless File.exist?(git_binary)
- message += "\nCheck log/gitaly-test.log for errors.\n"
+ message += "\nCheck log/gitaly-test.log & log/praefect-test.log for errors.\n"
unless ENV['CI']
message += "\nIf binaries are missing, try running `make -C tmp/tests/gitaly all WITH_BUNDLED_GIT=YesPlease`.\n"
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index ff8908e531a..db8d45f61ea 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -244,15 +244,16 @@ module GraphqlHelpers
def graphql_mutation(name, input, fields = nil, &block)
raise ArgumentError, 'Please pass either `fields` parameter or a block to `#graphql_mutation`, but not both.' if fields.present? && block_given?
+ name = name.graphql_name if name.respond_to?(:graphql_name)
mutation_name = GraphqlHelpers.fieldnamerize(name)
input_variable_name = "$#{input_variable_name_for_mutation(name)}"
mutation_field = GitlabSchema.mutation.fields[mutation_name]
fields = yield if block_given?
- fields ||= all_graphql_fields_for(mutation_field.type.to_graphql)
+ fields ||= all_graphql_fields_for(mutation_field.type.to_type_signature)
query = <<~MUTATION
- mutation(#{input_variable_name}: #{mutation_field.arguments['input'].type.to_graphql}) {
+ mutation(#{input_variable_name}: #{mutation_field.arguments['input'].type.to_type_signature}) {
#{mutation_name}(input: #{input_variable_name}) {
#{fields}
}
@@ -264,7 +265,7 @@ module GraphqlHelpers
end
def variables_for_mutation(name, input)
- graphql_input = prepare_input_for_mutation(input)
+ graphql_input = prepare_variables(input)
{ input_variable_name_for_mutation(name) => graphql_input }
end
@@ -273,25 +274,35 @@ module GraphqlHelpers
return unless variables
return variables if variables.is_a?(String)
- ::Gitlab::Utils::MergeHash.merge(Array.wrap(variables).map(&:to_h)).to_json
+ # Combine variables into a single hash.
+ hash = ::Gitlab::Utils::MergeHash.merge(Array.wrap(variables).map(&:to_h))
+
+ prepare_variables(hash).to_json
end
- # Recursively convert a Hash with Ruby-style keys to GraphQL fieldname-style keys
+ # Recursively convert any ruby object we can pass as a variable value
+ # to an object we can serialize with JSON, using fieldname-style keys
#
- # prepare_input_for_mutation({ 'my_key' => 1 })
- # => { 'myKey' => 1}
- def prepare_input_for_mutation(input)
- input.to_h do |name, value|
- value = prepare_input_for_mutation(value) if value.is_a?(Hash)
+ # prepare_variables({ 'my_key' => 1 })
+ # => { 'myKey' => 1 }
+ # prepare_variables({ enums: [:FOO, :BAR], user_id: global_id_of(user) })
+ # => { 'enums' => ['FOO', 'BAR'], 'userId' => "gid://User/123" }
+ # prepare_variables({ nested: { hash_values: { are_supported: true } } })
+ # => { 'nested' => { 'hashValues' => { 'areSupported' => true } } }
+ def prepare_variables(input)
+ return input.map { prepare_variables(_1) } if input.is_a?(Array)
+ return input.to_s if input.is_a?(GlobalID) || input.is_a?(Symbol)
+ return input unless input.is_a?(Hash)
- [GraphqlHelpers.fieldnamerize(name), value]
+ input.to_h do |name, value|
+ [GraphqlHelpers.fieldnamerize(name), prepare_variables(value)]
end
end
def input_variable_name_for_mutation(mutation_name)
mutation_name = GraphqlHelpers.fieldnamerize(mutation_name)
mutation_field = GitlabSchema.mutation.fields[mutation_name]
- input_type = field_type(mutation_field.arguments['input'])
+ input_type = mutation_field.arguments['input'].type.unwrap.to_type_signature
GraphqlHelpers.fieldnamerize(input_type)
end
@@ -346,6 +357,10 @@ module GraphqlHelpers
end
end
+ def query_double(schema:)
+ double('query', schema: schema)
+ end
+
def wrap_fields(fields)
fields = Array.wrap(fields).map do |field|
case field
@@ -646,11 +661,11 @@ module GraphqlHelpers
end
end
- def global_id_of(model, id: nil, model_name: nil)
+ def global_id_of(model = nil, id: nil, model_name: nil)
if id || model_name
- ::Gitlab::GlobalId.build(model, id: id, model_name: model_name).to_s
+ ::Gitlab::GlobalId.as_global_id(id || model.id, model_name: model_name || model.class.name)
else
- model.to_global_id.to_s
+ model.to_global_id
end
end
@@ -683,26 +698,94 @@ module GraphqlHelpers
end
end
- # assumes query_string to be let-bound in the current context
- def execute_query(query_type, schema: empty_schema, graphql: query_string)
+ # assumes query_string and user to be let-bound in the current context
+ def execute_query(query_type, schema: empty_schema, graphql: query_string, raise_on_error: false)
schema.query(query_type)
- schema.execute(
+ r = schema.execute(
graphql,
context: { current_user: user },
variables: {}
)
+
+ if raise_on_error && r.to_h['errors'].present?
+ raise NoData, r.to_h['errors']
+ end
+
+ r
end
def empty_schema
Class.new(GraphQL::Schema) do
use GraphQL::Pagination::Connections
use Gitlab::Graphql::Pagination::Connections
+ use BatchLoader::GraphQL
lazy_resolve ::Gitlab::Graphql::Lazy, :force
end
end
+ # Wrapper around a_hash_including that supports unpacking with **
+ class UnpackableMatcher < SimpleDelegator
+ include RSpec::Matchers
+
+ attr_reader :to_hash
+
+ def initialize(hash)
+ @to_hash = hash
+ super(a_hash_including(hash))
+ end
+
+ def to_json(_opts = {})
+ to_hash.to_json
+ end
+
+ def as_json(opts = {})
+ to_hash.as_json(opts)
+ end
+ end
+
+ # Construct a matcher for GraphQL entity response objects, of the form
+ # `{ "id" => "some-gid" }`.
+ #
+ # Usage:
+ #
+ # ```ruby
+ # expect(graphql_data_at(:path, :to, :entity)).to match a_graphql_entity_for(user)
+ # ```
+ #
+ # This can be called as:
+ #
+ # ```ruby
+ # a_graphql_entity_for(project, :full_path) # also checks that `entity['fullPath'] == project.full_path
+ # a_graphql_entity_for(project, full_path: 'some/path') # same as above, with explicit values
+ # a_graphql_entity_for(user, :username, foo: 'bar') # combinations of the above
+ # a_graphql_entity_for(foo: 'bar') # if properties are defined, the model is not necessary
+ # ```
+ #
+ # Note that the model instance must not be nil, unless some properties are
+ # explicitly passed in. The following are rejected with `ArgumentError`:
+ #
+ # ```
+ # a_graphql_entity_for(nil, :username)
+ # a_graphql_entity_for(:username)
+ # a_graphql_entity_for
+ # ```
+ #
+ def a_graphql_entity_for(model = nil, *fields, **attrs)
+ raise ArgumentError, 'model is nil' if model.nil? && fields.any?
+
+ attrs.transform_keys! { GraphqlHelpers.fieldnamerize(_1) }
+ attrs['id'] = global_id_of(model).to_s if model
+ fields.each do |name|
+ attrs[GraphqlHelpers.fieldnamerize(name)] = model.public_send(name)
+ end
+
+ raise ArgumentError, 'no attributes' if attrs.empty?
+
+ UnpackableMatcher.new(attrs)
+ end
+
# A lookahead that selects everything
def positive_lookahead
double(selects?: true).tap do |selection|
diff --git a/spec/support/helpers/migrations_helpers.rb b/spec/support/helpers/migrations_helpers.rb
index afa7ee84bda..60097e301c4 100644
--- a/spec/support/helpers/migrations_helpers.rb
+++ b/spec/support/helpers/migrations_helpers.rb
@@ -1,12 +1,18 @@
# frozen_string_literal: true
module MigrationsHelpers
- def active_record_base
- Gitlab::Database.database_base_models.fetch(self.class.metadata[:database] || :main)
+ def active_record_base(database: nil)
+ database_name = database || self.class.metadata[:database] || :main
+
+ unless Gitlab::Database::DATABASE_NAMES.include?(database_name.to_s)
+ raise ArgumentError, "#{database_name} is not a valid argument"
+ end
+
+ Gitlab::Database.database_base_models[database_name] || Gitlab::Database.database_base_models[:main]
end
- def table(name)
- Class.new(active_record_base) do
+ def table(name, database: nil)
+ Class.new(active_record_base(database: database)) do
self.table_name = name
self.inheritance_column = :_type_disabled
@@ -150,6 +156,13 @@ module MigrationsHelpers
end
def migrate!
+ open_transactions = ActiveRecord::Base.connection.open_transactions
+ allow_next_instance_of(described_class) do |migration|
+ allow(migration).to receive(:transaction_open?) do
+ ActiveRecord::Base.connection.open_transactions > open_transactions
+ end
+ end
+
migration_context.up do |migration|
migration.name == described_class.name
end
diff --git a/spec/support/helpers/namespaces_test_helper.rb b/spec/support/helpers/namespaces_test_helper.rb
new file mode 100644
index 00000000000..9762c38a9bb
--- /dev/null
+++ b/spec/support/helpers/namespaces_test_helper.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module NamespacesTestHelper
+ def get_buy_minutes_path(namespace)
+ buy_minutes_subscriptions_path(selected_group: namespace.id)
+ end
+
+ def get_buy_storage_path(namespace)
+ buy_storage_subscriptions_path(selected_group: namespace.id)
+ end
+end
+
+NamespacesTestHelper.prepend_mod
diff --git a/spec/support/helpers/navbar_structure_helper.rb b/spec/support/helpers/navbar_structure_helper.rb
index 315303401cc..e11548d0b75 100644
--- a/spec/support/helpers/navbar_structure_helper.rb
+++ b/spec/support/helpers/navbar_structure_helper.rb
@@ -93,7 +93,7 @@ module NavbarStructureHelper
)
end
- def analytics_sub_nav_item
+ def project_analytics_sub_nav_item
[
_('Value stream'),
_('CI/CD'),
@@ -102,6 +102,12 @@ module NavbarStructureHelper
_('Repository')
]
end
+
+ def group_analytics_sub_nav_item
+ [
+ _('Contribution')
+ ]
+ end
end
NavbarStructureHelper.prepend_mod
diff --git a/spec/support/helpers/next_instance_of.rb b/spec/support/helpers/next_instance_of.rb
index 95d8936588c..461d411a5ce 100644
--- a/spec/support/helpers/next_instance_of.rb
+++ b/spec/support/helpers/next_instance_of.rb
@@ -22,9 +22,15 @@ module NextInstanceOf
def stub_new(target, number, ordered = false, *new_args, &blk)
receive_new = receive(:new)
receive_new.ordered if ordered
- receive_new.exactly(number).times if number
receive_new.with(*new_args) if new_args.any?
+ if number.is_a?(Range)
+ receive_new.at_least(number.begin).times if number.begin
+ receive_new.at_most(number.end).times if number.end
+ elsif number
+ receive_new.exactly(number).times
+ end
+
target.to receive_new.and_wrap_original do |method, *original_args|
method.call(*original_args).tap(&blk)
end
diff --git a/spec/support/helpers/project_helpers.rb b/spec/support/helpers/project_helpers.rb
index 89f0163b4b6..2ea6405e48c 100644
--- a/spec/support/helpers/project_helpers.rb
+++ b/spec/support/helpers/project_helpers.rb
@@ -24,4 +24,20 @@ module ProjectHelpers
project.update!(params)
end
+
+ def create_project_with_statistics(namespace = nil, with_data: false, size_multiplier: 1)
+ project = namespace.present? ? create(:project, namespace: namespace) : create(:project)
+ project.tap do |p|
+ create(:project_statistics, project: p, with_data: with_data, size_multiplier: size_multiplier)
+ end
+ end
+
+ def grace_months_after_deletion_notification
+ (::Gitlab::CurrentSettings.inactive_projects_delete_after_months -
+ ::Gitlab::CurrentSettings.inactive_projects_send_warning_email_after_months).months
+ end
+
+ def deletion_date
+ Date.parse(grace_months_after_deletion_notification.from_now.to_s).to_s
+ end
end
diff --git a/spec/support/helpers/query_recorder.rb b/spec/support/helpers/query_recorder.rb
index d18a1d23584..01839a74e65 100644
--- a/spec/support/helpers/query_recorder.rb
+++ b/spec/support/helpers/query_recorder.rb
@@ -80,7 +80,8 @@ module ActiveRecord
if values[:cached] && skip_cached
@cached << values[:sql]
- elsif !skip_schema_queries || !values[:name]&.include?("SCHEMA")
+ elsif !ignorable?(values)
+
backtrace = @query_recorder_debug ? show_backtrace(values, duration) : nil
@log << values[:sql]
store_sql_by_source(values: values, duration: duration, backtrace: backtrace)
@@ -102,5 +103,12 @@ module ActiveRecord
def occurrences
@occurrences ||= @log.group_by(&:to_s).transform_values(&:count)
end
+
+ def ignorable?(values)
+ return true if skip_schema_queries && values[:name]&.include?("SCHEMA")
+ return true if values[:name]&.match(/License Load/)
+
+ false
+ end
end
end
diff --git a/spec/support/helpers/rendered_helpers.rb b/spec/support/helpers/rendered_helpers.rb
new file mode 100644
index 00000000000..137b7d5f708
--- /dev/null
+++ b/spec/support/helpers/rendered_helpers.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module RenderedHelpers
+ # Wraps the `rendered` in `expect` to make it the target of an expectation.
+ # Designed to read nicely for one-liners.
+ # rubocop:disable RSpec/VoidExpect
+ def expect_rendered
+ render
+ expect(rendered)
+ end
+ # rubocop:enable RSpec/VoidExpect
+end
diff --git a/spec/support/helpers/saas_test_helper.rb b/spec/support/helpers/saas_test_helper.rb
new file mode 100644
index 00000000000..a8162603cd9
--- /dev/null
+++ b/spec/support/helpers/saas_test_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module SaasTestHelper
+ def get_next_url
+ "https://next.gitlab.com"
+ end
+end
+
+SaasTestHelper.prepend_mod
diff --git a/spec/support/helpers/stub_feature_flags.rb b/spec/support/helpers/stub_feature_flags.rb
index 77f31169ecb..f1654e55b7e 100644
--- a/spec/support/helpers/stub_feature_flags.rb
+++ b/spec/support/helpers/stub_feature_flags.rb
@@ -70,4 +70,18 @@ module StubFeatureFlags
def skip_default_enabled_yaml_check
allow(Feature::Definition).to receive(:default_enabled?).and_return(false)
end
+
+ def stub_feature_flag_definition(name, opts = {})
+ opts = opts.with_defaults(
+ name: name,
+ type: 'development',
+ default_enabled: false
+ )
+
+ Feature::Definition.new("#{opts[:type]}/#{name}.yml", opts).tap do |definition|
+ all_definitions = Feature::Definition.definitions
+ all_definitions[definition.key] = definition
+ allow(Feature::Definition).to receive(:definitions).and_return(all_definitions)
+ end
+ end
end
diff --git a/spec/support/helpers/stub_object_storage.rb b/spec/support/helpers/stub_object_storage.rb
index d49a14f7f5b..024f06cae1b 100644
--- a/spec/support/helpers/stub_object_storage.rb
+++ b/spec/support/helpers/stub_object_storage.rb
@@ -7,11 +7,6 @@ module StubObjectStorage
**params)
end
- def stub_object_storage_pseudonymizer
- stub_object_storage(connection_params: Pseudonymizer::Uploader.object_store_credentials,
- remote_directory: Pseudonymizer::Uploader.remote_directory)
- end
-
def stub_object_storage_uploader(
config:,
uploader:,
diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb
index d81d0d436a1..11f469c1d27 100644
--- a/spec/support/helpers/test_env.rb
+++ b/spec/support/helpers/test_env.rb
@@ -374,7 +374,7 @@ module TestEnv
end
def seed_db
- Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.import
+ Gitlab::DatabaseImporters::WorkItems::BaseTypeImporter.upsert_types
end
private
diff --git a/spec/support/helpers/trial_status_widget_test_helper.rb b/spec/support/helpers/trial_status_widget_test_helper.rb
new file mode 100644
index 00000000000..d75620d17ee
--- /dev/null
+++ b/spec/support/helpers/trial_status_widget_test_helper.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+module TrialStatusWidgetTestHelper
+ def purchase_href(group)
+ new_subscriptions_path(namespace_id: group.id, plan_id: 'ultimate-plan-id')
+ end
+end
+
+TrialStatusWidgetTestHelper.prepend_mod
diff --git a/spec/support/helpers/workhorse_helpers.rb b/spec/support/helpers/workhorse_helpers.rb
index 83bda6e03b1..6f22df9ae0f 100644
--- a/spec/support/helpers/workhorse_helpers.rb
+++ b/spec/support/helpers/workhorse_helpers.rb
@@ -114,16 +114,18 @@ module WorkhorseHelpers
end
params["#{key}.remote_id"] = file.remote_id if file.respond_to?(:remote_id) && file.remote_id.present?
+ params["#{key}.sha256"] = file.sha256 if file.respond_to?(:sha256) && file.sha256.present?
end
end
- def fog_to_uploaded_file(file)
+ def fog_to_uploaded_file(file, sha256: nil)
filename = File.basename(file.key)
UploadedFile.new(nil,
filename: filename,
remote_id: filename,
- size: file.content_length
+ size: file.content_length,
+ sha256: sha256
)
end
end
diff --git a/spec/support/helpers/workhorse_lfs_helpers.rb b/spec/support/helpers/workhorse_lfs_helpers.rb
new file mode 100644
index 00000000000..c9644826317
--- /dev/null
+++ b/spec/support/helpers/workhorse_lfs_helpers.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+module WorkhorseLfsHelpers
+ extend self
+
+ def put_finalize(
+ lfs_tmp = nil, with_tempfile: false, verified: true, remote_object: nil,
+ args: {}, to_project: nil, size: nil, sha256: nil)
+
+ lfs_tmp ||= "#{sample_oid}012345678"
+ to_project ||= project
+ uploaded_file =
+ if with_tempfile
+ upload_path = LfsObjectUploader.workhorse_local_upload_path
+ file_path = upload_path + '/' + lfs_tmp
+
+ FileUtils.mkdir_p(upload_path)
+ FileUtils.touch(file_path)
+ File.truncate(file_path, sample_size)
+
+ UploadedFile.new(file_path, filename: File.basename(file_path), sha256: sample_oid)
+ elsif remote_object
+ fog_to_uploaded_file(remote_object, sha256: sample_oid)
+ else
+ UploadedFile.new(
+ nil,
+ size: size || sample_size,
+ sha256: sha256 || sample_oid,
+ remote_id: 'remote id'
+ )
+ end
+
+ finalize_headers = headers
+ finalize_headers.merge!(workhorse_internal_api_request_header) if verified
+
+ workhorse_finalize(
+ objects_url(to_project, sample_oid, sample_size),
+ method: :put,
+ file_key: :file,
+ params: args.merge(file: uploaded_file),
+ headers: finalize_headers,
+ send_rewritten_field: include_workhorse_jwt_header
+ )
+ end
+end