Commit 3e1190cf authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'qa/gb/selenium-handle-domain-sessions-ee' into 'master'

Explicit QA Runtime::Browse that handles sessions better / EE

See merge request gitlab-org/gitlab-ee!3704
parents 742ef572 d23f7cdd
...@@ -9,6 +9,7 @@ module QA ...@@ -9,6 +9,7 @@ module QA
autoload :User, 'qa/runtime/user' autoload :User, 'qa/runtime/user'
autoload :Namespace, 'qa/runtime/namespace' autoload :Namespace, 'qa/runtime/namespace'
autoload :Scenario, 'qa/runtime/scenario' autoload :Scenario, 'qa/runtime/scenario'
autoload :Browser, 'qa/runtime/browser'
end end
## ##
...@@ -65,7 +66,6 @@ module QA ...@@ -65,7 +66,6 @@ module QA
autoload :Base, 'qa/page/base' autoload :Base, 'qa/page/base'
module Main module Main
autoload :Entry, 'qa/page/main/entry'
autoload :Login, 'qa/page/main/login' autoload :Login, 'qa/page/main/login'
autoload :Menu, 'qa/page/main/menu' autoload :Menu, 'qa/page/main/menu'
autoload :OAuth, 'qa/page/main/oauth' autoload :OAuth, 'qa/page/main/oauth'
......
...@@ -6,7 +6,6 @@ module QA ...@@ -6,7 +6,6 @@ module QA
attr_accessor :address attr_accessor :address
def perform def perform
QA::Page::Main::Entry.act { visit_login_page }
QA::Page::Main::Login.act { sign_in_using_credentials } QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area } QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_geo_nodes } QA::Page::Admin::Menu.act { go_to_geo_nodes }
......
...@@ -4,7 +4,6 @@ module QA ...@@ -4,7 +4,6 @@ module QA
module License module License
class Add < QA::Scenario::Template class Add < QA::Scenario::Template
def perform(license) def perform(license)
QA::Page::Main::Entry.act { visit_login_page }
QA::Page::Main::Login.act { sign_in_using_credentials } QA::Page::Main::Login.act { sign_in_using_credentials }
QA::Page::Main::Menu.act { go_to_admin_area } QA::Page::Main::Menu.act { go_to_admin_area }
QA::Page::Admin::Menu.act { go_to_license } QA::Page::Admin::Menu.act { go_to_license }
......
...@@ -12,13 +12,7 @@ module QA ...@@ -12,13 +12,7 @@ module QA
attribute :geo_skip_setup?, '--without-setup' attribute :geo_skip_setup?, '--without-setup'
def perform(**args) def perform(**args)
QA::Specs::Config.act { configure_capybara! }
unless args[:geo_skip_setup?] unless args[:geo_skip_setup?]
# TODO, Factory::License -> gitlab-org/gitlab-qa#86
#
QA::Runtime::Scenario.define(:gitlab_address, args[:geo_primary_address])
Geo::Primary.act do Geo::Primary.act do
add_license add_license
enable_hashed_storage enable_hashed_storage
...@@ -49,7 +43,9 @@ module QA ...@@ -49,7 +43,9 @@ module QA
# #
puts 'Adding GitLab EE license ...' puts 'Adding GitLab EE license ...'
Scenario::License::Add.perform(ENV['EE_LICENSE']) QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Scenario::License::Add.perform(ENV['EE_LICENSE'])
end
end end
def enable_hashed_storage def enable_hashed_storage
...@@ -57,7 +53,9 @@ module QA ...@@ -57,7 +53,9 @@ module QA
# #
puts 'Enabling hashed repository storage setting ...' puts 'Enabling hashed repository storage setting ...'
QA::Scenario::Gitlab::Admin::HashedStorage.perform(:enabled) QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
QA::Scenario::Gitlab::Admin::HashedStorage.perform(:enabled)
end
end end
def add_secondary_node def add_secondary_node
...@@ -65,8 +63,10 @@ module QA ...@@ -65,8 +63,10 @@ module QA
# #
puts 'Adding new Geo secondary node ...' puts 'Adding new Geo secondary node ...'
Scenario::Geo::Node.perform do |node| QA::Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
node.address = QA::Runtime::Scenario.geo_secondary_address Scenario::Geo::Node.perform do |node|
node.address = QA::Runtime::Scenario.geo_secondary_address
end
end end
end end
......
...@@ -7,18 +7,12 @@ module QA ...@@ -7,18 +7,12 @@ module QA
require 'qa/ee' require 'qa/ee'
end end
##
# TODO generic solution for screenshot in factories
#
# gitlab-org/gitlab-qa#86
#
def perform_before_hooks def perform_before_hooks
return unless ENV['EE_LICENSE'] return unless ENV['EE_LICENSE']
EE::Scenario::License::Add.perform(ENV['EE_LICENSE']) QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login) do
rescue EE::Scenario::License::Add.perform(ENV['EE_LICENSE'])
Capybara::Screenshot.screenshot_and_save_page end
raise
end end
end end
end end
......
...@@ -10,6 +10,18 @@ module QA ...@@ -10,6 +10,18 @@ module QA
visit current_url visit current_url
end end
def wait(css = '.application', time: 60)
Time.now.tap do |start|
while Time.now - start < time
break if page.has_css?(css, wait: 5)
refresh
end
end
yield if block_given?
end
def scroll_to(selector, text: nil) def scroll_to(selector, text: nil)
page.execute_script <<~JS page.execute_script <<~JS
var elements = Array.from(document.querySelectorAll('#{selector}')); var elements = Array.from(document.querySelectorAll('#{selector}'));
...@@ -24,6 +36,10 @@ module QA ...@@ -24,6 +36,10 @@ module QA
page.within(selector) { yield } if block_given? page.within(selector) { yield } if block_given?
end end
def self.path
raise NotImplementedError
end
end end
end end
end end
...@@ -4,6 +4,7 @@ module QA ...@@ -4,6 +4,7 @@ module QA
class New < Page::Base class New < Page::Base
def set_path(path) def set_path(path)
fill_in 'group_path', with: path fill_in 'group_path', with: path
fill_in 'group_name', with: path
end end
def set_description(description) def set_description(description)
......
module QA
module Page
module Main
class Entry < Page::Base
def visit_login_page
visit("#{Runtime::Scenario.gitlab_address}/users/sign_in")
wait_for_instance_to_be_ready
end
private
def wait_for_instance_to_be_ready
# This resolves cold boot / background tasks problems
#
start = Time.now
while Time.now - start < 1000
break if page.has_css?('.application', wait: 10)
refresh
end
end
end
end
end
end
...@@ -2,6 +2,10 @@ module QA ...@@ -2,6 +2,10 @@ module QA
module Page module Page
module Main module Main
class Login < Page::Base class Login < Page::Base
def initialize
wait('.application', time: 500)
end
def sign_in_using_credentials def sign_in_using_credentials
if page.has_content?('Change your password') if page.has_content?('Change your password')
fill_in :user_password, with: Runtime::User.password fill_in :user_password, with: Runtime::User.password
...@@ -13,6 +17,10 @@ module QA ...@@ -13,6 +17,10 @@ module QA
fill_in :user_password, with: Runtime::User.password fill_in :user_password, with: Runtime::User.password
click_button 'Sign in' click_button 'Sign in'
end end
def self.path
'/users/sign_in'
end
end end
end end
end end
......
...@@ -2,10 +2,6 @@ module QA ...@@ -2,10 +2,6 @@ module QA
module Page module Page
module Mattermost module Mattermost
class Login < Page::Base class Login < Page::Base
def initialize
visit(Runtime::Scenario.mattermost_address + '/login')
end
def sign_in_using_oauth def sign_in_using_oauth
click_link class: 'btn btn-custom-login gitlab' click_link class: 'btn btn-custom-login gitlab'
...@@ -13,6 +9,10 @@ module QA ...@@ -13,6 +9,10 @@ module QA
click_button 'Authorize' click_button 'Authorize'
end end
end end
def self.path
'/login'
end
end end
end end
end end
......
...@@ -3,37 +3,39 @@ require 'capybara/rspec' ...@@ -3,37 +3,39 @@ require 'capybara/rspec'
require 'capybara-screenshot/rspec' require 'capybara-screenshot/rspec'
require 'selenium-webdriver' require 'selenium-webdriver'
# rubocop:disable Metrics/MethodLength
# rubocop:disable Metrics/LineLength
module QA module QA
module Specs module Runtime
class Config < Scenario::Template class Browser
include Scenario::Actable include QA::Scenario::Actable
def perform def initialize
configure_rspec! self.class.configure!
configure_capybara!
end end
def configure_rspec! ##
RSpec.configure do |config| # Visit a page that belongs to a GitLab instance under given address.
config.expect_with :rspec do |expectations| #
expectations.include_chain_clauses_in_custom_matcher_descriptions = true # Example:
end #
# visit(:gitlab, Page::Main::Login)
config.mock_with :rspec do |mocks| # visit('http://gitlab.example/users/sign_in')
mocks.verify_partial_doubles = true #
end # In case of an address that is a symbol we will try to guess address
# based on `Runtime::Scenario#something_address`.
config.order = :random #
Kernel.srand config.seed def visit(address, page, &block)
config.formatter = :documentation Browser::Session.new(address, page).tap do |session|
config.color = true session.perform(&block)
end end
end end
def configure_capybara! def self.visit(address, page, &block)
new.visit(address, page, &block)
end
def self.configure!
return if Capybara.drivers.include?(:chrome)
Capybara.register_driver :chrome do |app| Capybara.register_driver :chrome do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome( capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
'chromeOptions' => { 'chromeOptions' => {
...@@ -53,11 +55,55 @@ module QA ...@@ -53,11 +55,55 @@ module QA
config.default_driver = :chrome config.default_driver = :chrome
config.javascript_driver = :chrome config.javascript_driver = :chrome
config.default_max_wait_time = 10 config.default_max_wait_time = 10
# https://github.com/mattheworiordan/capybara-screenshot/issues/164 # https://github.com/mattheworiordan/capybara-screenshot/issues/164
config.save_path = 'tmp' config.save_path = 'tmp'
end end
end end
class Session
include Capybara::DSL
def initialize(instance, page = nil)
@instance = instance
@address = host + page&.path
end
def host
if @instance.is_a?(Symbol)
Runtime::Scenario.send("#{@instance}_address")
else
@instance.to_s
end
end
def perform(&block)
visit(@address)
yield if block_given?
rescue
raise if block.nil?
# RSpec examples will take care of screenshots on their own
#
unless block.binding.receiver.is_a?(RSpec::Core::ExampleGroup)
screenshot_and_save_page
end
raise
ensure
clear! if block_given?
end
##
# Selenium allows to reset session cookies for current domain only.
#
# See gitlab-org/gitlab-qa#102
#
def clear!
visit(@address)
reset_session!
end
end
end end
end end
end end
...@@ -8,7 +8,6 @@ module QA ...@@ -8,7 +8,6 @@ module QA
include Bootable include Bootable
def perform(address, *files) def perform(address, *files)
Specs::Config.act { configure_capybara! }
Runtime::Scenario.define(:gitlab_address, address) Runtime::Scenario.define(:gitlab_address, address)
## ##
......
...@@ -6,7 +6,6 @@ module QA ...@@ -6,7 +6,6 @@ module QA
def perform(*traits) def perform(*traits)
raise ArgumentError unless traits.include?(:enabled) raise ArgumentError unless traits.include?(:enabled)
Page::Main::Entry.act { visit_login_page }
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Page::Main::Menu.act { go_to_admin_area } Page::Main::Menu.act { go_to_admin_area }
Page::Admin::Menu.act { go_to_settings } Page::Admin::Menu.act { go_to_settings }
......
module QA module QA
feature 'GitLab Geo replication', :geo do feature 'GitLab Geo replication', :geo do
scenario 'users pushes code to the primary node' do scenario 'users pushes code to the primary node' do
Page::Main::Entry.act { visit(Runtime::Scenario.geo_primary_address) } Runtime::Browser.visit(:geo_primary, QA::Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |scenario| Scenario::Gitlab::Project::Create.perform do |scenario|
scenario.name = 'geo-project' scenario.name = 'geo-project'
scenario.description = 'Geo test project' scenario.description = 'Geo test project'
end end
geo_project_name = Page::Project::Show.act { project_name } geo_project_name = Page::Project::Show.act { project_name }
expect(geo_project_name).to include 'geo-project' expect(geo_project_name).to include 'geo-project'
Git::Repository.perform do |repository| Git::Repository.perform do |repository|
repository.location = Page::Project::Show.act do repository.location = Page::Project::Show.act do
choose_repository_clone_http choose_repository_clone_http
repository_location repository_location
end end
repository.use_default_credentials repository.use_default_credentials
repository.act do repository.act do
clone clone
configure_identity('GitLab QA', 'root@gitlab.com') configure_identity('GitLab QA', 'root@gitlab.com')
add_file('README.md', '# This is Geo project!') add_file('README.md', '# This is Geo project!')
commit('Add README.md') commit('Add README.md')
push_changes push_changes
end
end end
end
Page::Main::Entry.act { visit(Runtime::Scenario.geo_secondary_address) } Runtime::Browser.visit(:geo_secondary, QA::Page::Main::Login) do
Page::Main::OAuth.act do
authorize! if needs_authorization?
end
Page::Main::OAuth.act do expect(page).to have_content 'You are on a secondary (read-only) Geo node'
authorize! if needs_authorization?
end
expect(page).to have_content 'You are on a secondary (read-only) Geo node' Page::Main::Menu.perform do |menu|
menu.go_to_projects
Page::Main::Menu.perform do |menu| expect(page).to have_content(geo_project_name)
menu.go_to_projects end
expect(page).to have_content(geo_project_name) sleep 10 # wait for repository replication
end
sleep 10 # wait for repository replication
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::Project::Show.perform do Page::Project::Show.perform do
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 end
......
module QA module QA
feature 'standard root login', :core do feature 'standard user login', :core do
scenario 'user logs in using credentials' do scenario 'user logs in using credentials' do
Page::Main::Entry.act { visit_login_page } 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
......
module QA module QA
feature 'create a new group', :mattermost do feature 'create a new group', :mattermost do
scenario 'creating a group with a mattermost team' do scenario 'creating a group with a mattermost team' do
Page::Main::Entry.act { visit_login_page } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Page::Main::Menu.act { go_to_groups } Page::Main::Menu.act { go_to_groups }
......
module QA module QA
feature 'logging in to Mattermost', :mattermost do feature 'logging in to Mattermost', :mattermost do
scenario 'can use gitlab oauth' do scenario 'can use gitlab oauth' do
Page::Main::Entry.act { visit_login_page } Runtime::Browser.visit(:gitlab, Page::Main::Login) do
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Page::Mattermost::Login.act { sign_in_using_oauth }
Page::Mattermost::Main.perform do |page| Runtime::Browser.visit(:mattermost, Page::Mattermost::Login) do
expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/) Page::Mattermost::Login.act { sign_in_using_oauth }
end
end
## Page::Mattermost::Main.perform do |page|
# TODO, temporary workaround for gitlab-org/gitlab-qa#102. expect(page).to have_content(/(Welcome to: Mattermost|Logout GitLab Mattermost)/)
# end
after do end
visit Runtime::Scenario.mattermost_address end
reset_session!
visit Runtime::Scenario.gitlab_address
reset_session!
end end
end end
end end
module QA module QA
feature 'create a new project', :core do feature 'create a new project', :core do
scenario 'user creates a new project' do scenario 'user creates a new project' do
Page::Main::Entry.act { visit_login_page } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |project| Scenario::Gitlab::Project::Create.perform do |project|
......
...@@ -9,7 +9,7 @@ module QA ...@@ -9,7 +9,7 @@ module QA
end end
before do before do
Page::Main::Entry.act { visit_login_page } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |scenario| Scenario::Gitlab::Project::Create.perform do |scenario|
......
...@@ -2,7 +2,7 @@ module QA ...@@ -2,7 +2,7 @@ module QA
feature 'push code to repository', :core do feature 'push code to repository', :core do
context 'with regular account over http' do context 'with regular account over http' do
scenario 'user pushes code to the repository' do scenario 'user pushes code to the repository' do
Page::Main::Entry.act { visit_login_page } Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials } Page::Main::Login.act { sign_in_using_credentials }
Scenario::Gitlab::Project::Create.perform do |scenario| Scenario::Gitlab::Project::Create.perform do |scenario|
......
...@@ -17,7 +17,7 @@ module QA ...@@ -17,7 +17,7 @@ module QA
tags.to_a.each { |tag| args.push(['-t', tag.to_s]) } tags.to_a.each { |tag| args.push(['-t', tag.to_s]) }
args.push(files) args.push(files)
Specs::Config.perform Runtime::Browser.configure!
RSpec::Core::Runner.run(args.flatten, $stderr, $stdout).tap do |status| RSpec::Core::Runner.run(args.flatten, $stderr, $stdout).tap do |status|
abort if status.nonzero? abort if status.nonzero?
......
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