Commit f0eb7432 authored by Sanad Liaquat's avatar Sanad Liaquat 🏔

Add specs for group managed accounts

Also adds necessary page objects and element selectors
and stablizes existing group_saml specs
Also adds /qa/.rakeTasks generated for Ruby mine to gitignore
parent c94c53b6
Pipeline #95248521 passed with stages
in 166 minutes and 33 seconds
......@@ -82,3 +82,4 @@ jsdoc/
**/tmp/rubocop_cache/**
.overcommit.yml
.projections.json
/qa/.rakeTasks
......@@ -152,7 +152,7 @@
- email = " (#{@user.unconfirmed_email})"
%p This user has an unconfirmed email address#{email}. You may force a confirmation.
%br
= link_to 'Confirm user', confirm_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?' }
= link_to 'Confirm user', confirm_admin_user_path(@user), method: :put, class: "btn btn-info", data: { confirm: 'Are you sure?', qa_selector: 'confirm_user_button' }
= render_if_exists 'admin/users/user_detail_note'
......
......@@ -4,7 +4,7 @@
- link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
= link_to link_text, polymorphic_path([:leave, source, :members]),
method: :delete,
data: { confirm: leave_confirmation_message(source) },
data: { confirm: leave_confirmation_message(source), qa_selector: 'leave_group_link' },
class: 'access-request-link js-leave-link'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord
= link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
......
......@@ -15,7 +15,8 @@
.form-group
%label.toggle-wrapper.mb-0.js-group-saml-enforced-sso-toggle-area
%button{ type: 'button',
class: "js-project-feature-toggle js-group-saml-enforced-sso-toggle project-feature-toggle d-inline qa-enforced-sso-toggle-button #{'is-checked' if saml_provider.enforced_sso?}",
class: "js-project-feature-toggle js-group-saml-enforced-sso-toggle project-feature-toggle d-inline #{'is-checked' if saml_provider.enforced_sso?}",
data: { qa_selector: 'enforced_sso_toggle_button' },
"aria-label": s_("GroupSAML|Enforced SSO") }
= f.hidden_field :enforced_sso, { class: 'js-group-saml-enforced-sso-input js-project-feature-toggle-input'}
%span.toggle-icon
......@@ -31,6 +32,7 @@
%label.toggle-wrapper.mb-0.js-group-saml-enforced-group-managed-accounts-toggle-area
%button{ type: 'button',
class: "js-project-feature-toggle js-group-saml-enforced-group-managed-accounts-toggle project-feature-toggle d-inline #{'is-checked' if saml_provider.enforced_group_managed_accounts?}",
data: { qa_selector: 'group_managed_accounts_toggle_button' },
"aria-label": s_("GroupSAML|Enforced SSO") }
= f.hidden_field :enforced_group_managed_accounts, { class: 'js-group-saml-enforced-group-managed-accounts-input js-project-feature-toggle-input'}
%span.toggle-icon
......@@ -45,18 +47,18 @@
.well-segment.borderless.mb-3.col-12.col-lg-9.p-0
= f.label :sso_url, class: 'label-bold' do
= s_('GroupSAML|Identity provider single sign on URL')
= f.text_field :sso_url, placeholder: 'e.g. https://example.com/adfs/ls', class: 'form-control qa-identity-provider-sso-field'
= f.text_field :sso_url, placeholder: 'e.g. https://example.com/adfs/ls', class: 'form-control', data: { qa_selector: 'identity_provider_sso_field' }
.form-text.text-muted
= s_('GroupSAML|Members will be forwarded here when signing in to your group. Get this from your identity provider, where it can also be called "SSO Service Location", "SAML Token Issuance Endpoint", or "SAML 2.0/W-Federation URL".')
.well-segment.borderless.mb-3.col-12.col-lg-9.p-0
= f.label :certificate_fingerprint, class: 'label-bold' do
= s_('GroupSAML|Certificate fingerprint')
= f.text_field :certificate_fingerprint, placeholder: 'e.g. 0a:1b:2c:3d:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff', class: 'form-control qa-certificate-fingerprint-field'
= f.text_field :certificate_fingerprint, placeholder: 'e.g. 0a:1b:2c:3d:00:11:22:33:44:55:66:77:88:99:aa:bb:cc:dd:ee:ff', class: 'form-control', data: { qa_selector: 'certificate_fingerprint_field' }
.form-text.text-muted
= s_('GroupSAML|SHA1 fingerprint of the SAML token signing certificate. Get this from your identity provider, where it can also be called "Thumbprint".')
.mt-3
= f.submit _("Save changes"), class: 'btn btn-success qa-save-changes-button'
= f.submit _("Save changes"), class: 'btn btn-success', data: { qa_selector: 'save_changes_button' }
#js-saml-test-button.has-tooltip.pull-right
= render 'test_button', saml_provider: @saml_provider
......@@ -30,5 +30,5 @@
.well-segment.borderless
%label= _("GitLab single sign on URL")
- user_login_url = sso_group_saml_providers_url(@group, token: @group.saml_discovery_token)
%div= link_to user_login_url, user_login_url, class: "qa-user-login-url-link"
%div= link_to user_login_url, user_login_url, data: { qa_selector: 'user_login_url_link' }
.form-text.text-muted= _("Used by members to sign in to your group in GitLab")
......@@ -12,10 +12,10 @@
= (_("Finish setting up your dedicated account for <strong>%{group_name}</strong>.") % { group_name: @group_name }).html_safe
.form-group
= f.label :email, class: 'label-bold'
= f.email_field :email, class: "form-control qa-new-user-email", required: true, disabled: true
= f.email_field :email, class: "form-control", required: true, disabled: true, data: { qa_selector: 'new_user_email_field' }
.name.form-group
= f.label :name, _('Full name'), class: 'label-bold'
= f.text_field :name, class: "form-control top qa-new-user-name js-block-emoji", required: true, disabled: resource.name.present?
= f.text_field :name, class: "form-control top js-block-emoji", required: true, data: { qa_selector: 'new_user_username_field' }, disabled: resource.name.present?
.username.form-group
= f.label :username, class: 'label-bold'
= f.text_field :username, class: "form-control qa-new-user-username js-block-emoji", pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, required: true, title: _("Please create a username with only alphanumeric characters.")
......@@ -35,7 +35,7 @@
.d-flex.justify-content-center
= render 'user_info'
.submit-container
= f.submit _("Sign out & Register"), class: "btn-register btn qa-new-user-register-button"
= f.submit _("Sign out & Register"), class: "btn-register btn qa-new-user-register-button", data: { qa_selector: 'sign_out_and_register_button' }
- else
.submit-container
= f.submit _("Register"), class: "btn-register btn qa-new-user-register-button"
......@@ -31,6 +31,7 @@ module QA
module Group
autoload :Menu, 'qa/ee/page/group/menu'
autoload :SamlSSOSignIn, 'qa/ee/page/group/saml_sso_sign_in'
autoload :SamlSSOSignUp, 'qa/ee/page/group/saml_sso_sign_up'
autoload :Members, 'qa/ee/page/group/members'
module Settings
......
......@@ -9,6 +9,13 @@ module QA
element :saml_sso_signin_button
end
def sign_in
Support::Retrier.retry_until do
click_signin
!has_element?(:saml_sso_signin_button, wait: 0)
end
end
def click_signin
click_element :saml_sso_signin_button
end
......
# frozen_string_literal: true
module QA
module EE
module Page
module Group
class SamlSSOSignUp < QA::Page::Base
view 'ee/app/views/groups/sso/sign_up_form.html.haml' do
element :sign_out_and_register_button
element :new_user_email_field
element :new_user_username_field
end
def click_signout_and_register_button
click_element :sign_out_and_register_button
end
def current_email
find_element(:new_user_email_field)[:value]
end
def current_username
find_element(:new_user_username_field)[:value]
end
end
end
end
end
end
......@@ -10,6 +10,7 @@ module QA
element :identity_provider_sso_field
element :certificate_fingerprint_field
element :enforced_sso_toggle_button
element :group_managed_accounts_toggle_button
element :save_changes_button
end
......@@ -30,7 +31,31 @@ module QA
end
def enforce_sso
click_element :enforced_sso_toggle_button unless find_element(:enforced_sso_toggle_button)[:class].include?('is-checked')
Support::Retrier.retry_until do
click_element :enforced_sso_toggle_button unless find_element(:enforced_sso_toggle_button)[:class].include?('is-checked')
find_element(:enforced_sso_toggle_button)[:class].include?('is-checked')
end
end
def disable_enforce_sso
Support::Retrier.retry_until do
click_element :enforced_sso_toggle_button if find_element(:enforced_sso_toggle_button)[:class].include?('is-checked')
!find_element(:enforced_sso_toggle_button)[:class].include?('is-checked')
end
end
def enable_group_managed_accounts
Support::Retrier.retry_until do
click_element :group_managed_accounts_toggle_button unless find_element(:group_managed_accounts_toggle_button)[:class].include?('is-checked')
find_element(:group_managed_accounts_toggle_button)[:class].include?('is-checked')
end
end
def disable_group_managed_accounts
Support::Retrier.retry_until do
click_element :group_managed_accounts_toggle_button if find_element(:group_managed_accounts_toggle_button)[:class].include?('is-checked')
!find_element(:group_managed_accounts_toggle_button)[:class].include?('is-checked')
end
end
def click_save_changes
......@@ -44,6 +69,10 @@ module QA
def click_user_login_url_link
click_element :user_login_url_link
end
def user_login_url_link_text
find_element(:user_login_url_link).text
end
end
end
end
......
......@@ -10,9 +10,19 @@ module QA
element :impersonate_user_link
end
view 'app/views/admin/users/show.html.haml' do
element :confirm_user_button
end
def click_impersonate_user
click_element(:impersonate_user_link)
end
def confirm_user
accept_confirm do
click_element :confirm_user_button
end
end
end
end
end
......
......@@ -18,6 +18,10 @@ module QA
element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern
end
view 'app/views/shared/members/_access_request_links.html.haml' do
element :leave_group_link
end
def click_subgroup(name)
click_link name
end
......@@ -42,6 +46,12 @@ module QA
click_element :new_in_group_button
end
def leave_group
accept_alert do
click_element :leave_group_link
end
end
private
def select_kind(kind)
......
......@@ -64,12 +64,12 @@ module QA
end
def visit!
Runtime::Logger.debug("Visiting #{web_url}")
visit(web_url)
Runtime::Logger.debug(%Q[Visiting #{self.class.name} at "#{web_url}"]) if Runtime::Env.debug?
Support::Retrier.retry_until do
visit(web_url)
wait { current_url == web_url }
wait { current_url.include?(URI.parse(web_url).path.split('/').last || web_url) }
end
end
......
......@@ -11,6 +11,10 @@ module QA
post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
end
def list_members
JSON.parse(get(Runtime::API::Request.new(api_client, api_members_path).url).body)
end
def api_members_path
"#{api_get_path}/members"
end
......
......@@ -7,6 +7,8 @@ module QA
# creating it if it doesn't yet exist.
#
class Sandbox < Base
include Members
attr_accessor :path
attribute :id
......
......@@ -36,12 +36,12 @@ module QA
# In case of an address that is a symbol we will try to guess address
# based on `Runtime::Scenario#something_address`.
#
def visit(address, page_class, &block)
Browser::Session.new(address, page_class).perform(&block)
def visit(address, page_class, skip_elements_validation: false, &block)
Browser::Session.new(address, page_class, skip_elements_validation: skip_elements_validation).perform(&block)
end
def self.visit(address, page_class, &block)
new.visit(address, page_class, &block)
def self.visit(address, page_class, skip_elements_validation: false, &block)
new.visit(address, page_class, skip_elements_validation: skip_elements_validation, &block)
end
def self.configure!
......@@ -140,9 +140,10 @@ module QA
attr_reader :page_class
def initialize(instance, page_class)
def initialize(instance, page_class, skip_elements_validation: false)
@session_address = Runtime::Address.new(instance, page_class)
@page_class = page_class
@skip_elements_validation = skip_elements_validation
end
def url
......@@ -152,7 +153,7 @@ module QA
def perform(&block)
visit(url)
page_class.validate_elements_present!
page_class.validate_elements_present! unless @skip_elements_validation
if QA::Runtime::Env.qa_cookies
browser = Capybara.current_session.driver.browser
......
......@@ -19,6 +19,28 @@ module QA
set_feature(key, false)
end
def remove(key)
request = Runtime::API::Request.new(api_client, "/features/#{key}")
response = delete(request.url)
unless response.code == QA::Support::Api::HTTP_STATUS_NO_CONTENT
raise SetFeatureError, "Deleting feature flag #{key} failed with `#{response}`."
end
end
def enable_and_verify(key)
Support::Retrier.retry_on_exception(sleep_interval: 2) do
enable(key)
is_enabled = false
QA::Support::Waiter.wait(interval: 1) do
is_enabled = enabled?(key)
end
raise SetFeatureError, "#{key} was not enabled!" unless is_enabled
end
end
def enabled?(key)
feature = JSON.parse(get_features).find { |flag| flag["name"] == key }
feature && feature["state"] == "on"
......
......@@ -8,7 +8,9 @@ module QA
Page::Main::Login.perform(&:sign_in_with_saml)
Vendor::SAMLIdp::Page::Login.perform(&:login)
Vendor::SAMLIdp::Page::Login.perform do |login_page|
login_page.login('user1', 'user1pass')
end
expect(page).to have_content('Welcome to GitLab')
end
......
......@@ -7,18 +7,22 @@ module QA
module SAMLIdp
module Page
class Login < Page::Base
def login
fill_in 'username', with: 'user1'
fill_in 'password', with: 'user1pass'
def login(username, password)
QA::Runtime::Logger.debug("Logging into SAMLIdp with username: #{username} and password:#{password}") if QA::Runtime::Env.debug?
fill_in 'username', with: username
fill_in 'password', with: password
click_on 'Login'
end
def login_if_required
login if login_required?
def login_if_required(username, password)
login(username, password) if login_required?
end
def login_required?
page.has_text?('Enter your username and password')
login_required = page.has_text?('Enter your username and password') if QA::Runtime::Env.debug?
QA::Runtime::Logger.debug("login_required: #{login_required}")
login_required
end
end
end
......
......@@ -274,7 +274,7 @@ describe QA::Resource::Base do
resource.web_url = subject.current_url
resource.visit!
expect(resource).to have_received(:visit).with(subject.current_url)
expect(resource).to have_received(:visit).with(subject.current_url).twice
end
end
end
......@@ -20,7 +20,7 @@ RSpec.configure do |config|
QA::Specs::Helpers::Quarantine.configure_rspec
config.before do |example|
QA::Runtime::Logger.debug("Starting test: #{example.full_description}") if QA::Runtime::Env.debug?
QA::Runtime::Logger.debug("\nStarting test: #{example.full_description}\n") if QA::Runtime::Env.debug?
end
config.after(:context) do
......
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