Commit 1fbcd765 authored by Rémy Coutable's avatar Rémy Coutable

[EE] Improve QA scenarios contexts & descriptions consistency

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent c435f10a
...@@ -31,7 +31,7 @@ module QA ...@@ -31,7 +31,7 @@ module QA
if rspec_options.any? if rspec_options.any?
rspec_options rspec_options
else else
['--tag', self.class.focus.join(','), '--', ::File.expand_path('../../specs/features', __dir__)] ['--', ::File.expand_path('../../specs/features', __dir__)]
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'API users' do context :manage do
before(:context) do describe 'Users API' do
@api_client = Runtime::API::Client.new(:gitlab) before(:context) do
end @api_client = Runtime::API::Client.new(:gitlab)
end
context 'when authenticated' do
let(:request) { Runtime::API::Request.new(@api_client, '/users') } let(:request) { Runtime::API::Request.new(@api_client, '/users') }
it 'get list of users' do it 'GET /users' do
get request.url get request.url
expect_status(200) expect_status(200)
end end
it 'submit request with a valid user name' do it 'GET /users/:username with a valid username' do
get request.url, { params: { username: Runtime::User.username } } get request.url, { params: { username: Runtime::User.username } }
expect_status(200) expect_status(200)
...@@ -22,20 +24,12 @@ module QA ...@@ -22,20 +24,12 @@ module QA
) )
end end
it 'submit request with an invalid user name' do it 'GET /users/:username with an invalid username' do
get request.url, { params: { username: SecureRandom.hex(10) } } get request.url, { params: { username: SecureRandom.hex(10) } }
expect_status(200) expect_status(200)
expect(json_body).to eq([]) expect(json_body).to eq([])
end end
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
end end
# frozen_string_literal: true
module QA module QA
describe 'Geo Nodes API' do context :geo, :orchestrated, :geo do
before(:all) do describe 'Geo Nodes API' do
get_personal_access_token before(:all) do
end get_personal_access_token
end
shared_examples 'retrieving configuration about Geo nodes' do shared_examples 'retrieving configuration about Geo nodes' do
it 'GET /geo_nodes' do it 'GET /geo_nodes' do
get api_endpoint('/geo_nodes') get api_endpoint('/geo_nodes')
expect_status(200) expect_status(200)
expect(json_body.size).to be >= 2 expect(json_body.size).to be >= 2
expect_json('?', primary: true) expect_json('?', primary: true)
expect_json_types('*', primary: :boolean, current: :boolean, expect_json_types('*', primary: :boolean, current: :boolean,
files_max_capacity: :integer, repos_max_capacity: :integer, files_max_capacity: :integer, repos_max_capacity: :integer,
clone_protocol: :string, _links: :object) clone_protocol: :string, _links: :object)
end end
it 'GET /geo_nodes/:id' do it 'GET /geo_nodes/:id' do
get api_endpoint("/geo_nodes/#{geo_node[:id]}") get api_endpoint("/geo_nodes/#{geo_node[:id]}")
expect_status(200) expect_status(200)
expect(json_body).to eq geo_node expect(json_body).to eq geo_node
end
end end
end
shared_examples 'retrieving status about all Geo nodes' do shared_examples 'retrieving status about all Geo nodes' do
it 'GET /geo_nodes/status' do it 'GET /geo_nodes/status' do
get api_endpoint('/geo_nodes/status') get api_endpoint('/geo_nodes/status')
expect_status(200) expect_status(200)
expect(json_body.size).to be >= 2 expect(json_body.size).to be >= 2
# only need to check that some of the key values are there # only need to check that some of the key values are there
expect_json_types('*', health: :string, expect_json_types('*', health: :string,
attachments_count: :integer, attachments_count: :integer,
db_replication_lag_seconds: :integer_or_null, db_replication_lag_seconds: :integer_or_null,
lfs_objects_count: :integer, lfs_objects_count: :integer,
job_artifacts_count: :integer, job_artifacts_count: :integer,
projects_count: :integer, projects_count: :integer,
repositories_count: :integer, repositories_count: :integer,
wikis_count: :integer, wikis_count: :integer,
replication_slots_count: :integer_or_null, replication_slots_count: :integer_or_null,
version: :string_or_null) version: :string_or_null)
end
end end
end
shared_examples 'retrieving status about a specific Geo node' do shared_examples 'retrieving status about a specific Geo node' do
it 'GET /geo_nodes/:id/status of primary node' do it 'GET /geo_nodes/:id/status of primary node' do
get api_endpoint("/geo_nodes/#{@primary_node[:id]}/status") get api_endpoint("/geo_nodes/#{@primary_node[:id]}/status")
expect_status(200) expect_status(200)
expect_json(geo_node_id: @primary_node[:id]) expect_json(geo_node_id: @primary_node[:id])
end end
it 'GET /geo_nodes/:id/status of secondary node' do it 'GET /geo_nodes/:id/status of secondary node' do
get api_endpoint("/geo_nodes/#{@secondary_node[:id]}/status") get api_endpoint("/geo_nodes/#{@secondary_node[:id]}/status")
expect_status(200) expect_status(200)
expect_json(geo_node_id: @secondary_node[:id]) expect_json(geo_node_id: @secondary_node[:id])
end end
it 'GET /geo_nodes/:id/status of an invalid node' do it 'GET /geo_nodes/:id/status of an invalid node' do
get api_endpoint("/geo_nodes/1000/status") get api_endpoint("/geo_nodes/1000/status")
expect_status(404) expect_status(404)
end
end end
end
shared_examples 'retrieving project sync failures ocurred on the current node' do shared_examples 'retrieving project sync failures ocurred on the current node' do
it 'GET /geo_nodes/current/failures' do it 'GET /geo_nodes/current/failures' do
get api_endpoint("/geo_nodes/current/failures") get api_endpoint("/geo_nodes/current/failures")
expect_status(200) expect_status(200)
expect(json_body).to be_an Array expect(json_body).to be_an Array
end
end end
end
describe 'Geo Nodes API on primary node', :geo do describe 'Geo Nodes API on primary node', :geo do
before(:context) do before(:context) do
fetch_nodes(:geo_primary) fetch_nodes(:geo_primary)
end end
include_examples 'retrieving configuration about Geo nodes' do include_examples 'retrieving configuration about Geo nodes' do
let(:geo_node) { @primary_node } let(:geo_node) { @primary_node }
end end
include_examples 'retrieving status about all Geo nodes' include_examples 'retrieving status about all Geo nodes'
include_examples 'retrieving status about a specific Geo node' include_examples 'retrieving status about a specific Geo node'
describe 'editing a Geo node' do describe 'editing a Geo node' do
it 'PUT /geo_nodes/:id for primary node' do it 'PUT /geo_nodes/:id for primary node' do
put api_endpoint("/geo_nodes/#{@primary_node[:id]}"), put api_endpoint("/geo_nodes/#{@primary_node[:id]}"),
{ params: { files_max_capacity: 1000 } } { params: { files_max_capacity: 1000 } }
expect_status(403) expect_status(403)
end end
it 'PUT /geo_nodes/:id for secondary node' do it 'PUT /geo_nodes/:id for secondary node' do
endpoint = api_endpoint("/geo_nodes/#{@secondary_node[:id]}") endpoint = api_endpoint("/geo_nodes/#{@secondary_node[:id]}")
new_attributes = { enabled: false, files_max_capacity: 1000, repos_max_capacity: 2000 } new_attributes = { enabled: false, files_max_capacity: 1000, repos_max_capacity: 2000 }
put endpoint, new_attributes put endpoint, new_attributes
expect_status(200) expect_status(200)
expect_json(new_attributes) expect_json(new_attributes)
# restore the original values # restore the original values
put endpoint, { enabled: @secondary_node[:enabled], put endpoint, { enabled: @secondary_node[:enabled],
files_max_capacity: @secondary_node[:files_max_capacity], files_max_capacity: @secondary_node[:files_max_capacity],
repos_max_capacity: @secondary_node[:repos_max_capacity] } repos_max_capacity: @secondary_node[:repos_max_capacity] }
expect_status(200) expect_status(200)
end end
it 'PUT /geo_nodes/:id for an invalid node' do it 'PUT /geo_nodes/:id for an invalid node' do
put api_endpoint("/geo_nodes/1000"), put api_endpoint("/geo_nodes/1000"),
{ params: { files_max_capacity: 1000 } } { params: { files_max_capacity: 1000 } }
expect_status(404) expect_status(404)
end
end end
end
describe 'repairing a Geo node' do describe 'repairing a Geo node' do
it 'POST /geo_nodes/:id/repair for primary node' do it 'POST /geo_nodes/:id/repair for primary node' do
post api_endpoint("/geo_nodes/#{@primary_node[:id]}/repair") post api_endpoint("/geo_nodes/#{@primary_node[:id]}/repair")
expect_status(200) expect_status(200)
expect_json(geo_node_id: @primary_node[:id]) expect_json(geo_node_id: @primary_node[:id])
end end
it 'POST /geo_nodes/:id/repair for secondary node' do it 'POST /geo_nodes/:id/repair for secondary node' do
post api_endpoint("/geo_nodes/#{@secondary_node[:id]}/repair") post api_endpoint("/geo_nodes/#{@secondary_node[:id]}/repair")
expect_status(200) expect_status(200)
expect_json(geo_node_id: @secondary_node[:id]) expect_json(geo_node_id: @secondary_node[:id])
end end
it 'POST /geo_nodes/:id/repair for an invalid node' do it 'POST /geo_nodes/:id/repair for an invalid node' do
post api_endpoint("/geo_nodes/1000/repair") post api_endpoint("/geo_nodes/1000/repair")
expect_status(404) expect_status(404)
end
end end
end end
end
describe 'Geo Nodes API on secondary node', :geo do describe 'Geo Nodes API on secondary node', :geo do
before(:context) do before(:context) do
fetch_nodes(:geo_secondary) fetch_nodes(:geo_secondary)
end end
include_examples 'retrieving configuration about Geo nodes' do include_examples 'retrieving configuration about Geo nodes' do
let(:geo_node) { @nodes.first } let(:geo_node) { @nodes.first }
end end
include_examples 'retrieving status about all Geo nodes' include_examples 'retrieving status about all Geo nodes'
include_examples 'retrieving status about a specific Geo node' include_examples 'retrieving status about a specific Geo node'
include_examples 'retrieving project sync failures ocurred on the current node' include_examples 'retrieving project sync failures ocurred on the current node'
it 'GET /geo_nodes is not current' do it 'GET /geo_nodes is not current' do
get api_endpoint('/geo_nodes') get api_endpoint('/geo_nodes')
expect_status(200) expect_status(200)
expect_json('?', current: false) expect_json('?', current: false)
end end
describe 'editing a Geo node' do describe 'editing a Geo node' do
it 'PUT /geo_nodes/:id for primary node' do it 'PUT /geo_nodes/:id for primary node' do
put api_endpoint("/geo_nodes/#{@primary_node[:id]}"), put api_endpoint("/geo_nodes/#{@primary_node[:id]}"),
{ params: { files_max_capacity: 1000 } } { params: { files_max_capacity: 1000 } }
expect_status(403) expect_status(403)
end end
it 'PUT /geo_nodes/:id for secondary node' do it 'PUT /geo_nodes/:id for secondary node' do
put api_endpoint("/geo_nodes/#{@secondary_node[:id]}"), put api_endpoint("/geo_nodes/#{@secondary_node[:id]}"),
{ params: { files_max_capacity: 1000 } } { params: { files_max_capacity: 1000 } }
expect_status(403) expect_status(403)
end end
it 'PUT /geo_nodes/:id for an invalid node' do it 'PUT /geo_nodes/:id for an invalid node' do
put api_endpoint('/geo_nodes/1000'), put api_endpoint('/geo_nodes/1000'),
{ params: { files_max_capacity: 1000 } } { params: { files_max_capacity: 1000 } }
expect_status(403) expect_status(403)
end
end end
end
describe 'repairing a Geo node' do describe 'repairing a Geo node' do
it 'POST /geo_nodes/:id/repair for primary node' do it 'POST /geo_nodes/:id/repair for primary node' do
post api_endpoint("/geo_nodes/#{@primary_node[:id]}/repair") post api_endpoint("/geo_nodes/#{@primary_node[:id]}/repair")
expect_status(403) expect_status(403)
end end
it 'POST /geo_nodes/:id/repair for secondary node' do it 'POST /geo_nodes/:id/repair for secondary node' do
post api_endpoint("/geo_nodes/#{@secondary_node[:id]}/repair") post api_endpoint("/geo_nodes/#{@secondary_node[:id]}/repair")
expect_status(403) expect_status(403)
end end
it 'POST /geo_nodes/:id/repair for an invalid node' do it 'POST /geo_nodes/:id/repair for an invalid node' do
post api_endpoint('/geo_nodes/1000/repair') post api_endpoint('/geo_nodes/1000/repair')
expect_status(403) expect_status(403)
end
end end
end end
end
def api_endpoint(endpoint) def api_endpoint(endpoint)
QA::Runtime::API::Request.new(@api_client, endpoint).url QA::Runtime::API::Request.new(@api_client, endpoint).url
end end
def fetch_nodes(node_type) def fetch_nodes(node_type)
@api_client = Runtime::API::Client.new(node_type, personal_access_token: @personal_access_token) @api_client = Runtime::API::Client.new(node_type, personal_access_token: @personal_access_token)
get api_endpoint('/geo_nodes') get api_endpoint('/geo_nodes')
@nodes = json_body @nodes = json_body
@primary_node = @nodes.detect { |node| node[:primary] == true } @primary_node = @nodes.detect { |node| node[:primary] == true }
@secondary_node = @nodes.detect { |node| node[:primary] == false } @secondary_node = @nodes.detect { |node| node[:primary] == false }
end end
# go to the primary and create a personal_access_token, which will be used # go to the primary and create a personal_access_token, which will be used
# for accessing both the primary and secondary # for accessing both the primary and secondary
def get_personal_access_token def get_personal_access_token
api_client = Runtime::API::Client.new(:geo_primary) api_client = Runtime::API::Client.new(:geo_primary)
@personal_access_token = api_client.personal_access_token @personal_access_token = api_client.personal_access_token
end
end end
end end
end end
# frozen_string_literal: true
module QA module QA
describe 'LDAP user login', :orchestrated, :ldap do context :manage, :orchestrated, :ldap do
before do describe 'LDAP login' do
Runtime::Env.user_type = 'ldap' before do
end Runtime::Env.user_type = 'ldap'
end
it 'user logs in using LDAP credentials' do it 'user logs into GitLab using LDAP credentials' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
# TODO, since `Signed in successfully` message was removed # TODO, since `Signed in successfully` message was removed
# this is the only way to tell if user is signed in correctly. # this is the only way to tell if user is signed in correctly.
# #
Page::Menu::Main.perform do |menu| Page::Menu::Main.perform do |menu|
expect(menu).to have_personal_area expect(menu).to have_personal_area
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'logging in to Mattermost', :orchestrated, :mattermost do context :manage, :orchestrated, :mattermost do
it 'can use gitlab oauth' do describe 'Mattermost login' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) do it 'user logs into Mattermost using GitLab OAuth' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do
Page::Mattermost::Login.act { sign_in_using_oauth } Page::Mattermost::Login.act { sign_in_using_oauth }
Page::Mattermost::Main.perform do |page| Page::Mattermost::Main.perform do |page|
expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/)
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'create a new project', :smoke do context :manage, :smoke do
it 'user creates a new project' do describe 'Project creation' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user creates a new project' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
created_project = Factory::Resource::Project.fabricate! do |project| created_project = Factory::Resource::Project.fabricate! do |project|
project.name = 'awesome-project' project.name = 'awesome-project'
project.description = 'create awesome project test' project.description = 'create awesome project test'
end end
expect(created_project.name).to match /^awesome-project-\h{16}$/ expect(created_project.name).to match /^awesome-project-\h{16}$/
expect(page).to have_content( expect(page).to have_content(
/Project \S?awesome-project\S+ was successfully created/ /Project \S?awesome-project\S+ was successfully created/
) )
expect(page).to have_content('create awesome project test') expect(page).to have_content('create awesome project test')
expect(page).to have_content('The repository for this project is empty') expect(page).to have_content('The repository for this project is empty')
end
end end
end end
end end
# frozen_string_literal: true
module QA module QA
describe 'user imports a GitHub repo', :orchestrated, :github do context :manage, :orchestrated, :github do
let(:imported_project) do describe 'Project import from GitHub' do
Factory::Resource::ProjectImportedFromGithub.fabricate! do |project| let(:imported_project) do
project.name = 'imported-project' Factory::Resource::ProjectImportedFromGithub.fabricate! do |project|
project.personal_access_token = Runtime::Env.github_access_token project.name = 'imported-project'
project.github_repository_path = 'gitlab-qa/test-project' project.personal_access_token = Runtime::Env.github_access_token
project.github_repository_path = 'gitlab-qa/test-project'
end
end end
end
after do after do
# We need to delete the imported project because it's impossible to import # We need to delete the imported project because it's impossible to import
# the same GitHub project twice for a given user. # the same GitHub project twice for a given user.
api_client = Runtime::API::Client.new(:gitlab) 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_project_request = Runtime::API::Request.new(api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{imported_project.name}")}")
delete delete_project_request.url delete delete_project_request.url
expect_status(202) expect_status(202)
end end
it 'user imports a GitHub repo' do it 'user imports a GitHub repo' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
imported_project # import the project imported_project # import the project
Page::Menu::Main.act { go_to_projects } Page::Menu::Main.act { go_to_projects }
Page::Dashboard::Projects.perform do |dashboard| Page::Dashboard::Projects.perform do |dashboard|
dashboard.go_to_project(imported_project.name) dashboard.go_to_project(imported_project.name)
end end
Page::Project::Show.act { wait_for_import } Page::Project::Show.act { wait_for_import }
verify_repository_import verify_repository_import
verify_issues_import verify_issues_import
verify_merge_requests_import verify_merge_requests_import
verify_labels_import verify_labels_import
verify_milestones_import verify_milestones_import
verify_wiki_import verify_wiki_import
end end
def verify_repository_import 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('This test project is used for automated GitHub import by GitLab QA.')
expect(page).to have_content(imported_project.name) expect(page).to have_content(imported_project.name)
end end
def verify_issues_import def verify_issues_import
Page::Menu::Side.act { click_issues } Page::Menu::Side.act { click_issues }
expect(page).to have_content('This is a sample issue') expect(page).to have_content('This is a sample issue')
click_link '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.') expect(page).to have_content('We should populate this project with issues, pull requests and wiki pages.')
# Comments # Comments
expect(page).to have_content('This is a comment from @rymai.') expect(page).to have_content('This is a comment from @rymai.')
Page::Issuable::Sidebar.perform do |issuable| Page::Issuable::Sidebar.perform do |issuable|
expect(issuable).to have_label('enhancement') expect(issuable).to have_label('enhancement')
expect(issuable).to have_label('help wanted') expect(issuable).to have_label('help wanted')
expect(issuable).to have_label('good first issue') expect(issuable).to have_label('good first issue')
end
end end
end
def verify_merge_requests_import def verify_merge_requests_import
Page::Menu::Side.act { click_merge_requests } Page::Menu::Side.act { click_merge_requests }
expect(page).to have_content('Improve README.md') expect(page).to have_content('Improve README.md')
click_link 'Improve README.md' click_link 'Improve README.md'
expect(page).to have_content('This improves the README file a bit.') expect(page).to have_content('This improves the README file a bit.')
# Review comment are not supported yet # Review comment are not supported yet
expect(page).not_to have_content('Really nice change.') expect(page).not_to have_content('Really nice change.')
# Comments # Comments
expect(page).to have_content('Nice work! This is a comment from @rymai.') expect(page).to have_content('Nice work! This is a comment from @rymai.')
# Diff comments # Diff comments
expect(page).to have_content('[Review comment] I like that!') 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('[Review comment] Nice blank line.')
expect(page).to have_content('[Single diff comment] Much better without this line!') expect(page).to have_content('[Single diff comment] Much better without this line!')
Page::Issuable::Sidebar.perform do |issuable| Page::Issuable::Sidebar.perform do |issuable|
expect(issuable).to have_label('bug') expect(issuable).to have_label('bug')
expect(issuable).to have_label('enhancement') expect(issuable).to have_label('enhancement')
end
end end
end
def verify_labels_import def verify_labels_import
# TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228 # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/19228
# to build upon it. # to build upon it.
end end
def verify_milestones_import def verify_milestones_import
# TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727 # TODO: Waiting on https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/18727
# to build upon it. # to build upon it.
end end
def verify_wiki_import def verify_wiki_import
Page::Menu::Side.act { click_wiki } Page::Menu::Side.act { click_wiki }
expect(page).to have_content('Welcome to the test-project wiki!') expect(page).to have_content('Welcome to the test-project wiki!')
end
end end
end end
end end
# frozen_string_literal: true
module QA module QA
describe 'activity page' do context :manage do
it 'push creates an event in the activity page' do describe 'Project activity' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user creates an event in the activity page upon Git push' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
Factory::Repository::ProjectPush.fabricate! do |push| Factory::Repository::ProjectPush.fabricate! do |push|
push.file_name = 'README.md' push.file_name = 'README.md'
push.file_content = '# This is a test project' push.file_content = '# This is a test project'
push.commit_message = 'Add README.md' push.commit_message = 'Add README.md'
end end
Page::Menu::Side.act { go_to_activity } Page::Menu::Side.act { go_to_activity }
Page::Project::Activity.act { go_to_push_events } Page::Project::Activity.act { go_to_push_events }
expect(page).to have_content('pushed new branch master') expect(page).to have_content('pushed new branch master')
end
end end
end end
end end
# frozen_string_literal: true
module QA module QA
describe 'creates issue', :smoke do context :plan, :smoke do
let(:issue_title) { 'issue title' } describe 'Issue creation' do
let(:issue_title) { 'issue title' }
it 'user creates issue' do it 'user creates an issue' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Factory::Resource::Issue.fabricate! do |issue| Factory::Resource::Issue.fabricate! do |issue|
issue.title = issue_title issue.title = issue_title
end end
Page::Menu::Side.act { click_issues } Page::Menu::Side.act { click_issues }
expect(page).to have_content(issue_title) expect(page).to have_content(issue_title)
end
end end
end end
end end
module QA # frozen_string_literal: true
describe 'creates a merge request with milestone' 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| module QA
expect(sidebar).to have_milestone(current_milestone.title) 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 end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'Project fork' do context :create do
it 'can submit merge requests to upstream master' do describe 'Merge request creation from fork' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user forks a project, submits a merge request and maintainer merges it' do
Page::Main::Login.act { sign_in_using_credentials } 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 = Factory::Resource::MergeRequestFromFork.fabricate! do |merge_request|
merge_request.fork_branch = 'feature-branch' merge_request.fork_branch = 'feature-branch'
end end
Page::Menu::Main.perform { |main| main.sign_out } Page::Menu::Main.perform { |main| main.sign_out }
Page::Main::Login.perform { |login| login.sign_in_using_credentials } Page::Main::Login.perform { |login| login.sign_in_using_credentials }
merge_request.visit! merge_request.visit!
Page::MergeRequest::Show.perform { |show| show.merge! } Page::MergeRequest::Show.perform { |show| show.merge! }
expect(page).to have_content('The changes were merged') expect(page).to have_content('The changes were merged')
end
end end
end end
end end
module QA # frozen_string_literal: true
describe 'merge request rebase' 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| module QA
push.project = project context :create do
push.file_name = "other.txt" describe 'Merge request rebasing' do
push.file_content = "New file added!" it 'user rebases source branch of merge request' do
push.branch_name = "master" Runtime::Browser.visit(:gitlab, Page::Main::Login)
push.new_branch = false Page::Main::Login.act { sign_in_using_credentials }
end
project = Factory::Resource::Project.fabricate! do |project|
merge_request.visit! project.name = "only-fast-forward"
end
Page::MergeRequest::Show.perform do |merge_request|
expect(merge_request).to have_content('Needs rebasing') Page::Menu::Side.act { go_to_settings }
expect(merge_request).not_to be_fast_forward_possible Page::Project::Settings::MergeRequest.act { enable_ff_only }
expect(merge_request).not_to have_merge_button
merge_request = Factory::Resource::MergeRequest.fabricate! do |merge_request|
merge_request.rebase! merge_request.project = project
merge_request.title = 'Needs rebasing'
expect(merge_request).to have_merge_button end
expect(merge_request.fast_forward_possible?).to be_truthy
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
end end
......
module QA # frozen_string_literal: true
describe 'merge request squash commits' 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| module QA
project.name = "squash-before-merge" context :create do
end 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 = Factory::Resource::MergeRequest.fabricate! do |merge_request|
merge_request.project = project merge_request.project = project
merge_request.title = 'Squashing commits' merge_request.title = 'Squashing commits'
end end
Factory::Repository::ProjectPush.fabricate! do |push| Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project push.project = project
push.commit_message = 'to be squashed' push.commit_message = 'to be squashed'
push.branch_name = merge_request.source_branch push.branch_name = merge_request.source_branch
push.new_branch = false push.new_branch = false
push.file_name = 'other.txt' push.file_name = 'other.txt'
push.file_content = "Test with unicode characters ❤✓€❄" push.file_content = "Test with unicode characters ❤✓€❄"
end end
merge_request.visit! merge_request.visit!
expect(page).to have_text('to be squashed') expect(page).to have_text('to be squashed')
Page::MergeRequest::Show.perform do |merge_request_page| Page::MergeRequest::Show.perform do |merge_request_page|
merge_request_page.mark_to_squash merge_request_page.mark_to_squash
merge_request_page.merge! merge_request_page.merge!
merge_request.project.visit! merge_request.project.visit!
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.uri = Page::Project::Show.act do repository.uri = Page::Project::Show.act do
choose_repository_clone_http choose_repository_clone_http
repository_location.uri repository_location.uri
end end
repository.use_default_credentials repository.use_default_credentials
repository.act { clone } repository.act { clone }
expect(repository.commits.size).to eq 3 expect(repository.commits.size).to eq 3
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'clone code from the repository' do context :create do
context 'with regular account over http' do describe 'Git clone over HTTP' do
let(:location) do let(:location) do
Page::Project::Show.act do Page::Project::Show.act do
choose_repository_clone_http choose_repository_clone_http
......
module QA # frozen_string_literal: true
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 module QA
updated_file_content = 'QA Test - Updated file content' context :create do
commit_message_for_update = 'QA Test - Update file' describe 'Files management' do
it 'user creates, edits and deletes a file via the Web' do
Page::File::Show.act { click_edit } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
Page::File::Form.act do
remove_content # Create
add_content(updated_file_content) file_name = 'QA Test - File name'
add_commit_message(commit_message_for_update) file_content = 'QA Test - File content'
commit_changes commit_message_for_create = 'QA Test - Create new file'
end
Factory::Resource::File.fabricate! do |file|
expect(page).to have_content('Your changes have been successfully committed.') file.name = file_name
expect(page).to have_content(updated_file_content) file.content = file_content
expect(page).to have_content(commit_message_for_update) file.commit_message = commit_message_for_create
end
# Delete
commit_message_for_delete = 'QA Test - Delete file' expect(page).to have_content('The file has been successfully created.')
expect(page).to have_content(file_name)
Page::File::Show.act do expect(page).to have_content(file_content)
click_delete expect(page).to have_content(commit_message_for_create)
add_commit_message(commit_message_for_delete)
click_delete_file # 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
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
end end
# frozen_string_literal: true
module QA module QA
describe 'push code to repository' do context :create do
context 'with regular account over http' do describe 'Git push over HTTP' do
it 'user pushes code to the repository' do it 'user pushes code to the repository' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
......
# frozen_string_literal: true
module QA module QA
describe 'branch protection support' do context :create do
let(:branch_name) { 'protected-branch' } describe 'Protected branch support' do
let(:commit_message) { 'Protected push commit message' } let(:branch_name) { 'protected-branch' }
let(:project) do let(:commit_message) { 'Protected push commit message' }
Factory::Resource::Project.fabricate! do |resource| let(:project) do
resource.name = 'protected-branch-project' Factory::Resource::Project.fabricate! do |resource|
resource.name = 'protected-branch-project'
end
end end
end
before do before do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
end end
after do after do
# We need to clear localStorage because we're using it for the dropdown, # We need to clear localStorage because we're using it for the dropdown,
# and capybara doesn't do this for us. # and capybara doesn't do this for us.
# https://github.com/teamcapybara/capybara/issues/1702 # https://github.com/teamcapybara/capybara/issues/1702
Capybara.execute_script 'localStorage.clear()' Capybara.execute_script 'localStorage.clear()'
end end
context 'when developers and maintainers are allowed to push to a protected branch' do 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 it 'user with push rights successfully pushes to the protected branch' do
create_protected_branch(allow_to_push: true) create_protected_branch(allow_to_push: true)
push = push_new_file(branch_name) push = push_new_file(branch_name)
expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/) expect(push.output).to match(/remote: To create a merge request for protected-branch, visit/)
end
end end
end
context 'when developers and maintainers are not allowed to push to a protected branch' do 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 it 'user without push rights fails to push to the protected branch' do
create_protected_branch(allow_to_push: false) create_protected_branch(allow_to_push: false)
push = push_new_file(branch_name) push = push_new_file(branch_name)
expect(push.output) expect(push.output)
.to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/) .to match(/remote\: GitLab\: You are not allowed to push code to protected branches on this project/)
expect(push.output) expect(push.output)
.to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/) .to match(/\[remote rejected\] #{branch_name} -> #{branch_name} \(pre-receive hook declined\)/)
end
end end
end
def create_protected_branch(allow_to_push:) def create_protected_branch(allow_to_push:)
Factory::Resource::Branch.fabricate! do |resource| Factory::Resource::Branch.fabricate! do |resource|
resource.branch_name = branch_name resource.branch_name = branch_name
resource.project = project resource.project = project
resource.allow_to_push = allow_to_push resource.allow_to_push = allow_to_push
resource.protected = true resource.protected = true
end
end end
end
def push_new_file(branch) def push_new_file(branch)
Factory::Repository::ProjectPush.fabricate! do |resource| Factory::Repository::ProjectPush.fabricate! do |resource|
resource.project = project resource.project = project
resource.file_name = 'new_file.md' resource.file_name = 'new_file.md'
resource.file_content = '# This is a new file' resource.file_content = '# This is a new file'
resource.commit_message = 'Add new_file.md' resource.commit_message = 'Add new_file.md'
resource.branch_name = branch_name resource.branch_name = branch_name
resource.new_branch = false resource.new_branch = false
end
end end
end end
end end
......
module QA # frozen_string_literal: true
describe 'Wiki Functionality' do
def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
end
def validate_content(content) module QA
expect(page).to have_content('Wiki was successfully updated') context :create do
expect(page).to have_content(/#{content}/) describe 'Wiki management' do
end def login
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
end
before do def validate_content(content)
login expect(page).to have_content('Wiki was successfully updated')
end expect(page).to have_content(/#{content}/)
end
it 'User creates, edits, clones, and pushes to the wiki' do before do
wiki = Factory::Resource::Wiki.fabricate! do |resource| login
resource.title = 'Home'
resource.content = '# My First Wiki Content'
resource.message = 'Update home'
end end
validate_content('My First Wiki Content') 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
Page::Project::Wiki::Edit.act { go_to_edit_page } validate_content('My First Wiki Content')
Page::Project::Wiki::New.perform do |page|
page.set_content("My Second Wiki Content")
page.save_changes
end
validate_content('My Second 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
Factory::Repository::WikiPush.fabricate! do |push| validate_content('My Second Wiki Content')
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') 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 end
end end
module QA # frozen_string_literal: true
describe 'CI/CD Pipelines', :orchestrated, :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 module QA
Runtime::Browser.visit(:gitlab, Page::Main::Login) context :verify, :docker do
Page::Main::Login.act { sign_in_using_credentials } describe 'Pipeline creation and processing' do
let(:executor) { "qa-runner-#{Time.now.to_i}" }
Factory::Resource::Runner.fabricate! do |runner| after do
runner.name = executor Service::Runner.new(executor).remove!
end end
Page::Project::Settings::CICD.perform do |settings| it 'users creates a pipeline which gets processed' do
sleep 5 # Runner should register within 5 seconds Runtime::Browser.visit(:gitlab, Page::Main::Login)
settings.refresh Page::Main::Login.act { sign_in_using_credentials }
settings.expand_runners_settings do |page| project = Factory::Resource::Project.fabricate! do |project|
expect(page).to have_content(executor) project.name = 'project-with-pipelines'
expect(page).to have_online_runner project.description = 'Project with CI/CD Pipelines.'
end 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| Factory::Resource::Runner.fabricate! do |runner|
project.name = 'project-with-pipelines' runner.project = project
project.description = 'Project with CI/CD Pipelines.' runner.name = executor
end runner.tags = %w[qa test]
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| Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project push.project = project
push.file_name = '.gitlab-ci.yml' push.file_name = '.gitlab-ci.yml'
push.commit_message = 'Add .gitlab-ci.yml' push.commit_message = 'Add .gitlab-ci.yml'
push.file_content = <<~EOF push.file_content = <<~EOF
test-success: test-success:
tags: tags:
- qa - qa
- test - test
script: echo 'OK' script: echo 'OK'
test-failure: test-failure:
tags: tags:
- qa - qa
- test - test
script: script:
- echo 'FAILURE' - echo 'FAILURE'
- exit 1 - exit 1
test-tags: test-tags:
tags: tags:
- qa - qa
- docker - docker
script: echo 'NOOP' script: echo 'NOOP'
test-artifacts: test-artifacts:
tags: tags:
- qa - qa
- test - test
script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt script: mkdir my-artifacts; echo "CONTENTS" > my-artifacts/artifact.txt
artifacts: artifacts:
paths: paths:
- my-artifacts/ - my-artifacts/
EOF EOF
end end
Page::Project::Show.act { wait_for_push } Page::Project::Show.act { wait_for_push }
expect(page).to have_content('Add .gitlab-ci.yml') expect(page).to have_content('Add .gitlab-ci.yml')
Page::Menu::Side.act { click_ci_cd_pipelines } Page::Menu::Side.act { click_ci_cd_pipelines }
expect(page).to have_content('All 1') expect(page).to have_content('All 1')
expect(page).to have_content('Add .gitlab-ci.yml') expect(page).to have_content('Add .gitlab-ci.yml')
puts 'Waiting for the runner to process the pipeline' puts 'Waiting for the runner to process the pipeline'
sleep 15 # Runner should process all jobs within 15 seconds. sleep 15 # Runner should process all jobs within 15 seconds.
Page::Project::Pipeline::Index.act { go_to_latest_pipeline } Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
Page::Project::Pipeline::Show.perform do |pipeline| Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to be_running expect(pipeline).to be_running
expect(pipeline).to have_build('test-success', status: :success) expect(pipeline).to have_build('test-success', status: :success)
expect(pipeline).to have_build('test-failure', status: :failed) expect(pipeline).to have_build('test-failure', status: :failed)
expect(pipeline).to have_build('test-tags', status: :pending) expect(pipeline).to have_build('test-tags', status: :pending)
expect(pipeline).to have_build('test-artifacts', status: :success) expect(pipeline).to have_build('test-artifacts', status: :success)
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'secret variables support' do context :verify do
it 'user adds a secret variable' do describe 'Secret variable support' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user adds a secret variable' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
Factory::Resource::SecretVariable.fabricate! do |resource| Factory::Resource::SecretVariable.fabricate! do |resource|
resource.key = 'VARIABLE_KEY' resource.key = 'VARIABLE_KEY'
resource.value = 'some secret variable' resource.value = 'some secret variable'
end end
Page::Project::Settings::CICD.perform do |settings| Page::Project::Settings::CICD.perform do |settings|
settings.expand_secret_variables do |page| settings.expand_secret_variables do |page|
expect(page).to have_field(with: 'VARIABLE_KEY') expect(page).to have_field(with: 'VARIABLE_KEY')
expect(page).not_to have_field(with: 'some secret variable') expect(page).not_to have_field(with: 'some secret variable')
page.reveal_variables page.reveal_variables
expect(page).to have_field(with: 'some secret variable') expect(page).to have_field(with: 'some secret variable')
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'deploy keys support' do context :release do
it 'user adds a deploy key' do describe 'Deploy key creation' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user adds a deploy key' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
key = Runtime::Key::RSA.new key = Runtime::Key::RSA.new
deploy_key_title = 'deploy key title' deploy_key_title = 'deploy key title'
deploy_key_value = key.public_key deploy_key_value = key.public_key
deploy_key = Factory::Resource::DeployKey.fabricate! do |resource| deploy_key = Factory::Resource::DeployKey.fabricate! do |resource|
resource.title = deploy_key_title resource.title = deploy_key_title
resource.key = deploy_key_value resource.key = deploy_key_value
end end
expect(deploy_key.fingerprint).to eq(key.fingerprint) expect(deploy_key.fingerprint).to eq(key.fingerprint)
end
end end
end end
end end
# frozen_string_literal: true
require 'digest/sha1' require 'digest/sha1'
module QA module QA
describe 'cloning code using a deploy key', :docker do context :release, :docker do
def login describe 'Git clone using a deploy key' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) def login
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
end Page::Main::Login.act { sign_in_using_credentials }
end
before(:all) do before(:all) do
login login
@runner_name = "qa-runner-#{Time.now.to_i}" @runner_name = "qa-runner-#{Time.now.to_i}"
@project = Factory::Resource::Project.fabricate! do |resource| @project = Factory::Resource::Project.fabricate! do |resource|
resource.name = 'deploy-key-clone-project' resource.name = 'deploy-key-clone-project'
end end
@repository_location = @project.repository_ssh_location @repository_location = @project.repository_ssh_location
Factory::Resource::Runner.fabricate! do |resource| Factory::Resource::Runner.fabricate! do |resource|
resource.project = @project resource.project = @project
resource.name = @runner_name resource.name = @runner_name
resource.tags = %w[qa docker] resource.tags = %w[qa docker]
resource.image = 'gitlab/gitlab-runner:ubuntu' resource.image = 'gitlab/gitlab-runner:ubuntu'
end
Page::Menu::Main.act { sign_out }
end end
Page::Menu::Main.act { sign_out } after(:all) do
end Service::Runner.new(@runner_name).remove!
end
after(:all) do keys = [
Service::Runner.new(@runner_name).remove! [Runtime::Key::RSA, 8192],
end [Runtime::Key::ECDSA, 521],
[Runtime::Key::ED25519]
]
keys = [ keys.each do |(key_class, bits)|
[Runtime::Key::RSA, 8192], it "user sets up a deploy key with #{key_class}(#{bits}) to clone code using pipelines" do
[Runtime::Key::ECDSA, 521], key = key_class.new(*bits)
[Runtime::Key::ED25519]
]
keys.each do |(key_class, bits)| login
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
Factory::Resource::DeployKey.fabricate! do |resource| deploy_key_name = "DEPLOY_KEY_#{key.name}_#{key.bits}"
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
Factory::Resource::SecretVariable.fabricate! do |resource| gitlab_ci = <<~YAML
resource.project = @project cat-config:
resource.key = deploy_key_name script:
resource.value = key.private_key - mkdir -p ~/.ssh
end - 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
gitlab_ci = <<~YAML sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
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::Show.act { wait_for_push } Page::Project::Job::Show.perform do |job|
Page::Menu::Side.act { click_ci_cd_pipelines } job.wait(reload: false) do
Page::Project::Pipeline::Index.act { go_to_latest_pipeline } job.completed? && !job.trace_loading?
Page::Project::Pipeline::Show.act { go_to_first_job } end
Page::Project::Job::Show.perform do |job| expect(job.passed?).to be_truthy, "Job status did not become \"passed\"."
job.wait(reload: false) do expect(job.output).to include(sha1sum)
job.completed? && !job.trace_loading?
end 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
......
# frozen_string_literal: true
require 'pathname' require 'pathname'
module QA module QA
describe 'Auto Devops', :orchestrated, :kubernetes do context :configure, :orchestrated, :kubernetes do
after do describe 'Auto DevOps support' do
@cluster&.remove! after do
end @cluster&.remove!
end
it 'user creates a new project and runs auto devops' do it 'user creates a new project and runs auto devops' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |p| project = Factory::Resource::Project.fabricate! do |p|
p.name = 'project-with-autodevops' p.name = 'project-with-autodevops'
p.description = 'Project with Auto Devops' p.description = 'Project with Auto Devops'
end end
# Disable code_quality check in Auto DevOps pipeline as it takes # Disable code_quality check in Auto DevOps pipeline as it takes
# too long and times out the test # too long and times out the test
Factory::Resource::SecretVariable.fabricate! do |resource| Factory::Resource::SecretVariable.fabricate! do |resource|
resource.key = 'CODE_QUALITY_DISABLED' resource.key = 'CODE_QUALITY_DISABLED'
resource.value = '1' resource.value = '1'
end end
# Create Auto Devops compatible repo # Create Auto Devops compatible repo
Factory::Repository::ProjectPush.fabricate! do |push| Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project push.project = project
push.directory = Pathname push.directory = Pathname
.new(__dir__) .new(__dir__)
.join('../../../fixtures/auto_devops_rack') .join('../../../fixtures/auto_devops_rack')
push.commit_message = 'Create Auto DevOps compatible rack application' push.commit_message = 'Create Auto DevOps compatible rack application'
end end
Page::Project::Show.act { wait_for_push } Page::Project::Show.act { wait_for_push }
# Create and connect K8s cluster # Create and connect K8s cluster
@cluster = Service::KubernetesCluster.new.create! @cluster = Service::KubernetesCluster.new.create!
kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster| kubernetes_cluster = Factory::Resource::KubernetesCluster.fabricate! do |cluster|
cluster.project = project cluster.project = project
cluster.cluster = @cluster cluster.cluster = @cluster
cluster.install_helm_tiller = true cluster.install_helm_tiller = true
cluster.install_ingress = true cluster.install_ingress = true
cluster.install_prometheus = true cluster.install_prometheus = true
cluster.install_runner = true cluster.install_runner = true
end end
project.visit! project.visit!
Page::Menu::Side.act { click_ci_cd_settings } Page::Menu::Side.act { click_ci_cd_settings }
Page::Project::Settings::CICD.perform do |p| Page::Project::Settings::CICD.perform do |p|
p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io") p.enable_auto_devops_with_domain("#{kubernetes_cluster.ingress_ip}.nip.io")
end end
project.visit! project.visit!
Page::Menu::Side.act { click_ci_cd_pipelines } Page::Menu::Side.act { click_ci_cd_pipelines }
Page::Project::Pipeline::Index.act { go_to_latest_pipeline } Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
Page::Project::Pipeline::Show.perform do |pipeline| Page::Project::Pipeline::Show.perform do |pipeline|
expect(pipeline).to have_build('build', status: :success, wait: 600) 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('test', status: :success, wait: 600)
expect(pipeline).to have_build('production', status: :success, wait: 1200) expect(pipeline).to have_build('production', status: :success, wait: 1200)
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'create a new group', :orchestrated, :mattermost do context :configure, :orchestrated, :mattermost do
it 'creating a group with a mattermost team' do describe 'Mattermost support' do
Runtime::Browser.visit(:gitlab, Page::Main::Login) it 'user creates a group with a mattermost team' do
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Menu::Main.act { go_to_groups } Page::Main::Login.act { sign_in_using_credentials }
Page::Menu::Main.act { go_to_groups }
Page::Dashboard::Groups.perform do |page| Page::Dashboard::Groups.perform do |page|
page.go_to_new_group page.go_to_new_group
expect(page).to have_content( expect(page).to have_content(
/Create a Mattermost team for this group/ /Create a Mattermost team for this group/
) )
end
end end
end end
end end
......
module QA # frozen_string_literal: true
describe 'GitLab Geo attachment replication', :geo do
let(:file_to_attach) { File.absolute_path(File.join('spec', 'fixtures', 'banana_sample.gif')) }
it 'user uploads attachment to the primary node' do
Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project| module QA
project.name = 'project-for-issues' context :geo, :orchestrated, :geo do
project.description = 'project for adding issues' describe 'GitLab Geo attachment replication' do
end let(:file_to_attach) { File.absolute_path(File.join('spec', 'fixtures', 'banana_sample.gif')) }
issue = Factory::Resource::Issue.fabricate! do |issue| it 'user uploads attachment to the primary node' do
issue.title = 'My geo issue' Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
issue.project = project Page::Main::Login.act { sign_in_using_credentials }
end
Page::Project::Issue::Show.perform do |show| project = Factory::Resource::Project.fabricate! do |project|
show.comment('See attached banana for scale', attachment: file_to_attach) project.name = 'project-for-issues'
end project.description = 'project for adding issues'
end
Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do |session| issue = Factory::Resource::Issue.fabricate! do |issue|
Page::Main::OAuth.act do issue.title = 'My geo issue'
authorize! if needs_authorization? issue.project = project
end end
EE::Page::Main::Banner.perform do |banner| Page::Project::Issue::Show.perform do |show|
expect(banner).to have_secondary_read_only_banner show.comment('See attached banana for scale', attachment: file_to_attach)
end end
expect(page).to have_content 'You are on a secondary, read-only Geo node' Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do |session|
Page::Main::OAuth.act do
authorize! if needs_authorization?
end
Page::Menu::Main.perform do |menu| EE::Page::Main::Banner.perform do |banner|
menu.go_to_projects expect(banner).to have_secondary_read_only_banner
end end
Page::Dashboard::Projects.perform do |dashboard| expect(page).to have_content 'You are on a secondary, read-only Geo node'
dashboard.wait_for_project_replication(project.name)
dashboard.go_to_project(project.name) Page::Menu::Main.perform do |menu|
end menu.go_to_projects
end
Page::Menu::Side.act { click_issues } Page::Dashboard::Projects.perform do |dashboard|
dashboard.wait_for_project_replication(project.name)
Page::Project::Issue::Index.perform do |index| dashboard.go_to_project(project.name)
index.wait_for_issue_replication(issue) end
end
image_url = find('a[href$="banana_sample.gif"]')[:href] Page::Menu::Side.act { click_issues }
Page::Project::Issue::Show.perform do |show| Page::Project::Issue::Index.perform do |index|
# Wait for attachment replication index.wait_for_issue_replication(issue)
found = show.wait(reload: false) do
show.asset_exists?(image_url)
end end
expect(found).to be_truthy image_url = find('a[href$="banana_sample.gif"]')[:href]
Page::Project::Issue::Show.perform do |show|
# Wait for attachment replication
found = show.wait(reload: false) do
show.asset_exists?(image_url)
end
expect(found).to be_truthy
end
end end
end end
end end
......
# frozen_string_literal: true
module QA module QA
describe 'GitLab Geo project rename replication', :geo do context :geo, :orchestrated, :geo do
it 'user renames project' do describe 'GitLab Geo project rename replication' do
# create the project and push code it 'user renames project' do
Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do # create the project and push code
Page::Main::Login.act { sign_in_using_credentials } Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project| project = Factory::Resource::Project.fabricate! do |project|
project.name = 'geo-before-rename' project.name = 'geo-before-rename'
project.description = 'Geo project to be renamed' project.description = 'Geo project to be renamed'
end end
geo_project_name = project.name geo_project_name = project.name
expect(project.name).to include 'geo-before-rename' expect(project.name).to include 'geo-before-rename'
Factory::Repository::ProjectPush.fabricate! do |push| Factory::Repository::ProjectPush.fabricate! do |push|
push.project = project push.project = project
push.file_name = 'README.md' push.file_name = 'README.md'
push.file_content = '# This is Geo project!' push.file_content = '# This is Geo project!'
push.commit_message = 'Add README.md' push.commit_message = 'Add README.md'
end end
# rename the project # rename the project
Page::Menu::Main.act { go_to_projects } Page::Menu::Main.act { go_to_projects }
Page::Dashboard::Projects.perform do |dashboard| Page::Dashboard::Projects.perform do |dashboard|
dashboard.go_to_project(geo_project_name) dashboard.go_to_project(geo_project_name)
end end
Page::Menu::Side.act { go_to_settings } Page::Menu::Side.act { go_to_settings }
geo_project_renamed = "geo-after-rename-#{SecureRandom.hex(8)}" geo_project_renamed = "geo-after-rename-#{SecureRandom.hex(8)}"
Page::Project::Settings::Main.perform do |settings| Page::Project::Settings::Main.perform do |settings|
settings.expand_advanced_settings do |page| settings.expand_advanced_settings do |page|
page.rename_to(geo_project_renamed) page.rename_to(geo_project_renamed)
end
end end
end
# check renamed project exist on secondary node # check renamed project exist on secondary node
Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do
Page::Main::OAuth.act do Page::Main::OAuth.act do
authorize! if needs_authorization? authorize! if needs_authorization?
end end
EE::Page::Main::Banner.perform do |banner| EE::Page::Main::Banner.perform do |banner|
expect(banner).to have_secondary_read_only_banner expect(banner).to have_secondary_read_only_banner
end end
Page::Menu::Main.perform do |menu| Page::Menu::Main.perform do |menu|
menu.go_to_projects menu.go_to_projects
end end
Page::Dashboard::Projects.perform do |dashboard| Page::Dashboard::Projects.perform do |dashboard|
dashboard.wait_for_project_replication(geo_project_renamed) dashboard.wait_for_project_replication(geo_project_renamed)
dashboard.go_to_project(geo_project_renamed) dashboard.go_to_project(geo_project_renamed)
end end
Page::Project::Show.perform do |show| Page::Project::Show.perform do |show|
show.wait_for_repository_replication show.wait_for_repository_replication
expect(page).to have_content 'README.md' expect(page).to have_content 'README.md'
expect(page).to have_content 'This is Geo project!' expect(page).to have_content 'This is Geo project!'
end
end end
end end
end end
......
module QA # frozen_string_literal: true
describe 'GitLab Geo repository replication', :geo do
it 'users pushes code to the primary node' do
Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project|
project.name = 'geo-project'
project.description = 'Geo test project'
end
geo_project_name = Page::Project::Show.act { project_name } module QA
expect(geo_project_name).to include 'geo-project' context :geo, :orchestrated, :geo do
describe 'GitLab Geo repository replication' do
it 'users pushes code to the primary node' do
Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials }
project = Factory::Resource::Project.fabricate! do |project|
project.name = 'geo-project'
project.description = 'Geo test project'
end
Factory::Repository::ProjectPush.fabricate! do |push| geo_project_name = Page::Project::Show.act { project_name }
push.file_name = 'README.md' expect(geo_project_name).to include 'geo-project'
push.file_content = '# This is Geo project!'
push.commit_message = 'Add README.md'
push.project = project
end
Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do Factory::Repository::ProjectPush.fabricate! do |push|
Page::Main::OAuth.act do push.file_name = 'README.md'
authorize! if needs_authorization? push.file_content = '# This is Geo project!'
push.commit_message = 'Add README.md'
push.project = project
end end
EE::Page::Main::Banner.perform do |banner| Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do
expect(banner).to have_secondary_read_only_banner Page::Main::OAuth.act do
end authorize! if needs_authorization?
end
Page::Menu::Main.perform do |menu| EE::Page::Main::Banner.perform do |banner|
menu.go_to_projects expect(banner).to have_secondary_read_only_banner
end end
Page::Dashboard::Projects.perform do |dashboard| Page::Menu::Main.perform do |menu|
dashboard.wait_for_project_replication(geo_project_name) menu.go_to_projects
end
dashboard.go_to_project(geo_project_name) Page::Dashboard::Projects.perform do |dashboard|
end dashboard.wait_for_project_replication(geo_project_name)
dashboard.go_to_project(geo_project_name)
end
Page::Project::Show.perform do |show| Page::Project::Show.perform do |show|
show.wait_for_repository_replication show.wait_for_repository_replication
expect(page).to have_content 'README.md' expect(page).to have_content 'README.md'
expect(page).to have_content 'This is Geo project!' expect(page).to have_content 'This is Geo project!'
end
end end
end end
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment