diff options
Diffstat (limited to 'qa')
78 files changed, 1328 insertions, 966 deletions
diff --git a/qa/README.md b/qa/README.md index be4cf89ebbc..f8a5c00efd4 100644 --- a/qa/README.md +++ b/qa/README.md @@ -35,7 +35,7 @@ following call would login to a local [GDK] instance and run all specs in `qa/specs/features`: ``` -bin/qa Test::Instance http://localhost:3000 +bin/qa Test::Instance::All http://localhost:3000 ``` ### Writing tests @@ -48,14 +48,14 @@ You can also supply specific tests to run as another parameter. For example, to run the repository-related specs, you can execute: ``` -bin/qa Test::Instance http://localhost qa/specs/features/repository/ +bin/qa Test::Instance::All http://localhost qa/specs/features/repository/ ``` Since the arguments would be passed to `rspec`, you could use all `rspec` options there. For example, passing `--backtrace` and also line number: ``` -bin/qa Test::Instance http://localhost qa/specs/features/project/create_spec.rb:3 --backtrace +bin/qa Test::Instance::All http://localhost qa/specs/features/project/create_spec.rb:3 --backtrace ``` ### Overriding the authenticated user @@ -67,7 +67,7 @@ If you need to authenticate as a different user, you can provide the `GITLAB_USERNAME` and `GITLAB_PASSWORD` environment variables: ``` -GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password bin/qa Test::Instance https://gitlab.example.com +GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password bin/qa Test::Instance::All https://gitlab.example.com ``` If your user doesn't have permission to default sandbox group @@ -75,13 +75,13 @@ If your user doesn't have permission to default sandbox group `GITLAB_SANDBOX_NAME`: ``` -GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sandbox bin/qa Test::Instance https://gitlab.example.com +GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sandbox bin/qa Test::Instance::All https://gitlab.example.com ``` In addition, the `GITLAB_USER_TYPE` can be set to "ldap" to sign in as an LDAP user: ``` -GITLAB_USER_TYPE=ldap GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sandbox bin/qa Test::Instance https://gitlab.example.com +GITLAB_USER_TYPE=ldap GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sandbox bin/qa Test::Instance::All https://gitlab.example.com ``` All [supported environment variables are here](https://gitlab.com/gitlab-org/gitlab-qa#supported-environment-variables). @@ -77,7 +77,6 @@ module QA # autoload :Bootable, 'qa/scenario/bootable' autoload :Actable, 'qa/scenario/actable' - autoload :Taggable, 'qa/scenario/taggable' autoload :Template, 'qa/scenario/template' ## @@ -85,12 +84,17 @@ module QA # module Test autoload :Instance, 'qa/scenario/test/instance' + module Instance + autoload :All, 'qa/scenario/test/instance/all' + autoload :Smoke, 'qa/scenario/test/instance/smoke' + end module Integration autoload :Github, 'qa/scenario/test/integration/github' autoload :LDAP, 'qa/scenario/test/integration/ldap' autoload :Kubernetes, 'qa/scenario/test/integration/kubernetes' autoload :Mattermost, 'qa/scenario/test/integration/mattermost' + autoload :ObjectStorage, 'qa/scenario/test/integration/object_storage' end module Sanity diff --git a/qa/qa/factory/resource/fork.rb b/qa/qa/factory/resource/fork.rb index 1d0c76a3d30..01969c31438 100644 --- a/qa/qa/factory/resource/fork.rb +++ b/qa/qa/factory/resource/fork.rb @@ -4,7 +4,12 @@ module QA class Fork < Factory::Base dependency Factory::Repository::ProjectPush, as: :push - dependency Factory::Resource::User, as: :user + dependency Factory::Resource::User, as: :user do |user| + if Runtime::Env.forker? + user.username = Runtime::Env.forker_username + user.password = Runtime::Env.forker_password + end + end product(:user) { |factory| factory.user } diff --git a/qa/qa/factory/resource/user.rb b/qa/qa/factory/resource/user.rb index e08df9e0cd0..eac2a873bd5 100644 --- a/qa/qa/factory/resource/user.rb +++ b/qa/qa/factory/resource/user.rb @@ -4,28 +4,52 @@ module QA module Factory module Resource class User < Factory::Base - attr_accessor :name, :username, :email, :password + attr_reader :unique_id + attr_writer :username, :password, :name, :email def initialize - @name = "name-#{SecureRandom.hex(8)}" - @username = "username-#{SecureRandom.hex(8)}" - @email = "mail#{SecureRandom.hex(8)}@mail.com" - @password = 'password' + @unique_id = SecureRandom.hex(8) end - product(:name) { |factory| factory.name } + def username + @username ||= "qa-user-#{unique_id}" + end - product(:username) { |factory| factory.username } + def password + @password ||= 'password' + end - product(:email) { |factory| factory.email } + def name + @name ||= username + end + + def email + @email ||= "#{username}@example.com" + end + + def credentials_given? + defined?(@username) && defined?(@password) + end + product(:name) { |factory| factory.name } + product(:username) { |factory| factory.username } + product(:email) { |factory| factory.email } product(:password) { |factory| factory.password } def fabricate! - Page::Menu::Main.act { sign_out } - Page::Main::Login.act { switch_to_register_tab } - Page::Main::SignUp.perform do |page| - page.sign_up!(name: name, username: username, email: email, password: password) + Page::Menu::Main.perform { |main| main.sign_out } + + if credentials_given? + Page::Main::Login.perform do |login| + login.sign_in_using_credentials(self) + end + else + Page::Main::Login.perform do |login| + login.switch_to_register_tab + end + Page::Main::SignUp.perform do |signup| + signup.sign_up!(self) + end end end end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 3df6db05970..bdbb18b5045 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -28,7 +28,7 @@ module QA end def use_default_credentials - self.username = Runtime::User.name + self.username = Runtime::User.username self.password = Runtime::User.password end diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 6cdfbd1c125..afc8b66d878 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -40,17 +40,19 @@ module QA end end - def sign_in_using_credentials + def sign_in_using_credentials(user = nil) # Don't try to log-in if we're already logged-in return if Page::Menu::Main.act { has_personal_area?(wait: 0) } using_wait_time 0 do set_initial_password_if_present + raise NotImplementedError if Runtime::User.ldap_user? && user&.credentials_given? + if Runtime::User.ldap_user? sign_in_using_ldap_credentials else - sign_in_using_gitlab_credentials + sign_in_using_gitlab_credentials(user || Runtime::User) end end @@ -69,21 +71,30 @@ module QA click_on 'Register' end + def switch_to_ldap_tab + click_on 'LDAP' + end + + def switch_to_standard_tab + click_on 'Standard' + end + private def sign_in_using_ldap_credentials - click_link 'LDAP' + switch_to_ldap_tab fill_in :username, with: Runtime::User.ldap_username fill_in :password, with: Runtime::User.ldap_password click_button 'Sign in' end - def sign_in_using_gitlab_credentials - click_link 'Standard' if page.has_content?('LDAP') + def sign_in_using_gitlab_credentials(user) + switch_to_sign_in_tab unless page.has_button?('Sign in') + switch_to_standard_tab if page.has_content?('LDAP') - fill_in :user_login, with: Runtime::User.name - fill_in :user_password, with: Runtime::User.password + fill_in :user_login, with: user.username + fill_in :user_password, with: user.password click_button 'Sign in' end diff --git a/qa/qa/page/main/sign_up.rb b/qa/qa/page/main/sign_up.rb index 9a834e94b81..33ab56236f4 100644 --- a/qa/qa/page/main/sign_up.rb +++ b/qa/qa/page/main/sign_up.rb @@ -11,12 +11,12 @@ module QA element :register_button, 'submit "Register"' end - def sign_up!(name:, username:, email:, password:) - fill_in :new_user_name, with: name - fill_in :new_user_username, with: username - fill_in :new_user_email, with: email - fill_in :new_user_email_confirmation, with: email - fill_in :new_user_password, with: password + def sign_up!(user) + fill_in :new_user_name, with: user.name + fill_in :new_user_username, with: user.username + fill_in :new_user_email, with: user.email + fill_in :new_user_email_confirmation, with: user.email + fill_in :new_user_password, with: user.password click_button 'Register' Page::Menu::Main.act { has_personal_area? } diff --git a/qa/qa/page/project/import/github.rb b/qa/qa/page/project/import/github.rb index 36567927194..1a410a0f8a5 100644 --- a/qa/qa/page/project/import/github.rb +++ b/qa/qa/page/project/import/github.rb @@ -14,7 +14,7 @@ module QA element :project_import_row, 'data: { qa: { repo_path: repo.full_name } }' element :project_namespace_select element :project_namespace_field, 'select_tag :namespace_id' - element :project_path_field, 'text_field_tag :path, repo.name' + element :project_path_field, 'text_field_tag :path, sanitize_project_name(repo.name)' element :import_button, "_('Import')" end diff --git a/qa/qa/page/project/settings/secret_variables.rb b/qa/qa/page/project/settings/secret_variables.rb index d2f5d5a9060..937ae6797c8 100644 --- a/qa/qa/page/project/settings/secret_variables.rb +++ b/qa/qa/page/project/settings/secret_variables.rb @@ -23,7 +23,13 @@ module QA # After we fill the key, JS would generate another field so # we need to use the same index to find the corresponding one. keys[index].set(key) - all_elements(:ci_variable_input_value)[index].set(value) + node = all_elements(:ci_variable_input_value)[index] + + # Simply run `node.set(value)` is too slow for long text here, + # so we need to run JavaScript directly to set the value. + # The code was inspired from: + # https://github.com/teamcapybara/capybara/blob/679548cea10773d45e32808f4d964377cfe5e892/lib/capybara/selenium/node.rb#L217 + execute_script("arguments[0].value = #{value.to_json}", node) end def save_variables diff --git a/qa/qa/page/view.rb b/qa/qa/page/view.rb index b2a2da4dbf3..c59fad2e223 100644 --- a/qa/qa/page/view.rb +++ b/qa/qa/page/view.rb @@ -1,3 +1,5 @@ +require 'pathname' + module QA module Page class View @@ -9,7 +11,7 @@ module QA end def pathname - @pathname ||= Pathname.new(::File.join(__dir__, '../../../', @path)) + @pathname ||= ::Pathname.new(::File.join(__dir__, '../../../', @path)) .cleanpath.expand_path end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 5dc194e0aef..841c959045f 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -39,6 +39,18 @@ module QA ENV['GITLAB_PASSWORD'] end + def forker? + forker_username && forker_password + end + + def forker_username + ENV['GITLAB_FORKER_USERNAME'] + end + + def forker_password + ENV['GITLAB_FORKER_PASSWORD'] + end + def ldap_username ENV['GITLAB_LDAP_USERNAME'] end diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb index c80ee6d4d96..b016777c987 100644 --- a/qa/qa/runtime/user.rb +++ b/qa/qa/runtime/user.rb @@ -3,12 +3,12 @@ module QA module User extend self - def default_name + def default_username 'root' end - def name - Runtime::Env.user_username || default_name + def username + Runtime::Env.user_username || default_username end def password diff --git a/qa/qa/scenario/taggable.rb b/qa/qa/scenario/taggable.rb deleted file mode 100644 index b1f24d742e0..00000000000 --- a/qa/qa/scenario/taggable.rb +++ /dev/null @@ -1,17 +0,0 @@ -module QA - module Scenario - module Taggable - # rubocop:disable Gitlab/ModuleWithInstanceVariables - - def tags(*tags) - @tags = tags - end - - def focus - @tags.to_a - end - - # rubocop:enable Gitlab/ModuleWithInstanceVariables - end - end -end diff --git a/qa/qa/scenario/template.rb b/qa/qa/scenario/template.rb index d21a9d52997..a87d925ce32 100644 --- a/qa/qa/scenario/template.rb +++ b/qa/qa/scenario/template.rb @@ -1,15 +1,40 @@ module QA module Scenario class Template - def self.perform(*args) - new.tap do |scenario| - yield scenario if block_given? - break scenario.perform(*args) + class << self + def perform(*args) + new.tap do |scenario| + yield scenario if block_given? + break scenario.perform(*args) + end + end + + def tags(*tags) + @tags = tags + end + + def focus + @tags.to_a end end - def perform(*_args) - raise NotImplementedError + def perform(address, *rspec_options) + Runtime::Scenario.define(:gitlab_address, address) + + ## + # Perform before hooks, which are different for CE and EE + # + Runtime::Release.perform_before_hooks + + 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 + end end end end diff --git a/qa/qa/scenario/test/instance.rb b/qa/qa/scenario/test/instance.rb index 46eb2dabb11..a2d503cc015 100644 --- a/qa/qa/scenario/test/instance.rb +++ b/qa/qa/scenario/test/instance.rb @@ -1,17 +1,23 @@ +# frozen_string_literal: true + module QA module Scenario module Test - ## - # Base class for running the suite against any GitLab instance, - # including staging and on-premises installation. - # - class Instance < Template + # This class exists for back-compatibility so that gitlab-qa can continue + # to call Test::Instance instead of Test::Instance::All until at least + # the current latest GitLab version has the Test::Instance::All class. + # As of Aug, 22nd 2018. Only GitLab >= 11.3 has this class. + module Instance include Bootable - extend Taggable - tags :core + def self.perform(*args) + self.tap do |scenario| + yield scenario if block_given? + break scenario.do_perform(*args) + end + end - def perform(address, *rspec_options) + def self.do_perform(address, *rspec_options) Runtime::Scenario.define(:gitlab_address, address) ## @@ -21,12 +27,11 @@ module QA Specs::Runner.perform do |specs| specs.tty = true - specs.tags = self.class.focus specs.options = if rspec_options.any? rspec_options else - ::File.expand_path('../../specs/features', __dir__) + ['--', ::File.expand_path('../../specs/features', __dir__)] end end end diff --git a/qa/qa/scenario/test/instance/all.rb b/qa/qa/scenario/test/instance/all.rb new file mode 100644 index 00000000000..a07c26431bd --- /dev/null +++ b/qa/qa/scenario/test/instance/all.rb @@ -0,0 +1,15 @@ +module QA + module Scenario + module Test + ## + # Base class for running the suite against any GitLab instance, + # including staging and on-premises installation. + # + module Instance + class All < Template + include Bootable + end + end + end + end +end diff --git a/qa/qa/scenario/test/instance/smoke.rb b/qa/qa/scenario/test/instance/smoke.rb new file mode 100644 index 00000000000..a7d2cb27f27 --- /dev/null +++ b/qa/qa/scenario/test/instance/smoke.rb @@ -0,0 +1,17 @@ +module QA + module Scenario + module Test + module Instance + ## + # Base class for running the suite against any GitLab instance, + # including staging and on-premises installation. + # + class Smoke < Template + include Bootable + + tags :smoke + end + end + end + end +end diff --git a/qa/qa/scenario/test/integration/github.rb b/qa/qa/scenario/test/integration/github.rb index 1d22b532aa5..76c3923d68a 100644 --- a/qa/qa/scenario/test/integration/github.rb +++ b/qa/qa/scenario/test/integration/github.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class Github < Test::Instance + class Github < Test::Instance::All tags :github def perform(address, *rspec_options) diff --git a/qa/qa/scenario/test/integration/kubernetes.rb b/qa/qa/scenario/test/integration/kubernetes.rb index 7479073e979..405962caeed 100644 --- a/qa/qa/scenario/test/integration/kubernetes.rb +++ b/qa/qa/scenario/test/integration/kubernetes.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class Kubernetes < Test::Instance + class Kubernetes < Test::Instance::All tags :kubernetes end end diff --git a/qa/qa/scenario/test/integration/ldap.rb b/qa/qa/scenario/test/integration/ldap.rb index 257ed81d9e1..769fa389785 100644 --- a/qa/qa/scenario/test/integration/ldap.rb +++ b/qa/qa/scenario/test/integration/ldap.rb @@ -2,7 +2,7 @@ module QA module Scenario module Test module Integration - class LDAP < Test::Instance + class LDAP < Test::Instance::All tags :ldap end end diff --git a/qa/qa/scenario/test/integration/mattermost.rb b/qa/qa/scenario/test/integration/mattermost.rb index 13bfad28b0b..ece6fba75c9 100644 --- a/qa/qa/scenario/test/integration/mattermost.rb +++ b/qa/qa/scenario/test/integration/mattermost.rb @@ -6,8 +6,8 @@ module QA # Run test suite against any GitLab instance where mattermost is enabled, # including staging and on-premises installation. # - class Mattermost < Test::Instance - tags :core, :mattermost + class Mattermost < Test::Instance::All + tags :mattermost def perform(address, mattermost, *rspec_options) Runtime::Scenario.define(:mattermost_address, mattermost) diff --git a/qa/qa/scenario/test/integration/object_storage.rb b/qa/qa/scenario/test/integration/object_storage.rb new file mode 100644 index 00000000000..2e028bbb5c6 --- /dev/null +++ b/qa/qa/scenario/test/integration/object_storage.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module QA + module Scenario + module Test + module Integration + class ObjectStorage < Test::Instance::All + tags :object_storage + end + end + end + end +end diff --git a/qa/qa/specs/features/api/1_manage/.gitkeep b/qa/qa/specs/features/api/1_manage/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/1_manage/.gitkeep diff --git a/qa/qa/specs/features/api/1_manage/users_spec.rb b/qa/qa/specs/features/api/1_manage/users_spec.rb new file mode 100644 index 00000000000..3e3c9e859aa --- /dev/null +++ b/qa/qa/specs/features/api/1_manage/users_spec.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +module QA + context :manage do + describe 'Users API' do + before(:context) do + @api_client = Runtime::API::Client.new(:gitlab) + end + + let(:request) { Runtime::API::Request.new(@api_client, '/users') } + + it 'GET /users' do + get request.url + + expect_status(200) + end + + it 'GET /users/:username with a valid username' do + get request.url, { params: { username: Runtime::User.username } } + + expect_status(200) + expect(json_body).to contain_exactly( + a_hash_including(username: Runtime::User.username) + ) + end + + it 'GET /users/:username with an invalid username' do + get request.url, { params: { username: SecureRandom.hex(10) } } + + expect_status(200) + expect(json_body).to eq([]) + end + end + end +end diff --git a/qa/qa/specs/features/api/2_plan/.gitkeep b/qa/qa/specs/features/api/2_plan/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/2_plan/.gitkeep diff --git a/qa/qa/specs/features/api/basics_spec.rb b/qa/qa/specs/features/api/3_create/repository/files_spec.rb index 6563b56d1b4..bc0b5ebfe10 100644 --- a/qa/qa/specs/features/api/basics_spec.rb +++ b/qa/qa/specs/features/api/3_create/repository/files_spec.rb @@ -1,13 +1,13 @@ require 'securerandom' module QA - describe 'API basics', :core do + describe 'API basics' do before(:context) do @api_client = Runtime::API::Client.new(:gitlab) end let(:project_name) { "api-basics-#{SecureRandom.hex(8)}" } - let(:sanitized_project_path) { CGI.escape("#{Runtime::User.name}/#{project_name}") } + let(:sanitized_project_path) { CGI.escape("#{Runtime::User.username}/#{project_name}") } it 'user creates a project with a file and deletes them afterwards' do create_project_request = Runtime::API::Request.new(@api_client, '/projects') diff --git a/qa/qa/specs/features/api/4_verify/.gitkeep b/qa/qa/specs/features/api/4_verify/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/4_verify/.gitkeep diff --git a/qa/qa/specs/features/api/5_package/.gitkeep b/qa/qa/specs/features/api/5_package/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/5_package/.gitkeep diff --git a/qa/qa/specs/features/api/6_release/.gitkeep b/qa/qa/specs/features/api/6_release/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/6_release/.gitkeep diff --git a/qa/qa/specs/features/api/7_configure/.gitkeep b/qa/qa/specs/features/api/7_configure/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/api/7_configure/.gitkeep diff --git a/qa/qa/specs/features/api/users_spec.rb b/qa/qa/specs/features/api/users_spec.rb deleted file mode 100644 index 8a63d8095c9..00000000000 --- a/qa/qa/specs/features/api/users_spec.rb +++ /dev/null @@ -1,41 +0,0 @@ -module QA - describe 'API users', :core do - before(:context) do - @api_client = Runtime::API::Client.new(:gitlab) - end - - context 'when authenticated' do - let(:request) { Runtime::API::Request.new(@api_client, '/users') } - - it 'get list of users' do - get request.url - - expect_status(200) - end - - it 'submit request with a valid user name' do - get request.url, { params: { username: Runtime::User.name } } - - expect_status(200) - expect(json_body).to contain_exactly( - a_hash_including(username: Runtime::User.name) - ) - end - - it 'submit request with an invalid user name' do - get request.url, { params: { username: SecureRandom.hex(10) } } - - expect_status(200) - expect(json_body).to eq([]) - end - end - - it 'submit request with an invalid token' do - request = Runtime::API::Request.new(@api_client, '/users', private_token: 'invalid') - - get request.url - - expect_status(401) - end - end -end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb new file mode 100644 index 00000000000..1c7da930567 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_in_spec.rb @@ -0,0 +1,17 @@ +module QA + context :manage, :smoke do + describe 'basic user login' do + it 'user logs in using basic credentials' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb new file mode 100644 index 00000000000..c9958917be9 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + context :manage, :orchestrated, :ldap do + describe 'LDAP login' do + before do + Runtime::Env.user_type = 'ldap' + end + + it 'user logs into GitLab using LDAP credentials' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # TODO, since `Signed in successfully` message was removed + # this is the only way to tell if user is signed in correctly. + # + Page::Menu::Main.perform do |menu| + expect(menu).to have_personal_area + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb new file mode 100644 index 00000000000..6eda2c750d4 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/login/log_into_mattermost_via_gitlab_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module QA + context :manage, :orchestrated, :mattermost do + describe 'Mattermost login' do + it 'user logs into Mattermost using GitLab OAuth' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) do + Page::Main::Login.act { sign_in_using_credentials } + + Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do + Page::Mattermost::Login.act { sign_in_using_oauth } + + Page::Mattermost::Main.perform do |page| + expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) + end + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb new file mode 100644 index 00000000000..bb1f3ab26d1 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/create_project_spec.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module QA + context :manage, :smoke do + describe 'Project creation' do + it 'user creates a new project' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + created_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'awesome-project' + project.description = 'create awesome project test' + end + + expect(created_project.name).to match /^awesome-project-\h{16}$/ + + expect(page).to have_content( + /Project \S?awesome-project\S+ was successfully created/ + ) + + expect(page).to have_content('create awesome project test') + expect(page).to have_content('The repository for this project is empty') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb new file mode 100644 index 00000000000..2ef8de61441 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/import_github_repo_spec.rb @@ -0,0 +1,110 @@ +# frozen_string_literal: true + +module QA + context :manage, :orchestrated, :github do + describe 'Project import from GitHub' do + let(:imported_project) do + Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| + project.name = 'imported-project' + project.personal_access_token = Runtime::Env.github_access_token + project.github_repository_path = 'gitlab-qa/test-project' + end + end + + after do + # We need to delete the imported project because it's impossible to import + # the same GitHub project twice for a given user. + api_client = Runtime::API::Client.new(:gitlab) + delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") + delete delete_project_request.url + + expect_status(202) + end + + it 'user imports a GitHub repo' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + imported_project # import the project + + Page::Menu::Main.act { go_to_projects } + Page::Dashboard::Projects.perform do |dashboard| + dashboard.go_to_project(imported_project.name) + end + + Page::Project::Show.act { wait_for_import } + + verify_repository_import + verify_issues_import + verify_merge_requests_import + verify_labels_import + verify_milestones_import + verify_wiki_import + end + + def verify_repository_import + expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') + expect(page).to have_content(imported_project.name) + end + + def verify_issues_import + Page::Menu::Side.act { click_issues } + expect(page).to have_content('This is a sample issue') + + click_link 'This is a sample issue' + + expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') + + # Comments + expect(page).to have_content('This is a comment from @rymai.') + + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('enhancement') + expect(issuable).to have_label('help wanted') + expect(issuable).to have_label('good first issue') + end + end + + def verify_merge_requests_import + Page::Menu::Side.act { click_merge_requests } + expect(page).to have_content('Improve README.md') + + click_link 'Improve README.md' + + expect(page).to have_content('This improves the README file a bit.') + + # Review comment are not supported yet + expect(page).not_to have_content('Really nice change.') + + # Comments + expect(page).to have_content('Nice work! This is a comment from @rymai.') + + # Diff comments + expect(page).to have_content('[Review comment] I like that!') + expect(page).to have_content('[Review comment] Nice blank line.') + expect(page).to have_content('[Single diff comment] Much better without this line!') + + Page::Issuable::Sidebar.perform do |issuable| + expect(issuable).to have_label('bug') + expect(issuable).to have_label('enhancement') + end + end + + def verify_labels_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 + # to build upon it. + end + + def verify_milestones_import + # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 + # to build upon it. + end + + def verify_wiki_import + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('Welcome to the test-project wiki!') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb new file mode 100644 index 00000000000..34bb6f1c197 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/1_manage/project/view_project_activity_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module QA + context :manage do + describe 'Project activity' do + it 'user creates an event in the activity page upon Git push' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Repository::ProjectPush.fabricate! do |push| + push.file_name = 'README.md' + push.file_content = '# This is a test project' + push.commit_message = 'Add README.md' + end + + Page::Menu::Side.act { go_to_activity } + + Page::Project::Activity.act { go_to_push_events } + + expect(page).to have_content('pushed new branch master') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb new file mode 100644 index 00000000000..542f532a629 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/2_plan/issue/create_issue_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +module QA + context :plan, :smoke do + describe 'Issue creation' do + let(:issue_title) { 'issue title' } + + def create_issue + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Issue.fabricate! do |issue| + issue.title = issue_title + end + end + + it 'user creates an issue' do + create_issue + + Page::Menu::Side.act { click_issues } + + expect(page).to have_content(issue_title) + end + + context 'when using attachments in comments', :object_storage do + let(:file_to_attach) do + File.absolute_path(File.join('spec', 'fixtures', 'banana_sample.gif')) + end + + it 'user comments on an issue with an attachment' do + create_issue + + Page::Project::Issue::Show.perform do |show| + show.comment('See attached banana for scale', attachment: file_to_attach) + + show.refresh + + image_url = find('a[href$="banana_sample.gif"]')[:href] + + found = show.wait(reload: false) do + show.asset_exists?(image_url) + end + + expect(found).to be_truthy + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb new file mode 100644 index 00000000000..bcf55a02a61 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/create_merge_request_spec.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Merge request creation' do + it 'user creates a new merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + current_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-merge-request-and-milestone' + end + + current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| + milestone.title = 'unique-milestone' + milestone.project = current_project + end + + Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.title = 'This is a merge request with a milestone' + merge_request.description = 'Great feature with milestone' + merge_request.project = current_project + merge_request.milestone = current_milestone + end + + expect(page).to have_content('This is a merge request with a milestone') + expect(page).to have_content('Great feature with milestone') + expect(page).to have_content(/Opened [\w\s]+ ago/) + + Page::Issuable::Sidebar.perform do |sidebar| + expect(sidebar).to have_milestone(current_milestone.title) + end + end + end + end + + describe 'creates a merge request', :smoke do + it 'user creates a new merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + current_project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-merge-request' + end + + Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.title = 'This is a merge request' + merge_request.description = 'Great feature' + merge_request.project = current_project + end + + expect(page).to have_content('This is a merge request') + expect(page).to have_content('Great feature') + expect(page).to have_content(/Opened [\w\s]+ ago/) + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb new file mode 100644 index 00000000000..407a15800ab --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/merge_merge_request_from_fork_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Merge request creation from fork' do + it 'user forks a project, submits a merge request and maintainer merges it' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| + merge_request.fork_branch = 'feature-branch' + end + + Page::Menu::Main.perform { |main| main.sign_out } + Page::Main::Login.perform { |login| login.sign_in_using_credentials } + + merge_request.visit! + + Page::MergeRequest::Show.perform { |show| show.merge! } + + expect(page).to have_content('The changes were merged') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb new file mode 100644 index 00000000000..ddcbc94b1b1 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/rebase_merge_request_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Merge request rebasing' do + it 'user rebases source branch of merge request' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "only-fast-forward" + end + + Page::Menu::Side.act { go_to_settings } + Page::Project::Settings::MergeRequest.act { enable_ff_only } + + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Needs rebasing' + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = "other.txt" + push.file_content = "New file added!" + push.branch_name = "master" + push.new_branch = false + end + + merge_request.visit! + + Page::MergeRequest::Show.perform do |merge_request| + expect(merge_request).to have_content('Needs rebasing') + expect(merge_request).not_to be_fast_forward_possible + expect(merge_request).not_to have_merge_button + + merge_request.rebase! + + expect(merge_request).to have_merge_button + expect(merge_request.fast_forward_possible?).to be_truthy + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb new file mode 100644 index 00000000000..b5b8855a35d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/merge_request/squash_merge_request_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Merge request squashing' do + it 'user squashes commits while merging' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = "squash-before-merge" + end + + merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| + merge_request.project = project + merge_request.title = 'Squashing commits' + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.commit_message = 'to be squashed' + push.branch_name = merge_request.source_branch + push.new_branch = false + push.file_name = 'other.txt' + push.file_content = "Test with unicode characters ❤✓€❄" + end + + merge_request.visit! + + expect(page).to have_text('to be squashed') + + Page::MergeRequest::Show.perform do |merge_request_page| + merge_request_page.mark_to_squash + merge_request_page.merge! + + merge_request.project.visit! + + Git::Repository.perform do |repository| + repository.uri = Page::Project::Show.act do + choose_repository_clone_http + repository_location.uri + end + + repository.use_default_credentials + + repository.act { clone } + + expect(repository.commits.size).to eq 3 + end + end + end + end + end +end diff --git a/qa/qa/specs/features/repository/clone_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb index a04ce4e44d9..b19bdd950fa 100644 --- a/qa/qa/specs/features/repository/clone_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/clone_spec.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module QA - describe 'clone code from the repository', :core do - context 'with regular account over http' do + context :create do + describe 'Git clone over HTTP' do let(:location) do Page::Project::Show.act do choose_repository_clone_http diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb new file mode 100644 index 00000000000..82d635065a0 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/create_edit_delete_file_via_web_spec.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Files management' do + it 'user creates, edits and deletes a file via the Web' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + # Create + file_name = 'QA Test - File name' + file_content = 'QA Test - File content' + commit_message_for_create = 'QA Test - Create new file' + + Factory::Resource::File.fabricate! do |file| + file.name = file_name + file.content = file_content + file.commit_message = commit_message_for_create + end + + expect(page).to have_content('The file has been successfully created.') + expect(page).to have_content(file_name) + expect(page).to have_content(file_content) + expect(page).to have_content(commit_message_for_create) + + # Edit + updated_file_content = 'QA Test - Updated file content' + commit_message_for_update = 'QA Test - Update file' + + Page::File::Show.act { click_edit } + + Page::File::Form.act do + remove_content + add_content(updated_file_content) + add_commit_message(commit_message_for_update) + commit_changes + end + + expect(page).to have_content('Your changes have been successfully committed.') + expect(page).to have_content(updated_file_content) + expect(page).to have_content(commit_message_for_update) + + # Delete + commit_message_for_delete = 'QA Test - Delete file' + + Page::File::Show.act do + click_delete + add_commit_message(commit_message_for_delete) + click_delete_file + end + + expect(page).to have_content('The file has been successfully deleted.') + expect(page).to have_content(commit_message_for_delete) + expect(page).to have_no_content(file_name) + end + end + end +end diff --git a/qa/qa/specs/features/repository/push_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb index fc40b60d915..40dfd138a1b 100644 --- a/qa/qa/specs/features/repository/push_spec.rb +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_over_http_spec.rb @@ -1,6 +1,8 @@ +# frozen_string_literal: true + module QA - describe 'push code to repository', :core do - context 'with regular account over http' do + context :create do + describe 'Git push over HTTP' do it 'user pushes code to the repository' do Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb new file mode 100644 index 00000000000..1d9cc33080d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/push_protected_branch_spec.rb @@ -0,0 +1,70 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Protected branch support' do + let(:branch_name) { 'protected-branch' } + let(:commit_message) { 'Protected push commit message' } + let(:project) do + Factory::Resource::Project.fabricate! do |resource| + resource.name = 'protected-branch-project' + end + end + + before do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + after do + # We need to clear localStorage because we're using it for the dropdown, + # and capybara doesn't do this for us. + # https://github.com/teamcapybara/capybara/issues/1702 + Capybara.execute_script 'localStorage.clear()' + end + + context 'when developers and maintainers are allowed to push to a protected branch' do + it 'user with push rights successfully pushes to the protected branch' do + create_protected_branch(allow_to_push: true) + + push = push_new_file(branch_name) + + expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) + end + end + + context 'when developers and maintainers are not allowed to push to a protected branch' do + it 'user without push rights fails to push to the protected branch' do + create_protected_branch(allow_to_push: false) + + push = push_new_file(branch_name) + + expect(push.output) + .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) + expect(push.output) + .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) + end + end + + def create_protected_branch(allow_to_push:) + Factory::Resource::Branch.fabricate! do |resource| + resource.branch_name = branch_name + resource.project = project + resource.allow_to_push = allow_to_push + resource.protected = true + end + end + + def push_new_file(branch) + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = project + resource.file_name = 'new_file.md' + resource.file_content = '# This is a new file' + resource.commit_message = 'Add new_file.md' + resource.branch_name = branch_name + resource.new_branch = false + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb new file mode 100644 index 00000000000..8009b9e8609 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/wiki/create_edit_clone_push_wiki_spec.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'Wiki management' do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + def validate_content(content) + expect(page).to have_content('Wiki was successfully updated') + expect(page).to have_content(/#{content}/) + end + + before do + login + end + + it 'user creates, edits, clones, and pushes to the wiki' do + wiki = Factory::Resource::Wiki.fabricate! do |resource| + resource.title = 'Home' + resource.content = '# My First Wiki Content' + resource.message = 'Update home' + end + + validate_content('My First Wiki Content') + + Page::Project::Wiki::Edit.act { go_to_edit_page } + Page::Project::Wiki::New.perform do |page| + page.set_content("My Second Wiki Content") + page.save_changes + end + + validate_content('My Second Wiki Content') + + Factory::Repository::WikiPush.fabricate! do |push| + push.wiki = wiki + push.file_name = 'Home.md' + push.file_content = '# My Third Wiki Content' + push.commit_message = 'Update Home.md' + end + Page::Menu::Side.act { click_wiki } + + expect(page).to have_content('My Third Wiki Content') + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb new file mode 100644 index 00000000000..cdfe9b90e15 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/pipeline/create_and_process_pipeline_spec.rb @@ -0,0 +1,87 @@ +# frozen_string_literal: true + +module QA + context :verify, :orchestrated, :docker do + describe 'Pipeline creation and processing' do + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + after do + Service::Runner.new(executor).remove! + end + + it 'users creates a pipeline which gets processed' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |project| + project.name = 'project-with-pipelines' + project.description = 'Project with CI/CD Pipelines.' + end + + Factory::Resource::Runner.fabricate! do |runner| + runner.project = project + runner.name = executor + runner.tags = %w[qa test] + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.file_name = '.gitlab-ci.yml' + push.commit_message = 'Add .gitlab-ci.yml' + push.file_content = <<~EOF + test-success: + tags: + - qa + - test + script: echo 'OK' + + test-failure: + tags: + - qa + - test + script: + - echo 'FAILURE' + - exit 1 + + test-tags: + tags: + - qa + - docker + script: echo 'NOOP' + + test-artifacts: + tags: + - qa + - test + script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt + artifacts: + paths: + - my-artifacts/ + EOF + end + + Page::Project::Show.act { wait_for_push } + + expect(page).to have_content('Add .gitlab-ci.yml') + + Page::Menu::Side.act { click_ci_cd_pipelines } + + expect(page).to have_content('All 1') + expect(page).to have_content('Add .gitlab-ci.yml') + + puts 'Waiting for the runner to process the pipeline' + sleep 15 # Runner should process all jobs within 15 seconds. + + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to be_running + expect(pipeline).to have_build('test-success', status: :success) + expect(pipeline).to have_build('test-failure', status: :failed) + expect(pipeline).to have_build('test-tags', status: :pending) + expect(pipeline).to have_build('test-artifacts', status: :success) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb new file mode 100644 index 00000000000..8d83a20f5bf --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/runner/register_runner_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module QA + context :verify, :docker do + describe 'Runner registration' do + let(:executor) { "qa-runner-#{Time.now.to_i}" } + + after do + Service::Runner.new(executor).remove! + end + + it 'user registers a new specific runner' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::Runner.fabricate! do |runner| + runner.name = executor + end + + Page::Project::Settings::CICD.perform do |settings| + sleep 5 # Runner should register within 5 seconds + settings.refresh + + settings.expand_runners_settings do |page| + expect(page).to have_content(executor) + expect(page).to have_online_runner + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb new file mode 100644 index 00000000000..08a87df5837 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/4_verify/secret_variable/add_secret_variable_spec.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module QA + context :verify do + describe 'Secret variable support' do + it 'user adds a secret variable' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'VARIABLE_KEY' + resource.value = 'some secret variable' + end + + Page::Project::Settings::CICD.perform do |settings| + settings.expand_secret_variables do |page| + expect(page).to have_field(with: 'VARIABLE_KEY') + expect(page).not_to have_field(with: 'some secret variable') + + page.reveal_variables + + expect(page).to have_field(with: 'some secret variable') + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/5_package/.gitkeep b/qa/qa/specs/features/browser_ui/5_package/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/5_package/.gitkeep diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb new file mode 100644 index 00000000000..17dfa887434 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/add_deploy_key_spec.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +module QA + context :release do + describe 'Deploy key creation' do + it 'user adds a deploy key' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + key = Runtime::Key::RSA.new + deploy_key_title = 'deploy key title' + deploy_key_value = key.public_key + + deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| + resource.title = deploy_key_title + resource.key = deploy_key_value + end + + expect(deploy_key.fingerprint).to eq(key.fingerprint) + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb new file mode 100644 index 00000000000..8352d13b06d --- /dev/null +++ b/qa/qa/specs/features/browser_ui/6_release/deploy_key/clone_using_deploy_key_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'digest/sha1' + +module QA + context :release, :docker do + describe 'Git clone using a deploy key' do + def login + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + end + + before(:all) do + login + + @runner_name = "qa-runner-#{Time.now.to_i}" + + @project = Factory::Resource::Project.fabricate! do |resource| + resource.name = 'deploy-key-clone-project' + end + + @repository_location = @project.repository_ssh_location + + Factory::Resource::Runner.fabricate! do |resource| + resource.project = @project + resource.name = @runner_name + resource.tags = %w[qa docker] + resource.image = 'gitlab/gitlab-runner:ubuntu' + end + + Page::Menu::Main.act { sign_out } + end + + after(:all) do + Service::Runner.new(@runner_name).remove! + end + + keys = [ + [Runtime::Key::RSA, 8192], + [Runtime::Key::ECDSA, 521], + [Runtime::Key::ED25519] + ] + + keys.each do |(key_class, bits)| + it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do + key = key_class.new(*bits) + + login + + Factory::Resource::DeployKey.fabricate! do |resource| + resource.project = @project + resource.title = "deploy key #{key.name}(#{key.bits})" + resource.key = key.public_key + end + + deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" + + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.project = @project + resource.key = deploy_key_name + resource.value = key.private_key + end + + gitlab_ci = <<~YAML + cat-config: + script: + - mkdir -p ~/.ssh + - ssh-keyscan -p #{@repository_location.port} #{@repository_location.host} >> ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - ssh-add -D + - echo "$#{deploy_key_name}" | ssh-add - + - git clone #{@repository_location.git_uri} + - cd #{@project.name} + - git checkout #{deploy_key_name} + - sha1sum .gitlab-ci.yml + tags: + - qa + - docker + YAML + + Factory::Repository::ProjectPush.fabricate! do |resource| + resource.project = @project + resource.file_name = '.gitlab-ci.yml' + resource.commit_message = 'Add .gitlab-ci.yml' + resource.file_content = gitlab_ci + resource.branch_name = deploy_key_name + resource.new_branch = true + end + + sha1sum = Digest::SHA1.hexdigest(gitlab_ci) + + Page::Project::Show.act { wait_for_push } + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + Page::Project::Pipeline::Show.act { go_to_first_job } + + Page::Project::Job::Show.perform do |job| + job.wait(reload: false) do + job.completed? && !job.trace_loading? + end + + expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." + expect(job.output).to include(sha1sum) + end + 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 new file mode 100644 index 00000000000..dd24e8ffba5 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require 'pathname' + +module QA + context :configure, :orchestrated, :kubernetes do + describe 'Auto DevOps support' do + after do + @cluster&.remove! + end + + it 'user creates a new project and runs auto devops' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + project = Factory::Resource::Project.fabricate! do |p| + p.name = 'project-with-autodevops' + p.description = 'Project with Auto Devops' + end + + # Disable code_quality check in Auto DevOps pipeline as it takes + # too long and times out the test + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'CODE_QUALITY_DISABLED' + resource.value = '1' + end + + # Create Auto Devops compatible repo + Factory::Repository::ProjectPush.fabricate! do |push| + push.project = project + push.directory = Pathname + .new(__dir__) + .join('../../../fixtures/auto_devops_rack') + push.commit_message = 'Create Auto DevOps compatible rack application' + end + + Page::Project::Show.act { wait_for_push } + + # Create and connect K8s cluster + @cluster = Service::KubernetesCluster.new.create! + kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| + cluster.project = project + cluster.cluster = @cluster + cluster.install_helm_tiller = true + cluster.install_ingress = true + cluster.install_prometheus = true + cluster.install_runner = true + end + + project.visit! + Page::Menu::Side.act { click_ci_cd_settings } + Page::Project::Settings::CICD.perform do |p| + p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") + end + + project.visit! + Page::Menu::Side.act { click_ci_cd_pipelines } + Page::Project::Pipeline::Index.act { go_to_latest_pipeline } + + Page::Project::Pipeline::Show.perform do |pipeline| + expect(pipeline).to have_build('build', status: :success, wait: 600) + expect(pipeline).to have_build('test', status: :success, wait: 600) + expect(pipeline).to have_build('production', status: :success, wait: 1200) + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb new file mode 100644 index 00000000000..6ffdc55538a --- /dev/null +++ b/qa/qa/specs/features/browser_ui/7_configure/mattermost/create_group_with_mattermost_team_spec.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module QA + context :configure, :orchestrated, :mattermost do + describe 'Mattermost support' do + it 'user creates a group with a mattermost team' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + Page::Menu::Main.act { go_to_groups } + + Page::Dashboard::Groups.perform do |page| + page.go_to_new_group + + expect(page).to have_content( + /Create a Mattermost team for this group/ + ) + end + end + end + end +end diff --git a/qa/qa/specs/features/login/ldap_spec.rb b/qa/qa/specs/features/login/ldap_spec.rb deleted file mode 100644 index b7a284c584b..00000000000 --- a/qa/qa/specs/features/login/ldap_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -module QA - describe 'LDAP user login', :ldap do - before do - Runtime::Env.user_type = 'ldap' - end - - it 'user logs in using LDAP credentials' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # TODO, since `Signed in successfully` message was removed - # this is the only way to tell if user is signed in correctly. - # - Page::Menu::Main.perform do |menu| - expect(menu).to have_personal_area - end - end - end -end diff --git a/qa/qa/specs/features/mattermost/group_create_spec.rb b/qa/qa/specs/features/mattermost/group_create_spec.rb deleted file mode 100644 index a59761da341..00000000000 --- a/qa/qa/specs/features/mattermost/group_create_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -module QA - describe 'create a new group', :mattermost do - it 'creating a group with a mattermost team' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - Page::Menu::Main.act { go_to_groups } - - Page::Dashboard::Groups.perform do |page| - page.go_to_new_group - - expect(page).to have_content( - /Create a Mattermost team for this group/ - ) - end - end - end -end diff --git a/qa/qa/specs/features/mattermost/login_spec.rb b/qa/qa/specs/features/mattermost/login_spec.rb deleted file mode 100644 index b140191e160..00000000000 --- a/qa/qa/specs/features/mattermost/login_spec.rb +++ /dev/null @@ -1,17 +0,0 @@ -module QA - describe 'logging in to Mattermost', :mattermost do - it 'can use gitlab oauth' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) do - Page::Main::Login.act { sign_in_using_credentials } - - Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do - Page::Mattermost::Login.act { sign_in_using_oauth } - - Page::Mattermost::Main.perform do |page| - expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) - end - end - end - end - end -end diff --git a/qa/qa/specs/features/merge_request/create_spec.rb b/qa/qa/specs/features/merge_request/create_spec.rb deleted file mode 100644 index 36d7efb02e1..00000000000 --- a/qa/qa/specs/features/merge_request/create_spec.rb +++ /dev/null @@ -1,32 +0,0 @@ -module QA - describe 'creates a merge request', :core do - it 'user creates a new merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - current_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-merge-request-and-milestone' - end - - current_milestone = Factory::Resource::ProjectMilestone.fabricate! do |milestone| - milestone.title = 'unique-milestone' - milestone.project = current_project - end - - Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.title = 'This is a merge request with a milestone' - merge_request.description = 'Great feature with milestone' - merge_request.project = current_project - merge_request.milestone = current_milestone - end - - expect(page).to have_content('This is a merge request with a milestone') - expect(page).to have_content('Great feature with milestone') - expect(page).to have_content(/Opened [\w\s]+ ago/) - - Page::Issuable::Sidebar.perform do |sidebar| - expect(sidebar).to have_milestone(current_milestone.title) - end - end - end -end diff --git a/qa/qa/specs/features/merge_request/rebase_spec.rb b/qa/qa/specs/features/merge_request/rebase_spec.rb deleted file mode 100644 index 163dcbe7963..00000000000 --- a/qa/qa/specs/features/merge_request/rebase_spec.rb +++ /dev/null @@ -1,39 +0,0 @@ -module QA - describe 'merge request rebase', :core do - it 'rebases source branch of merge request' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = "only-fast-forward" - end - - Page::Menu::Side.act { go_to_settings } - Page::Project::Settings::MergeRequest.act { enable_ff_only } - - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Needs rebasing' - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = "other.txt" - push.file_content = "New file added!" - end - - merge_request.visit! - - Page::MergeRequest::Show.perform do |merge_request| - expect(merge_request).to have_content('Needs rebasing') - expect(merge_request).not_to be_fast_forward_possible - expect(merge_request).not_to have_merge_button - - merge_request.rebase! - - expect(merge_request).to have_merge_button - expect(merge_request.fast_forward_possible?).to be_truthy - end - end - end -end diff --git a/qa/qa/specs/features/merge_request/squash_spec.rb b/qa/qa/specs/features/merge_request/squash_spec.rb deleted file mode 100644 index 4856bbe1a69..00000000000 --- a/qa/qa/specs/features/merge_request/squash_spec.rb +++ /dev/null @@ -1,50 +0,0 @@ -module QA - describe 'merge request squash commits', :core do - it 'when squash commits is marked before merge' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = "squash-before-merge" - end - - merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request| - merge_request.project = project - merge_request.title = 'Squashing commits' - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.commit_message = 'to be squashed' - push.branch_name = merge_request.source_branch - push.new_branch = false - push.file_name = 'other.txt' - push.file_content = "Test with unicode characters ❤✓€❄" - end - - merge_request.visit! - - expect(page).to have_text('to be squashed') - - Page::MergeRequest::Show.perform do |merge_request_page| - merge_request_page.mark_to_squash - merge_request_page.merge! - - merge_request.project.visit! - - Git::Repository.perform do |repository| - repository.uri = Page::Project::Show.act do - choose_repository_clone_http - repository_location.uri - end - - repository.use_default_credentials - - repository.act { clone } - - expect(repository.commits.size).to eq 3 - end - end - end - end -end diff --git a/qa/qa/specs/features/project/activity_spec.rb b/qa/qa/specs/features/project/activity_spec.rb deleted file mode 100644 index 02074e386b6..00000000000 --- a/qa/qa/specs/features/project/activity_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -module QA - describe 'activity page', :core do - it 'push creates an event in the activity page' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Repository::ProjectPush.fabricate! do |push| - push.file_name = 'README.md' - push.file_content = '# This is a test project' - push.commit_message = 'Add README.md' - end - - Page::Menu::Side.act { go_to_activity } - - Page::Project::Activity.act { go_to_push_events } - - expect(page).to have_content('pushed new branch master') - end - end -end diff --git a/qa/qa/specs/features/project/add_deploy_key_spec.rb b/qa/qa/specs/features/project/add_deploy_key_spec.rb deleted file mode 100644 index 14642af97ad..00000000000 --- a/qa/qa/specs/features/project/add_deploy_key_spec.rb +++ /dev/null @@ -1,19 +0,0 @@ -module QA - describe 'deploy keys support', :core do - it 'user adds a deploy key' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - key = Runtime::Key::RSA.new - deploy_key_title = 'deploy key title' - deploy_key_value = key.public_key - - deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| - resource.title = deploy_key_title - resource.key = deploy_key_value - end - - expect(deploy_key.fingerprint).to eq(key.fingerprint) - end - end -end diff --git a/qa/qa/specs/features/project/add_secret_variable_spec.rb b/qa/qa/specs/features/project/add_secret_variable_spec.rb deleted file mode 100644 index 32c91dd9d4d..00000000000 --- a/qa/qa/specs/features/project/add_secret_variable_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -module QA - describe 'secret variables support', :core do - it 'user adds a secret variable' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = 'VARIABLE_KEY' - resource.value = 'some secret variable' - end - - Page::Project::Settings::CICD.perform do |settings| - settings.expand_secret_variables do |page| - expect(page).to have_field(with: 'VARIABLE_KEY') - expect(page).not_to have_field(with: 'some secret variable') - - page.reveal_variables - - expect(page).to have_field(with: 'some secret variable') - end - end - end - end -end diff --git a/qa/qa/specs/features/project/auto_devops_spec.rb b/qa/qa/specs/features/project/auto_devops_spec.rb deleted file mode 100644 index bc713b46d81..00000000000 --- a/qa/qa/specs/features/project/auto_devops_spec.rb +++ /dev/null @@ -1,57 +0,0 @@ -require 'pathname' - -module QA - describe 'Auto Devops', :kubernetes do - after do - @cluster&.remove! - end - - it 'user creates a new project and runs auto devops' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |p| - p.name = 'project-with-autodevops' - p.description = 'Project with Auto Devops' - end - - # Create Auto Devops compatible repo - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.directory = Pathname - .new(__dir__) - .join('../../../fixtures/auto_devops_rack') - push.commit_message = 'Create Auto DevOps compatible rack application' - end - - Page::Project::Show.act { wait_for_push } - - # Create and connect K8s cluster - @cluster = Service::KubernetesCluster.new.create! - kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| - cluster.project = project - cluster.cluster = @cluster - cluster.install_helm_tiller = true - cluster.install_ingress = true - cluster.install_prometheus = true - cluster.install_runner = true - end - - project.visit! - Page::Menu::Side.act { click_ci_cd_settings } - Page::Project::Settings::CICD.perform do |p| - p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") - end - - project.visit! - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to have_build('build', status: :success, wait: 600) - expect(pipeline).to have_build('test', status: :success, wait: 600) - expect(pipeline).to have_build('production', status: :success, wait: 600) - end - end - end -end diff --git a/qa/qa/specs/features/project/create_issue_spec.rb b/qa/qa/specs/features/project/create_issue_spec.rb deleted file mode 100644 index ac2ed2ca2a1..00000000000 --- a/qa/qa/specs/features/project/create_issue_spec.rb +++ /dev/null @@ -1,18 +0,0 @@ -module QA - describe 'creates issue', :core do - let(:issue_title) { 'issue title' } - - it 'user creates issue' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::Issue.fabricate! do |issue| - issue.title = issue_title - end - - Page::Menu::Side.act { click_issues } - - expect(page).to have_content(issue_title) - end - end -end diff --git a/qa/qa/specs/features/project/create_spec.rb b/qa/qa/specs/features/project/create_spec.rb deleted file mode 100644 index 14ecd464685..00000000000 --- a/qa/qa/specs/features/project/create_spec.rb +++ /dev/null @@ -1,22 +0,0 @@ -module QA - describe 'create a new project', :core do - it 'user creates a new project' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - created_project = Factory::Resource::Project.fabricate! do |project| - project.name = 'awesome-project' - project.description = 'create awesome project test' - end - - expect(created_project.name).to match /^awesome-project-\h{16}$/ - - expect(page).to have_content( - /Project \S?awesome-project\S+ was successfully created/ - ) - - expect(page).to have_content('create awesome project test') - expect(page).to have_content('The repository for this project is empty') - end - end -end diff --git a/qa/qa/specs/features/project/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb deleted file mode 100644 index 054f49b408a..00000000000 --- a/qa/qa/specs/features/project/deploy_key_clone_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -require 'digest/sha1' - -module QA - describe 'cloning code using a deploy key', :core, :docker do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - before(:all) do - login - - @runner_name = "qa-runner-#{Time.now.to_i}" - - @project = Factory::Resource::Project.fabricate! do |resource| - resource.name = 'deploy-key-clone-project' - end - - @repository_location = @project.repository_ssh_location - - Factory::Resource::Runner.fabricate! do |resource| - resource.project = @project - resource.name = @runner_name - resource.tags = %w[qa docker] - resource.image = 'gitlab/gitlab-runner:ubuntu' - end - - Page::Menu::Main.act { sign_out } - end - - after(:all) do - Service::Runner.new(@runner_name).remove! - end - - keys = [ - [Runtime::Key::RSA, 8192], - [Runtime::Key::ECDSA, 521], - [Runtime::Key::ED25519] - ] - - keys.each do |(key_class, bits)| - it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do - key = key_class.new(*bits) - - login - - Factory::Resource::DeployKey.fabricate! do |resource| - resource.project = @project - resource.title = "deploy key #{key.name}(#{key.bits})" - resource.key = key.public_key - end - - deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}" - - Factory::Resource::SecretVariable.fabricate! do |resource| - resource.project = @project - resource.key = deploy_key_name - resource.value = key.private_key - end - - gitlab_ci = <<~YAML - cat-config: - script: - - mkdir -p ~/.ssh - - ssh-keyscan -p #{@repository_location.port} #{@repository_location.host} >> ~/.ssh/known_hosts - - eval $(ssh-agent -s) - - ssh-add -D - - echo "$#{deploy_key_name}" | ssh-add - - - git clone #{@repository_location.git_uri} - - cd #{@project.name} - - git checkout #{deploy_key_name} - - sha1sum .gitlab-ci.yml - tags: - - qa - - docker - YAML - - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = @project - resource.file_name = '.gitlab-ci.yml' - resource.commit_message = 'Add .gitlab-ci.yml' - resource.file_content = gitlab_ci - resource.branch_name = deploy_key_name - resource.new_branch = true - end - - sha1sum = Digest::SHA1.hexdigest(gitlab_ci) - - Page::Project::Show.act { wait_for_push } - Page::Menu::Side.act { click_ci_cd_pipelines } - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - Page::Project::Pipeline::Show.act { go_to_first_job } - - Page::Project::Job::Show.perform do |job| - job.wait(reload: false) do - job.completed? && !job.trace_loading? - end - - expect(job.passed?).to be_truthy, "Job status did not become \"passed\"." - expect(job.output).to include(sha1sum) - end - end - end - end -end diff --git a/qa/qa/specs/features/project/file_spec.rb b/qa/qa/specs/features/project/file_spec.rb deleted file mode 100644 index 5659784cd5c..00000000000 --- a/qa/qa/specs/features/project/file_spec.rb +++ /dev/null @@ -1,54 +0,0 @@ -module QA - describe 'File Functionality', :core do - it 'lets a user create, edit and delete a file via WebUI' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - # Create - file_name = 'QA Test - File name' - file_content = 'QA Test - File content' - commit_message_for_create = 'QA Test - Create new file' - - Factory::Resource::File.fabricate! do |file| - file.name = file_name - file.content = file_content - file.commit_message = commit_message_for_create - end - - expect(page).to have_content('The file has been successfully created.') - expect(page).to have_content(file_name) - expect(page).to have_content(file_content) - expect(page).to have_content(commit_message_for_create) - - # Edit - updated_file_content = 'QA Test - Updated file content' - commit_message_for_update = 'QA Test - Update file' - - Page::File::Show.act { click_edit } - - Page::File::Form.act do - remove_content - add_content(updated_file_content) - add_commit_message(commit_message_for_update) - commit_changes - end - - expect(page).to have_content('Your changes have been successfully committed.') - expect(page).to have_content(updated_file_content) - expect(page).to have_content(commit_message_for_update) - - # Delete - commit_message_for_delete = 'QA Test - Delete file' - - Page::File::Show.act do - click_delete - add_commit_message(commit_message_for_delete) - click_delete_file - end - - expect(page).to have_content('The file has been successfully deleted.') - expect(page).to have_content(commit_message_for_delete) - expect(page).to have_no_content(file_name) - end - end -end diff --git a/qa/qa/specs/features/project/fork_project_spec.rb b/qa/qa/specs/features/project/fork_project_spec.rb deleted file mode 100644 index 8ad0120305a..00000000000 --- a/qa/qa/specs/features/project/fork_project_spec.rb +++ /dev/null @@ -1,23 +0,0 @@ -module QA - describe 'Project fork', :core do - it 'can submit merge requests to upstream master' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - merge_request = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request| - merge_request.fork_branch = 'feature-branch' - end - - Page::Menu::Main.act { sign_out } - Page::Main::Login.act do - switch_to_sign_in_tab - sign_in_using_credentials - end - - merge_request.visit! - Page::MergeRequest::Show.act { merge! } - - expect(page).to have_content('The changes were merged') - end - end -end diff --git a/qa/qa/specs/features/project/import_from_github_spec.rb b/qa/qa/specs/features/project/import_from_github_spec.rb deleted file mode 100644 index 221b5c27fba..00000000000 --- a/qa/qa/specs/features/project/import_from_github_spec.rb +++ /dev/null @@ -1,106 +0,0 @@ -module QA - describe 'user imports a GitHub repo', :core, :github do - let(:imported_project) do - Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| - project.name = 'imported-project' - project.personal_access_token = Runtime::Env.github_access_token - project.github_repository_path = 'gitlab-qa/test-project' - end - end - - after do - # We need to delete the imported project because it's impossible to import - # the same GitHub project twice for a given user. - api_client = Runtime::API::Client.new(:gitlab) - delete_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}") - delete delete_project_request.url - - expect_status(202) - end - - it 'user imports a GitHub repo' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - imported_project # import the project - - Page::Menu::Main.act { go_to_projects } - Page::Dashboard::Projects.perform do |dashboard| - dashboard.go_to_project(imported_project.name) - end - - Page::Project::Show.act { wait_for_import } - - verify_repository_import - verify_issues_import - verify_merge_requests_import - verify_labels_import - verify_milestones_import - verify_wiki_import - end - - def verify_repository_import - expect(page).to have_content('This test project is used for automated GitHub import by GitLab QA.') - expect(page).to have_content(imported_project.name) - end - - def verify_issues_import - Page::Menu::Side.act { click_issues } - expect(page).to have_content('This is a sample issue') - - click_link 'This is a sample issue' - - expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.') - - # Comments - expect(page).to have_content('This is a comment from @rymai.') - - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('enhancement') - expect(issuable).to have_label('help wanted') - expect(issuable).to have_label('good first issue') - end - end - - def verify_merge_requests_import - Page::Menu::Side.act { click_merge_requests } - expect(page).to have_content('Improve README.md') - - click_link 'Improve README.md' - - expect(page).to have_content('This improves the README file a bit.') - - # Review comment are not supported yet - expect(page).not_to have_content('Really nice change.') - - # Comments - expect(page).to have_content('Nice work! This is a comment from @rymai.') - - # Diff comments - expect(page).to have_content('[Review comment] I like that!') - expect(page).to have_content('[Review comment] Nice blank line.') - expect(page).to have_content('[Single diff comment] Much better without this line!') - - Page::Issuable::Sidebar.perform do |issuable| - expect(issuable).to have_label('bug') - expect(issuable).to have_label('enhancement') - end - end - - def verify_labels_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 - # to build upon it. - end - - def verify_milestones_import - # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 - # to build upon it. - end - - def verify_wiki_import - Page::Menu::Side.act { click_wiki } - - expect(page).to have_content('Welcome to the test-project wiki!') - end - end -end diff --git a/qa/qa/specs/features/project/pipelines_spec.rb b/qa/qa/specs/features/project/pipelines_spec.rb deleted file mode 100644 index ddedde7a8bc..00000000000 --- a/qa/qa/specs/features/project/pipelines_spec.rb +++ /dev/null @@ -1,102 +0,0 @@ -module QA - describe 'CI/CD Pipelines', :core, :docker do - let(:executor) { "qa-runner-#{Time.now.to_i}" } - - after do - Service::Runner.new(executor).remove! - end - - it 'user registers a new specific runner' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - Factory::Resource::Runner.fabricate! do |runner| - runner.name = executor - end - - Page::Project::Settings::CICD.perform do |settings| - sleep 5 # Runner should register within 5 seconds - settings.refresh - - settings.expand_runners_settings do |page| - expect(page).to have_content(executor) - expect(page).to have_online_runner - end - end - end - - it 'users creates a new pipeline' do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - - project = Factory::Resource::Project.fabricate! do |project| - project.name = 'project-with-pipelines' - project.description = 'Project with CI/CD Pipelines.' - end - - Factory::Resource::Runner.fabricate! do |runner| - runner.project = project - runner.name = executor - runner.tags = %w[qa test] - end - - Factory::Repository::ProjectPush.fabricate! do |push| - push.project = project - push.file_name = '.gitlab-ci.yml' - push.commit_message = 'Add .gitlab-ci.yml' - push.file_content = <<~EOF - test-success: - tags: - - qa - - test - script: echo 'OK' - - test-failure: - tags: - - qa - - test - script: - - echo 'FAILURE' - - exit 1 - - test-tags: - tags: - - qa - - docker - script: echo 'NOOP' - - test-artifacts: - tags: - - qa - - test - script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt - artifacts: - paths: - - my-artifacts/ - EOF - end - - Page::Project::Show.act { wait_for_push } - - expect(page).to have_content('Add .gitlab-ci.yml') - - Page::Menu::Side.act { click_ci_cd_pipelines } - - expect(page).to have_content('All 1') - expect(page).to have_content('Add .gitlab-ci.yml') - - puts 'Waiting for the runner to process the pipeline' - sleep 15 # Runner should process all jobs within 15 seconds. - - Page::Project::Pipeline::Index.act { go_to_latest_pipeline } - - Page::Project::Pipeline::Show.perform do |pipeline| - expect(pipeline).to be_running - expect(pipeline).to have_build('test-success', status: :success) - expect(pipeline).to have_build('test-failure', status: :failed) - expect(pipeline).to have_build('test-tags', status: :pending) - expect(pipeline).to have_build('test-artifacts', status: :success) - end - end - end -end diff --git a/qa/qa/specs/features/project/wikis_spec.rb b/qa/qa/specs/features/project/wikis_spec.rb deleted file mode 100644 index 59cc455fffc..00000000000 --- a/qa/qa/specs/features/project/wikis_spec.rb +++ /dev/null @@ -1,45 +0,0 @@ -module QA - describe 'Wiki Functionality', :core do - def login - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - def validate_content(content) - expect(page).to have_content('Wiki was successfully updated') - expect(page).to have_content(/#{content}/) - end - - before do - login - end - - it 'User creates, edits, clones, and pushes to the wiki' do - wiki = Factory::Resource::Wiki.fabricate! do |resource| - resource.title = 'Home' - resource.content = '# My First Wiki Content' - resource.message = 'Update home' - end - - validate_content('My First Wiki Content') - - Page::Project::Wiki::Edit.act { go_to_edit_page } - Page::Project::Wiki::New.perform do |page| - page.set_content("My Second Wiki Content") - page.save_changes - end - - validate_content('My Second Wiki Content') - - Factory::Repository::WikiPush.fabricate! do |push| - push.wiki = wiki - push.file_name = 'Home.md' - push.file_content = '# My Third Wiki Content' - push.commit_message = 'Update Home.md' - end - Page::Menu::Side.act { click_wiki } - - expect(page).to have_content('My Third Wiki Content') - end - end -end diff --git a/qa/qa/specs/features/repository/protected_branches_spec.rb b/qa/qa/specs/features/repository/protected_branches_spec.rb deleted file mode 100644 index c2de94516d9..00000000000 --- a/qa/qa/specs/features/repository/protected_branches_spec.rb +++ /dev/null @@ -1,66 +0,0 @@ -module QA - describe 'branch protection support', :core do - let(:branch_name) { 'protected-branch' } - let(:commit_message) { 'Protected push commit message' } - let(:project) do - Factory::Resource::Project.fabricate! do |resource| - resource.name = 'protected-branch-project' - end - end - - before do - Runtime::Browser.visit(:gitlab, Page::Main::Login) - Page::Main::Login.act { sign_in_using_credentials } - end - - after do - # We need to clear localStorage because we're using it for the dropdown, - # and capybara doesn't do this for us. - # https://github.com/teamcapybara/capybara/issues/1702 - Capybara.execute_script 'localStorage.clear()' - end - - context 'when developers and maintainers are allowed to push to a protected branch' do - it 'user with push rights successfully pushes to the protected branch' do - create_protected_branch(allow_to_push: true) - - push = push_new_file(branch_name) - - expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) - end - end - - context 'when developers and maintainers are not allowed to push to a protected branch' do - it 'user without push rights fails to push to the protected branch' do - create_protected_branch(allow_to_push: false) - - push = push_new_file(branch_name) - - expect(push.output) - .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) - expect(push.output) - .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) - end - end - - def create_protected_branch(allow_to_push:) - Factory::Resource::Branch.fabricate! do |resource| - resource.branch_name = branch_name - resource.project = project - resource.allow_to_push = allow_to_push - resource.protected = true - end - end - - def push_new_file(branch) - Factory::Repository::ProjectPush.fabricate! do |resource| - resource.project = project - resource.file_name = 'new_file.md' - resource.file_content = '# This is a new file' - resource.commit_message = 'Add new_file.md' - resource.branch_name = branch_name - resource.new_branch = false - end - end - end -end diff --git a/qa/qa/specs/runner.rb b/qa/qa/specs/runner.rb index f8f6fe65599..ccb9d5591de 100644 --- a/qa/qa/specs/runner.rb +++ b/qa/qa/specs/runner.rb @@ -14,7 +14,13 @@ module QA def perform args = [] args.push('--tty') if tty - tags.to_a.each { |tag| args.push(['-t', tag.to_s]) } + + if tags.any? + tags.each { |tag| args.push(['-t', tag.to_s]) } + else + args.push(%w[-t ~orchestrated]) + end + args.push(options) Runtime::Browser.configure! diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb index 851026c71f0..5493a33cd2a 100644 --- a/qa/spec/runtime/env_spec.rb +++ b/qa/spec/runtime/env_spec.rb @@ -77,8 +77,35 @@ describe QA::Runtime::Env do end end + describe '.forker?' do + it 'returns false if no forker credentials are defined' do + expect(described_class).not_to be_forker + end + + it 'returns false if only forker username is defined' do + stub_env('GITLAB_FORKER_USERNAME', 'foo') + + expect(described_class).not_to be_forker + end + + it 'returns false if only forker password is defined' do + stub_env('GITLAB_FORKER_PASSWORD', 'bar') + + expect(described_class).not_to be_forker + end + + it 'returns true if forker username and password are defined' do + stub_env('GITLAB_FORKER_USERNAME', 'foo') + stub_env('GITLAB_FORKER_PASSWORD', 'bar') + + expect(described_class).to be_forker + end + end + describe '.github_access_token' do it 'returns "" if GITHUB_ACCESS_TOKEN is not defined' do + stub_env('GITHUB_ACCESS_TOKEN', nil) + expect(described_class.github_access_token).to eq('') end @@ -90,6 +117,8 @@ describe QA::Runtime::Env do describe '.require_github_access_token!' do it 'raises ArgumentError if GITHUB_ACCESS_TOKEN is not defined' do + stub_env('GITHUB_ACCESS_TOKEN', nil) + expect { described_class.require_github_access_token! }.to raise_error(ArgumentError) end diff --git a/qa/spec/scenario/test/instance_spec.rb b/qa/spec/scenario/test/instance/all_spec.rb index 0d0b534911f..1d96352550b 100644 --- a/qa/spec/scenario/test/instance_spec.rb +++ b/qa/spec/scenario/test/instance/all_spec.rb @@ -1,7 +1,7 @@ -describe QA::Scenario::Test::Instance do +describe QA::Scenario::Test::Instance::All do subject do Class.new(described_class) do - tags :rspec + tags :rspec, :foo end end @@ -26,16 +26,16 @@ describe QA::Scenario::Test::Instance do end context 'no paths' do - it 'should call runner with default arguments' do + it 'calls runner with default arguments' do subject.perform("test") expect(runner).to have_received(:options=) - .with(::File.expand_path('../../../qa/specs/features', __dir__)) + .with(['--tag', 'rspec,foo', '--', ::File.expand_path('../../../../qa/specs/features', __dir__)]) end end context 'specifying paths' do - it 'should call runner with paths' do + it 'calls runner with paths' do subject.perform('test', 'path1', 'path2') expect(runner).to have_received(:options=).with(%w[path1 path2]) diff --git a/qa/spec/scenario/test/instance/smoke_spec.rb b/qa/spec/scenario/test/instance/smoke_spec.rb new file mode 100644 index 00000000000..386eefae930 --- /dev/null +++ b/qa/spec/scenario/test/instance/smoke_spec.rb @@ -0,0 +1,45 @@ +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 + end +end |