Skip to content
代码片段 群组 项目
未验证 提交 190a0fba 编辑于 作者: Andrejs Cunskis's avatar Andrejs Cunskis
浏览文件

Implement headless readiness check for gitlab

Use web browser for sign in page check on dot_com environments

Add specs for dot_com scenario
上级 67e74040
No related branches found
No related tags found
无相关合并请求
......@@ -16,9 +16,8 @@ def perform_before_hooks
return false
end
QA::Support::Retrier.retry_on_exception do
QA::Runtime::Browser.visit(:gitlab, QA::Page::Main::Login)
end
# Perform app readiness check before continuing with the whole test suite
Tools::ReadinessCheck.perform(wait: 60)
# Reset admin password if admin token is present but can't be used due to expired password
reset_admin_password!
......
# frozen_string_literal: true
require "nokogiri"
module QA
module Tools
# Helper to assert GitLab instance readiness without starting a web browser
#
class ReadinessCheck
include Support::API
def self.perform(wait: 60)
new(wait: wait).perform
end
def initialize(wait:)
@wait = wait
end
# Validate gitlab readiness via check for presence of sign-in-form element
#
# @return [void]
def perform
error = nil
info("Waiting for Gitlab to become ready!")
Support::Retrier.retry_until(max_duration: wait, sleep_interval: 1, raise_on_failure: false, log: false) do
result = !required_elements_missing?
error = nil
result
rescue StandardError => e
error = "#{error_base} #{e.message}"
false
end
raise error if error
info("Gitlab is ready!")
end
private
delegate :debug, :info, to: QA::Runtime::Logger
attr_reader :wait
# Sign in page url
#
# @return [String]
def url
@url ||= "#{Support::GitlabAddress.address_with_port(with_default_port: false)}/users/sign_in"
end
# Error message base
#
# @return [String]
def error_base
@error_base ||= "Gitlab readiness check failed, valid sign_in page did not appear within #{wait} seconds!"
end
# Required elements css selectors
#
# @return [Array<String>]
def elements_css
@element_css ||= QA::Page::Main::Login.elements.select(&:required?).map(&:selector_css)
end
# Check for missing required elements on sign-in page
#
# @return [Boolean]
def required_elements_missing?
debug("Checking for required element presence on '#{url}'")
# Do not perform headless request on .com due to cloudfare
return rendered_elements_missing? if Runtime::Env.running_on_dot_com?
response = get(url)
unless ok_response?(response)
msg = "Got unsucessfull response code: #{response.code}"
debug(msg) && raise(msg)
end
unless required_elements_present?(response)
msg = "Sign in page missing required elements: '#{elements_css}'"
debug(msg) && raise(msg)
end
debug("Required elements are present!")
false
end
# Perform check for present elements via web browser
#
# @return [Boolean]
def rendered_elements_missing?
debug("Checking for required elements via web browser")
Runtime::Browser.visit(:gitlab, Page::Main::Login)
false
rescue StandardError => e
debug("Sign in page did not render fully")
raise(e)
end
# Validate response code is 200
#
# @param [RestClient::Response] response
# @return [Boolean]
def ok_response?(response)
response.code == Support::API::HTTP_STATUS_OK
end
# Check required elements are present on sign-in page
#
# @param [RestClient::Response] response
# @return [Boolean]
def required_elements_present?(response)
doc = Nokogiri::HTML.parse(response.body)
elements_css.all? { |sel| doc.css(sel).any? }
end
end
end
end
# frozen_string_literal: true
RSpec.describe QA::Tools::ReadinessCheck do
subject(:readiness_check) { described_class.new(wait: wait) }
let(:url) { "example.com" }
let(:wait) { 1 }
let(:msg_base) { "Gitlab readiness check failed, valid sign_in page did not appear within #{wait} seconds!" }
let(:dot_com) { false }
let(:response) { instance_double(RestClient::Response, code: code, body: body) }
let(:code) { 200 }
let(:body) { "" }
before do
allow(QA::Runtime::Env).to receive(:running_on_dot_com?).and_return(dot_com)
allow(QA::Support::GitlabAddress).to receive(:address_with_port).with(with_default_port: false).and_return(url)
allow(readiness_check).to receive(:get).with("#{url}/users/sign_in").and_return(response)
end
context "with successfull response" do
let(:body) do
<<~HTML
<!DOCTYPE html>
<body data-testid="login-page">
</body>
</html>
HTML
end
it "validates readiness" do
expect { readiness_check.perform }.not_to raise_error
end
end
context "with missing sign in form" do
let(:body) do
<<~HTML
<!DOCTYPE html>
</html>
HTML
end
it "raises an error on validation" do
expect { readiness_check.perform }.to raise_error(/#{msg_base} Sign in page missing required elements/)
end
end
context "with unsuccessfull response code" do
let(:code) { 500 }
it "raises an error on validation" do
expect { readiness_check.perform }.to raise_error(
"#{msg_base} Got unsucessfull response code: #{code}"
)
end
end
context "with request timeout" do
before do
allow(readiness_check).to receive(:get).and_raise(RestClient::Exceptions::OpenTimeout)
end
it "raises an error on validation" do
expect { readiness_check.perform }.to raise_error("#{msg_base} Timed out connecting to server")
end
end
context "when running on dot com" do
let(:dot_com) { true }
context "with successfull check" do
before do
allow(QA::Runtime::Browser).to receive(:visit).with(:gitlab, QA::Page::Main::Login)
end
it "validates readiness" do
expect { readiness_check.perform }.not_to raise_error
end
end
context "with unsuccessfull check" do
before do
allow(QA::Runtime::Browser).to receive(:visit).with(:gitlab, QA::Page::Main::Login).and_raise("not loaded")
end
it "raises an error on validation" do
expect { readiness_check.perform }.to raise_error("#{msg_base} not loaded")
end
end
end
end
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册