[QA] Add a new scenario to test GitHub import
Signed-off-by: Rémy Coutable <remy@rymai.me>
This commit is contained in:
parent
01796734d0
commit
2ad990bba0
18 changed files with 337 additions and 19 deletions
|
@ -40,7 +40,7 @@
|
|||
= project.human_import_status_name
|
||||
|
||||
- @repos.each do |repo|
|
||||
%tr{ id: "repo_#{repo.id}" }
|
||||
%tr{ id: "repo_#{repo.id}", data: { qa: { repo_path: repo.full_name } } }
|
||||
%td
|
||||
= provider_project_link(provider, repo.full_name)
|
||||
%td.import-target
|
||||
|
@ -50,7 +50,7 @@
|
|||
- if current_user.can_select_namespace?
|
||||
- selected = params[:namespace_id] || :current_user
|
||||
- opts = current_user.can_create_group? ? { extra_group: Group.new(name: repo.owner.login, path: repo.owner.login) } : {}
|
||||
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace', tabindex: 1 }
|
||||
= select_tag :namespace_id, namespaces_options(selected, opts.merge({ display_path: true })), { class: 'input-group-text select2 js-select-namespace qa-project-namespace-select', tabindex: 1 }
|
||||
- else
|
||||
= text_field_tag :path, current_user.namespace_path, class: "input-group-text input-large form-control", tabindex: 1, disabled: true
|
||||
%span.input-group-prepend
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
%li.dropdown-bold-header GitLab
|
||||
- if current_user.can_create_project?
|
||||
%li
|
||||
= link_to 'New project', new_project_path
|
||||
= link_to 'New project', new_project_path, class: 'qa-global-new-project-link'
|
||||
- if current_user.can_create_group?
|
||||
%li
|
||||
= link_to 'New group', new_group_path
|
||||
|
|
9
qa/qa.rb
9
qa/qa.rb
|
@ -40,6 +40,7 @@ module QA
|
|||
autoload :Issue, 'qa/factory/resource/issue'
|
||||
autoload :Project, 'qa/factory/resource/project'
|
||||
autoload :MergeRequest, 'qa/factory/resource/merge_request'
|
||||
autoload :ProjectImportedFromGithub, 'qa/factory/resource/project_imported_from_github'
|
||||
autoload :DeployKey, 'qa/factory/resource/deploy_key'
|
||||
autoload :Branch, 'qa/factory/resource/branch'
|
||||
autoload :SecretVariable, 'qa/factory/resource/secret_variable'
|
||||
|
@ -79,6 +80,7 @@ module QA
|
|||
autoload :Instance, 'qa/scenario/test/instance'
|
||||
|
||||
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'
|
||||
|
@ -132,6 +134,10 @@ module QA
|
|||
autoload :Show, 'qa/page/project/show'
|
||||
autoload :Activity, 'qa/page/project/activity'
|
||||
|
||||
module Import
|
||||
autoload :Github, 'qa/page/project/import/github'
|
||||
end
|
||||
|
||||
module Pipeline
|
||||
autoload :Index, 'qa/page/project/pipeline/index'
|
||||
autoload :Show, 'qa/page/project/pipeline/show'
|
||||
|
@ -185,7 +191,7 @@ module QA
|
|||
end
|
||||
|
||||
module Issuable
|
||||
autoload :Show, 'qa/page/issuable/show'
|
||||
autoload :Sidebar, 'qa/page/issuable/sidebar'
|
||||
end
|
||||
|
||||
module MergeRequest
|
||||
|
@ -210,6 +216,7 @@ module QA
|
|||
#
|
||||
module Component
|
||||
autoload :Dropzone, 'qa/page/component/dropzone'
|
||||
autoload :Select2, 'qa/page/component/select2'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ module QA
|
|||
Page::Group::New.perform do |group|
|
||||
group.set_path(@path)
|
||||
group.set_description(@description)
|
||||
group.set_visibility('Private')
|
||||
group.set_visibility('Public')
|
||||
group.create
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,16 +5,12 @@ module QA
|
|||
module Resource
|
||||
class Project < Factory::Base
|
||||
attr_writer :description
|
||||
attr_reader :name
|
||||
|
||||
dependency Factory::Resource::Group, as: :group
|
||||
|
||||
def name=(name)
|
||||
@name = "#{name}-#{SecureRandom.hex(8)}"
|
||||
@description = 'My awesome project'
|
||||
end
|
||||
|
||||
product :name do
|
||||
Page::Project::Show.act { project_name }
|
||||
product :name do |factory|
|
||||
factory.name
|
||||
end
|
||||
|
||||
product :repository_ssh_location do
|
||||
|
@ -24,6 +20,14 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
def initialize
|
||||
@description = 'My awesome project'
|
||||
end
|
||||
|
||||
def name=(raw_name)
|
||||
@name = "#{raw_name}-#{SecureRandom.hex(8)}"
|
||||
end
|
||||
|
||||
def fabricate!
|
||||
group.visit!
|
||||
|
||||
|
|
37
qa/qa/factory/resource/project_imported_from_github.rb
Normal file
37
qa/qa/factory/resource/project_imported_from_github.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
require 'securerandom'
|
||||
|
||||
module QA
|
||||
module Factory
|
||||
module Resource
|
||||
class ProjectImportedFromGithub < Resource::Project
|
||||
attr_writer :personal_access_token, :github_repository_path
|
||||
|
||||
dependency Factory::Resource::Group, as: :group
|
||||
|
||||
product :name do |factory|
|
||||
factory.name
|
||||
end
|
||||
|
||||
def fabricate!
|
||||
group.visit!
|
||||
|
||||
Page::Group::Show.act { go_to_new_project }
|
||||
|
||||
Page::Project::New.perform do |page|
|
||||
page.go_to_import_project
|
||||
end
|
||||
|
||||
Page::Project::New.perform do |page|
|
||||
page.go_to_github_import
|
||||
end
|
||||
|
||||
Page::Project::Import::Github.perform do |page|
|
||||
page.add_personal_access_token(@personal_access_token)
|
||||
page.list_repos
|
||||
page.import!(@github_repository_path, @name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -21,8 +21,8 @@ module QA
|
|||
|
||||
Page::Group::New.perform do |group|
|
||||
group.set_path(@name)
|
||||
group.set_description('GitLab QA Sandbox')
|
||||
group.set_visibility('Private')
|
||||
group.set_description('GitLab QA Sandbox Group')
|
||||
group.set_visibility('Public')
|
||||
group.create
|
||||
end
|
||||
end
|
||||
|
|
11
qa/qa/page/component/select2.rb
Normal file
11
qa/qa/page/component/select2.rb
Normal file
|
@ -0,0 +1,11 @@
|
|||
module QA
|
||||
module Page
|
||||
module Component
|
||||
module Select2
|
||||
def select_item(item_text)
|
||||
find('ul.select2-result-sub > li', text: item_text).click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,15 +1,14 @@
|
|||
module QA
|
||||
module Page
|
||||
module Issuable
|
||||
class Show < Page::Base
|
||||
class Sidebar < Page::Base
|
||||
view 'app/views/shared/issuable/_sidebar.html.haml' do
|
||||
element :labels_block, ".issuable-show-labels"
|
||||
end
|
||||
|
||||
def has_label?(label)
|
||||
page.within('.issuable-show-labels') do
|
||||
element = find('span', text: label, wait: 1)
|
||||
!element.nil?
|
||||
!!find('span', text: label)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -10,6 +10,8 @@ module QA
|
|||
element :operations_kubernetes_link, "title: _('Kubernetes')"
|
||||
element :issues_link, /link_to.*shortcuts-issues/
|
||||
element :issues_link_text, "Issues"
|
||||
element :merge_requests_link, /link_to.*shortcuts-merge_requests/
|
||||
element :merge_requests_link_text, "Merge Requests"
|
||||
element :top_level_items, '.sidebar-top-level-items'
|
||||
element :operations_section, "class: 'shortcuts-operations'"
|
||||
element :activity_link, "title: 'Activity'"
|
||||
|
@ -62,6 +64,12 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
def click_merge_requests
|
||||
within_sidebar do
|
||||
click_link('Merge Requests')
|
||||
end
|
||||
end
|
||||
|
||||
def click_wiki
|
||||
within_sidebar do
|
||||
click_link('Wiki')
|
||||
|
|
66
qa/qa/page/project/import/github.rb
Normal file
66
qa/qa/page/project/import/github.rb
Normal file
|
@ -0,0 +1,66 @@
|
|||
module QA
|
||||
module Page
|
||||
module Project
|
||||
module Import
|
||||
class Github < Page::Base
|
||||
include Page::Component::Select2
|
||||
|
||||
view 'app/views/import/github/new.html.haml' do
|
||||
element :personal_access_token_field, 'text_field_tag :personal_access_token'
|
||||
element :list_repos_button, "submit_tag _('List your GitHub repositories')"
|
||||
end
|
||||
|
||||
view 'app/views/import/_githubish_status.html.haml' do
|
||||
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 :import_button, "_('Import')"
|
||||
end
|
||||
|
||||
def add_personal_access_token(personal_access_token)
|
||||
fill_in 'personal_access_token', with: personal_access_token
|
||||
end
|
||||
|
||||
def list_repos
|
||||
click_button 'List your GitHub repositories'
|
||||
end
|
||||
|
||||
def import!(full_path, name)
|
||||
choose_test_namespace(full_path)
|
||||
set_path(full_path, name)
|
||||
import_project(full_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def within_repo_path(full_path)
|
||||
page.within(%Q(tr[data-qa-repo-path="#{full_path}"])) do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def choose_test_namespace(full_path)
|
||||
within_repo_path(full_path) do
|
||||
click_element :project_namespace_select
|
||||
end
|
||||
|
||||
select_item(Runtime::Namespace.path)
|
||||
end
|
||||
|
||||
def set_path(full_path, name)
|
||||
within_repo_path(full_path) do
|
||||
fill_in 'path', with: name
|
||||
end
|
||||
end
|
||||
|
||||
def import_project(full_path)
|
||||
within_repo_path(full_path) do
|
||||
click_button 'Import'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -2,6 +2,12 @@ module QA
|
|||
module Page
|
||||
module Project
|
||||
class New < Page::Base
|
||||
include Page::Component::Select2
|
||||
|
||||
view 'app/views/projects/new.html.haml' do
|
||||
element :import_project_tab, "Import project"
|
||||
end
|
||||
|
||||
view 'app/views/projects/_new_project_fields.html.haml' do
|
||||
element :project_namespace_select
|
||||
element :project_namespace_field, /select :namespace_id.*class: 'select2/
|
||||
|
@ -10,10 +16,18 @@ module QA
|
|||
element :project_create_button, "submit 'Create project'"
|
||||
end
|
||||
|
||||
view 'app/views/projects/_import_project_pane.html.haml' do
|
||||
element :import_github, "icon('github', text: 'GitHub')"
|
||||
end
|
||||
|
||||
def choose_test_namespace
|
||||
click_element :project_namespace_select
|
||||
|
||||
find('ul.select2-result-sub > li', text: Runtime::Namespace.path).click
|
||||
select_item(Runtime::Namespace.path)
|
||||
end
|
||||
|
||||
def go_to_import_project
|
||||
click_on 'Import project'
|
||||
end
|
||||
|
||||
def choose_name(name)
|
||||
|
@ -27,6 +41,10 @@ module QA
|
|||
def create_new_project
|
||||
click_on 'Create project'
|
||||
end
|
||||
|
||||
def go_to_github_import
|
||||
click_link 'GitHub'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,6 +22,10 @@ module QA
|
|||
element :branches_dropdown
|
||||
end
|
||||
|
||||
view 'app/views/projects/_files.html.haml' do
|
||||
element :tree_holder, '.tree-holder'
|
||||
end
|
||||
|
||||
def project_name
|
||||
find('.qa-project-name').text
|
||||
end
|
||||
|
@ -46,6 +50,12 @@ module QA
|
|||
click_element :create_merge_request
|
||||
end
|
||||
|
||||
def wait_for_import
|
||||
wait(reload: true) do
|
||||
has_css?('.tree-holder')
|
||||
end
|
||||
end
|
||||
|
||||
def go_to_new_issue
|
||||
click_element :new_menu_toggle
|
||||
|
||||
|
|
|
@ -66,6 +66,17 @@ module QA
|
|||
def has_gcloud_credentials?
|
||||
%w[GCLOUD_ACCOUNT_KEY GCLOUD_ACCOUNT_EMAIL].none? { |var| ENV[var].to_s.empty? }
|
||||
end
|
||||
|
||||
# Specifies the token that can be used for the GitHub API
|
||||
def github_access_token
|
||||
ENV['GITHUB_ACCESS_TOKEN'].to_s.strip
|
||||
end
|
||||
|
||||
def require_github_access_token!
|
||||
return unless github_access_token.empty?
|
||||
|
||||
raise ArgumentError, "Please provide GITHUB_ACCESS_TOKEN"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,7 +16,7 @@ module QA
|
|||
end
|
||||
|
||||
def sandbox_name
|
||||
Runtime::Env.sandbox_name || 'gitlab-qa-sandbox'
|
||||
Runtime::Env.sandbox_name || 'gitlab-qa-sandbox-group'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
18
qa/qa/scenario/test/integration/github.rb
Normal file
18
qa/qa/scenario/test/integration/github.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
module QA
|
||||
module Scenario
|
||||
module Test
|
||||
module Integration
|
||||
class Github < Test::Instance
|
||||
tags :github
|
||||
|
||||
def perform(address, *rspec_options)
|
||||
# This test suite requires a GitHub personal access token
|
||||
Runtime::Env.require_github_access_token!
|
||||
|
||||
super
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
106
qa/qa/specs/features/project/import_from_github_spec.rb
Normal file
106
qa/qa/specs/features/project/import_from_github_spec.rb
Normal file
|
@ -0,0 +1,106 @@
|
|||
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
|
|
@ -76,4 +76,27 @@ describe QA::Runtime::Env do
|
|||
expect { described_class.user_type }.to raise_error(ArgumentError)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.github_access_token' do
|
||||
it 'returns "" if GITHUB_ACCESS_TOKEN is not defined' do
|
||||
expect(described_class.github_access_token).to eq('')
|
||||
end
|
||||
|
||||
it 'returns stripped string if GITHUB_ACCESS_TOKEN is defined' do
|
||||
stub_env('GITHUB_ACCESS_TOKEN', ' abc123 ')
|
||||
expect(described_class.github_access_token).to eq('abc123')
|
||||
end
|
||||
end
|
||||
|
||||
describe '.require_github_access_token!' do
|
||||
it 'raises ArgumentError if GITHUB_ACCESS_TOKEN is not defined' do
|
||||
expect { described_class.require_github_access_token! }.to raise_error(ArgumentError)
|
||||
end
|
||||
|
||||
it 'does not raise if GITHUB_ACCESS_TOKEN is defined' do
|
||||
stub_env('GITHUB_ACCESS_TOKEN', ' abc123 ')
|
||||
|
||||
expect { described_class.require_github_access_token! }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue