Files
freeipa/ipatests/test_webui/test_loginscreen.py
Christian Heimes 15d5e44ee8 Py3: Replace six.moves imports
Replace six.moves and six.StringIO/BytesIO imports with cannonical
Python 3 packages.

Note: six.moves.input behaves differently than builtin input function.
Therefore I left six.moves.input for now.

See: https://pagure.io/freeipa/issue/7715
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Fraser Tweedale <ftweedal@redhat.com>
2018-10-05 12:06:19 +02:00

402 lines
14 KiB
Python

#
# Copyright (C) 2018 FreeIPA Contributors see COPYING for license
#
"""
Test LoginScreen widget and all it's views
"""
import urllib
from ipatests.test_webui.ui_driver import UI_driver
from ipatests.test_webui.ui_driver import screenshot
import ipatests.test_webui.data_loginscreen as loginscreen
try:
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.wait import WebDriverWait
except ImportError:
pass
import pytest
@pytest.mark.tier1
class TestLoginScreen(UI_driver):
def setup(self, *args, **kwargs):
super(TestLoginScreen, self).setup(*args, **kwargs)
self.init_app()
self.add_test_user()
self.logout()
def teardown(self, *args, **kwargs):
# log out first
if (self.logged_in()):
self.logout()
else:
self.load_url(self.get_base_url())
# log in as administrator
self.login()
self.delete_test_user()
super(TestLoginScreen, self).teardown(*args, **kwargs)
def delete_test_user(self):
"""
Delete user for tests
"""
# User is not logged in
assert self.logged_in()
self.navigate_to_entity(loginscreen.ENTITY)
self.delete_record(loginscreen.PKEY)
def add_test_user(self):
"""
Add user for tests
"""
# User is not logged in
assert self.logged_in()
self.add_record(loginscreen.ENTITY, loginscreen.DATA_ITEST_USER,
navigate=False)
def assert_notification(self, type='success', assert_text=None,
link_text=None, link_url=None):
"""
Assert whether we have a notification of particular type
"""
notification_type = 'div.validation-summary .alert-{}'.format(type)
# wait for a half sec for notification to appear
self.wait(0.5)
is_present = self.find(notification_type, By.CSS_SELECTOR)
# Notification not present
assert is_present
if assert_text:
assert assert_text in is_present.text
if link_text and link_url:
link = self.find_xelement(".//a", is_present)
# Text on link placed on validation widget
assert link_text == link.text
# URL of link placed on validation widget
assert link_url == link.get_attribute('href')
def find_xelement(self, expression, parent, strict=True):
"""
Find element by xpath related to a given parent
"""
return self.find(expression, By.XPATH, parent, many=False,
strict=strict)
def find_xelements(self, expression, parent, strict=True):
"""
Find elements by xpath related to the given parent
"""
return self.find(expression, By.XPATH, parent, many=True,
strict=strict)
def button_click_on_login_screen(self, name):
"""
Find a button with the given name on LoginScreen widget and
then click on
"""
login_screen = self.get_login_screen()
button = self.find_xelement(".//button[@name='{}']".format(name),
login_screen)
assert button.is_displayed()
button.click()
def get_input_field(self, name, parent):
"""
Find a input field with the given name and parent
"""
return self.find_xelement(
".//input[@name='{}']".format(name),
parent
)
def load_url(self, url):
"""
Navigate to Web page and wait for loading of all dependencies.
"""
self.driver.get(url)
runner = self
WebDriverWait(self.driver, 10).until(
lambda d: runner.files_loaded()
)
def relogin_with_new_password(self):
"""
Log out and then log in using a new password.
It is need to check a new password
"""
if (self.logged_in()):
self.logout()
else:
self.load_url(self.get_base_url())
self.login(loginscreen.PKEY, loginscreen.PASSWD_ITEST_USER_NEW)
# User is not logged in
assert self.logged_in()
def reset_password(self, username=None, current_password=None,
new_password=None, link_text=None, link_url=None):
"""
Reset password with the given one
"""
login_screen = self.get_login_screen()
if username is not None:
username_field = self.get_input_field('username', login_screen)
cur_pass_field = self.get_input_field('current_password', login_screen)
new_pass_field = self.get_input_field('new_password', login_screen)
verify_pass_field = self.get_input_field('verify_password',
login_screen)
if username is not None:
username_field.send_keys(username)
cur_pass_field.send_keys(current_password)
new_pass_field.send_keys(new_password)
verify_pass_field.send_keys(new_password)
verify_pass_field.send_keys(Keys.RETURN)
self.wait()
self.assert_notification(assert_text='Password change complete',
link_text=link_text, link_url=link_url)
def get_data_from_form_row(self, form_row):
"""
Parse data from the form record to a comparable structure
"""
result = []
label = self.find_xelement(".//label", form_row)
assert label.is_displayed()
result.append(label.get_attribute('name'))
result.append(label.text)
req = self.find_xelement("./../..", label)
result.append(self.has_class(req, 'required'))
field = self.find_xelement(".//input", form_row)
# not editable field
editable = field.is_displayed()
if not editable:
field = self.find_xelement(".//p", form_row)
result.append(editable)
assert field.is_displayed()
result.append(field.get_attribute('type'))
result.append(field.get_attribute('name'))
if not editable:
result.append(field.text)
else:
result.append(field.get_attribute('value'))
result.append(field.get_attribute('placeholder'))
return tuple(result)
def get_data_from_button(self, button):
"""
Parse data from the button to a comparable structure
"""
result = []
result.append(button.get_attribute('name'))
result.append(button.get_attribute('title'))
return tuple(result)
def assert_form_equals(self, actual_form, expected_form):
"""
Compare two forms
"""
assert len(actual_form) == len(expected_form)
for act_row, exp_row in zip(actual_form, expected_form):
# structure of rows
# label_name, label_text,
# required, editable,
# input_type, input_name,
# input_text, placeholder
assert self.get_data_from_form_row(act_row) == exp_row
def assert_buttons_equal(self, actual_buttons, expected_buttons):
"""
Compare button sets
"""
assert len(actual_buttons) == len(expected_buttons)
for act_button, exp_button in zip(actual_buttons, expected_buttons):
assert self.get_data_from_button(act_button) == exp_button
def assert_validations_equal(self, actual_alerts, expected_alerts):
"""
Compare validation sets
"""
assert len(actual_alerts) == len(expected_alerts)
for act_alert, exp_alert in zip(actual_alerts, expected_alerts):
assert (act_alert.text,) == exp_alert
def has_validation(self, parent):
return self.find_xelement(".//div[@name='validation']", parent,
strict=False)
def check_elements_of_form(self, form_data):
login_screen = self.get_login_screen()
form = self.find_xelement(".//div[@class='form-horizontal']",
login_screen)
# rows
form_rows = self.find_xelements(
".//div[contains(@class, 'form-group')]", form
)
form_rows = [el for el in form_rows if el.is_displayed() and not
self.has_validation(el)]
self.assert_form_equals(form_rows, form_data['rows'])
# buttons
buttons = self.find_xelements(".//button", login_screen)
buttons = [el for el in buttons if el.is_displayed()]
self.assert_buttons_equal(buttons, form_data['buttons'])
def check_alerts(self, form_data):
login_screen = self.get_login_screen()
# Push the the most rigth button to see the Required fields
# it should be either 'Reset' or 'Reset and Login' or 'Login' button
self.button_click_on_login_screen(form_data['buttons'][-1][0])
alerts = self.find_xelements(
".//*[@data-name][contains(@class, 'alert-danger')]", login_screen
)
required_msgs = form_data['required_msg']
self.assert_validations_equal(alerts, required_msgs)
def load_reset_and_login_view(self):
self.load()
assert self.login_screen_visible()
username = loginscreen.PKEY
current_password = loginscreen.PASSWD_ITEST_USER
login_screen = self.get_login_screen()
username_field = self.get_input_field('username', login_screen)
cur_pass_field = self.get_input_field('password', login_screen)
username_field.send_keys(username)
cur_pass_field.send_keys(current_password)
cur_pass_field.send_keys(Keys.RETURN)
self.wait()
self.assert_notification(
type='info',
assert_text=(
'Your password has expired. Please enter a new password.'
)
)
def check_cancel(self):
"""
Check 'login' view after a cancel of password reset
"""
self.button_click_on_login_screen('cancel')
self.check_elements_of_form(loginscreen.FILLED_LOGIN_FORM)
@screenshot
def test_reset_password_view(self):
self.load_url('/'.join((self.get_base_url(), 'reset_password.html')))
assert self.login_screen_visible()
self.check_elements_of_form(loginscreen.RESET_PASSWORD_FORM)
self.check_alerts(loginscreen.RESET_PASSWORD_FORM)
username = loginscreen.PKEY
current_password = loginscreen.PASSWD_ITEST_USER
new_password = loginscreen.PASSWD_ITEST_USER_NEW
self.reset_password(username, current_password, new_password)
self.relogin_with_new_password()
@screenshot
def test_reset_password_view_with_redirect(self):
redir_url = self.get_base_url().lower()
encoded_redir_url = urllib.parse.urlencode({'url': redir_url})
target_url = '/'.join((self.get_base_url(), 'reset_password.html?{}'))
self.load_url(target_url.format(encoded_redir_url))
assert self.login_screen_visible()
self.check_elements_of_form(loginscreen.RESET_PASSWORD_FORM)
self.check_alerts(loginscreen.RESET_PASSWORD_FORM)
username = loginscreen.PKEY
current_password = loginscreen.PASSWD_ITEST_USER
new_password = loginscreen.PASSWD_ITEST_USER_NEW
self.reset_password(username, current_password, new_password,
link_text='Continue to next page',
link_url=redir_url,
)
self.relogin_with_new_password()
@screenshot
def test_reset_password_view_with_delayed_redirect(self):
redir_url = self.get_base_url().lower() + '/'
encoded_redir_url = urllib.parse.urlencode(
{'url': redir_url, 'delay': 5}
)
target_url = '/'.join((self.get_base_url(), 'reset_password.html?{}'))
self.load_url(target_url.format(encoded_redir_url))
assert self.login_screen_visible()
self.check_elements_of_form(loginscreen.RESET_PASSWORD_FORM)
self.check_alerts(loginscreen.RESET_PASSWORD_FORM)
username = loginscreen.PKEY
current_password = loginscreen.PASSWD_ITEST_USER
new_password = loginscreen.PASSWD_ITEST_USER_NEW
self.reset_password(username, current_password, new_password,
link_text='Continue to next page',
link_url=redir_url,
)
self.assert_notification(type='info',
assert_text='You will be redirected in ')
self.wait(3)
# check url after start delay timer, but before end
assert self.driver.current_url != redir_url
self.wait(5)
assert self.driver.current_url == redir_url
self.relogin_with_new_password()
@screenshot
def test_reset_password_and_login_view(self):
self.load_reset_and_login_view()
self.check_elements_of_form(loginscreen.RESET_AND_LOGIN_FORM)
self.check_alerts(loginscreen.RESET_AND_LOGIN_FORM)
# check click on 'Cancel' button
self.check_cancel()
self.button_click_on_login_screen('login')
# check if user is not logged
assert not self.logged_in()
current_password = loginscreen.PASSWD_ITEST_USER
new_password = loginscreen.PASSWD_ITEST_USER_NEW
# username is already here, do not fill up
self.reset_password(current_password=current_password,
new_password=new_password)
# waiting for auto login process
self.wait(5)
assert self.logged_in()
# check again if new password is valid
self.relogin_with_new_password()
@screenshot
def test_login_view(self):
self.load()
# check empty 'login' view
self.check_elements_of_form(loginscreen.EMPTY_LOGIN_FORM)
self.check_alerts(loginscreen.EMPTY_LOGIN_FORM)
# check non empty 'login' view
login_screen = self.get_login_screen()
username_field = self.get_input_field('username', login_screen)
username_field.send_keys(loginscreen.PKEY)
self.wait(0.5)
self.check_elements_of_form(loginscreen.LOGIN_FORM)
self.check_alerts(loginscreen.LOGIN_FORM)