ui_tests: extend test_user suite

Extend WebUI test_user suite with the following test cases:

test_add_user_special
test_user_misc
test_ssh_keys
test_add_delete_undo_reset
test_disable_delete_admin
test_login_without_username

https://pagure.io/freeipa/issue/7507

Reviewed-By: Petr Vobornik <pvoborni@redhat.com>
Reviewed-By: Varun Mylaraiah <mvarun@redhat.com>
This commit is contained in:
Michal Reznik
2018-04-19 15:19:37 +02:00
parent 00a8d00ea9
commit e16a76ad97
2 changed files with 563 additions and 7 deletions

View File

@@ -17,6 +17,7 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
ENTITY = 'user' ENTITY = 'user'
PKEY = 'itest-user' PKEY = 'itest-user'
@@ -35,17 +36,67 @@ DATA = {
'mod': [ 'mod': [
('textbox', 'givenname', 'OtherName'), ('textbox', 'givenname', 'OtherName'),
('textbox', 'sn', 'OtherSurname'), ('textbox', 'sn', 'OtherSurname'),
('textbox', 'initials', 'NOS'),
('textbox', 'loginshell', '/bin/csh'),
('textbox', 'homedirectory', '/home/alias'),
('multivalued', 'telephonenumber', [ ('multivalued', 'telephonenumber', [
('add', '123456789'), ('add', '123456789'),
('add', '987654321'), ('add', '987654321'),
]), ]),
('multivalued', 'mail', [
('add', 'one@ipa.test'),
('add', 'two@ipa.test'),
('add', 'three@ipa.test'),
]),
('multivalued', 'pager', [
('add', '1234567'),
('add', '7654321'),
]),
('multivalued', 'mobile', [
('add', '001123456'),
('add', '001654321'),
]),
('multivalued', 'facsimiletelephonenumber', [
('add', '1122334'),
('add', '4332211'),
]),
('textbox', 'street', 'Wonderwall ave.'),
('textbox', 'l', 'Atlantis'),
('textbox', 'st', 'Universe'),
('textbox', 'postalcode', '61600'),
('multivalued', 'carlicense', [
('add', 'ZLA-1336'),
]),
('textbox', 'ou', 'QE'),
('combobox', 'manager', 'admin'), ('combobox', 'manager', 'admin'),
('textbox', 'employeenumber', '123'),
('textbox', 'employeetype', 'contractor'),
('textbox', 'preferredlanguage', 'Spanish'),
], ],
'mod_v': [ 'mod_v': [
('textbox', 'givenname', 'OtherName'), ('textbox', 'givenname', 'OtherName'),
('textbox', 'sn', 'OtherSurname'), ('textbox', 'sn', 'OtherSurname'),
('textbox', 'initials', 'NOS'),
('textbox', 'loginshell', '/bin/csh'),
('textbox', 'homedirectory', '/home/alias'),
('label', 'krbmaxrenewableage', '604800'),
('label', 'krbmaxticketlife', '86400'),
('multivalued', 'telephonenumber', ['123456789', '987654321']), ('multivalued', 'telephonenumber', ['123456789', '987654321']),
('multivalued', 'mail', ['one@ipa.test', 'two@ipa.test',
'three@ipa.test']),
('multivalued', 'pager', ['1234567', '7654321']),
('multivalued', 'mobile', ['001123456', '001654321']),
('multivalued', 'facsimiletelephonenumber', ['1122334', '4332211']),
('textbox', 'street', 'Wonderwall ave.'),
('textbox', 'l', 'Atlantis'),
('textbox', 'st', 'Universe'),
('textbox', 'postalcode', '61600'),
('multivalued', 'carlicense', ['ZLA-1336']),
('textbox', 'ou', 'QE'),
('combobox', 'manager', 'admin'), ('combobox', 'manager', 'admin'),
('textbox', 'employeenumber', '123'),
('textbox', 'employeetype', 'contractor'),
('textbox', 'preferredlanguage', 'Spanish'),
], ],
} }
@@ -85,3 +136,106 @@ DATA4 = {
('combobox', 'gidnumber', '77777'), ('combobox', 'gidnumber', '77777'),
] ]
} }
PKEY_SPECIAL_CHARS = '1spe.cial_us-er$'
PASSWD_SCECIAL_CHARS = '!!!@@@###$$$'
DATA_SPECIAL_CHARS = {
'pkey': PKEY_SPECIAL_CHARS,
'add': [
('textbox', 'uid', PKEY_SPECIAL_CHARS),
('textbox', 'givenname', 'S$p|e>c--i_a%l_'),
('textbox', 'sn', '%U&s?e+r'),
('password', 'userpassword', PASSWD_SCECIAL_CHARS),
('password', 'userpassword2', PASSWD_SCECIAL_CHARS),
]
}
PKEY_LONG_LOGIN = 'itest-user' * 5
DATA_LONG_LOGIN = {
'pkey': PKEY_LONG_LOGIN,
'add': [
('textbox', 'uid', PKEY_LONG_LOGIN),
('textbox', 'givenname', 'Name8'),
('textbox', 'sn', 'Surname8'),
]
}
PKEY_PASSWD_LEAD_SPACE = 'itest-user-passwd-leading-space'
DATA_PASSWD_LEAD_SPACE = {
'pkey': PKEY_PASSWD_LEAD_SPACE,
'add': [
('textbox', 'uid', PKEY_PASSWD_LEAD_SPACE),
('textbox', 'givenname', 'Name7'),
('textbox', 'sn', 'Surname7'),
('password', 'userpassword', ' Password123 '),
('password', 'userpassword2', ' Password123 '),
]
}
PKEY_PASSWD_TRAIL_SPACE = 'itest-user-passwd-trailing-space'
DATA_PASSWD_TRAIL_SPACE = {
'pkey': PKEY_PASSWD_LEAD_SPACE,
'add': [
('textbox', 'uid', PKEY_PASSWD_LEAD_SPACE),
('textbox', 'givenname', 'Name8'),
('textbox', 'sn', 'Surname8'),
('password', 'userpassword', 'Password123 '),
('password', 'userpassword2', 'Password123 '),
]
}
PKEY_PASSWD_MISMATCH = 'itest-user-passwd-mismatch'
DATA_PASSWD_MISMATCH = {
'pkey': PKEY_PASSWD_MISMATCH,
'add': [
('textbox', 'uid', PKEY_PASSWD_MISMATCH),
('textbox', 'givenname', 'Name9'),
('textbox', 'sn', 'Surname9'),
('password', 'userpassword', 'Password123'),
('password', 'userpassword2', 'Password12'),
]
}
PKEY_NO_LOGIN = 'itest-user-no-login'
DATA_NO_LOGIN = {
'pkey': PKEY_NO_LOGIN,
'add': [
('textbox', 'givenname', 'Name10'),
('textbox', 'sn', 'Surname10'),
('password', 'userpassword', 'Password123'),
('password', 'userpassword2', 'Password123'),
]
}
SSH_RSA = (
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBVmLXpTDhrYkABOPlADFk'
'GV8/QfgQqUQ0xn29hk18t/NTEQOW/Daq4EF84e9aTiopRXIk7jahBLzwWTZI'
'WwuvegGYqs89bDhUHZEnS9TBfXkkYq9LamlEVooR5kxb/kPtCnmMMXhQUOzH'
'xqakuZiN4AduRCzaecu0mearVjZWAChM3fYp4sMXKoRzek2F/xOUh81GxrW0'
'kbhpbaeXd6oG8p6AC3QCrEspzX78WEOCPSTJlx/BAv77A27b5zO2cSeZNbZq'
'XFqaQQj8AX46qoATWLhOnokoE2xeJTKikG/4nmc3D2KO6SRh66dEQWtJuVVw'
'ZqgQRdaseDjjgR1FKbC1'
)
SSH_RSA2 = (
'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBVmLXpTDhrYkABOPlADFk'
'GV8/QfgQqUQ0xn29hk18t/NTEQOW/Daq4EF84e9aTiopRXIk7jahBLzwWTZI'
'WwuvegGYqs89bDhUHZEnS9TBfXkkYq9LamlEVooR5kxb/kPtCnmMMXhQUOzH'
'xqakuZiN4AduRCzaecu0mearVjZWAChM3fYp4sMXKoRzek2F/xOUh81GxrW0'
'kbhpbaeXd6oG8p6AC3QCrEspzX78WEOCPSTJlx/BAv77A27b5zO2cSeZNbZq'
'XFqaQQj8AX46qoATWLhOnokoE2xeJTKikG/4nmc3D2KO6SRh66dEQWtJuVVw'
'ZqgQRdaseDjjgR1FK222'
)
SSH_DSA = (
'ssh-dss AAAAB3NzaC1kc3MAAACBAKSh2gHHQ0lsPEKZU7utlx3I/M8FtSMx'
'+MtE+QjReRPIWHjwTHLC6j5Bh2A8kwwiiqiiiDbvkJPgV3+5zmrnWvTICzet'
'zS4vOgk6ymDux2J/1JPRb6c2yjjFaYL0SndC6abdgohyUAJPzNkgEhnQll/o'
'QeavJXzLyonaX1wcl+R1AAAAFQCuMfl69Zyrx5B1qZmUsRVqG24W7wAAAIEA'
'pFVe4JOuhRjSufJXMV+nzoqkhIhDEOYLqcpnq3cUrvBFEkQ5tKyYephFJxq+'
'u7xkFx4d/K5eC7NH6/o/ziBocKJ7ESXBihC2lGLsHnWqreN9vCBihspBij+n'
'/wUpgcq2dMBDC2BzqCfdashM1xHm1XahqCvV87pvjRhl1avy+K0AAACAEQKs'
'3kKhEB/WGuAQa+tojRyIwtBc4lzZuJia4qOg6R4oSviKINwEtFtH08snteGn'
'c4qiZ6XBrfYJT2VS1yjFVj+OmGSHmrX1GdfRfco8Y1ZYC7VLwt20dutw9hKK'
'MSHI9NrJ5oOZ/GONlaKuqzKtTNb/vOIn/8yz52Od3X2Ehh1='
)

