summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
Diffstat (limited to 'qa')
-rw-r--r--qa/Gemfile.lock4
-rw-r--r--qa/qa.rb9
-rw-r--r--qa/qa/factory/resource/group.rb26
-rw-r--r--qa/qa/page/component/clone_panel.rb (renamed from qa/qa/page/shared/clone_panel.rb)4
-rw-r--r--qa/qa/page/component/groups_filter.rb35
-rw-r--r--qa/qa/page/dashboard/groups.rb9
-rw-r--r--qa/qa/page/dashboard/projects.rb3
-rw-r--r--qa/qa/page/group/show.rb6
-rw-r--r--qa/qa/page/project/issue/show.rb2
-rw-r--r--qa/qa/page/project/show.rb6
-rw-r--r--qa/qa/page/project/wiki/show.rb4
-rw-r--r--qa/qa/scenario/template.rb8
-rw-r--r--qa/qa/scenario/test/instance.rb7
-rw-r--r--qa/qa/scenario/test/integration/object_storage.rb2
-rw-r--r--qa/qa/scenario/test/sanity/failing.rb18
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb2
-rw-r--r--qa/qa/specs/features/sanity/failing_spec.rb13
-rw-r--r--qa/qa/specs/runner.rb4
-rw-r--r--qa/spec/git/repository_spec.rb2
-rw-r--r--qa/spec/scenario/test/instance/all_spec.rb44
-rw-r--r--qa/spec/scenario/test/instance/smoke_spec.rb44
-rw-r--r--qa/spec/scenario/test/integration/github_spec.rb21
-rw-r--r--qa/spec/scenario/test/integration/kubernetes_spec.rb9
-rw-r--r--qa/spec/scenario/test/integration/ldap_spec.rb9
-rw-r--r--qa/spec/scenario/test/integration/mattermost_spec.rb18
-rw-r--r--qa/spec/scenario/test/integration/object_storage_spec.rb9
-rw-r--r--qa/spec/specs/runner_spec.rb49
-rw-r--r--qa/spec/support/shared_examples/scenario_shared_examples.rb49
28 files changed, 283 insertions, 133 deletions
diff --git a/qa/Gemfile.lock b/qa/Gemfile.lock
index 1bc424335f8..8f523e55adc 100644
--- a/qa/Gemfile.lock
+++ b/qa/Gemfile.lock
@@ -77,7 +77,7 @@ GEM
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.7.0)
rspec-support (3.7.0)
- rubyzip (1.2.1)
+ rubyzip (1.2.2)
selenium-webdriver (3.8.0)
childprocess (~> 0.5)
rubyzip (~> 1.0)
@@ -103,4 +103,4 @@ DEPENDENCIES
selenium-webdriver (~> 3.8.0)
BUNDLED WITH
- 1.16.1
+ 1.16.4
diff --git a/qa/qa.rb b/qa/qa.rb
index 8e23b444f3b..c21cb3c1929 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
$: << File.expand_path(File.dirname(__FILE__))
Encoding.default_external = 'UTF-8'
@@ -98,6 +100,7 @@ module QA
end
module Sanity
+ autoload :Failing, 'qa/scenario/test/sanity/failing'
autoload :Selectors, 'qa/scenario/test/sanity/selectors'
end
end
@@ -212,10 +215,6 @@ module QA
end
end
- module Shared
- autoload :ClonePanel, 'qa/page/shared/clone_panel'
- end
-
module Profile
autoload :PersonalAccessTokens, 'qa/page/profile/personal_access_tokens'
end
@@ -249,7 +248,9 @@ module QA
# Classes describing components that are used by several pages.
#
module Component
+ autoload :ClonePanel, 'qa/page/component/clone_panel'
autoload :Dropzone, 'qa/page/component/dropzone'
+ autoload :GroupsFilter, 'qa/page/component/groups_filter'
autoload :Select2, 'qa/page/component/select2'
end
end
diff --git a/qa/qa/factory/resource/group.rb b/qa/qa/factory/resource/group.rb
index 531fccd2ad8..033fc48c08f 100644
--- a/qa/qa/factory/resource/group.rb
+++ b/qa/qa/factory/resource/group.rb
@@ -2,7 +2,7 @@ module QA
module Factory
module Resource
class Group < Factory::Base
- attr_writer :path, :description
+ attr_accessor :path, :description
dependency Factory::Resource::Sandbox, as: :sandbox
@@ -14,17 +14,23 @@ module QA
def fabricate!
sandbox.visit!
- Page::Group::Show.perform do |page|
- if page.has_subgroup?(@path)
- page.go_to_subgroup(@path)
+ Page::Group::Show.perform do |group_show|
+ if group_show.has_subgroup?(path)
+ group_show.go_to_subgroup(path)
else
- page.go_to_new_subgroup
+ group_show.go_to_new_subgroup
- Page::Group::New.perform do |group|
- group.set_path(@path)
- group.set_description(@description)
- group.set_visibility('Public')
- group.create
+ Page::Group::New.perform do |group_new|
+ group_new.set_path(path)
+ group_new.set_description(description)
+ group_new.set_visibility('Public')
+ group_new.create
+ end
+
+ # Ensure that the group was actually created
+ group_show.wait(time: 1) do
+ group_show.has_text?(path) &&
+ group_show.has_new_project_or_subgroup_dropdown?
end
end
end
diff --git a/qa/qa/page/shared/clone_panel.rb b/qa/qa/page/component/clone_panel.rb
index 73e3dff956d..8e8ff4e3bb0 100644
--- a/qa/qa/page/shared/clone_panel.rb
+++ b/qa/qa/page/component/clone_panel.rb
@@ -1,6 +1,8 @@
+# frozen_string_literal: true
+
module QA
module Page
- module Shared
+ module Component
module ClonePanel
def self.included(base)
base.view 'app/views/shared/_clone_panel.html.haml' do
diff --git a/qa/qa/page/component/groups_filter.rb b/qa/qa/page/component/groups_filter.rb
new file mode 100644
index 00000000000..69d465e8ac7
--- /dev/null
+++ b/qa/qa/page/component/groups_filter.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module QA
+ module Page
+ module Component
+ module GroupsFilter
+ def self.included(base)
+ base.view 'app/views/shared/groups/_search_form.html.haml' do
+ element :groups_filter, 'search_field_tag :filter'
+ element :groups_filter_placeholder, 'Filter by name...'
+ end
+
+ base.view 'app/views/shared/groups/_empty_state.html.haml' do
+ element :groups_empty_state
+ end
+
+ base.view 'app/assets/javascripts/groups/components/groups.vue' do
+ element :groups_list_tree_container
+ end
+ end
+
+ private
+
+ def filter_by_name(name)
+ wait(reload: false) do
+ page.has_css?(element_selector_css(:groups_empty_state)) ||
+ page.has_css?(element_selector_css(:groups_list_tree_container))
+ end
+
+ fill_in 'Filter by name...', with: name
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/page/dashboard/groups.rb b/qa/qa/page/dashboard/groups.rb
index e853e0d85e0..5654cc01e09 100644
--- a/qa/qa/page/dashboard/groups.rb
+++ b/qa/qa/page/dashboard/groups.rb
@@ -2,19 +2,12 @@ module QA
module Page
module Dashboard
class Groups < Page::Base
- view 'app/views/shared/groups/_search_form.html.haml' do
- element :groups_filter, 'search_field_tag :filter'
- element :groups_filter_placeholder, 'Filter by name...'
- end
+ include Page::Component::GroupsFilter
view 'app/views/dashboard/_groups_head.html.haml' do
element :new_group_button, 'link_to _("New group")'
end
- def filter_by_name(name)
- fill_in 'Filter by name...', with: name
- end
-
def has_group?(name)
filter_by_name(name)
diff --git a/qa/qa/page/dashboard/projects.rb b/qa/qa/page/dashboard/projects.rb
index 73942cb856a..5b2827c089c 100644
--- a/qa/qa/page/dashboard/projects.rb
+++ b/qa/qa/page/dashboard/projects.rb
@@ -3,6 +3,7 @@ module QA
module Dashboard
class Projects < Page::Base
view 'app/views/dashboard/projects/index.html.haml'
+
view 'app/views/shared/projects/_search_form.html.haml' do
element :form_filter_by_name, /form_tag.+id: 'project-filter-form'/
end
@@ -13,6 +14,8 @@ module QA
find_link(text: name).click
end
+ private
+
def filter_by_name(name)
page.within('form#project-filter-form') do
fill_in :name, with: name
diff --git a/qa/qa/page/group/show.rb b/qa/qa/page/group/show.rb
index 3e0eaa392f5..ac85f16d8af 100644
--- a/qa/qa/page/group/show.rb
+++ b/qa/qa/page/group/show.rb
@@ -2,6 +2,8 @@ module QA
module Page
module Group
class Show < Page::Base
+ include Page::Component::GroupsFilter
+
view 'app/views/groups/show.html.haml' do
element :new_project_or_subgroup_dropdown, '.new-project-subgroup'
element :new_project_or_subgroup_dropdown_toggle, '.dropdown-toggle'
@@ -21,8 +23,8 @@ module QA
click_link name
end
- def filter_by_name(name)
- fill_in 'Filter by name...', with: name
+ def has_new_project_or_subgroup_dropdown?
+ page.has_css?(element_selector_css(:new_project_or_subgroup_dropdown))
end
def has_subgroup?(name)
diff --git a/qa/qa/page/project/issue/show.rb b/qa/qa/page/project/issue/show.rb
index 5bc0598a524..587a02163b9 100644
--- a/qa/qa/page/project/issue/show.rb
+++ b/qa/qa/page/project/issue/show.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
module QA
module Page
module Project
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index c751b472535..267e7bbc249 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -2,7 +2,7 @@ module QA
module Page
module Project
class Show < Page::Base
- include Page::Shared::ClonePanel
+ include Page::Component::ClonePanel
view 'app/views/projects/_last_push.html.haml' do
element :create_merge_request
@@ -23,7 +23,7 @@ module QA
end
view 'app/views/projects/buttons/_fork.html.haml' do
- element :fork_label, "%span= s_('GoToYourFork|Fork')"
+ element :fork_label, "%span= s_('ProjectOverview|Fork')"
element :fork_link, "link_to new_project_fork_path(@project)"
end
@@ -32,7 +32,7 @@ module QA
end
view 'app/presenters/project_presenter.rb' do
- element :new_file_button, "label: _('New file'),"
+ element :new_file_button, "_('New file'),"
end
def project_name
diff --git a/qa/qa/page/project/wiki/show.rb b/qa/qa/page/project/wiki/show.rb
index 044e514bab3..c47a715687f 100644
--- a/qa/qa/page/project/wiki/show.rb
+++ b/qa/qa/page/project/wiki/show.rb
@@ -1,9 +1,11 @@
+# frozen_string_literal: true
+
module QA
module Page
module Project
module Wiki
class Show < Page::Base
- include Page::Shared::ClonePanel
+ include Page::Component::ClonePanel
view 'app/views/projects/wikis/pages.html.haml' do
element :clone_repository_link, 'Clone repository'
diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb
index a87d925ce32..cb1a1de6b9a 100644
--- a/qa/qa/scenario/template.rb
+++ b/qa/qa/scenario/template.rb
@@ -28,12 +28,8 @@ module QA
Specs::Runner.perform do |specs|
specs.tty = true
- specs.options =
- if rspec_options.any?
- rspec_options
- else
- ['--tag', self.class.focus.join(','), '--', ::File.expand_path('../specs/features', __dir__)]
- end
+ specs.tags = self.class.focus
+ specs.options = rspec_options if rspec_options.any?
end
end
end
diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb
index a2d503cc015..b4098619e4e 100644
--- a/qa/qa/scenario/test/instance.rb
+++ b/qa/qa/scenario/test/instance.rb
@@ -27,12 +27,7 @@ module QA
Specs::Runner.perform do |specs|
specs.tty = true
- specs.options =
- if rspec_options.any?
- rspec_options
- else
- ['--', ::File.expand_path('../../specs/features', __dir__)]
- end
+ specs.options = rspec_options if rspec_options.any?
end
end
end
diff --git a/qa/qa/scenario/test/integration/object_storage.rb b/qa/qa/scenario/test/integration/object_storage.rb
index 874789db20d..2e028bbb5c6 100644
--- a/qa/qa/scenario/test/integration/object_storage.rb
+++ b/qa/qa/scenario/test/integration/object_storage.rb
@@ -4,7 +4,7 @@ module QA
module Scenario
module Test
module Integration
- class ObjectStorage < Test::Instance
+ class ObjectStorage < Test::Instance::All
tags :object_storage
end
end
diff --git a/qa/qa/scenario/test/sanity/failing.rb b/qa/qa/scenario/test/sanity/failing.rb
new file mode 100644
index 00000000000..03452f6693d
--- /dev/null
+++ b/qa/qa/scenario/test/sanity/failing.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+module QA
+ module Scenario
+ module Test
+ module Sanity
+ ##
+ # This scenario exits with a 1 exit code.
+ #
+ class Failing < Template
+ include Bootable
+
+ tags :failing
+ end
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index dd24e8ffba5..e558049756d 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -30,7 +30,7 @@ module QA
push.project = project
push.directory = Pathname
.new(__dir__)
- .join('../../../fixtures/auto_devops_rack')
+ .join('../../../../../fixtures/auto_devops_rack')
push.commit_message = 'Create Auto DevOps compatible rack application'
end
diff --git a/qa/qa/specs/features/sanity/failing_spec.rb b/qa/qa/specs/features/sanity/failing_spec.rb
new file mode 100644
index 00000000000..7e0480e9067
--- /dev/null
+++ b/qa/qa/specs/features/sanity/failing_spec.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module QA
+ context 'Sanity checks', :orchestrated, :failing do
+ describe 'Failing orchestrated example' do
+ it 'always fails' do
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+
+ expect(page).to have_text("These Aren't the Texts You're Looking For", wait: 1)
+ end
+ end
+ end
+end
diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb
index ccb9d5591de..5b5699d8a93 100644
--- a/qa/qa/specs/runner.rb
+++ b/qa/qa/specs/runner.rb
@@ -16,9 +16,9 @@ module QA
args.push('--tty') if tty
if tags.any?
- tags.each { |tag| args.push(['-t', tag.to_s]) }
+ tags.each { |tag| args.push(['--tag', tag.to_s]) }
else
- args.push(%w[-t ~orchestrated])
+ args.push(%w[--tag ~orchestrated])
end
args.push(options)
diff --git a/qa/spec/git/repository_spec.rb b/qa/spec/git/repository_spec.rb
index 5c65128d10c..53bff3bf0b3 100644
--- a/qa/spec/git/repository_spec.rb
+++ b/qa/spec/git/repository_spec.rb
@@ -29,7 +29,7 @@ describe QA::Git::Repository do
def cd_empty_temp_directory
tmp_dir = 'tmp/git-repository-spec/'
- FileUtils.rm_r(tmp_dir) if ::File.exist?(tmp_dir)
+ FileUtils.rm_rf(tmp_dir) if ::File.exist?(tmp_dir)
FileUtils.mkdir_p tmp_dir
FileUtils.cd tmp_dir
end
diff --git a/qa/spec/scenario/test/instance/all_spec.rb b/qa/spec/scenario/test/instance/all_spec.rb
index 1d96352550b..9311d1d8199 100644
--- a/qa/spec/scenario/test/instance/all_spec.rb
+++ b/qa/spec/scenario/test/instance/all_spec.rb
@@ -1,45 +1,3 @@
describe QA::Scenario::Test::Instance::All do
- subject do
- Class.new(described_class) do
- tags :rspec, :foo
- end
- end
-
- context '#perform' do
- let(:arguments) { spy('Runtime::Scenario') }
- let(:release) { spy('Runtime::Release') }
- let(:runner) { spy('Specs::Runner') }
-
- before do
- stub_const('QA::Runtime::Release', release)
- stub_const('QA::Runtime::Scenario', arguments)
- stub_const('QA::Specs::Runner', runner)
-
- allow(runner).to receive(:perform).and_yield(runner)
- end
-
- it 'sets an address of the subject' do
- subject.perform("hello")
-
- expect(arguments).to have_received(:define)
- .with(:gitlab_address, "hello")
- end
-
- context 'no paths' do
- it 'calls runner with default arguments' do
- subject.perform("test")
-
- expect(runner).to have_received(:options=)
- .with(['--tag', 'rspec,foo', '--', ::File.expand_path('../../../../qa/specs/features', __dir__)])
- end
- end
-
- context 'specifying paths' do
- it 'calls runner with paths' do
- subject.perform('test', 'path1', 'path2')
-
- expect(runner).to have_received(:options=).with(%w[path1 path2])
- end
- end
- end
+ it_behaves_like 'a QA scenario class'
end
diff --git a/qa/spec/scenario/test/instance/smoke_spec.rb b/qa/spec/scenario/test/instance/smoke_spec.rb
index 386eefae930..b5db9783af3 100644
--- a/qa/spec/scenario/test/instance/smoke_spec.rb
+++ b/qa/spec/scenario/test/instance/smoke_spec.rb
@@ -1,45 +1,5 @@
describe QA::Scenario::Test::Instance::Smoke do
- subject { Class.new(described_class) { tags :smoke } }
-
- context '#perform' do
- let(:arguments) { spy('Runtime::Scenario') }
- let(:release) { spy('Runtime::Release') }
- let(:runner) { spy('Specs::Runner') }
-
- before do
- stub_const('QA::Runtime::Release', release)
- stub_const('QA::Runtime::Scenario', arguments)
- stub_const('QA::Specs::Runner', runner)
-
- allow(runner).to receive(:perform).and_yield(runner)
- end
-
- it 'sets an address of the subject' do
- subject.perform("hello")
-
- expect(arguments).to have_received(:define)
- .with(:gitlab_address, "hello")
- end
-
- it 'has a smoke tag' do
- expect(subject.focus).to eq([:smoke]) # rubocop:disable Focus
- end
-
- context 'no paths' do
- it 'calls runner with default arguments' do
- subject.perform("test")
-
- expect(runner).to have_received(:options=)
- .with(['--tag', 'smoke', '--', ::File.expand_path('../../../../qa/specs/features', __dir__)])
- end
- end
-
- context 'specifying paths' do
- it 'calls runner with paths' do
- subject.perform('test', 'path1', 'path2')
-
- expect(runner).to have_received(:options=).with(%w[path1 path2])
- end
- end
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:smoke] }
end
end
diff --git a/qa/spec/scenario/test/integration/github_spec.rb b/qa/spec/scenario/test/integration/github_spec.rb
new file mode 100644
index 00000000000..c2aeb1ded1d
--- /dev/null
+++ b/qa/spec/scenario/test/integration/github_spec.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::Github do
+ context '#perform' do
+ let(:env) { spy('Runtime::Env') }
+
+ before do
+ stub_const('QA::Runtime::Env', env)
+ end
+
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:github] }
+
+ it 'requires a GitHub access token' do
+ subject.perform('gitlab_address')
+
+ expect(env).to have_received(:require_github_access_token!)
+ end
+ end
+ end
+end
diff --git a/qa/spec/scenario/test/integration/kubernetes_spec.rb b/qa/spec/scenario/test/integration/kubernetes_spec.rb
new file mode 100644
index 00000000000..cb43994b229
--- /dev/null
+++ b/qa/spec/scenario/test/integration/kubernetes_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::Kubernetes do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:kubernetes] }
+ end
+ end
+end
diff --git a/qa/spec/scenario/test/integration/ldap_spec.rb b/qa/spec/scenario/test/integration/ldap_spec.rb
new file mode 100644
index 00000000000..198856aec3f
--- /dev/null
+++ b/qa/spec/scenario/test/integration/ldap_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::LDAP do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:ldap] }
+ end
+ end
+end
diff --git a/qa/spec/scenario/test/integration/mattermost_spec.rb b/qa/spec/scenario/test/integration/mattermost_spec.rb
new file mode 100644
index 00000000000..59caf2ba2cd
--- /dev/null
+++ b/qa/spec/scenario/test/integration/mattermost_spec.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::Mattermost do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:args) { %w[gitlab_address mattermost_address] }
+ let(:tags) { [:mattermost] }
+ let(:options) { ['path1']}
+
+ it 'requires a GitHub access token' do
+ subject.perform(*args)
+
+ expect(attributes).to have_received(:define)
+ .with(:mattermost_address, 'mattermost_address')
+ end
+ end
+ end
+end
diff --git a/qa/spec/scenario/test/integration/object_storage_spec.rb b/qa/spec/scenario/test/integration/object_storage_spec.rb
new file mode 100644
index 00000000000..2b7188223e0
--- /dev/null
+++ b/qa/spec/scenario/test/integration/object_storage_spec.rb
@@ -0,0 +1,9 @@
+# frozen_string_literal: true
+
+describe QA::Scenario::Test::Integration::ObjectStorage do
+ context '#perform' do
+ it_behaves_like 'a QA scenario class' do
+ let(:tags) { [:object_storage] }
+ end
+ end
+end
diff --git a/qa/spec/specs/runner_spec.rb b/qa/spec/specs/runner_spec.rb
new file mode 100644
index 00000000000..b237b954889
--- /dev/null
+++ b/qa/spec/specs/runner_spec.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+describe QA::Specs::Runner do
+ context '#perform' do
+ before do
+ allow(QA::Runtime::Browser).to receive(:configure!)
+ end
+
+ it 'excludes the orchestrated tag by default' do
+ expect(RSpec::Core::Runner).to receive(:run)
+ .with(['--tag', '~orchestrated', File.expand_path('../../qa/specs/features', __dir__)], $stderr, $stdout)
+ .and_return(0)
+
+ subject.perform
+ end
+
+ context 'when tty is set' do
+ subject do
+ described_class.new.tap do |runner|
+ runner.tty = true
+ end
+ end
+
+ it 'sets the `--tty` flag' do
+ expect(RSpec::Core::Runner).to receive(:run)
+ .with(['--tty', '--tag', '~orchestrated', File.expand_path('../../qa/specs/features', __dir__)], $stderr, $stdout)
+ .and_return(0)
+
+ subject.perform
+ end
+ end
+
+ context 'when tags are set' do
+ subject do
+ described_class.new.tap do |runner|
+ runner.tags = %i[orchestrated github]
+ end
+ end
+
+ it 'focuses on the given tags' do
+ expect(RSpec::Core::Runner).to receive(:run)
+ .with(['--tag', 'orchestrated', '--tag', 'github', File.expand_path('../../qa/specs/features', __dir__)], $stderr, $stdout)
+ .and_return(0)
+
+ subject.perform
+ end
+ end
+ end
+end
diff --git a/qa/spec/support/shared_examples/scenario_shared_examples.rb b/qa/spec/support/shared_examples/scenario_shared_examples.rb
new file mode 100644
index 00000000000..5fd55d7d96b
--- /dev/null
+++ b/qa/spec/support/shared_examples/scenario_shared_examples.rb
@@ -0,0 +1,49 @@
+# frozen_string_literal: true
+
+shared_examples 'a QA scenario class' do
+ let(:attributes) { spy('Runtime::Scenario') }
+ let(:release) { spy('Runtime::Release') }
+ let(:runner) { spy('Specs::Runner') }
+
+ let(:args) { ['gitlab_address'] }
+ let(:tags) { [] }
+ let(:options) { %w[path1 path2] }
+
+ before do
+ stub_const('QA::Runtime::Release', release)
+ stub_const('QA::Runtime::Scenario', attributes)
+ stub_const('QA::Specs::Runner', runner)
+
+ allow(runner).to receive(:perform).and_yield(runner)
+ end
+
+ it 'responds to perform' do
+ expect(subject).to respond_to(:perform)
+ end
+
+ it 'sets an address of the subject' do
+ subject.perform(*args)
+
+ expect(attributes).to have_received(:define).with(:gitlab_address, 'gitlab_address')
+ end
+
+ it 'performs before hooks' do
+ subject.perform(*args)
+
+ expect(release).to have_received(:perform_before_hooks)
+ end
+
+ it 'sets tags on runner' do
+ subject.perform(*args)
+
+ expect(runner).to have_received(:tags=).with(tags)
+ end
+
+ context 'specifying RSpec options' do
+ it 'sets options on runner' do
+ subject.perform(*args, *options)
+
+ expect(runner).to have_received(:options=).with(options)
+ end
+ end
+end