diff options
author | Lin Jen-Shin <godfat@godfat.org> | 2018-03-03 00:10:21 +0800 |
---|---|---|
committer | Lin Jen-Shin <godfat@godfat.org> | 2018-03-03 00:10:21 +0800 |
commit | 6c5a7d5305e257244168799df0420359d0ad7b57 (patch) | |
tree | 197f0293855b02cccfb97e3f319594530b285344 /qa | |
parent | 461ecbcf07f0785b5ea50c62b114bf8217ac5199 (diff) | |
parent | 9b704ef327cc0224bf09c1e8d8d27df88ab13734 (diff) | |
download | gitlab-ce-6c5a7d5305e257244168799df0420359d0ad7b57.tar.gz |
Merge remote-tracking branch 'upstream/master' into 42572-release-controller
* upstream/master: (889 commits)
SlackService - respect `notify_only_default_branch` for push events
Clarify usage ping wording in admin area
Update incoming emails documents
Allow to include also descendant group labels
Update docs on grouping CI jobs
Support additional LabelsFinder parameters for group labels
Extend Cluster Applications to install GitLab Runner to Kubernetes cluster
Remove registry list webpack entry point
Remove trailing newline that was causing an EE conflict
Small fixes in Vuex docs
Remove u2f webpack bundle
Update documentation WRT to request parameters
remove common_vue CommonsChunk config
Fetch commit signatures from Gitaly in batches
migrate stl_viewer to dynamic import
migrate sketch_viewer to dynamic import
migrate pdf_viewer to dynamic import
migrate notebook_viewer to dynamic import
migrate balsamiq_viewer to dynamic import
Add some strings that were missing in gitlab.pot
...
Diffstat (limited to 'qa')
35 files changed, 593 insertions, 83 deletions
diff --git a/qa/README.md b/qa/README.md index 3c1b61900d9..3a99a30d379 100644 --- a/qa/README.md +++ b/qa/README.md @@ -70,6 +70,30 @@ If you need to authenticate as a different user, you can provide the GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password bin/qa Test::Instance https://gitlab.example.com ``` +If your user doesn't have permission to default sandbox group +`gitlab-qa-sandbox`, you could also use another sandbox group by giving +`GITLAB_SANDBOX_NAME`: + +``` +GITLAB_USERNAME=jsmith GITLAB_PASSWORD=password GITLAB_SANDBOX_NAME=jsmith-qa-sandbox bin/qa Test::Instance 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 +``` + All [supported environment variables are here](https://gitlab.com/gitlab-org/gitlab-qa#supported-environment-variables). +### Building a Docker image to test + +Once you have made changes to the CE/EE repositories, you may want to build a +Docker image to test locally instead of waiting for the `gitlab-ce-qa` or +`gitlab-ee-qa` nightly builds. To do that, you can run from this directory: + +```sh +docker build -t gitlab/gitlab-ce-qa:nightly . +``` + [GDK]: https://gitlab.com/gitlab-org/gitlab-development-kit/ @@ -117,6 +117,10 @@ module QA autoload :Show, 'qa/page/project/pipeline/show' end + module Job + autoload :Show, 'qa/page/project/job/show' + end + module Settings autoload :Common, 'qa/page/project/settings/common' autoload :Advanced, 'qa/page/project/settings/advanced' @@ -126,6 +130,7 @@ module QA autoload :DeployKeys, 'qa/page/project/settings/deploy_keys' autoload :SecretVariables, 'qa/page/project/settings/secret_variables' autoload :Runners, 'qa/page/project/settings/runners' + autoload :MergeRequest, 'qa/page/project/settings/merge_request' end module Issue @@ -141,6 +146,7 @@ module QA module MergeRequest autoload :New, 'qa/page/merge_request/new' + autoload :Show, 'qa/page/merge_request/show' end module Admin @@ -165,6 +171,7 @@ module QA # module Git autoload :Repository, 'qa/git/repository' + autoload :Location, 'qa/git/location' end ## diff --git a/qa/qa/factory/base.rb b/qa/qa/factory/base.rb index bd66b74a164..afaa96b4541 100644 --- a/qa/qa/factory/base.rb +++ b/qa/qa/factory/base.rb @@ -22,7 +22,7 @@ module QA factory.fabricate!(*args) - return Factory::Product.populate!(self) + return Factory::Product.populate!(factory) end end diff --git a/qa/qa/factory/product.rb b/qa/qa/factory/product.rb index d004e642f9b..996b7f14f61 100644 --- a/qa/qa/factory/product.rb +++ b/qa/qa/factory/product.rb @@ -17,8 +17,9 @@ module QA def self.populate!(factory) new.tap do |product| - factory.attributes.each_value do |attribute| - product.instance_exec(&attribute.block).tap do |value| + factory.class.attributes.each_value do |attribute| + product.instance_exec(factory, attribute.block) do |factory, block| + value = block.call(factory) product.define_singleton_method(attribute.name) { value } end end diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb index 2f4de4173d4..6e8905cde78 100644 --- a/qa/qa/factory/repository/push.rb +++ b/qa/qa/factory/repository/push.rb @@ -2,7 +2,7 @@ module QA module Factory module Repository class Push < Factory::Base - attr_writer :file_name, :file_content, :commit_message, :branch_name + attr_writer :file_name, :file_content, :commit_message, :branch_name, :new_branch dependency Factory::Resource::Project, as: :project do |project| project.name = 'project-with-code' @@ -14,6 +14,7 @@ module QA @file_content = '# This is test project' @commit_message = "Add #{@file_name}" @branch_name = 'master' + @new_branch = true end def fabricate! @@ -29,6 +30,7 @@ module QA repository.clone repository.configure_identity('GitLab QA', 'root@gitlab.com') + repository.checkout(@branch_name) unless @new_branch repository.add_file(@file_name, @file_content) repository.commit(@commit_message) repository.push_changes(@branch_name) diff --git a/qa/qa/factory/resource/merge_request.rb b/qa/qa/factory/resource/merge_request.rb index ce04e904aaf..539fe6b8a70 100644 --- a/qa/qa/factory/resource/merge_request.rb +++ b/qa/qa/factory/resource/merge_request.rb @@ -9,11 +9,20 @@ module QA :source_branch, :target_branch + product :project do |factory| + factory.project + end + + product :source_branch do |factory| + factory.source_branch + end + dependency Factory::Resource::Project, as: :project do |project| project.name = 'project-with-merge-request' end dependency Factory::Repository::Push, as: :target do |push, factory| + factory.project.visit! push.project = factory.project push.branch_name = "master:#{factory.target_branch}" end diff --git a/qa/qa/factory/resource/runner.rb b/qa/qa/factory/resource/runner.rb index 5f37f8ac2e9..03b69eb1bdf 100644 --- a/qa/qa/factory/resource/runner.rb +++ b/qa/qa/factory/resource/runner.rb @@ -4,7 +4,7 @@ module QA module Factory module Resource class Runner < Factory::Base - attr_writer :name, :tags + attr_writer :name, :tags, :image dependency Factory::Resource::Project, as: :project do |project| project.name = 'project-with-ci-cd' @@ -19,6 +19,10 @@ module QA @tags || %w[qa e2e] end + def image + @image || 'gitlab/gitlab-runner:alpine' + end + def fabricate! project.visit! @@ -31,6 +35,7 @@ module QA runner.token = runners.registration_token runner.address = runners.coordinator_address runner.tags = tags + runner.image = image runner.register! end end diff --git a/qa/qa/factory/resource/secret_variable.rb b/qa/qa/factory/resource/secret_variable.rb index af0fa8af2df..c734d739b4a 100644 --- a/qa/qa/factory/resource/secret_variable.rb +++ b/qa/qa/factory/resource/secret_variable.rb @@ -4,18 +4,6 @@ module QA class SecretVariable < Factory::Base attr_accessor :key, :value - product :key do - Page::Project::Settings::CICD.act do - expand_secret_variables(&:variable_key) - end - end - - product :value do - Page::Project::Settings::CICD.act do - expand_secret_variables(&:variable_value) - end - end - dependency Factory::Resource::Project, as: :project do |project| project.name = 'project-with-secret-variables' project.description = 'project for adding secret variable test' diff --git a/qa/qa/git/location.rb b/qa/qa/git/location.rb new file mode 100644 index 00000000000..30538388530 --- /dev/null +++ b/qa/qa/git/location.rb @@ -0,0 +1,32 @@ +require 'uri' +require 'forwardable' + +module QA + module Git + class Location + extend Forwardable + + attr_reader :git_uri, :uri + def_delegators :@uri, :user, :host, :path + + # See: config/initializers/1_settings.rb + # Settings#build_gitlab_shell_ssh_path_prefix + def initialize(git_uri) + @git_uri = git_uri + @uri = + if git_uri.start_with?('ssh://') + URI.parse(git_uri) + else + *rest, path = git_uri.split(':') + # Host cannot have : so we'll need to escape it + user_host = rest.join('%3A').sub(/\A\[(.+)\]\z/, '\1') + URI.parse("ssh://#{user_host}/#{path}") + end + end + + def port + uri.port || 22 + end + end + end +end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 8f999511d58..b3150e8f3fa 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -1,3 +1,4 @@ +require 'cgi' require 'uri' module QA @@ -32,7 +33,11 @@ module QA end def clone(opts = '') - `git clone #{opts} #{@uri.to_s} ./` + `git clone #{opts} #{@uri.to_s} ./ #{suppress_output}` + end + + def checkout(branch_name) + `git checkout "#{branch_name}"` end def shallow_clone @@ -60,12 +65,22 @@ module QA end def push_changes(branch = 'master') - `git push #{@uri.to_s} #{branch}` + `git push #{@uri.to_s} #{branch} #{suppress_output}` end def commits `git log --oneline`.split("\n") end + + private + + def suppress_output + # If we're running as the default user, it's probably a temporary + # instance and output can be useful for debugging + return if @username == Runtime::User.default_name + + "&> #{File::NULL}" + end end end end diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 5c3af4b9115..a313d46205d 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -17,7 +17,8 @@ module QA start = Time.now while Time.now - start < max - return true if yield + result = yield + return result if result sleep(time) @@ -97,6 +98,10 @@ module QA views.map(&:errors).flatten end + def self.elements + views.map(&:elements).flatten + end + class DSL attr_reader :views diff --git a/qa/qa/page/main/login.rb b/qa/qa/page/main/login.rb index 0d1ffd9694a..596205fe540 100644 --- a/qa/qa/page/main/login.rb +++ b/qa/qa/page/main/login.rb @@ -31,22 +31,37 @@ module QA end end + def set_initial_password_if_present + if page.has_content?('Change your password') + fill_in :user_password, with: Runtime::User.password + fill_in :user_password_confirmation, with: Runtime::User.password + click_button 'Change your password' + end + end + + def sign_in_using_credentials + if Runtime::User.ldap_user? + sign_in_using_ldap_credentials + else + sign_in_using_gitlab_credentials + end + end + def sign_in_using_ldap_credentials - click_link 'LDAP' + using_wait_time 0 do + set_initial_password_if_present - fill_in :username, with: Runtime::User.name - fill_in :password, with: Runtime::User.password + click_link 'LDAP' - click_button 'Sign in' + fill_in :username, with: Runtime::User.ldap_username + fill_in :password, with: Runtime::User.ldap_password + click_button 'Sign in' + end end - def sign_in_using_credentials + def sign_in_using_gitlab_credentials using_wait_time 0 do - if page.has_content?('Change your password') - fill_in :user_password, with: Runtime::User.password - fill_in :user_password_confirmation, with: Runtime::User.password - click_button 'Change your password' - end + set_initial_password_if_present click_link 'Standard' if page.has_content?('LDAP') diff --git a/qa/qa/page/merge_request/show.rb b/qa/qa/page/merge_request/show.rb new file mode 100644 index 00000000000..35875487da8 --- /dev/null +++ b/qa/qa/page/merge_request/show.rb @@ -0,0 +1,46 @@ +module QA + module Page + module MergeRequest + class Show < Page::Base + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_ready_to_merge.js' do + element :merge_button + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_merged.vue' do + element :merged_status, 'The changes were merged into' + end + + view 'app/assets/javascripts/vue_merge_request_widget/components/states/mr_widget_rebase.vue' do + element :mr_rebase_button + element :fast_forward_nessage, "Fast-forward merge is not possible" + end + + def rebase! + wait(reload: false) do + click_element :mr_rebase_button + + has_text?("The source branch HEAD has recently changed.") + end + end + + def fast_forward_possible? + !has_text?("Fast-forward merge is not possible") + end + + def has_merge_button? + refresh + + has_selector?('.accept-merge-request') + end + + def merge! + wait(reload: false) do + click_element :merge_button + + has_text?("The changes were merged into") + end + end + end + end + end +end diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb new file mode 100644 index 00000000000..21bda74efb2 --- /dev/null +++ b/qa/qa/page/project/job/show.rb @@ -0,0 +1,19 @@ +module QA::Page + module Project::Job + class Show < QA::Page::Base + view 'app/views/projects/jobs/show.html.haml' do + element :build_output, '.js-build-output' + end + + def output + css = '.js-build-output' + + wait(reload: false) do + has_css?(css) + end + + find(css).text + end + end + end +end diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb index 32c108393b9..ce430a2a6ee 100644 --- a/qa/qa/page/project/pipeline/index.rb +++ b/qa/qa/page/project/pipeline/index.rb @@ -6,7 +6,13 @@ module QA::Page end def go_to_latest_pipeline - first('.js-pipeline-url-link').click + css = '.js-pipeline-url-link' + + link = wait(reload: false) do + first(css) + end + + link.click end end end diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index 0835173f1cd..b183552d46c 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -11,6 +11,7 @@ module QA::Page view 'app/assets/javascripts/pipelines/components/graph/job_component.vue' do element :job_component, /class.*ci-job-component.*/ + element :job_link, /class.*js-pipeline-graph-job-link.*/ end view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do @@ -30,6 +31,16 @@ module QA::Page end end end + + def go_to_first_job + css = '.js-pipeline-graph-job-link' + + wait(reload: false) do + has_css?(css) + end + + first(css).click + end end end end diff --git a/qa/qa/page/project/settings/merge_request.rb b/qa/qa/page/project/settings/merge_request.rb new file mode 100644 index 00000000000..b147c91b467 --- /dev/null +++ b/qa/qa/page/project/settings/merge_request.rb @@ -0,0 +1,27 @@ +module QA + module Page + module Project + module Settings + class MergeRequest < QA::Page::Base + include Common + + view 'app/views/projects/_merge_request_fast_forward_settings.html.haml' do + element :radio_button_merge_ff + end + + view 'app/views/projects/edit.html.haml' do + element :merge_request_settings, 'Merge request settings' + element :save_merge_request_changes + end + + def enable_ff_only + expand_section('Merge request settings') do + click_element :radio_button_merge_ff + click_element :save_merge_request_changes + end + end + end + end + end + end +end diff --git a/qa/qa/page/project/settings/secret_variables.rb b/qa/qa/page/project/settings/secret_variables.rb index fea4acb389a..c95c79f137d 100644 --- a/qa/qa/page/project/settings/secret_variables.rb +++ b/qa/qa/page/project/settings/secret_variables.rb @@ -6,39 +6,37 @@ module QA include Common view 'app/views/ci/variables/_variable_row.html.haml' do + element :variable_row, '.ci-variable-row-body' element :variable_key, '.js-ci-variable-input-key' element :variable_value, '.js-ci-variable-input-value' + element :key_placeholder, 'Input variable key' + element :value_placeholder, 'Input variable value' end view 'app/views/ci/variables/_index.html.haml' do element :save_variables, '.js-secret-variables-save-button' + element :reveal_values, '.js-secret-value-reveal-button' end def fill_variable_key(key) - page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do - page.find('.js-ci-variable-input-key').set(key) - end + fill_in('Input variable key', with: key, match: :first) end def fill_variable_value(value) - page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do - page.find('.js-ci-variable-input-value').set(value) - end + fill_in('Input variable value', with: value, match: :first) end def save_variables - click_button('Save variables') + find('.js-secret-variables-save-button').click end - def variable_key - page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do - page.find('.js-ci-variable-input-key').value - end + def reveal_variables + find('.js-secret-value-reveal-button').click end - def variable_value - page.within('.js-ci-variable-list-section .js-row:nth-child(1)') do - page.find('.js-ci-variable-input-value').value + def variable_value(key) + within('.ci-variable-row-body', text: key) do + find('.js-ci-variable-input-value').value end end end diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 9d2a84ea644..0c7ad46d36b 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -22,27 +22,33 @@ module QA end def choose_repository_clone_http - wait(reload: false) do - click_element :clone_dropdown - - page.within('.clone-options-dropdown') do - click_link('HTTP') - end + choose_repository_clone('HTTP', 'http') + end - # Ensure git clone textbox was updated to http URI - repository_location.include?('http') - end + def choose_repository_clone_ssh + # It's not always beginning with ssh:// so detecting with @ + # would be more reliable because ssh would always contain it. + # We can't use .git because HTTP also contain that part. + choose_repository_clone('SSH', '@') end def repository_location find('#project_clone').value end + def repository_location_uri + Git::Location.new(repository_location) + end + def project_name find('.qa-project-name').text end def new_merge_request + wait(reload: true) do + has_css?(element_selector_css(:create_merge_request)) + end + click_element :create_merge_request end @@ -56,6 +62,21 @@ module QA click_link 'New issue' end + + private + + def choose_repository_clone(kind, detect_text) + wait(reload: false) do + click_element :clone_dropdown + + page.within('.clone-options-dropdown') do + click_link(kind) + end + + # Ensure git clone textbox was updated + repository_location.include?(detect_text) + end + end end end end diff --git a/qa/qa/runtime/env.rb b/qa/qa/runtime/env.rb index 56944e8b641..fe432edfa2a 100644 --- a/qa/qa/runtime/env.rb +++ b/qa/qa/runtime/env.rb @@ -16,6 +16,36 @@ module QA def personal_access_token ENV['PERSONAL_ACCESS_TOKEN'] end + + # By default, "standard" denotes a standard GitLab user login. + # Set this to "ldap" if the user should be logged in via LDAP. + def user_type + (ENV['GITLAB_USER_TYPE'] || 'standard').tap do |type| + unless %w(ldap standard).include?(type) + raise ArgumentError.new("Invalid user type '#{type}': must be 'ldap' or 'standard'") + end + end + end + + def user_username + ENV['GITLAB_USERNAME'] + end + + def user_password + ENV['GITLAB_PASSWORD'] + end + + def ldap_username + ENV['GITLAB_LDAP_USERNAME'] + end + + def ldap_password + ENV['GITLAB_LDAP_PASSWORD'] + end + + def sandbox_name + ENV['GITLAB_SANDBOX_NAME'] + end end end end diff --git a/qa/qa/runtime/namespace.rb b/qa/qa/runtime/namespace.rb index a72c2d21898..8d05b387416 100644 --- a/qa/qa/runtime/namespace.rb +++ b/qa/qa/runtime/namespace.rb @@ -16,7 +16,7 @@ module QA end def sandbox_name - 'gitlab-qa-sandbox' + Runtime::Env.sandbox_name || 'gitlab-qa-sandbox' end end end diff --git a/qa/qa/runtime/rsa_key.rb b/qa/qa/runtime/rsa_key.rb index d456062bce7..fcd7dcc4f02 100644 --- a/qa/qa/runtime/rsa_key.rb +++ b/qa/qa/runtime/rsa_key.rb @@ -7,7 +7,7 @@ module QA extend Forwardable attr_reader :key - def_delegators :@key, :fingerprint + def_delegators :@key, :fingerprint, :to_pem def initialize(bits = 4096) @key = OpenSSL::PKey::RSA.new(bits) diff --git a/qa/qa/runtime/user.rb b/qa/qa/runtime/user.rb index 60027c89ab1..c80ee6d4d96 100644 --- a/qa/qa/runtime/user.rb +++ b/qa/qa/runtime/user.rb @@ -3,12 +3,28 @@ module QA module User extend self + def default_name + 'root' + end + def name - ENV['GITLAB_USERNAME'] || 'root' + Runtime::Env.user_username || default_name end def password - ENV['GITLAB_PASSWORD'] || '5iveL!fe' + Runtime::Env.user_password || '5iveL!fe' + end + + def ldap_user? + Runtime::Env.user_type == 'ldap' + end + + def ldap_username + Runtime::Env.ldap_username || name + end + + def ldap_password + Runtime::Env.ldap_password || password end end end diff --git a/qa/qa/service/runner.rb b/qa/qa/service/runner.rb index d0ee33c69f2..c0352e0467a 100644 --- a/qa/qa/service/runner.rb +++ b/qa/qa/service/runner.rb @@ -15,6 +15,14 @@ module QA @tags = %w[qa test] end + def network + shell "docker network inspect #{@network}" + rescue CommandError + 'bridge' + else + @network + end + def pull shell "docker pull #{@image}" end @@ -22,7 +30,7 @@ module QA def register! shell <<~CMD.tr("\n", ' ') docker run -d --rm --entrypoint=/bin/sh - --network #{@network} --name #{@name} + --network #{network} --name #{@name} -e CI_SERVER_URL=#{@address} -e REGISTER_NON_INTERACTIVE=true -e REGISTRATION_TOKEN=#{@token} diff --git a/qa/qa/service/shellout.rb b/qa/qa/service/shellout.rb index 898febde63c..76fb2af6319 100644 --- a/qa/qa/service/shellout.rb +++ b/qa/qa/service/shellout.rb @@ -3,6 +3,8 @@ require 'open3' module QA module Service module Shellout + CommandError = Class.new(StandardError) + ## # TODO, make it possible to use generic QA framework classes # as a library - gitlab-org/gitlab-qa#94 @@ -14,7 +16,7 @@ module QA out.each { |line| puts line } if wait.value.exited? && wait.value.exitstatus.nonzero? - raise "Command `#{command}` failed!" + raise CommandError, "Command `#{command}` failed!" end end end diff --git a/qa/qa/specs/features/api/users_spec.rb b/qa/qa/specs/features/api/users_spec.rb index 9d039590a0e..d4ff4ebbc9a 100644 --- a/qa/qa/specs/features/api/users_spec.rb +++ b/qa/qa/specs/features/api/users_spec.rb @@ -14,7 +14,7 @@ module QA end scenario 'submit request with a valid user name' do - get request.url, { params: { username: 'root' } } + get request.url, { params: { username: Runtime::User.name } } expect_status(200) expect(json_body).to be_an Array @@ -23,7 +23,7 @@ module QA end scenario 'submit request with an invalid user name' do - get request.url, { params: { username: 'invalid' } } + get request.url, { params: { username: SecureRandom.hex(10) } } expect_status(200) expect(json_body).to be_an Array diff --git a/qa/qa/specs/features/merge_request/rebase_spec.rb b/qa/qa/specs/features/merge_request/rebase_spec.rb new file mode 100644 index 00000000000..2a44d42af6f --- /dev/null +++ b/qa/qa/specs/features/merge_request/rebase_spec.rb @@ -0,0 +1,39 @@ +module QA + feature 'merge request rebase', :core do + scenario '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::Push.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/project/add_secret_variable_spec.rb b/qa/qa/specs/features/project/add_secret_variable_spec.rb index 36422a92afc..d1bf7849bd0 100644 --- a/qa/qa/specs/features/project/add_secret_variable_spec.rb +++ b/qa/qa/specs/features/project/add_secret_variable_spec.rb @@ -4,16 +4,21 @@ module QA Runtime::Browser.visit(:gitlab, Page::Main::Login) Page::Main::Login.act { sign_in_using_credentials } - variable_key = 'VARIABLE_KEY' - variable_value = 'variable value' - - variable = Factory::Resource::SecretVariable.fabricate! do |resource| - resource.key = variable_key - resource.value = variable_value + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.key = 'VARIABLE_KEY' + resource.value = 'some secret variable' end - expect(variable.key).to eq(variable_key) - expect(variable.value).to eq(variable_value) + 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/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb new file mode 100644 index 00000000000..19d3c83758a --- /dev/null +++ b/qa/qa/specs/features/project/deploy_key_clone_spec.rb @@ -0,0 +1,81 @@ +require 'digest/sha1' + +module QA + feature 'cloning code using a deploy key', :core, :docker do + let(:runner_name) { "qa-runner-#{Time.now.to_i}" } + let(:key) { Runtime::RSAKey.new } + + given(:project) do + Factory::Resource::Project.fabricate! do |resource| + resource.name = 'deploy-key-clone-project' + end + end + + after do + Service::Runner.new(runner_name).remove! + end + + scenario 'user sets up a deploy key to clone code using pipelines' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + 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 + + Factory::Resource::DeployKey.fabricate! do |resource| + resource.project = project + resource.title = 'deploy key title' + resource.key = key.public_key + end + + Factory::Resource::SecretVariable.fabricate! do |resource| + resource.project = project + resource.key = 'DEPLOY_KEY' + resource.value = key.to_pem + end + + project.visit! + + repository_uri = Page::Project::Show.act do + choose_repository_clone_ssh + repository_location_uri + end + + gitlab_ci = <<~YAML + cat-config: + script: + - mkdir -p ~/.ssh + - ssh-keyscan -p #{repository_uri.port} #{repository_uri.host} >> ~/.ssh/known_hosts + - eval $(ssh-agent -s) + - echo "$DEPLOY_KEY" | ssh-add - + - git clone #{repository_uri.git_uri} + - sha1sum #{project.name}/.gitlab-ci.yml + tags: + - qa + - docker + YAML + + Factory::Repository::Push.fabricate! do |resource| + resource.project = project + resource.file_name = '.gitlab-ci.yml' + resource.commit_message = 'Add .gitlab-ci.yml' + resource.file_content = gitlab_ci + 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| + expect(job.output).to include(sha1sum) + end + end + end +end diff --git a/qa/qa/specs/features/project/pipelines_spec.rb b/qa/qa/specs/features/project/pipelines_spec.rb index 1bb7730e06c..74f6474443d 100644 --- a/qa/qa/specs/features/project/pipelines_spec.rb +++ b/qa/qa/specs/features/project/pipelines_spec.rb @@ -69,7 +69,7 @@ module QA tags: - qa - test - script: echo "CONTENTS" > my-artifacts/artifact.txt + script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt artifacts: paths: - my-artifacts/ @@ -95,7 +95,7 @@ module QA 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: :failed) + expect(pipeline).to have_build('test-artifacts', status: :success) end end end diff --git a/qa/spec/factory/base_spec.rb b/qa/spec/factory/base_spec.rb index c5663049be8..04e04886699 100644 --- a/qa/spec/factory/base_spec.rb +++ b/qa/spec/factory/base_spec.rb @@ -7,6 +7,7 @@ describe QA::Factory::Base do before do allow(QA::Factory::Product).to receive(:new).and_return(product) + allow(QA::Factory::Product).to receive(:populate!).and_return(product) end it 'instantiates the factory and calls factory method' do @@ -76,6 +77,7 @@ describe QA::Factory::Base do allow(subject).to receive(:new).and_return(instance) allow(instance).to receive(:mydep).and_return(nil) allow(QA::Factory::Product).to receive(:new) + allow(QA::Factory::Product).to receive(:populate!) end it 'builds all dependencies first' do @@ -89,8 +91,16 @@ describe QA::Factory::Base do describe '.product' do subject do Class.new(described_class) do + def fabricate! + "any" + end + + # Defined only to be stubbed + def self.find_page + end + product :token do - page.do_something_on_page! + find_page.do_something_on_page! 'resulting value' end end @@ -105,16 +115,17 @@ describe QA::Factory::Base do let(:page) { spy('page') } before do - allow(subject).to receive(:new).and_return(factory) + allow(factory).to receive(:class).and_return(subject) allow(QA::Factory::Product).to receive(:new).and_return(product) allow(product).to receive(:page).and_return(page) + allow(subject).to receive(:find_page).and_return(page) end it 'populates product after fabrication' do subject.fabricate! - expect(page).to have_received(:do_something_on_page!) expect(product.token).to eq 'resulting value' + expect(page).to have_received(:do_something_on_page!) end end end diff --git a/qa/spec/factory/product_spec.rb b/qa/spec/factory/product_spec.rb index fdfb1ec90cc..f245aabbf43 100644 --- a/qa/spec/factory/product_spec.rb +++ b/qa/spec/factory/product_spec.rb @@ -1,9 +1,20 @@ describe QA::Factory::Product do - let(:factory) { spy('factory') } + let(:factory) do + QA::Factory::Base.new + end + + let(:attributes) do + { test: QA::Factory::Product::Attribute.new(:test, proc { 'returned' }) } + end + let(:product) { spy('product') } + before do + allow(QA::Factory::Base).to receive(:attributes).and_return(attributes) + end + describe '.populate!' do - it 'returns a fabrication product' do + it 'returns a fabrication product and define factory attributes as its methods' do expect(described_class).to receive(:new).and_return(product) result = described_class.populate!(factory) do |instance| @@ -11,6 +22,7 @@ describe QA::Factory::Product do end expect(result).to be product + expect(result.test).to eq('returned') end end diff --git a/qa/spec/git/location_spec.rb b/qa/spec/git/location_spec.rb new file mode 100644 index 00000000000..aef906ee836 --- /dev/null +++ b/qa/spec/git/location_spec.rb @@ -0,0 +1,55 @@ +describe QA::Git::Location do + describe '.new' do + context 'when URI starts with ssh://' do + context 'when URI has port' do + it 'parses correctly' do + uri = described_class + .new('ssh://git@qa.test:2222/sandbox/qa/repo.git') + + expect(uri.user).to eq('git') + expect(uri.host).to eq('qa.test') + expect(uri.port).to eq(2222) + expect(uri.path).to eq('/sandbox/qa/repo.git') + end + end + + context 'when URI does not have port' do + it 'parses correctly' do + uri = described_class + .new('ssh://git@qa.test/sandbox/qa/repo.git') + + expect(uri.user).to eq('git') + expect(uri.host).to eq('qa.test') + expect(uri.port).to eq(22) + expect(uri.path).to eq('/sandbox/qa/repo.git') + end + end + end + + context 'when URI does not start with ssh://' do + context 'when host does not have colons' do + it 'parses correctly' do + uri = described_class + .new('git@qa.test:sandbox/qa/repo.git') + + expect(uri.user).to eq('git') + expect(uri.host).to eq('qa.test') + expect(uri.port).to eq(22) + expect(uri.path).to eq('/sandbox/qa/repo.git') + end + end + + context 'when host has a colon' do + it 'parses correctly' do + uri = described_class + .new('[git@qa:test]:sandbox/qa/repo.git') + + expect(uri.user).to eq('git') + expect(uri.host).to eq('qa%3Atest') + expect(uri.port).to eq(22) + expect(uri.path).to eq('/sandbox/qa/repo.git') + end + end + end + end +end diff --git a/qa/spec/page/base_spec.rb b/qa/spec/page/base_spec.rb index 287adf35c46..52daa9697ee 100644 --- a/qa/spec/page/base_spec.rb +++ b/qa/spec/page/base_spec.rb @@ -14,7 +14,7 @@ describe QA::Page::Base do end view 'path/to/some/_partial.html.haml' do - element :something, 'string pattern' + element :another_element, 'string pattern' end end end @@ -25,11 +25,10 @@ describe QA::Page::Base do end it 'populates views objects with data about elements' do - subject.views.first.elements.tap do |elements| - expect(elements.size).to eq 2 - expect(elements).to all(be_an_instance_of QA::Page::Element) - expect(elements.map(&:name)).to eq [:something, :something_else] - end + expect(subject.elements.size).to eq 3 + expect(subject.elements).to all(be_an_instance_of QA::Page::Element) + expect(subject.elements.map(&:name)) + .to eq [:something, :something_else, :another_element] end end diff --git a/qa/spec/runtime/env_spec.rb b/qa/spec/runtime/env_spec.rb index 103573db6be..2b6365dbc41 100644 --- a/qa/spec/runtime/env_spec.rb +++ b/qa/spec/runtime/env_spec.rb @@ -55,4 +55,25 @@ describe QA::Runtime::Env do end end end + + describe '.user_type' do + it 'returns standard if not defined' do + expect(described_class.user_type).to eq('standard') + end + + it 'returns standard as defined' do + stub_env('GITLAB_USER_TYPE', 'standard') + expect(described_class.user_type).to eq('standard') + end + + it 'returns ldap as defined' do + stub_env('GITLAB_USER_TYPE', 'ldap') + expect(described_class.user_type).to eq('ldap') + end + + it 'returns an error if invalid user type' do + stub_env('GITLAB_USER_TYPE', 'foobar') + expect { described_class.user_type }.to raise_error(ArgumentError) + end + end end |