View File

@@ -33,15 +33,29 @@ import pytest
try: try:
from selenium.webdriver.common.by import By from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains
except ImportError: except ImportError:
pass pass
EMPTY_MOD = 'no modifications to be performed'
USR_EXIST = 'user with name "{}" already exists'
USR_ADDED = 'User successfully added'
INVALID_SSH_KEY = "invalid 'sshpubkey': invalid SSH public key"
INV_FIRSTNAME = ("invalid 'first': Leading and trailing spaces are "
"not allowed")
FIELD_REQ = 'Required field'
ERR_INCLUDE = 'may only include letters, numbers, _, -, . and $'
ERR_MISMATCH = 'Passwords must match'
ERR_ADMIN_DEL = ('admin cannot be deleted or disabled because it is the last '
'member of group admins')
USR_EXIST = 'user with name "{}" already exists' USR_EXIST = 'user with name "{}" already exists'
ENTRY_EXIST = 'This entry already exists' ENTRY_EXIST = 'This entry already exists'
ACTIVE_ERR = 'active user with name "{}" already exists' ACTIVE_ERR = 'active user with name "{}" already exists'
DISABLED = 'This entry is already disabled' DISABLED = 'This entry is already disabled'
LONG_LOGIN = "invalid 'login': can be at most 32 characters"
INV_PASSWD = ("invalid 'password': Leading and trailing spaces are "
"not allowed")
@pytest.mark.tier1 @pytest.mark.tier1
class user_tasks(UI_driver): class user_tasks(UI_driver):
@@ -50,6 +64,29 @@ class user_tasks(UI_driver):
content = file_d.read() content = file_d.read()
return content return content
def create_email_addr(self, pkey):
"""
Piece an email address together from hostname due possible different
DNS setup
"""
domain = '.'.join(self.config.get('ipa_server').split('.')[1:])
return '{}@{}'.format(pkey, domain)
def add_default_email_for_validation(self, data):
"""
E-mail is generated automatically and we do not know domain yet in
data_user so in order to validate all mail fields we need to get it
there.
"""
mail = self.create_email_addr(user.DATA.get('pkey'))
for ele in data['mod_v']:
if 'mail' in ele:
ele[2].append(mail)
return data
@pytest.mark.tier1 @pytest.mark.tier1
class test_user(user_tasks): class test_user(user_tasks):
@@ -60,7 +97,8 @@ class test_user(user_tasks):
Basic CRUD: user Basic CRUD: user
""" """
self.init_app() self.init_app()
self.basic_crud(user.ENTITY, user.DATA) data = self.add_default_email_for_validation(user.DATA)
self.basic_crud(user.ENTITY, data)
@screenshot @screenshot
def test_associations(self): def test_associations(self):
@@ -376,6 +414,237 @@ class test_user(user_tasks):
self.wait_for_request(n=3) self.wait_for_request(n=3)
self.assert_no_error_dialog() self.assert_no_error_dialog()
@screenshot
def test_login_without_username(self):
self.init_app(login='', password='xxx123')
alert_e = self.find('.alert[data-name="username"]',
By.CSS_SELECTOR)
assert 'Username: Required field' in alert_e.text, 'Alert expected'
assert self.login_screen_visible()
@screenshot
def test_disable_delete_admin(self):
"""
Test disabling/deleting admin is not allowed
"""
self.init_app()
self.navigate_to_entity(user.ENTITY)
# try to disable admin user
self.select_record('admin')
self.facet_button_click('disable')
self.dialog_button_click('ok')
self.assert_last_error_dialog(ERR_ADMIN_DEL, details=True)
self.dialog_button_click('ok')
self.assert_record('admin')
# try to delete admin user. Later we are
# confirming by keyboard to test also ticket 4097
self.select_record('admin')
self.facet_button_click('remove')
self.dialog_button_click('ok')
self.assert_last_error_dialog(ERR_ADMIN_DEL, details=True)
actions = ActionChains(self.driver)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.ENTER).perform()
self.wait(0.5)
self.assert_record('admin')
@screenshot
def test_add_user_special(self):
"""
Test various add user special cases
"""
self.init_app()
# Test invalid characters (#@*?) in login
self.navigate_to_entity(user.ENTITY)
self.facet_button_click('add')
self.fill_textbox('uid', 'itest-user#')
self.assert_field_validation(ERR_INCLUDE)
self.fill_textbox('uid', 'itest-user@')
self.assert_field_validation(ERR_INCLUDE)
self.fill_textbox('uid', 'itest-user*')
self.assert_field_validation(ERR_INCLUDE)
self.fill_textbox('uid', 'itest-user?')
self.assert_field_validation(ERR_INCLUDE)
self.dialog_button_click('cancel')
# Add an user with special chars
self.basic_crud(user.ENTITY, user.DATA_SPECIAL_CHARS)
# Add an user with long login (should FAIL)
self.add_record(user.ENTITY, user.DATA_LONG_LOGIN, negative=True)
self.assert_last_error_dialog(expected_err=LONG_LOGIN)
self.close_all_dialogs()
# Test password mismatch
self.add_record(user.ENTITY, user.DATA_PASSWD_MISMATCH, negative=True)
pass_e = self.find('.widget[name="userpassword2"]', By.CSS_SELECTOR)
self.assert_field_validation(ERR_MISMATCH, parent=pass_e)
self.dialog_button_click('cancel')
self.assert_record(user.DATA_PASSWD_MISMATCH.get('pkey'),
negative=True)
# test add and edit record
self.add_record(user.ENTITY, user.DATA2, dialog_btn='add_and_edit')
self.action_list_action('delete_active_user')
# click add and cancel
self.add_record(user.ENTITY, user.DATA, dialog_btn='cancel')
# add leading space before password (should FAIL)
self.navigate_to_entity(user.ENTITY)
self.facet_button_click('add')
self.fill_fields(user.DATA_PASSWD_LEAD_SPACE['add'])
self.dialog_button_click('add')
self.assert_last_error_dialog(INV_PASSWD)
self.close_all_dialogs()
# add trailing space before password (should FAIL)
self.navigate_to_entity(user.ENTITY)
self.facet_button_click('add')
self.fill_fields(user.DATA_PASSWD_TRAIL_SPACE['add'])
self.dialog_button_click('add')
self.assert_last_error_dialog(INV_PASSWD)
self.close_all_dialogs()
# add user using enter
self.add_record(user.ENTITY, user.DATA2, negative=True)
actions = ActionChains(self.driver)
actions.send_keys(Keys.ENTER).perform()
self.wait()
self.assert_notification(assert_text=USR_ADDED)
self.assert_record(user.PKEY2)
self.close_notifications()
# delete user using enter
self.select_record(user.PKEY2)
self.facet_button_click('remove')
actions.send_keys(Keys.ENTER).perform()
self.wait(0.5)
self.assert_notification(assert_text='1 item(s) deleted')
self.assert_record(user.PKEY2, negative=True)
@screenshot
def test_add_delete_undo_reset_multivalue(self):
"""
Test add and delete multivalue with reset and undo
"""
self.init_app()
first_mail = self.create_email_addr(user.DATA.get('pkey'))
self.add_record(user.ENTITY, user.DATA)
self.navigate_to_record(user.DATA.get('pkey'))
# add a new mail (without save) and reset
self.add_multivalued('mail', 'temp@ipa.test')
self.assert_undo_button('mail')
self.facet_button_click('revert')
self.assert_undo_button('mail', visible=False)
# click at delete on the first mail and reset
self.del_multivalued('mail', first_mail)
self.assert_undo_button('mail')
self.facet_button_click('revert')
self.assert_undo_button('mail', visible=False)
# edit the first mail and reset
self.edit_multivalued('mail', first_mail, 'temp@ipa.test')
self.assert_undo_button('mail')
self.facet_button_click('revert')
self.assert_undo_button('mail', visible=False)
# add a new mail and undo
self.add_multivalued('mail', 'temp@ipa.test')
self.assert_undo_button('mail')
self.undo_multivalued('mail', 'temp@ipa.test')
self.assert_undo_button('mail', visible=False)
# edit the first mail and undo
self.edit_multivalued('mail', first_mail, 'temp@ipa.test')
self.assert_undo_button('mail')
self.undo_multivalued('mail', 'temp@ipa.test')
self.assert_undo_button('mail', visible=False)
# cleanup
self.delete(user.ENTITY, [user.DATA])
def test_user_misc(self):
"""
Test various miscellaneous test cases under one roof to save init time
"""
self.init_app()
# add already existing user (should fail) / also test ticket 4098
self.add_record(user.ENTITY, user.DATA)
self.add_record(user.ENTITY, user.DATA, negative=True,
pre_delete=False)
self.assert_last_error_dialog(USR_EXIST.format(user.PKEY))
actions = ActionChains(self.driver)
actions.send_keys(Keys.TAB)
actions.send_keys(Keys.ENTER).perform()
self.wait(0.5)
self.dialog_button_click('cancel')
# add user without login name
self.add_record(user.ENTITY, user.DATA_NO_LOGIN)
self.assert_record('nsurname10')
# try to add same user without login name again (should fail)
self.add_record(user.ENTITY, user.DATA_NO_LOGIN, negative=True,
pre_delete=False)
self.assert_last_error_dialog(USR_EXIST.format('nsurname10'))
self.close_all_dialogs()
# try to modify user`s UID to -1 (should fail)
self.navigate_to_record(user.PKEY)
self.mod_record(
user.ENTITY, {'mod': [('textbox', 'uidnumber', '-1')]},
negative=True)
uid_e = self.find('.widget[name="uidnumber"]', By.CSS_SELECTOR)
self.assert_field_validation('Minimum value is 1', parent=uid_e)
self.facet_button_click('revert')
# edit user`s "First name" to value with leading space (should fail)
self.fill_input('givenname', ' leading_space')
self.facet_button_click('save')
self.assert_last_error_dialog(INV_FIRSTNAME)
self.dialog_button_click('cancel')
# edit user`s "First name" to value with trailing space (should fail)
self.fill_input('givenname', 'trailing_space ')
self.facet_button_click('save')
self.assert_last_error_dialog(INV_FIRSTNAME)
self.dialog_button_click('cancel')
# try with blank "First name" (should fail)
gn_input_s = "input[type='text'][name='givenname']"
gn_input_el = self.find(gn_input_s, By.CSS_SELECTOR, strict=True)
gn_input_el.clear()
gn_input_el.send_keys(Keys.BACKSPACE)
self.facet_button_click('save')
gn_e = self.find('.widget[name="givenname"]', By.CSS_SELECTOR)
self.assert_field_validation(FIELD_REQ, parent=gn_e)
self.close_notifications()
# search user / multiple users
self.navigate_to_entity(user.ENTITY)
self.wait(0.5)
self.find_record('user', user.DATA)
self.add_record(user.ENTITY, user.DATA2)
self.find_record('user', user.DATA2)
# search for both users (just 'itest-user' will do)
self.find_record('user', user.DATA)
self.assert_record(user.PKEY2)
# cleanup
self.delete_record([user.PKEY, user.PKEY2, user.PKEY_NO_LOGIN,
'nsurname10'])
@pytest.mark.tier1 @pytest.mark.tier1
class test_user_no_private_group(UI_driver): class test_user_no_private_group(UI_driver):
@@ -510,7 +779,7 @@ class TestLifeCycles(UI_driver):
# send multiple records to preserved # send multiple records to preserved
self.navigate_to_entity('stageuser') self.navigate_to_entity('stageuser')
self.navigate_to_entity('user') self.navigate_to_entity(user.ENTITY)
self.delete_record([user.PKEY, user.PKEY2], self.delete_record([user.PKEY, user.PKEY2],
confirm_btn=None) confirm_btn=None)
self.check_option('preserve', value='true') self.check_option('preserve', value='true')
@@ -527,7 +796,7 @@ class TestLifeCycles(UI_driver):
self.wait() self.wait()
# send multiple users to staged (through preserved) # send multiple users to staged (through preserved)
self.navigate_to_entity('user') self.navigate_to_entity(user.ENTITY)
self.delete_record([user.PKEY, user.PKEY2], self.delete_record([user.PKEY, user.PKEY2],
confirm_btn=None) confirm_btn=None)
self.check_option('preserve', value='true') self.check_option('preserve', value='true')
@@ -588,6 +857,139 @@ class TestLifeCycles(UI_driver):
self.assert_record_value('Enabled', [user.PKEY, user.PKEY2], self.assert_record_value('Enabled', [user.PKEY, user.PKEY2],
'nsaccountlock') 'nsaccountlock')
# cleanup and check for ticket 4245 (select all should not remain
# checked after delete action). Two "ok" buttons at the end are needed
# for delete confirmation and acknowledging that "admin" cannot be
# deleted.
self.navigate_to_entity(user.ENTITY)
select_all_btn = self.find('input[title="Select All"]',
By.CSS_SELECTOR)
select_all_btn.click()
self.facet_button_click('remove')
self.dialog_button_click('ok')
self.dialog_button_click('ok')
self.assert_value_checked('admin', 'uid', negative=True)
@pytest.mark.tier1
class TestSSHkeys(UI_driver):
@screenshot
def test_ssh_keys(self):
self.init_app()
# add and undo SSH key
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False,
navigate=True)
self.assert_num_ssh_keys(1)
self.undo_ssh_keys()
self.assert_num_ssh_keys(0)
# add and undo 2 SSH keys (using undo all)
ssh_keys = [user.SSH_RSA, user.SSH_DSA]
self.add_sshkey_to_record(ssh_keys, 'admin', save=False)
self.assert_num_ssh_keys(2)
self.undo_ssh_keys(btn_name='undo_all')
self.assert_num_ssh_keys(0)
# add SSH key and refresh
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.assert_num_ssh_keys(1)
self.facet_button_click('refresh')
self.assert_num_ssh_keys(0)
# add SSH key and revert
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.assert_num_ssh_keys(1)
self.facet_button_click('revert')
self.assert_num_ssh_keys(0)
# add SSH key, move elsewhere and cancel.
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.assert_num_ssh_keys(1)
self.switch_to_facet('memberof_group')
self.dialog_button_click('cancel')
self.assert_num_ssh_keys(1)
self.undo_ssh_keys()
# add SSH key, move elsewhere and click reset button.
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.assert_num_ssh_keys(1)
self.switch_to_facet('memberof_group')
self.wait_for_request()
self.dialog_button_click('revert')
self.wait()
self.switch_to_facet('details')
self.assert_num_ssh_keys(0)
# add SSH key, move elsewhere and click save button.
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.assert_num_ssh_keys(1)
self.switch_to_facet('memberof_group')
self.wait()
self.dialog_button_click('save')
self.wait_for_request(n=4)
self.switch_to_facet('details')
self.assert_num_ssh_keys(1)
self.delete_record_sshkeys('admin')
# add, save and delete RSA and DSA keys
keys = [user.SSH_RSA, user.SSH_DSA]
self.add_sshkey_to_record(keys, 'admin')
self.assert_num_ssh_keys(2)
self.delete_record_sshkeys('admin')
self.assert_num_ssh_keys(0)
# add RSA SSH keys with trailing space and "=" sign at the end
keys = [user.SSH_RSA+" ", user.SSH_RSA2+"="]
self.add_sshkey_to_record(keys, 'admin')
self.assert_num_ssh_keys(2)
self.delete_record_sshkeys('admin')
self.assert_num_ssh_keys(0)
# lets try to add empty SSH key (should fail)
self.add_sshkey_to_record('', 'admin')
self.assert_last_error_dialog(EMPTY_MOD)
self.dialog_button_click('cancel')
self.undo_ssh_keys()
# try to add invalid SSH key
self.add_sshkey_to_record('invalid_key', 'admin')
self.assert_last_error_dialog(INVALID_SSH_KEY)
self.dialog_button_click('cancel')
self.undo_ssh_keys()
# add duplicate SSH keys
self.add_sshkey_to_record(user.SSH_RSA, 'admin')
self.add_sshkey_to_record(user.SSH_RSA, 'admin', save=False)
self.facet_button_click('save')
self.assert_last_error_dialog(EMPTY_MOD)
self.dialog_button_click('cancel')
# test SSH key edit when user lacks write rights for related attribute
# see ticket 3800 (we use DATA_SPECIAL_CHARS just for convenience)
self.add_record(user.ENTITY, [user.DATA2, user.DATA_SPECIAL_CHARS])
self.add_sshkey_to_record(user.SSH_RSA, user.PKEY2, navigate=True)
self.logout()
self.init_app(user.PKEY_SPECIAL_CHARS, user.PASSWD_SCECIAL_CHARS)
self.navigate_to_record(user.PKEY2, entity=user.ENTITY)
show_ssh_key_btn = self.find('div.widget .btn[name="ipasshpubkey-0"]',
By.CSS_SELECTOR)
show_ssh_key_btn.click()
ssh_key_e = self.find('textarea', By.CSS_SELECTOR, self.get_dialog())
assert ssh_key_e.get_attribute('readonly') == 'true'
self.dialog_button_click('cancel')
self.logout()
self.init_app()
# cleanup # cleanup
self.navigate_to_entity('user') self.delete(user.ENTITY, [user.DATA2, user.DATA_SPECIAL_CHARS])
self.delete_record([user.PKEY, user.PKEY2]) self.delete_record_sshkeys('admin', navigate=True)