Add GitLab QA integrations tests to GitLab CE / EE
This commit is contained in:
parent
72e940df2c
commit
7d20e47622
|
@ -0,0 +1,3 @@
|
|||
--color
|
||||
--format documentation
|
||||
--require spec_helper
|
|
@ -0,0 +1,15 @@
|
|||
FROM ruby:2.3
|
||||
LABEL maintainer "Grzegorz Bizon <grzegorz@gitlab.com>"
|
||||
|
||||
RUN sed -i "s/httpredir.debian.org/ftp.us.debian.org/" /etc/apt/sources.list && \
|
||||
apt-get update && apt-get install -y --force-yes \
|
||||
libqt5webkit5-dev qt5-qmake qt5-default build-essential xvfb git && \
|
||||
apt-get clean
|
||||
|
||||
|
||||
WORKDIR /home/qa
|
||||
|
||||
COPY ./ ./
|
||||
RUN bundle install
|
||||
|
||||
ENTRYPOINT ["bin/test"]
|
|
@ -0,0 +1,8 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'capybara', '~> 2.12.1'
|
||||
gem 'capybara-screenshot', '~> 1.0.14'
|
||||
gem 'capybara-webkit', '~> 1.12.0'
|
||||
gem 'rake', '~> 12.0.0'
|
||||
gem 'rspec', '~> 3.5'
|
||||
gem 'rubocop', '~> 0.47.1'
|
|
@ -0,0 +1,2 @@
|
|||
## Integration tests for GitLab
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
|
||||
case "$1" in
|
||||
build)
|
||||
docker pull $CI_REGISTRY_IMAGE:latest
|
||||
docker build --cache-from $CI_REGISTRY_IMAGE:latest \
|
||||
-t $CI_REGISTRY_IMAGE:ce-latest -t $CI_REGISTRY_IMAGE:ee-latest \
|
||||
-t $CI_REGISTRY_IMAGE:ce-nightly -t $CI_REGISTRY_IMAGE:ee-nightly \
|
||||
-t $CI_REGISTRY_IMAGE:latest .
|
||||
;;
|
||||
publish)
|
||||
test -n "$CI_BUILD_TOKEN" || exit 1
|
||||
docker login --username gitlab-ci-token --password $CI_BUILD_TOKEN registry.gitlab.com
|
||||
docker push $CI_REGISTRY_IMAGE:latest
|
||||
docker push $CI_REGISTRY_IMAGE:ce-latest
|
||||
docker push $CI_REGISTRY_IMAGE:ee-latest
|
||||
docker push $CI_REGISTRY_IMAGE:ee-nightly
|
||||
docker push $CI_REGISTRY_IMAGE:ee-nightly
|
||||
docker logout registry.gitlab.com
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 [build|publish]"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
|
@ -0,0 +1,7 @@
|
|||
#!/usr/bin/env ruby
|
||||
|
||||
require_relative '../qa'
|
||||
|
||||
QA::Scenario
|
||||
.const_get(ARGV.shift)
|
||||
.perform(*ARGV)
|
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
xvfb-run bundle exec bin/qa $@
|
|
@ -0,0 +1,83 @@
|
|||
$LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
||||
|
||||
module QA
|
||||
##
|
||||
# GitLab QA runtime classes, mostly singletons.
|
||||
#
|
||||
module Runtime
|
||||
autoload :User, 'qa/runtime/user'
|
||||
autoload :Namespace, 'qa/runtime/namespace'
|
||||
end
|
||||
|
||||
##
|
||||
# GitLab QA Scenarios
|
||||
#
|
||||
module Scenario
|
||||
##
|
||||
# Support files
|
||||
#
|
||||
autoload :Actable, 'qa/scenario/actable'
|
||||
autoload :Template, 'qa/scenario/template'
|
||||
|
||||
##
|
||||
# Test scenario entrypoints.
|
||||
#
|
||||
module Test
|
||||
autoload :Instance, 'qa/scenario/test/instance'
|
||||
end
|
||||
|
||||
##
|
||||
# GitLab instance scenarios.
|
||||
#
|
||||
module Gitlab
|
||||
module Project
|
||||
autoload :Create, 'qa/scenario/gitlab/project/create'
|
||||
end
|
||||
|
||||
module License
|
||||
autoload :Add, 'qa/scenario/gitlab/license/add'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Classes describing structure of GitLab, pages, menus etc.
|
||||
#
|
||||
# Needed to execute click-driven-only black-box tests.
|
||||
#
|
||||
module Page
|
||||
autoload :Base, 'qa/page/base'
|
||||
|
||||
module Main
|
||||
autoload :Entry, 'qa/page/main/entry'
|
||||
autoload :Menu, 'qa/page/main/menu'
|
||||
autoload :Groups, 'qa/page/main/groups'
|
||||
autoload :Projects, 'qa/page/main/projects'
|
||||
end
|
||||
|
||||
module Project
|
||||
autoload :New, 'qa/page/project/new'
|
||||
autoload :Show, 'qa/page/project/show'
|
||||
end
|
||||
|
||||
module Admin
|
||||
autoload :Menu, 'qa/page/admin/menu'
|
||||
autoload :License, 'qa/page/admin/license'
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Classes describing operations on Git repositories.
|
||||
#
|
||||
module Git
|
||||
autoload :Repository, 'qa/git/repository'
|
||||
end
|
||||
|
||||
##
|
||||
# Classes that make it possible to execute features tests.
|
||||
#
|
||||
module Specs
|
||||
autoload :Config, 'qa/specs/config'
|
||||
autoload :Runner, 'qa/specs/runner'
|
||||
end
|
||||
end
|
|
@ -0,0 +1,71 @@
|
|||
require 'uri'
|
||||
|
||||
module QA
|
||||
module Git
|
||||
class Repository
|
||||
include Scenario::Actable
|
||||
|
||||
def self.perform(*args)
|
||||
Dir.mktmpdir do |dir|
|
||||
Dir.chdir(dir) { super }
|
||||
end
|
||||
end
|
||||
|
||||
def location=(address)
|
||||
@location = address
|
||||
@uri = URI(address)
|
||||
end
|
||||
|
||||
def username=(name)
|
||||
@username = name
|
||||
@uri.user = name
|
||||
end
|
||||
|
||||
def password=(pass)
|
||||
@password = pass
|
||||
@uri.password = pass
|
||||
end
|
||||
|
||||
def use_default_credentials
|
||||
self.username = Runtime::User.name
|
||||
self.password = Runtime::User.password
|
||||
end
|
||||
|
||||
def clone(opts = '')
|
||||
`git clone #{opts} #{@uri.to_s} ./`
|
||||
end
|
||||
|
||||
def shallow_clone
|
||||
clone('--depth 1')
|
||||
end
|
||||
|
||||
def configure_identity(name, email)
|
||||
`git config user.name #{name}`
|
||||
`git config user.email #{email}`
|
||||
end
|
||||
|
||||
def commit_file(name, contents, message)
|
||||
add_file(name, contents)
|
||||
commit(message)
|
||||
end
|
||||
|
||||
def add_file(name, contents)
|
||||
File.write(name, contents)
|
||||
|
||||
`git add #{name}`
|
||||
end
|
||||
|
||||
def commit(message)
|
||||
`git commit -m "#{message}"`
|
||||
end
|
||||
|
||||
def push_changes(branch = 'master')
|
||||
`git push #{@uri.to_s} #{branch}`
|
||||
end
|
||||
|
||||
def commits
|
||||
`git log --oneline`.split("\n")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
module QA
|
||||
module Page
|
||||
module Admin
|
||||
class License < Page::Base
|
||||
def no_license?
|
||||
page.has_content?('No GitLab Enterprise Edition ' \
|
||||
'license has been provided yet')
|
||||
end
|
||||
|
||||
def add_new_license(key)
|
||||
raise 'License key empty!' if key.to_s.empty?
|
||||
|
||||
choose 'Enter license key'
|
||||
fill_in 'License key', with: key
|
||||
click_button 'Upload license'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
module QA
|
||||
module Page
|
||||
module Admin
|
||||
class Menu < Page::Base
|
||||
def go_to_license
|
||||
within_middle_menu { click_link 'License' }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def within_middle_menu
|
||||
page.within('.nav-control') do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
module QA
|
||||
module Page
|
||||
class Base
|
||||
include Capybara::DSL
|
||||
include Scenario::Actable
|
||||
|
||||
def refresh
|
||||
visit current_path
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
module QA
|
||||
module Page
|
||||
module Main
|
||||
class Entry < Page::Base
|
||||
def initialize
|
||||
visit('/')
|
||||
|
||||
# This resolves cold boot problems with login page
|
||||
find('.application', wait: 120)
|
||||
end
|
||||
|
||||
def sign_in_using_credentials
|
||||
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
|
||||
|
||||
fill_in :user_login, with: Runtime::User.name
|
||||
fill_in :user_password, with: Runtime::User.password
|
||||
click_button 'Sign in'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
module QA
|
||||
module Page
|
||||
module Main
|
||||
class Groups < Page::Base
|
||||
def prepare_test_namespace
|
||||
return if page.has_content?(Runtime::Namespace.name)
|
||||
|
||||
click_on 'New Group'
|
||||
|
||||
fill_in 'group_path', with: Runtime::Namespace.name
|
||||
fill_in 'group_description',
|
||||
with: "QA test run at #{Runtime::Namespace.time}"
|
||||
choose 'Private'
|
||||
|
||||
click_button 'Create group'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,46 @@
|
|||
module QA
|
||||
module Page
|
||||
module Main
|
||||
class Menu < Page::Base
|
||||
def go_to_groups
|
||||
within_global_menu { click_link 'Groups' }
|
||||
end
|
||||
|
||||
def go_to_projects
|
||||
within_global_menu { click_link 'Projects' }
|
||||
end
|
||||
|
||||
def go_to_admin_area
|
||||
within_user_menu { click_link 'Admin Area' }
|
||||
end
|
||||
|
||||
def sign_out
|
||||
within_user_menu do
|
||||
find('.header-user-dropdown-toggle').click
|
||||
click_link('Sign out')
|
||||
end
|
||||
end
|
||||
|
||||
def has_personal_area?
|
||||
page.has_selector?('.header-user-dropdown-toggle')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def within_global_menu
|
||||
find('.global-dropdown-toggle').click
|
||||
|
||||
page.within('.global-dropdown-menu') do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def within_user_menu
|
||||
page.within('.dropdown-menu-nav') do
|
||||
yield
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
module QA
|
||||
module Page
|
||||
module Main
|
||||
class Projects < Page::Base
|
||||
def go_to_new_project
|
||||
##
|
||||
# There are 'New Project' and 'New project' buttons on the projects
|
||||
# page, so we can't use `click_on`.
|
||||
#
|
||||
button = find('a', text: /^new project$/i)
|
||||
button.click
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,24 @@
|
|||
module QA
|
||||
module Page
|
||||
module Project
|
||||
class New < Page::Base
|
||||
def choose_test_namespace
|
||||
find('#s2id_project_namespace_id').click
|
||||
find('.select2-result-label', text: Runtime::Namespace.name).click
|
||||
end
|
||||
|
||||
def choose_name(name)
|
||||
fill_in 'project_path', with: name
|
||||
end
|
||||
|
||||
def add_description(description)
|
||||
fill_in 'project_description', with: description
|
||||
end
|
||||
|
||||
def create_new_project
|
||||
click_on 'Create project'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
module QA
|
||||
module Page
|
||||
module Project
|
||||
class Show < Page::Base
|
||||
def choose_repository_clone_http
|
||||
find('#clone-dropdown').click
|
||||
|
||||
page.within('#clone-dropdown') do
|
||||
find('span', text: 'HTTP').click
|
||||
end
|
||||
end
|
||||
|
||||
def repository_location
|
||||
find('#project_clone').value
|
||||
end
|
||||
|
||||
def wait_for_push
|
||||
sleep 5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
module QA
|
||||
module Runtime
|
||||
module Namespace
|
||||
extend self
|
||||
|
||||
def time
|
||||
@time ||= Time.now
|
||||
end
|
||||
|
||||
def name
|
||||
'qa_test_' + time.strftime('%d_%m_%Y_%H-%M-%S')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
module QA
|
||||
module Runtime
|
||||
module User
|
||||
extend self
|
||||
|
||||
def name
|
||||
ENV['GITLAB_USERNAME'] || 'root'
|
||||
end
|
||||
|
||||
def password
|
||||
ENV['GITLAB_PASSWORD'] || 'test1234'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
module QA
|
||||
module Scenario
|
||||
module Actable
|
||||
def act(*args, &block)
|
||||
instance_exec(*args, &block)
|
||||
end
|
||||
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
end
|
||||
|
||||
module ClassMethods
|
||||
def perform
|
||||
yield new if block_given?
|
||||
end
|
||||
|
||||
def act(*args, &block)
|
||||
new.act(*args, &block)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
module QA
|
||||
module Scenario
|
||||
module Gitlab
|
||||
module License
|
||||
class Add < Scenario::Template
|
||||
def perform
|
||||
Page::Main::Entry.act { sign_in_using_credentials }
|
||||
Page::Main::Menu.act { go_to_admin_area }
|
||||
Page::Admin::Menu.act { go_to_license }
|
||||
|
||||
Page::Admin::License.act do
|
||||
add_new_license(ENV['EE_LICENSE']) if no_license?
|
||||
end
|
||||
|
||||
Page::Main::Menu.act { sign_out }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,31 @@
|
|||
require 'securerandom'
|
||||
|
||||
module QA
|
||||
module Scenario
|
||||
module Gitlab
|
||||
module Project
|
||||
class Create < Scenario::Template
|
||||
attr_writer :description
|
||||
|
||||
def name=(name)
|
||||
@name = "#{name}-#{SecureRandom.hex(8)}"
|
||||
end
|
||||
|
||||
def perform
|
||||
Page::Main::Menu.act { go_to_groups }
|
||||
Page::Main::Groups.act { prepare_test_namespace }
|
||||
Page::Main::Menu.act { go_to_projects }
|
||||
Page::Main::Projects.act { go_to_new_project }
|
||||
|
||||
Page::Project::New.perform do |page|
|
||||
page.choose_test_namespace
|
||||
page.choose_name(@name)
|
||||
page.add_description(@description)
|
||||
page.create_new_project
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
module QA
|
||||
module Scenario
|
||||
class Template
|
||||
def self.perform(*args)
|
||||
new.tap do |scenario|
|
||||
yield scenario if block_given?
|
||||
return scenario.perform(*args)
|
||||
end
|
||||
end
|
||||
|
||||
def perform(*_args)
|
||||
raise NotImplementedError
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,27 @@
|
|||
module QA
|
||||
module Scenario
|
||||
module Test
|
||||
##
|
||||
# Run test suite against any GitLab instance,
|
||||
# including staging and on-premises installation.
|
||||
#
|
||||
class Instance < Scenario::Template
|
||||
def perform(address, tag, *files)
|
||||
Specs::Config.perform do |specs|
|
||||
specs.address = address
|
||||
end
|
||||
|
||||
##
|
||||
# Temporary CE + EE support
|
||||
Scenario::Gitlab::License::Add.perform if tag.to_s == 'ee'
|
||||
|
||||
Specs::Runner.perform do |specs|
|
||||
files = files.any? ? files : 'qa/specs/features'
|
||||
|
||||
specs.rspec('--tty', '--tag', tag.to_s, files)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,78 @@
|
|||
require 'rspec/core'
|
||||
require 'capybara/rspec'
|
||||
require 'capybara-webkit'
|
||||
require 'capybara-screenshot/rspec'
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
# rubocop:disable Metrics/LineLength
|
||||
|
||||
module QA
|
||||
module Specs
|
||||
class Config < Scenario::Template
|
||||
attr_writer :address
|
||||
|
||||
def initialize
|
||||
@address = ENV['GITLAB_URL']
|
||||
end
|
||||
|
||||
def perform
|
||||
raise 'Please configure GitLab address!' unless @address
|
||||
|
||||
configure_rspec!
|
||||
configure_capybara!
|
||||
configure_webkit!
|
||||
end
|
||||
|
||||
def configure_rspec!
|
||||
RSpec.configure do |config|
|
||||
config.expect_with :rspec do |expectations|
|
||||
# This option will default to `true` in RSpec 4. It makes the `description`
|
||||
# and `failure_message` of custom matchers include text for helper methods
|
||||
# defined using `chain`.
|
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||
end
|
||||
|
||||
config.mock_with :rspec do |mocks|
|
||||
# Prevents you from mocking or stubbing a method that does not exist on
|
||||
# a real object. This is generally recommended, and will default to
|
||||
# `true` in RSpec 4.
|
||||
mocks.verify_partial_doubles = true
|
||||
end
|
||||
|
||||
# Run specs in random order to surface order dependencies.
|
||||
config.order = :random
|
||||
Kernel.srand config.seed
|
||||
|
||||
config.before(:all) do
|
||||
page.current_window.resize_to(1200, 1800)
|
||||
end
|
||||
|
||||
config.formatter = :documentation
|
||||
config.color = true
|
||||
end
|
||||
end
|
||||
|
||||
def configure_capybara!
|
||||
Capybara.configure do |config|
|
||||
config.app_host = @address
|
||||
config.default_driver = :webkit
|
||||
config.javascript_driver = :webkit
|
||||
config.default_max_wait_time = 4
|
||||
|
||||
# https://github.com/mattheworiordan/capybara-screenshot/issues/164
|
||||
config.save_path = 'tmp'
|
||||
end
|
||||
end
|
||||
|
||||
def configure_webkit!
|
||||
Capybara::Webkit.configure do |config|
|
||||
config.allow_url(@address)
|
||||
config.block_unknown_urls
|
||||
end
|
||||
rescue RuntimeError # rubocop:disable Lint/HandleExceptions
|
||||
# TODO, Webkit is already configured, this make this
|
||||
# configuration step idempotent, should be improved.
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,14 @@
|
|||
module QA
|
||||
feature 'standard root login', :ce, :ee do
|
||||
scenario 'user logs in using credentials' do
|
||||
Page::Main::Entry.act { sign_in_using_credentials }
|
||||
|
||||
# TODO, since `Signed in successfully` message was removed
|
||||
# this is the only way to tell if user is signed in correctly.
|
||||
#
|
||||
Page::Main::Menu.perform do |menu|
|
||||
expect(menu).to have_personal_area
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
module QA
|
||||
feature 'create a new project', :ce, :ee, :staging do
|
||||
scenario 'user creates a new project' do
|
||||
Page::Main::Entry.act { sign_in_using_credentials }
|
||||
|
||||
Scenario::Gitlab::Project::Create.perform do |project|
|
||||
project.name = 'awesome-project'
|
||||
project.description = 'create awesome project test'
|
||||
end
|
||||
|
||||
expect(page).to have_content(
|
||||
/Project \S?awesome-project\S+ was successfully created/
|
||||
)
|
||||
|
||||
expect(page).to have_content('create awesome project test')
|
||||
expect(page).to have_content('The repository for this project is empty')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,57 @@
|
|||
module QA
|
||||
feature 'clone code from the repository', :ce, :ee, :staging do
|
||||
context 'with regular account over http' do
|
||||
given(:location) do
|
||||
Page::Project::Show.act do
|
||||
choose_repository_clone_http
|
||||
repository_location
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Page::Main::Entry.act { sign_in_using_credentials }
|
||||
|
||||
Scenario::Gitlab::Project::Create.perform do |scenario|
|
||||
scenario.name = 'project-with-code'
|
||||
scenario.description = 'project for git clone tests'
|
||||
end
|
||||
|
||||
Git::Repository.perform do |repository|
|
||||
repository.location = location
|
||||
repository.use_default_credentials
|
||||
|
||||
repository.act do
|
||||
clone
|
||||
configure_identity('GitLab QA', 'root@gitlab.com')
|
||||
commit_file('test.rb', 'class Test; end', 'Add Test class')
|
||||
commit_file('README.md', '# Test', 'Add Readme')
|
||||
push_changes
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'user performs a deep clone' do
|
||||
Git::Repository.perform do |repository|
|
||||
repository.location = location
|
||||
repository.use_default_credentials
|
||||
|
||||
repository.act { clone }
|
||||
|
||||
expect(repository.commits.size).to eq 2
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'user performs a shallow clone' do
|
||||
Git::Repository.perform do |repository|
|
||||
repository.location = location
|
||||
repository.use_default_credentials
|
||||
|
||||
repository.act { shallow_clone }
|
||||
|
||||
expect(repository.commits.size).to eq 1
|
||||
expect(repository.commits.first).to include 'Add Readme'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
module QA
|
||||
feature 'push code to repository', :ce, :ee, :staging do
|
||||
context 'with regular account over http' do
|
||||
scenario 'user pushes code to the repository' do
|
||||
Page::Main::Entry.act { sign_in_using_credentials }
|
||||
|
||||
Scenario::Gitlab::Project::Create.perform do |scenario|
|
||||
scenario.name = 'project_with_code'
|
||||
scenario.description = 'project with repository'
|
||||
end
|
||||
|
||||
Git::Repository.perform do |repository|
|
||||
repository.location = Page::Project::Show.act do
|
||||
choose_repository_clone_http
|
||||
repository_location
|
||||
end
|
||||
|
||||
repository.use_default_credentials
|
||||
|
||||
repository.act do
|
||||
clone
|
||||
configure_identity('GitLab QA', 'root@gitlab.com')
|
||||
add_file('README.md', '# This is test project')
|
||||
commit('Add README.md')
|
||||
push_changes
|
||||
end
|
||||
end
|
||||
|
||||
Page::Project::Show.act do
|
||||
wait_for_push
|
||||
refresh
|
||||
end
|
||||
|
||||
expect(page).to have_content('README.md')
|
||||
expect(page).to have_content('This is test project')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
require 'rspec/core'
|
||||
|
||||
module QA
|
||||
module Specs
|
||||
class Runner
|
||||
include Scenario::Actable
|
||||
|
||||
def rspec(*args)
|
||||
RSpec::Core::Runner.run(args.flatten, $stderr, $stdout).tap do |status|
|
||||
abort if status.nonzero?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,47 @@
|
|||
describe QA::Scenario::Actable do
|
||||
subject do
|
||||
Class.new do
|
||||
include QA::Scenario::Actable
|
||||
|
||||
attr_accessor :something
|
||||
|
||||
def do_something(arg = nil)
|
||||
"some#{arg}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.act' do
|
||||
it 'provides means to run steps' do
|
||||
result = subject.act { do_something }
|
||||
|
||||
expect(result).to eq 'some'
|
||||
end
|
||||
|
||||
it 'supports passing variables' do
|
||||
result = subject.act('thing') do |variable|
|
||||
do_something(variable)
|
||||
end
|
||||
|
||||
expect(result).to eq 'something'
|
||||
end
|
||||
|
||||
it 'returns value from the last method' do
|
||||
result = subject.act { 'test' }
|
||||
|
||||
expect(result).to eq 'test'
|
||||
end
|
||||
end
|
||||
|
||||
describe '.perform' do
|
||||
it 'makes it possible to pass binding' do
|
||||
variable = 'something'
|
||||
|
||||
result = subject.perform do |object|
|
||||
object.something = variable
|
||||
end
|
||||
|
||||
expect(result).to eq 'something'
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
require_relative '../qa'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.expect_with :rspec do |expectations|
|
||||
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
||||
end
|
||||
|
||||
config.mock_with :rspec do |mocks|
|
||||
mocks.verify_partial_doubles = true
|
||||
end
|
||||
|
||||
config.shared_context_metadata_behavior = :apply_to_host_groups
|
||||
config.disable_monkey_patching!
|
||||
config.expose_dsl_globally = true
|
||||
config.warnings = true
|
||||
config.profile_examples = 10
|
||||
config.order = :random
|
||||
Kernel.srand config.seed
|
||||
end
|
Loading…
Reference in New Issue