summaryrefslogtreecommitdiff
path: root/spec/support
diff options
context:
space:
mode:
Diffstat (limited to 'spec/support')
-rw-r--r--spec/support/api/schema_matcher.rb2
-rw-r--r--spec/support/database_cleaner.rb56
-rw-r--r--spec/support/db_cleaner.rb50
-rw-r--r--spec/support/features/reportable_note_shared_examples.rb2
-rw-r--r--spec/support/features/variable_list_shared_examples.rb8
-rw-r--r--spec/support/helpers/file_mover_helpers.rb12
-rw-r--r--spec/support/helpers/graphql_helpers.rb20
-rw-r--r--spec/support/helpers/javascript_fixtures_helpers.rb27
-rw-r--r--spec/support/helpers/kubernetes_helpers.rb15
-rw-r--r--spec/support/helpers/login_helpers.rb13
-rw-r--r--spec/support/import_export/export_file_helper.rb2
-rw-r--r--spec/support/matchers/access_matchers.rb35
-rw-r--r--spec/support/pg_stat_activity.rb19
-rw-r--r--spec/support/shared_contexts/services_shared_context.rb8
-rw-r--r--spec/support/shared_examples/issuable_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/notify_shared_examples.rb28
-rw-r--r--spec/support/shared_examples/requests/api/discussions.rb31
-rw-r--r--spec/support/shared_examples/requests/api/merge_requests_list.rb31
-rw-r--r--spec/support/shared_examples/views/nav_sidebar.rb11
-rw-r--r--spec/support/webmock.rb10
20 files changed, 289 insertions, 93 deletions
diff --git a/spec/support/api/schema_matcher.rb b/spec/support/api/schema_matcher.rb
index 6591d56e473..f7d74df0656 100644
--- a/spec/support/api/schema_matcher.rb
+++ b/spec/support/api/schema_matcher.rb
@@ -1,6 +1,6 @@
module SchemaPath
def self.expand(schema, dir = '')
- Rails.root.join('spec', dir, "fixtures/api/schemas/#{schema}.json").to_s
+ Rails.root.join(dir, 'spec', "fixtures/api/schemas/#{schema}.json").to_s
end
end
diff --git a/spec/support/database_cleaner.rb b/spec/support/database_cleaner.rb
new file mode 100644
index 00000000000..edd7de94203
--- /dev/null
+++ b/spec/support/database_cleaner.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'database_cleaner/active_record/deletion'
+require_relative 'db_cleaner'
+
+module FakeInformationSchema
+ # Work around a bug in DatabaseCleaner when using the deletion strategy:
+ # https://github.com/DatabaseCleaner/database_cleaner/issues/347
+ #
+ # On MySQL, if the information schema is said to exist, we use an inaccurate
+ # row count leading to some tables not being cleaned when they should
+ def information_schema_exists?(_connection)
+ false
+ end
+end
+
+DatabaseCleaner::ActiveRecord::Deletion.prepend(FakeInformationSchema)
+
+RSpec.configure do |config|
+ include DbCleaner
+
+ # Ensure all sequences are reset at the start of the suite run
+ config.before(:suite) do
+ setup_database_cleaner
+ DatabaseCleaner.clean_with(:truncation)
+ end
+
+ config.append_after(:context) do
+ DatabaseCleaner.clean_with(:deletion, cache_tables: false)
+ end
+
+ config.before do
+ setup_database_cleaner
+ DatabaseCleaner.strategy = :transaction
+ end
+
+ config.before(:each, :js) do
+ DatabaseCleaner.strategy = :deletion, { except: deletion_except_tables, cache_tables: false }
+ end
+
+ config.before(:each, :delete) do
+ DatabaseCleaner.strategy = :deletion, { except: deletion_except_tables, cache_tables: false }
+ end
+
+ config.before(:each, :migration) do
+ DatabaseCleaner.strategy = :deletion, { cache_tables: false }
+ end
+
+ config.before do
+ DatabaseCleaner.start
+ end
+
+ config.append_after do
+ DatabaseCleaner.clean
+ end
+end
diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb
index 34b9efaaecd..c69fa322073 100644
--- a/spec/support/db_cleaner.rb
+++ b/spec/support/db_cleaner.rb
@@ -1,49 +1,9 @@
-require 'database_cleaner/active_record/deletion'
-
-module FakeInformationSchema
- # Work around a bug in DatabaseCleaner when using the deletion strategy:
- # https://github.com/DatabaseCleaner/database_cleaner/issues/347
- #
- # On MySQL, if the information schema is said to exist, we use an inaccurate
- # row count leading to some tables not being cleaned when they should
- def information_schema_exists?(_connection)
- false
- end
-end
-
-DatabaseCleaner::ActiveRecord::Deletion.prepend(FakeInformationSchema)
-
-RSpec.configure do |config|
- # Ensure all sequences are reset at the start of the suite run
- config.before(:suite) do
- DatabaseCleaner.clean_with(:truncation)
- end
-
- config.append_after(:context) do
- DatabaseCleaner.clean_with(:deletion, cache_tables: false)
- end
-
- config.before do
- DatabaseCleaner.strategy = :transaction
- end
-
- config.before(:each, :js) do
- DatabaseCleaner.strategy = :deletion, { cache_tables: false }
- end
-
- config.before(:each, :delete) do
- DatabaseCleaner.strategy = :deletion, { cache_tables: false }
- end
-
- config.before(:each, :migration) do
- DatabaseCleaner.strategy = :deletion, { cache_tables: false }
- end
-
- config.before do
- DatabaseCleaner.start
+module DbCleaner
+ def deletion_except_tables
+ []
end
- config.append_after do
- DatabaseCleaner.clean
+ def setup_database_cleaner
+ DatabaseCleaner[:active_record, { connection: ActiveRecord::Base }]
end
end
diff --git a/spec/support/features/reportable_note_shared_examples.rb b/spec/support/features/reportable_note_shared_examples.rb
index 8cfce49da8a..89dfbf931d2 100644
--- a/spec/support/features/reportable_note_shared_examples.rb
+++ b/spec/support/features/reportable_note_shared_examples.rb
@@ -41,7 +41,7 @@ shared_examples 'reportable note' do |type|
def open_dropdown(dropdown)
# make window wide enough that tooltip doesn't trigger horizontal scrollbar
- resize_window(1200, 800)
+ restore_window_size
dropdown.find('.more-actions-toggle').click
dropdown.find('.dropdown-menu li', match: :first)
diff --git a/spec/support/features/variable_list_shared_examples.rb b/spec/support/features/variable_list_shared_examples.rb
index 0a464d77cb7..73156d18c1b 100644
--- a/spec/support/features/variable_list_shared_examples.rb
+++ b/spec/support/features/variable_list_shared_examples.rb
@@ -8,7 +8,7 @@ shared_examples 'variable list' do
it 'adds new CI variable' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key value')
+ find('.js-ci-variable-input-value').set('key_value')
end
click_button('Save variables')
@@ -19,7 +19,7 @@ shared_examples 'variable list' do
# We check the first row because it re-sorts to alphabetical order on refresh
page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key value')
+ expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
end
end
@@ -44,7 +44,7 @@ shared_examples 'variable list' do
it 'adds new protected variable' do
page.within('.js-ci-variable-list-section .js-row:last-child') do
find('.js-ci-variable-input-key').set('key')
- find('.js-ci-variable-input-value').set('key value')
+ find('.js-ci-variable-input-value').set('key_value')
find('.ci-variable-protected-item .js-project-feature-toggle').click
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
@@ -58,7 +58,7 @@ shared_examples 'variable list' do
# We check the first row because it re-sorts to alphabetical order on refresh
page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do
expect(find('.js-ci-variable-input-key').value).to eq('key')
- expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key value')
+ expect(find('.js-ci-variable-input-value', visible: false).value).to eq('key_value')
expect(find('.js-ci-variable-input-protected', visible: false).value).to eq('true')
end
end
diff --git a/spec/support/helpers/file_mover_helpers.rb b/spec/support/helpers/file_mover_helpers.rb
new file mode 100644
index 00000000000..1ba7cc03354
--- /dev/null
+++ b/spec/support/helpers/file_mover_helpers.rb
@@ -0,0 +1,12 @@
+# frozen_string_literal: true
+
+module FileMoverHelpers
+ def stub_file_mover(file_path, stub_real_path: nil)
+ file_name = File.basename(file_path)
+ allow(Pathname).to receive(:new).and_call_original
+
+ expect_next_instance_of(Pathname, a_string_including(file_name)) do |pathname|
+ allow(pathname).to receive(:realpath) { stub_real_path || pathname.cleanpath }
+ end
+ end
+end
diff --git a/spec/support/helpers/graphql_helpers.rb b/spec/support/helpers/graphql_helpers.rb
index e468ee4676d..6cdc19ac2e5 100644
--- a/spec/support/helpers/graphql_helpers.rb
+++ b/spec/support/helpers/graphql_helpers.rb
@@ -77,13 +77,23 @@ module GraphqlHelpers
def query_graphql_field(name, attributes = {}, fields = nil)
fields ||= all_graphql_fields_for(name.classify)
attributes = attributes_to_graphql(attributes)
+ attributes = "(#{attributes})" if attributes.present?
<<~QUERY
- #{name}(#{attributes}) {
- #{fields}
- }
+ #{name}#{attributes}
+ #{wrap_fields(fields)}
QUERY
end
+ def wrap_fields(fields)
+ return unless fields.strip.present?
+
+ <<~FIELDS
+ {
+ #{fields}
+ }
+ FIELDS
+ end
+
def all_graphql_fields_for(class_name, parent_types = Set.new)
type = GitlabSchema.types[class_name.to_s]
return "" unless type
@@ -115,8 +125,8 @@ module GraphqlHelpers
end.join(", ")
end
- def post_graphql(query, current_user: nil, variables: nil)
- post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }
+ def post_graphql(query, current_user: nil, variables: nil, headers: {})
+ post api('/', current_user, version: 'graphql'), params: { query: query, variables: variables }, headers: headers
end
def post_graphql_mutation(mutation, current_user: nil)
diff --git a/spec/support/helpers/javascript_fixtures_helpers.rb b/spec/support/helpers/javascript_fixtures_helpers.rb
index 89c5ec7a718..f525b2f945e 100644
--- a/spec/support/helpers/javascript_fixtures_helpers.rb
+++ b/spec/support/helpers/javascript_fixtures_helpers.rb
@@ -2,11 +2,12 @@ require 'action_dispatch/testing/test_request'
require 'fileutils'
module JavaScriptFixturesHelpers
+ extend ActiveSupport::Concern
include Gitlab::Popen
- FIXTURE_PATH = 'spec/javascripts/fixtures'.freeze
+ FIXTURE_PATHS = %w[spec/javascripts/fixtures ee/spec/javascripts/fixtures].freeze
- def self.included(base)
+ included do |base|
base.around do |example|
# pick an arbitrary date from the past, so tests are not time dependent
Timecop.freeze(Time.utc(2015, 7, 3, 10)) { example.run }
@@ -15,26 +16,30 @@ module JavaScriptFixturesHelpers
# Public: Removes all fixture files from given directory
#
- # directory_name - directory of the fixtures (relative to FIXTURE_PATH)
+ # directory_name - directory of the fixtures (relative to FIXTURE_PATHS)
#
def clean_frontend_fixtures(directory_name)
- directory_name = File.expand_path(directory_name, FIXTURE_PATH)
- Dir[File.expand_path('*.html.raw', directory_name)].each do |file_name|
- FileUtils.rm(file_name)
+ FIXTURE_PATHS.each do |fixture_path|
+ directory_name = File.expand_path(directory_name, fixture_path)
+ Dir[File.expand_path('*.html.raw', directory_name)].each do |file_name|
+ FileUtils.rm(file_name)
+ end
end
end
# Public: Store a response object as fixture file
#
# response - string or response object to store
- # fixture_file_name - file name to store the fixture in (relative to FIXTURE_PATH)
+ # fixture_file_name - file name to store the fixture in (relative to FIXTURE_PATHS)
#
def store_frontend_fixture(response, fixture_file_name)
- fixture_file_name = File.expand_path(fixture_file_name, FIXTURE_PATH)
- fixture = response.respond_to?(:body) ? parse_response(response) : response
+ FIXTURE_PATHS.each do |fixture_path|
+ fixture_file_name = File.expand_path(fixture_file_name, fixture_path)
+ fixture = response.respond_to?(:body) ? parse_response(response) : response
- FileUtils.mkdir_p(File.dirname(fixture_file_name))
- File.write(fixture_file_name, fixture)
+ FileUtils.mkdir_p(File.dirname(fixture_file_name))
+ File.write(fixture_file_name, fixture)
+ end
end
def remove_repository(project)
diff --git a/spec/support/helpers/kubernetes_helpers.rb b/spec/support/helpers/kubernetes_helpers.rb
index 9dc89b483b2..cca11e112c9 100644
--- a/spec/support/helpers/kubernetes_helpers.rb
+++ b/spec/support/helpers/kubernetes_helpers.rb
@@ -9,6 +9,10 @@ module KubernetesHelpers
kube_response(kube_pods_body)
end
+ def kube_logs_response
+ kube_response(kube_logs_body)
+ end
+
def kube_deployments_response
kube_response(kube_deployments_body)
end
@@ -34,6 +38,13 @@ module KubernetesHelpers
WebMock.stub_request(:get, pods_url).to_return(response || kube_pods_response)
end
+ def stub_kubeclient_logs(pod_name, response = nil)
+ stub_kubeclient_discover(service.api_url)
+ logs_url = service.api_url + "/api/v1/namespaces/#{service.actual_namespace}/pods/#{pod_name}/log?tailLines=#{Clusters::Platforms::Kubernetes::LOGS_LIMIT}"
+
+ WebMock.stub_request(:get, logs_url).to_return(response || kube_logs_response)
+ end
+
def stub_kubeclient_deployments(response = nil)
stub_kubeclient_discover(service.api_url)
deployments_url = service.api_url + "/apis/extensions/v1beta1/namespaces/#{service.actual_namespace}/deployments"
@@ -212,6 +223,10 @@ module KubernetesHelpers
}
end
+ def kube_logs_body
+ "Log 1\nLog 2\nLog 3"
+ end
+
def kube_deployments_body
{
"kind" => "DeploymentList",
diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb
index 3fee6872498..4a0cf62a661 100644
--- a/spec/support/helpers/login_helpers.rb
+++ b/spec/support/helpers/login_helpers.rb
@@ -47,7 +47,7 @@ module LoginHelpers
end
def gitlab_sign_in_via(provider, user, uid, saml_response = nil)
- mock_auth_hash(provider, uid, user.email, saml_response)
+ mock_auth_hash_with_saml_xml(provider, uid, user.email, saml_response)
visit new_user_session_path
click_link provider
end
@@ -87,7 +87,12 @@ module LoginHelpers
click_link "oauth-login-#{provider}"
end
- def mock_auth_hash(provider, uid, email, saml_response = nil)
+ def mock_auth_hash_with_saml_xml(provider, uid, email, saml_response)
+ response_object = { document: saml_xml(saml_response) }
+ mock_auth_hash(provider, uid, email, response_object: response_object)
+ end
+
+ def mock_auth_hash(provider, uid, email, response_object: nil)
# The mock_auth configuration allows you to set per-provider (or default)
# authentication hashes to return during integration testing.
OmniAuth.config.mock_auth[provider.to_sym] = OmniAuth::AuthHash.new({
@@ -110,9 +115,7 @@ module LoginHelpers
image: 'mock_user_thumbnail_url'
}
},
- response_object: {
- document: saml_xml(saml_response)
- }
+ response_object: response_object
}
})
Rails.application.env_config['omniauth.auth'] = OmniAuth.config.mock_auth[provider.to_sym]
diff --git a/spec/support/import_export/export_file_helper.rb b/spec/support/import_export/export_file_helper.rb
index ac320934f5a..388b88f0331 100644
--- a/spec/support/import_export/export_file_helper.rb
+++ b/spec/support/import_export/export_file_helper.rb
@@ -91,7 +91,7 @@ module ExportFileHelper
loop do
object_with_parent = deep_find_with_parent(sensitive_word, project_hash)
- return nil unless object_with_parent && object_with_parent.object
+ return unless object_with_parent && object_with_parent.object
if is_safe_hash?(object_with_parent.parent, sensitive_word)
# It's in the safe list, remove hash and keep looking
diff --git a/spec/support/matchers/access_matchers.rb b/spec/support/matchers/access_matchers.rb
index 3e4ca8b7ab0..e6899e2d23c 100644
--- a/spec/support/matchers/access_matchers.rb
+++ b/spec/support/matchers/access_matchers.rb
@@ -7,29 +7,28 @@ module AccessMatchers
extend RSpec::Matchers::DSL
include Warden::Test::Helpers
- def emulate_user(user, membership = nil)
- case user
- when :user
- login_as(create(:user))
+ def emulate_user(user_type_or_trait, membership = nil)
+ case user_type_or_trait
+ when :user, :admin
+ login_as(create(user_type_or_trait))
+ when :external, :auditor
+ login_as(create(:user, user_type_or_trait))
when :visitor
logout
- when :admin
- login_as(create(:admin))
- when :external
- login_as(create(:user, external: true))
when User
- login_as(user)
+ login_as(user_type_or_trait)
when *Gitlab::Access.sym_options_with_owner.keys
- raise ArgumentError, "cannot emulate #{user} without membership parent" unless membership
-
- role = user
+ raise ArgumentError, "cannot emulate #{user_type_or_trait} without membership parent" unless membership
- if role == :owner && membership.owner
- user = membership.owner
- else
- user = create(:user)
- membership.public_send(:"add_#{role}", user)
- end
+ role = user_type_or_trait
+ user =
+ if role == :owner && membership.owner
+ membership.owner
+ else
+ create(:user).tap do |new_user|
+ membership.public_send(:"add_#{role}", new_user)
+ end
+ end
login_as(user)
else
diff --git a/spec/support/pg_stat_activity.rb b/spec/support/pg_stat_activity.rb
new file mode 100644
index 00000000000..f93fba08a19
--- /dev/null
+++ b/spec/support/pg_stat_activity.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+RSpec.configure do |config|
+ config.before do
+ if Gitlab::Database.postgresql? && ENV['PG_STAT_WARNING_THRESHOLD']
+ warning_threshold = ENV['PG_STAT_WARNING_THRESHOLD'].to_i
+ results = ActiveRecord::Base.connection.execute('SELECT * FROM pg_stat_activity')
+ ntuples = results.ntuples
+
+ warn("pg_stat_activity count: #{ntuples}")
+
+ if ntuples > warning_threshold
+ results.each do |result|
+ warn result.inspect
+ end
+ end
+ end
+ end
+end
diff --git a/spec/support/shared_contexts/services_shared_context.rb b/spec/support/shared_contexts/services_shared_context.rb
index d92e8318fa0..089f1798cd2 100644
--- a/spec/support/shared_contexts/services_shared_context.rb
+++ b/spec/support/shared_contexts/services_shared_context.rb
@@ -26,6 +26,14 @@ Service.available_services_names.each do |service|
end
end
+ before do
+ if service == 'github' && respond_to?(:stub_licensed_features)
+ stub_licensed_features(github_project_service_integration: true)
+ project.clear_memoization(:disabled_services)
+ project.clear_memoization(:licensed_feature_available)
+ end
+ end
+
def initialize_service(service)
service_item = project.find_or_initialize_service(service)
service_item.properties = service_attrs
diff --git a/spec/support/shared_examples/issuable_shared_examples.rb b/spec/support/shared_examples/issuable_shared_examples.rb
index c3d40c5b231..d97b21f71cd 100644
--- a/spec/support/shared_examples/issuable_shared_examples.rb
+++ b/spec/support/shared_examples/issuable_shared_examples.rb
@@ -31,7 +31,7 @@ shared_examples 'system notes for milestones' do
context 'project milestones' do
it 'creates a system note' do
expect do
- update_issuable(milestone: create(:milestone))
+ update_issuable(milestone: create(:milestone, project: project))
end.to change { Note.system.count }.by(1)
end
end
diff --git a/spec/support/shared_examples/notify_shared_examples.rb b/spec/support/shared_examples/notify_shared_examples.rb
index a38354060cf..4fff1c4e228 100644
--- a/spec/support/shared_examples/notify_shared_examples.rb
+++ b/spec/support/shared_examples/notify_shared_examples.rb
@@ -252,3 +252,31 @@ shared_examples 'a note email' do
end
end
end
+
+shared_examples 'appearance header and footer enabled' do
+ it "contains header and footer" do
+ create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: true
+
+ aggregate_failures do
+ expect(subject.html_part).to have_body_text("<div class=\"header-message\" style=\"\"><p>Foo</p></div>")
+ expect(subject.html_part).to have_body_text("<div class=\"footer-message\" style=\"\"><p>Bar</p></div>")
+
+ expect(subject.text_part).to have_body_text(/^Foo/)
+ expect(subject.text_part).to have_body_text(/Bar$/)
+ end
+ end
+end
+
+shared_examples 'appearance header and footer not enabled' do
+ it "does not contain header and footer" do
+ create :appearance, header_message: "Foo", footer_message: "Bar", email_header_and_footer_enabled: false
+
+ aggregate_failures do
+ expect(subject.html_part).not_to have_body_text("<div class=\"header-message\" style=\"\"><p>Foo</p></div>")
+ expect(subject.html_part).not_to have_body_text("<div class=\"footer-message\" style=\"\"><p>Bar</p></div>")
+
+ expect(subject.text_part).not_to have_body_text(/^Foo/)
+ expect(subject.text_part).not_to have_body_text(/Bar$/)
+ end
+ end
+end
diff --git a/spec/support/shared_examples/requests/api/discussions.rb b/spec/support/shared_examples/requests/api/discussions.rb
index e44da4faa5a..eff8e401bad 100644
--- a/spec/support/shared_examples/requests/api/discussions.rb
+++ b/spec/support/shared_examples/requests/api/discussions.rb
@@ -86,6 +86,37 @@ shared_examples 'discussions API' do |parent_type, noteable_type, id_name|
expect(response).to have_gitlab_http_status(404)
end
end
+
+ context 'when a project is public with private repo access' do
+ let!(:parent) { create(:project, :public, :repository, :repository_private, :snippets_private) }
+ let!(:user_without_access) { create(:user) }
+
+ context 'when user is not a team member of private repo' do
+ before do
+ project.team.truncate
+ end
+
+ context "creating a new note" do
+ before do
+ post api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions", user_without_access), params: { body: 'hi!' }
+ end
+
+ it 'raises 404 error' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+
+ context "fetching a discussion" do
+ before do
+ get api("/#{parent_type}/#{parent.id}/#{noteable_type}/#{noteable[id_name]}/discussions/#{note.discussion_id}", user_without_access)
+ end
+
+ it 'raises 404 error' do
+ expect(response).to have_gitlab_http_status(404)
+ end
+ end
+ end
+ end
end
describe "POST /#{parent_type}/:id/#{noteable_type}/:noteable_id/discussions/:discussion_id/notes" do
diff --git a/spec/support/shared_examples/requests/api/merge_requests_list.rb b/spec/support/shared_examples/requests/api/merge_requests_list.rb
index 6713ec47ace..32e3b81c3c5 100644
--- a/spec/support/shared_examples/requests/api/merge_requests_list.rb
+++ b/spec/support/shared_examples/requests/api/merge_requests_list.rb
@@ -186,6 +186,37 @@ shared_examples 'merge requests list' do
expect(json_response.length).to eq(0)
end
+ it 'returns an array of labeled merge requests where all labels match' do
+ path = endpoint_path + "?labels[]=#{label.title}&labels[]=#{label2.title}"
+
+ get api(path, user)
+
+ expect(response).to have_gitlab_http_status(200)
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ end
+
+ it 'returns an array of merge requests with any label when filtering by any label' do
+ get api(endpoint_path, user), params: { labels: [" #{label.title} ", " #{label2.title} "] }
+
+ expect_paginated_array_response
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
+ it 'returns an array of merge requests with any label when filtering by any label' do
+ get api(endpoint_path, user), params: { labels: ["#{label.title} , #{label2.title}"] }
+
+ expect_paginated_array_response
+ expect(json_response).to be_an Array
+ expect(json_response.length).to eq(1)
+ expect(json_response.first['labels']).to eq([label2.title, label.title])
+ expect(json_response.first['id']).to eq(merge_request.id)
+ end
+
it 'returns an array of merge requests with any label when filtering by any label' do
get api(endpoint_path, user), params: { labels: IssuesFinder::FILTER_ANY }
diff --git a/spec/support/shared_examples/views/nav_sidebar.rb b/spec/support/shared_examples/views/nav_sidebar.rb
new file mode 100644
index 00000000000..6ac5abe275d
--- /dev/null
+++ b/spec/support/shared_examples/views/nav_sidebar.rb
@@ -0,0 +1,11 @@
+# frozen_string_literal: true
+
+shared_examples 'has nav sidebar' do
+ it 'has collapsed nav sidebar on mobile' do
+ render
+
+ expect(rendered).to have_selector('.nav-sidebar')
+ expect(rendered).not_to have_selector('.sidebar-collapsed-desktop')
+ expect(rendered).not_to have_selector('.sidebar-expanded-mobile')
+ end
+end
diff --git a/spec/support/webmock.rb b/spec/support/webmock.rb
index af2906b7568..9ac7e7fc515 100644
--- a/spec/support/webmock.rb
+++ b/spec/support/webmock.rb
@@ -1,4 +1,12 @@
require 'webmock'
require 'webmock/rspec'
-WebMock.disable_net_connect!(allow_localhost: true)
+def webmock_allowed_hosts
+ %w[elasticsearch registry.gitlab.com-gitlab-org-test-elastic-image].tap do |hosts|
+ if ENV.key?('ELASTIC_URL')
+ hosts << URI.parse(ENV['ELASTIC_URL']).host
+ end
+ end.uniq
+end
+
+WebMock.disable_net_connect!(allow_localhost: true, allow: webmock_allowed_hosts)