diff options
Diffstat (limited to 'spec/support/helpers')
20 files changed, 164 insertions, 111 deletions
diff --git a/spec/support/helpers/ci/template_helpers.rb b/spec/support/helpers/ci/template_helpers.rb new file mode 100644 index 00000000000..7bab58a574e --- /dev/null +++ b/spec/support/helpers/ci/template_helpers.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +module Ci + module TemplateHelpers + def secure_analyzers_prefix + 'registry.gitlab.com/gitlab-org/security-products/analyzers' + end + end +end + +Ci::TemplateHelpers.prepend_mod diff --git a/spec/support/helpers/cycle_analytics_helpers.rb b/spec/support/helpers/cycle_analytics_helpers.rb index 4515b96c79e..e48c8125d84 100644 --- a/spec/support/helpers/cycle_analytics_helpers.rb +++ b/spec/support/helpers/cycle_analytics_helpers.rb @@ -12,9 +12,7 @@ module CycleAnalyticsHelpers page.all('.gl-path-button').collect(&:text).map {|name_with_median| name_with_median.split("\n")[0] } end - def add_custom_stage_to_form - page.find_button(s_('CreateValueStreamForm|Add another stage')).click - + def fill_in_custom_stage_fields index = page.all('[data-testid="value-stream-stage-fields"]').length last_stage = page.all('[data-testid="value-stream-stage-fields"]').last @@ -25,6 +23,12 @@ module CycleAnalyticsHelpers end end + def add_custom_stage_to_form + page.find_button(s_('CreateValueStreamForm|Add another stage')).click + + fill_in_custom_stage_fields + end + def save_value_stream(custom_value_stream_name) fill_in 'create-value-stream-name', with: custom_value_stream_name diff --git a/spec/support/helpers/database/table_schema_helpers.rb b/spec/support/helpers/database/table_schema_helpers.rb index 48d33442110..472eaa45b4b 100644 --- a/spec/support/helpers/database/table_schema_helpers.rb +++ b/spec/support/helpers/database/table_schema_helpers.rb @@ -43,6 +43,14 @@ module Database expect(index_exists_by_name(name, schema: schema)).to be_nil end + def expect_foreign_key_to_exist(table_name, name, schema: nil) + expect(foreign_key_exists_by_name(table_name, name, schema: schema)).to eq(true) + end + + def expect_foreign_key_not_to_exist(table_name, name, schema: nil) + expect(foreign_key_exists_by_name(table_name, name, schema: schema)).to be_nil + end + def expect_check_constraint(table_name, name, definition, schema: nil) expect(check_constraint_definition(table_name, name, schema: schema)).to eq("CHECK ((#{definition}))") end @@ -133,6 +141,18 @@ module Database SQL end + def foreign_key_exists_by_name(table_name, foreign_key_name, schema: nil) + table_name = schema ? "#{schema}.#{table_name}" : table_name + + connection.select_value(<<~SQL) + SELECT true + FROM pg_catalog.pg_constraint + WHERE pg_constraint.conrelid = '#{table_name}'::regclass + AND pg_constraint.contype = 'f' + AND pg_constraint.conname = '#{foreign_key_name}' + SQL + end + def check_constraint_definition(table_name, constraint_name, schema: nil) table_name = schema ? "#{schema}.#{table_name}" : table_name diff --git a/spec/support/helpers/feature_flag_helpers.rb b/spec/support/helpers/feature_flag_helpers.rb index af7a674f3bc..51ba9039b70 100644 --- a/spec/support/helpers/feature_flag_helpers.rb +++ b/spec/support/helpers/feature_flag_helpers.rb @@ -14,6 +14,12 @@ module FeatureFlagHelpers strategies: strategies) end + def create_strategy(feature_flag, name = 'default', parameters = {}) + create(:operations_strategy, + feature_flag: feature_flag, + name: name) + end + def within_feature_flag_row(index) within ".gl-responsive-table-row:nth-child(#{index + 1})" do yield diff --git a/spec/support/helpers/features/admin_users_helpers.rb b/spec/support/helpers/features/admin_users_helpers.rb new file mode 100644 index 00000000000..99b19eedcff --- /dev/null +++ b/spec/support/helpers/features/admin_users_helpers.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module Spec + module Support + module Helpers + module Features + module AdminUsersHelpers + def click_user_dropdown_toggle(user_id) + page.within("[data-testid='user-actions-#{user_id}']") do + find("[data-testid='dropdown-toggle']").click + end + end + + def click_action_in_user_dropdown(user_id, action) + click_user_dropdown_toggle(user_id) + + within find("[data-testid='user-actions-#{user_id}']") do + find('li button', exact_text: action).click + end + end + end + end + end + end +end diff --git a/spec/support/helpers/features/invite_members_modal_helper.rb b/spec/support/helpers/features/invite_members_modal_helper.rb index 1127c817656..7b8cd6963c0 100644 --- a/spec/support/helpers/features/invite_members_modal_helper.rb +++ b/spec/support/helpers/features/invite_members_modal_helper.rb @@ -9,7 +9,7 @@ module Spec click_on 'Invite members' page.within '#invite-members-modal' do - fill_in 'Select members or type email addresses', with: name + find('[data-testid="members-token-select-input"]').set(name) wait_for_requests click_button name diff --git a/spec/support/helpers/features/snippet_helpers.rb b/spec/support/helpers/features/snippet_helpers.rb index c26849a9680..dc718b1b212 100644 --- a/spec/support/helpers/features/snippet_helpers.rb +++ b/spec/support/helpers/features/snippet_helpers.rb @@ -1,14 +1,17 @@ # frozen_string_literal: true -# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). +# These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). # + +require Rails.root.join("spec/support/helpers/features/source_editor_spec_helpers.rb") + module Spec module Support module Helpers module Features module SnippetSpecHelpers include ActionView::Helpers::JavaScriptHelper - include Spec::Support::Helpers::Features::EditorLiteSpecHelpers + include Spec::Support::Helpers::Features::SourceEditorSpecHelpers def snippet_description_locator 'snippet-description' @@ -31,7 +34,7 @@ module Spec end def snippet_get_first_blob_value - page.find('.gl-editor-lite', match: :first) + page.find('.gl-source-editor', match: :first) end def snippet_description_value @@ -53,7 +56,7 @@ module Spec end def snippet_fill_in_content(value) - page.within('.gl-editor-lite') do + page.within('.gl-source-editor') do el = find('.inputarea') el.send_keys value end diff --git a/spec/support/helpers/features/editor_lite_spec_helpers.rb b/spec/support/helpers/features/source_editor_spec_helpers.rb index 0a67e753379..57057b47fbb 100644 --- a/spec/support/helpers/features/editor_lite_spec_helpers.rb +++ b/spec/support/helpers/features/source_editor_spec_helpers.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true -# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). +# These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). # module Spec module Support module Helpers module Features - module EditorLiteSpecHelpers + module SourceEditorSpecHelpers include ActionView::Helpers::JavaScriptHelper def editor_set_value(value) diff --git a/spec/support/helpers/features/top_nav_spec_helpers.rb b/spec/support/helpers/features/top_nav_spec_helpers.rb index ab664ce4283..87ed897ec74 100644 --- a/spec/support/helpers/features/top_nav_spec_helpers.rb +++ b/spec/support/helpers/features/top_nav_spec_helpers.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# These helpers help you interact within the Editor Lite (single-file editor, snippets, etc.). +# These helpers help you interact within the Source Editor (single-file editor, snippets, etc.). # module Spec module Support diff --git a/spec/support/helpers/grafana_api_helpers.rb b/spec/support/helpers/grafana_api_helpers.rb index e47b1a808f2..7a7b6fec5b4 100644 --- a/spec/support/helpers/grafana_api_helpers.rb +++ b/spec/support/helpers/grafana_api_helpers.rb @@ -31,7 +31,7 @@ module GrafanaApiHelpers end def stub_all_grafana_proxy_requests(base_url) - stub_request(:any, /#{base_url}\/api\/datasources\/proxy/) + stub_request(:any, %r{#{base_url}/api/datasources/proxy}) .to_return( status: 200, body: fixture_file('grafana/proxy_response.json'), diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb index 8fd8a548011..4c90b907d2d 100644 --- a/spec/support/helpers/javascript_fixtures_helpers.rb +++ b/spec/support/helpers/javascript_fixtures_helpers.rb @@ -43,12 +43,14 @@ module JavaScriptFixturesHelpers # Public: Reads a GraphQL query from the filesystem as a string # # query_path - file path to the GraphQL query, relative to `app/assets/javascripts` - # fragment_paths - an optional array of file paths to any fragments the query uses, - # also relative to `app/assets/javascripts` - def get_graphql_query_as_string(query_path, fragment_paths = []) - [query_path, *fragment_paths].map do |path| - File.read(File.join(Rails.root, '/app/assets/javascripts', path)) - end.join("\n") + def get_graphql_query_as_string(query_path) + path = Rails.root / 'app/assets/javascripts' / query_path + queries = Gitlab::Graphql::Queries.find(path) + if queries.length == 1 + queries.first.text(mode: Gitlab.ee? ? :ee : :ce ) + else + raise "Could not find query file at #{path}, please check your query_path" % path + end end private diff --git a/spec/support/helpers/jira_service_helper.rb b/spec/support/helpers/jira_service_helper.rb index ce908d53f88..3cfd0de06e8 100644 --- a/spec/support/helpers/jira_service_helper.rb +++ b/spec/support/helpers/jira_service_helper.rb @@ -4,7 +4,7 @@ module JiraServiceHelper JIRA_URL = "http://jira.example.net" JIRA_API = JIRA_URL + "/rest/api/2" - def jira_service_settings + def jira_integration_settings url = JIRA_URL username = 'jira-user' password = 'my-secret-password' @@ -77,7 +77,7 @@ module JiraServiceHelper JIRA_API + "/issue/#{issue_id}" end - def stub_jira_service_test + def stub_jira_integration_test WebMock.stub_request(:get, /serverInfo/).to_return(body: { url: 'http://url' }.to_json) end diff --git a/spec/support/helpers/live_debugger.rb b/spec/support/helpers/live_debugger.rb index cdb068760f4..f4199d518a3 100644 --- a/spec/support/helpers/live_debugger.rb +++ b/spec/support/helpers/live_debugger.rb @@ -7,8 +7,8 @@ module LiveDebugger puts puts "Current example is paused for live debugging." - if ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i - puts "Switch to the Chrome window that was automatically opened to run the test in order to view current page" + if is_headless_disabled? + puts "Switch to the browser window that was automatically opened to run the test in order to view current page" else puts "Opening #{current_url} in your default browser..." end @@ -16,10 +16,16 @@ module LiveDebugger puts "The current user credentials are: #{@current_user.username} / #{@current_user.password}" if @current_user puts "Press any key to resume the execution of the example!!" - `open #{current_url}` if ENV['CHROME_HEADLESS'] !~ /^(false|no|0)$/i + `open #{current_url}` if is_headless_disabled? loop until $stdin.getch puts "Back to the example!" end + + def is_headless_disabled? + ActiveSupport::Deprecation.warn("CHROME_HEADLESS is deprecated. Use WEBDRIVER_HEADLESS instead.") if ENV.key?('CHROME_HEADLESS') + + ENV['WEBDRIVER_HEADLESS'] =~ /^(false|no|0)$/i || ENV['CHROME_HEADLESS'] =~ /^(false|no|0)$/i + end end diff --git a/spec/support/helpers/merge_request_diff_helpers.rb b/spec/support/helpers/merge_request_diff_helpers.rb index 49beecc6d4b..30afde7efed 100644 --- a/spec/support/helpers/merge_request_diff_helpers.rb +++ b/spec/support/helpers/merge_request_diff_helpers.rb @@ -3,8 +3,8 @@ module MergeRequestDiffHelpers def click_diff_line(line_holder, diff_side = nil) line = get_line_components(line_holder, diff_side) - line[:content].hover - line[:num].find('.js-add-diff-note-button', visible: false).send_keys(:return) + line_holder.hover + line[:num].find('.js-add-diff-note-button').click end def get_line_components(line_holder, diff_side = nil) diff --git a/spec/support/helpers/require_migration.rb b/spec/support/helpers/require_migration.rb index 8de71d3073f..de3a8a81ab5 100644 --- a/spec/support/helpers/require_migration.rb +++ b/spec/support/helpers/require_migration.rb @@ -15,7 +15,7 @@ class RequireMigration end MIGRATION_FOLDERS = %w[db/migrate db/post_migrate].freeze - SPEC_FILE_PATTERN = /.+\/(?<file_name>.+)_spec\.rb/.freeze + SPEC_FILE_PATTERN = %r{.+/(?<file_name>.+)_spec\.rb}.freeze class << self def require_migration!(file_name) @@ -29,7 +29,7 @@ class RequireMigration migration_folders.flat_map do |path| migration_path = Rails.root.join(path).to_s - Find.find(migration_path).grep(/\d+_#{file_name}\.rb/) + Find.find(migration_path).select { |m| File.basename(m).match? /\A\d+_#{file_name}\.rb\z/ } end end diff --git a/spec/support/helpers/services_helper.rb b/spec/support/helpers/services_helper.rb deleted file mode 100644 index bf007815551..00000000000 --- a/spec/support/helpers/services_helper.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: true - -require_relative './after_next_helpers' - -module ServicesHelper - include AfterNextHelpers - - def expect_execution_of(service_class, *args) - expect_next(service_class, *args).to receive(:execute) - end -end diff --git a/spec/support/helpers/stub_experiments.rb b/spec/support/helpers/stub_experiments.rb index 408d16a7c08..8995b8f5f7b 100644 --- a/spec/support/helpers/stub_experiments.rb +++ b/spec/support/helpers/stub_experiments.rb @@ -11,7 +11,6 @@ module StubExperiments allow(Gitlab::Experimentation).to receive(:active?).and_call_original experiments.each do |experiment_key, enabled| - Feature.persist_used!("#{experiment_key}#{feature_flag_suffix}") allow(Gitlab::Experimentation).to receive(:active?).with(experiment_key) { enabled } end end @@ -26,7 +25,6 @@ module StubExperiments allow(Gitlab::Experimentation).to receive(:in_experiment_group?).and_call_original experiments.each do |experiment_key, enabled| - Feature.persist_used!("#{experiment_key}#{feature_flag_suffix}") allow(Gitlab::Experimentation).to receive(:in_experiment_group?).with(experiment_key, anything) { enabled } end end diff --git a/spec/support/helpers/stub_spam_services.rb b/spec/support/helpers/stub_spam_services.rb new file mode 100644 index 00000000000..841e8366845 --- /dev/null +++ b/spec/support/helpers/stub_spam_services.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module StubSpamServices + def stub_spam_services + allow(::Spam::SpamParams).to receive(:new_from_request) do + ::Spam::SpamParams.new( + captcha_response: double(:captcha_response), + spam_log_id: double(:spam_log_id), + ip_address: double(:ip_address), + user_agent: double(:user_agent), + referer: double(:referer) + ) + end + + allow_next_instance_of(::Spam::SpamActionService) do |service| + allow(service).to receive(:execute) + end + + allow_next_instance_of(::UserAgentDetailService) do |service| + allow(service).to receive(:create) + end + end +end diff --git a/spec/support/helpers/stubbed_feature.rb b/spec/support/helpers/stubbed_feature.rb index 67ceb7d9b35..4113a28182b 100644 --- a/spec/support/helpers/stubbed_feature.rb +++ b/spec/support/helpers/stubbed_feature.rb @@ -4,14 +4,6 @@ module StubbedFeature extend ActiveSupport::Concern - prepended do - cattr_reader(:persist_used) do - # persist feature flags in CI - # nil: indicates that we do not want to persist used feature flags - Gitlab::Utils.to_boolean(ENV['CI']) ? {} : nil - end - end - class_methods do # Turn stubbed feature flags on or off. def stub=(stub) @@ -41,8 +33,6 @@ module StubbedFeature feature_flag = super return feature_flag unless stub? - persist_used!(args.first) - # If feature flag is not persisted we mark the feature flag as enabled # We do `m.call` as we want to validate the execution of method arguments # and a feature flag state if it is not persisted @@ -52,17 +42,5 @@ module StubbedFeature feature_flag end - - # This method creates a temporary file in `tmp/feature_flags` - # if feature flag was touched during execution - def persist_used!(name) - return unless persist_used - return if persist_used[name] - - persist_used[name] = true - FileUtils.touch( - Rails.root.join('tmp', 'feature_flags', name.to_s + ".used") - ) - end end end diff --git a/spec/support/helpers/test_env.rb b/spec/support/helpers/test_env.rb index 40a3dbfbf25..8814d260fb3 100644 --- a/spec/support/helpers/test_env.rb +++ b/spec/support/helpers/test_env.rb @@ -1,7 +1,8 @@ # frozen_string_literal: true +require 'parallel' + module TestEnv - extend ActiveSupport::Concern extend self ComponentFailedToInstallError = Class.new(StandardError) @@ -94,50 +95,40 @@ module TestEnv TMP_TEST_PATH = Rails.root.join('tmp', 'tests').freeze REPOS_STORAGE = 'default' SECOND_STORAGE_PATH = Rails.root.join('tmp', 'tests', 'second_storage') + SETUP_METHODS = %i[setup_gitaly setup_gitlab_shell setup_workhorse setup_factory_repo setup_forked_repo].freeze + + # Can be overriden + def setup_methods + SETUP_METHODS + end # Test environment # # See gitlab.yml.example test section for paths # - def init(opts = {}) + def init unless Rails.env.test? puts "\nTestEnv.init can only be run if `RAILS_ENV` is set to 'test' not '#{Rails.env}'!\n" exit 1 end + start = Time.now # Disable mailer for spinach tests - disable_mailer if opts[:mailer] == false - clean_test_path - setup_gitlab_shell - - setup_gitaly - - # Feature specs are run through Workhorse - setup_workhorse - - # Create repository for FactoryBot.create(:project) - setup_factory_repo - - # Create repository for FactoryBot.create(:forked_project_with_submodules) - setup_forked_repo - end - - included do |config| - config.append_before do - set_current_example_group + # Install components in parallel as most of the setup is I/O. + Parallel.each(setup_methods) do |method| + public_send(method) end - end - def disable_mailer - allow_any_instance_of(NotificationService).to receive(:mailer) - .and_return(double.as_null_object) + post_init + + puts "\nTest environment set up in #{Time.now - start} seconds" end - def enable_mailer - allow_any_instance_of(NotificationService).to receive(:mailer) - .and_call_original + # Can be overriden + def post_init + start_gitaly(gitaly_dir) end # Clean /tmp/tests @@ -164,12 +155,11 @@ module TestEnv end def setup_gitaly - install_gitaly_args = [gitaly_dir, repos_path, gitaly_url].compact.join(',') - component_timed_setup('Gitaly', install_dir: gitaly_dir, version: Gitlab::GitalyClient.expected_server_version, - task: "gitlab:gitaly:install[#{install_gitaly_args}]") do + task: "gitlab:gitaly:install", + task_args: [gitaly_dir, repos_path, gitaly_url].compact) do Gitlab::SetupHelper::Gitaly.create_configuration( gitaly_dir, { 'default' => repos_path }, @@ -190,8 +180,6 @@ module TestEnv ) Gitlab::SetupHelper::Praefect.create_configuration(gitaly_dir, { 'praefect' => repos_path }, force: true) end - - start_gitaly(gitaly_dir) end def gitaly_socket_path @@ -273,19 +261,18 @@ module TestEnv raise "could not connect to #{service} at #{socket.inspect} after #{sleep_time} seconds" end + # Feature specs are run through Workhorse def setup_workhorse start = Time.now return if skip_compile_workhorse? - puts "\n==> Setting up GitLab Workhorse..." - FileUtils.rm_rf(workhorse_dir) Gitlab::SetupHelper::Workhorse.compile_into(workhorse_dir) Gitlab::SetupHelper::Workhorse.create_configuration(workhorse_dir, nil) File.write(workhorse_tree_file, workhorse_tree) if workhorse_source_clean? - puts " GitLab Workhorse set up in #{Time.now - start} seconds...\n" + puts "==> GitLab Workhorse set up in #{Time.now - start} seconds...\n" end def skip_compile_workhorse? @@ -349,10 +336,12 @@ module TestEnv ENV.fetch('GITLAB_WORKHORSE_URL', nil) end + # Create repository for FactoryBot.create(:project) def setup_factory_repo setup_repo(factory_repo_path, factory_repo_path_bare, factory_repo_name, BRANCH_SHA) end + # Create repository for FactoryBot.create(:forked_project_with_submodules) # This repo has a submodule commit that is not present in the main test # repository. def setup_forked_repo @@ -363,20 +352,18 @@ module TestEnv clone_url = "https://gitlab.com/gitlab-org/#{repo_name}.git" unless File.directory?(repo_path) - puts "\n==> Setting up #{repo_name} repository in #{repo_path}..." start = Time.now system(*%W(#{Gitlab.config.git.bin_path} clone --quiet -- #{clone_url} #{repo_path})) - puts " #{repo_path} set up in #{Time.now - start} seconds...\n" + puts "==> #{repo_path} set up in #{Time.now - start} seconds...\n" end set_repo_refs(repo_path, refs) unless File.directory?(repo_path_bare) - puts "\n==> Setting up #{repo_name} bare repository in #{repo_path_bare}..." start = Time.now # We must copy bare repositories because we will push to them. system(git_env, *%W(#{Gitlab.config.git.bin_path} clone --quiet --bare -- #{repo_path} #{repo_path_bare})) - puts " #{repo_path_bare} set up in #{Time.now - start} seconds...\n" + puts "==> #{repo_path_bare} set up in #{Time.now - start} seconds...\n" end end @@ -468,10 +455,6 @@ module TestEnv private - def set_current_example_group - Thread.current[:current_example_group] = ::RSpec.current_example.metadata[:example_group] - end - # These are directories that should be preserved at cleanup time def test_dirs @test_dirs ||= %w[ @@ -526,7 +509,7 @@ module TestEnv end end - def component_timed_setup(component, install_dir:, version:, task:) + def component_timed_setup(component, install_dir:, version:, task:, task_args: []) start = Time.now ensure_component_dir_name_is_correct!(component, install_dir) @@ -535,17 +518,22 @@ module TestEnv return if File.exist?(install_dir) && ci? if component_needs_update?(install_dir, version) - puts "\n==> Setting up #{component}..." # Cleanup the component entirely to ensure we start fresh FileUtils.rm_rf(install_dir) - unless system('rake', task) - raise ComponentFailedToInstallError + if ENV['SKIP_RAILS_ENV_IN_RAKE'] + # When we run `scripts/setup-test-env`, we take care of loading the necessary dependencies + # so we can run the rake task programmatically. + Rake::Task[task].invoke(*task_args) + else + # In other cases, we run the task via `rake` so that the environment + # and dependencies are automatically loaded. + raise ComponentFailedToInstallError unless system('rake', "#{task}[#{task_args.join(',')}]") end yield if block_given? - puts " #{component} set up in #{Time.now - start} seconds...\n" + puts "==> #{component} set up in #{Time.now - start} seconds...\n" end rescue ComponentFailedToInstallError puts "\n#{component} failed to install, cleaning up #{install_dir}!\n" |