Commit 79111c4c authored by Sanad Liaquat's avatar Sanad Liaquat

Merge branch 'qa-shl-group-managed-accounts-e2e-tests' into 'master'

Add group managed accounts spec

Closes gitlab-org/quality/nightly#140, #34434, and gitlab-org/quality/testcases#242

See merge request gitlab-org/gitlab!19449
parents ce529c00 0d175df3
...@@ -82,3 +82,4 @@ jsdoc/ ...@@ -82,3 +82,4 @@ jsdoc/
**/tmp/rubocop_cache/** **/tmp/rubocop_cache/**
.overcommit.yml .overcommit.yml
.projections.json .projections.json
/qa/.rakeTasks
...@@ -152,7 +152,7 @@ ...@@ -152,7 +152,7 @@
- email = " (#{@user.unconfirmed_email})" - email = " (#{@user.unconfirmed_email})"
%p This user has an unconfirmed email address#{email}. You may force a confirmation. %p This user has an unconfirmed email address#{email}. You may force a confirmation.
%br %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' = render_if_exists 'admin/users/user_detail_note'
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
- link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project') - link_text = source.is_a?(Group) ? _('Leave group') : _('Leave project')
= link_to link_text, polymorphic_path([:leave, source, :members]), = link_to link_text, polymorphic_path([:leave, source, :members]),
method: :delete, 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' class: 'access-request-link js-leave-link'
- elsif requester = source.requesters.find_by(user_id: current_user.id) # rubocop: disable CodeReuse/ActiveRecord - 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]), = link_to _('Withdraw Access Request'), polymorphic_path([:leave, source, :members]),
......
...@@ -15,7 +15,8 @@ ...@@ -15,7 +15,8 @@
.form-group .form-group
%label.toggle-wrapper.mb-0.js-group-saml-enforced-sso-toggle-area %label.toggle-wrapper.mb-0.js-group-saml-enforced-sso-toggle-area
%button{ type: 'button', %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") } "aria-label": s_("GroupSAML|Enforced SSO") }
= f.hidden_field :enforced_sso, { class: 'js-group-saml-enforced-sso-input js-project-feature-toggle-input'} = f.hidden_field :enforced_sso, { class: 'js-group-saml-enforced-sso-input js-project-feature-toggle-input'}
%span.toggle-icon %span.toggle-icon
...@@ -31,6 +32,7 @@ ...@@ -31,6 +32,7 @@
%label.toggle-wrapper.mb-0.js-group-saml-enforced-group-managed-accounts-toggle-area %label.toggle-wrapper.mb-0.js-group-saml-enforced-group-managed-accounts-toggle-area
%button{ type: 'button', %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?}", 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") } "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'} = f.hidden_field :enforced_group_managed_accounts, { class: 'js-group-saml-enforced-group-managed-accounts-input js-project-feature-toggle-input'}
%span.toggle-icon %span.toggle-icon
...@@ -45,18 +47,18 @@ ...@@ -45,18 +47,18 @@
.well-segment.borderless.mb-3.col-12.col-lg-9.p-0 .well-segment.borderless.mb-3.col-12.col-lg-9.p-0
= f.label :sso_url, class: 'label-bold' do = f.label :sso_url, class: 'label-bold' do
= s_('GroupSAML|Identity provider single sign on URL') = 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 .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".') = 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 .well-segment.borderless.mb-3.col-12.col-lg-9.p-0
= f.label :certificate_fingerprint, class: 'label-bold' do = f.label :certificate_fingerprint, class: 'label-bold' do
= s_('GroupSAML|Certificate fingerprint') = 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 .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".') = 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 .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 #js-saml-test-button.has-tooltip.pull-right
= render 'test_button', saml_provider: @saml_provider = render 'test_button', saml_provider: @saml_provider
...@@ -30,5 +30,5 @@ ...@@ -30,5 +30,5 @@
.well-segment.borderless .well-segment.borderless
%label= _("GitLab single sign on URL") %label= _("GitLab single sign on URL")
- user_login_url = sso_group_saml_providers_url(@group, token: @group.saml_discovery_token) - 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") .form-text.text-muted= _("Used by members to sign in to your group in GitLab")
...@@ -12,10 +12,10 @@ ...@@ -12,10 +12,10 @@
= (_("Finish setting up your dedicated account for <strong>%{group_name}</strong>.") % { group_name: @group_name }).html_safe = (_("Finish setting up your dedicated account for <strong>%{group_name}</strong>.") % { group_name: @group_name }).html_safe
.form-group .form-group
= f.label :email, class: 'label-bold' = 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 .name.form-group
= f.label :name, _('Full name'), class: 'label-bold' = 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 .username.form-group
= f.label :username, class: 'label-bold' = 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.") = 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 @@ ...@@ -35,7 +35,7 @@
.d-flex.justify-content-center .d-flex.justify-content-center
= render 'user_info' = render 'user_info'
.submit-container .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 - else
.submit-container .submit-container
= f.submit _("Register"), class: "btn-register btn qa-new-user-register-button" = f.submit _("Register"), class: "btn-register btn qa-new-user-register-button"
...@@ -32,6 +32,7 @@ module QA ...@@ -32,6 +32,7 @@ module QA
module Group module Group
autoload :Menu, 'qa/ee/page/group/menu' autoload :Menu, 'qa/ee/page/group/menu'
autoload :SamlSSOSignIn, 'qa/ee/page/group/saml_sso_sign_in' 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' autoload :Members, 'qa/ee/page/group/members'
module Settings module Settings
......
...@@ -9,8 +9,11 @@ module QA ...@@ -9,8 +9,11 @@ module QA
element :saml_sso_signin_button element :saml_sso_signin_button
end end
def click_signin def click_sign_in
Support::Retrier.retry_until do
click_element :saml_sso_signin_button click_element :saml_sso_signin_button
!has_element?(:saml_sso_signin_button, wait: 0)
end
end end
end end
end 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 ...@@ -10,6 +10,7 @@ module QA
element :identity_provider_sso_field element :identity_provider_sso_field
element :certificate_fingerprint_field element :certificate_fingerprint_field
element :enforced_sso_toggle_button element :enforced_sso_toggle_button
element :group_managed_accounts_toggle_button
element :save_changes_button element :save_changes_button
end end
...@@ -30,7 +31,31 @@ module QA ...@@ -30,7 +31,31 @@ module QA
end end
def enforce_sso def enforce_sso
Support::Retrier.retry_until do
click_element :enforced_sso_toggle_button unless find_element(:enforced_sso_toggle_button)[:class].include?('is-checked') 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 end
def click_save_changes def click_save_changes
...@@ -44,6 +69,10 @@ module QA ...@@ -44,6 +69,10 @@ module QA
def click_user_login_url_link def click_user_login_url_link
click_element :user_login_url_link click_element :user_login_url_link
end end
def user_login_url_link_text
find_element(:user_login_url_link).text
end
end end
end end
end end
......
...@@ -10,9 +10,19 @@ module QA ...@@ -10,9 +10,19 @@ module QA
element :impersonate_user_link element :impersonate_user_link
end end
view 'app/views/admin/users/show.html.haml' do
element :confirm_user_button
end
def click_impersonate_user def click_impersonate_user
click_element(:impersonate_user_link) click_element(:impersonate_user_link)
end end
def confirm_user
accept_confirm do
click_element :confirm_user_button
end
end
end end
end end
end end
......
...@@ -18,6 +18,10 @@ module QA ...@@ -18,6 +18,10 @@ module QA
element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern element :no_result_text, 'No groups or projects matched your search' # rubocop:disable QA/ElementWithPattern
end end
view 'app/views/shared/members/_access_request_links.html.haml' do
element :leave_group_link
end
def click_subgroup(name) def click_subgroup(name)
click_link name click_link name
end end
...@@ -42,6 +46,12 @@ module QA ...@@ -42,6 +46,12 @@ module QA
click_element :new_in_group_button click_element :new_in_group_button
end end
def leave_group
accept_alert do
click_element :leave_group_link
end
end
private private
def select_kind(kind) def select_kind(kind)
......
...@@ -64,12 +64,11 @@ module QA ...@@ -64,12 +64,11 @@ module QA
end end
def visit! def visit!
Runtime::Logger.debug("Visiting #{web_url}") Runtime::Logger.debug(%Q[Visiting #{self.class.name} at "#{web_url}"]) if Runtime::Env.debug?
Support::Retrier.retry_until do Support::Retrier.retry_until do
visit(web_url) visit(web_url)
wait { current_url.include?(URI.parse(web_url).path.split('/').last || web_url) }
wait { current_url == web_url }
end end
end end
......
...@@ -11,6 +11,10 @@ module QA ...@@ -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 } post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
end end
def list_members
JSON.parse(get(Runtime::API::Request.new(api_client, api_members_path).url).body)
end
def api_members_path def api_members_path
"#{api_get_path}/members" "#{api_get_path}/members"
end end
......
...@@ -7,6 +7,8 @@ module QA ...@@ -7,6 +7,8 @@ module QA
# creating it if it doesn't yet exist. # creating it if it doesn't yet exist.
# #
class Sandbox < Base class Sandbox < Base
include Members
attr_accessor :path attr_accessor :path
attribute :id attribute :id
......
...@@ -19,6 +19,28 @@ module QA ...@@ -19,6 +19,28 @@ module QA
set_feature(key, false) set_feature(key, false)
end 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) def enabled?(key)
feature = JSON.parse(get_features).find { |flag| flag["name"] == key } feature = JSON.parse(get_features).find { |flag| flag["name"] == key }
feature && feature["state"] == "on" feature && feature["state"] == "on"
......
...@@ -8,7 +8,9 @@ module QA ...@@ -8,7 +8,9 @@ module QA
Page::Main::Login.perform(&:sign_in_with_saml) 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') expect(page).to have_content('Welcome to GitLab')
end end
......
...@@ -7,18 +7,22 @@ module QA ...@@ -7,18 +7,22 @@ module QA
module SAMLIdp module SAMLIdp
module Page module Page
class Login < Page::Base class Login < Page::Base
def login def login(username, password)
fill_in 'username', with: 'user1' QA::Runtime::Logger.debug("Logging into SAMLIdp with username: #{username} and password:#{password}") if QA::Runtime::Env.debug?
fill_in 'password', with: 'user1pass'
fill_in 'username', with: username
fill_in 'password', with: password
click_on 'Login' click_on 'Login'
end end
def login_if_required def login_if_required(username, password)
login if login_required? login(username, password) if login_required?
end end
def login_required? def login_required?
page.has_text?('Enter your username and password') login_required = page.has_text?('Enter your username and password')
QA::Runtime::Logger.debug("login_required: #{login_required}") if QA::Runtime::Env.debug?
login_required
end end
end end
end end
......
...@@ -20,7 +20,7 @@ RSpec.configure do |config| ...@@ -20,7 +20,7 @@ RSpec.configure do |config|
QA::Specs::Helpers::Quarantine.configure_rspec QA::Specs::Helpers::Quarantine.configure_rspec
config.before do |example| 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 end
config.after(:context) do 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