URL: https://github.com/freeipa/freeipa/pull/1925
Author: Rezney
 Title: #1925: ui_tests: extend test_selinuxusermap.py suite
Action: opened

PR body:
"""
Extend test_selinuxusermap.py suite with new test cases. Details in the ticket.
    
We also modify "add_table_associations" to handle "cancel" and "negative" in 
the way other methods works.
    
Lastly, we start using dialog_btn=None to test keyboard confirmation as we did 
use it incorrectly with "Negative=True" where it was already confirmed by 
"click".
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1925/head:pr1925
git checkout pr1925
From 790ff512b48d90b1f82fa8eef285b259983ac93c Mon Sep 17 00:00:00 2001
From: Michal Reznik <mrez...@redhat.com>
Date: Mon, 14 May 2018 13:31:06 +0200
Subject: [PATCH 1/2] ui_tests: extend test_selinuxusermap.py suite

Extend test_selinuxusermap.py suite with new test cases. Details in
the ticket.

We also modify "add_table_associations" to handle "cancel" and
"negative" in the way other methods works.

Lastly, we start using dialog_btn=None to test keyboard confirmation
as we did use it incorrectly with "Negative=True" where it was already
confirmed by "click".

https://pagure.io/freeipa/issue/7544
---
 ipatests/test_webui/data_selinuxusermap.py | 100 +++++++++++
 ipatests/test_webui/test_netgroup.py       |   4 +-
 ipatests/test_webui/test_selinuxusermap.py | 263 +++++++++++++++++++++++++++++
 ipatests/test_webui/ui_driver.py           |  16 +-
 4 files changed, 376 insertions(+), 7 deletions(-)
 create mode 100644 ipatests/test_webui/data_selinuxusermap.py

diff --git a/ipatests/test_webui/data_selinuxusermap.py b/ipatests/test_webui/data_selinuxusermap.py
new file mode 100644
index 0000000000..c8e826bf27
--- /dev/null
+++ b/ipatests/test_webui/data_selinuxusermap.py
@@ -0,0 +1,100 @@
+#
+# Copyright (C) 2018  FreeIPA Contributors see COPYING for license
+#
+
+ENTITY = 'selinuxusermap'
+
+PKEY = 'itest-selinuxusermap'
+DATA = {
+    'pkey': PKEY,
+    'add': [
+        ('textbox', 'cn', PKEY),
+        ('textbox', 'ipaselinuxuser', 'user_u:s0'),
+    ],
+    'mod': [
+        ('textarea', 'description', 'itest-selinuxusermap desc'),
+    ],
+}
+
+PKEY2 = 'itest-selinuxusermap2'
+DATA2 = {
+    'pkey': PKEY2,
+    'add': [
+        ('textbox', 'cn', PKEY2),
+        ('textbox', 'ipaselinuxuser', 'unconfined_u:s0-s0:c0.c1023'),
+    ],
+    'mod': [
+        ('textarea', 'description', 'itest-selinuxusermap desc2'),
+    ],
+}
+
+PKEY_MLS_RANGE = 'itest-selinuxusermap_MLS_range'
+DATA_MLS_RANGE = {
+    'pkey': PKEY_MLS_RANGE,
+    'add': [
+        ('textbox', 'cn', PKEY_MLS_RANGE),
+        ('textbox', 'ipaselinuxuser', 'user_u:s0-s1'),
+    ],
+}
+
+PKEY_MCS_RANGE = 'itest-selinuxusermap_MLS_range'
+DATA_MCS_RANGE = {
+    'pkey': PKEY_MCS_RANGE,
+    'add': [
+        ('textbox', 'cn', PKEY_MCS_RANGE),
+        ('textbox', 'ipaselinuxuser', 'user_u:s0-s15:c0.c1023'),
+    ],
+}
+
+PKEY_MCS_COMMAS = 'itest-selinuxusermap_MCS_commas'
+DATA_MCS_COMMAS = {
+    'pkey': PKEY_MCS_COMMAS,
+    'add': [
+        ('textbox', 'cn', PKEY_MCS_COMMAS),
+        ('textbox', 'ipaselinuxuser', 'user_u:s0-s1:c0,c2,c15.c26'),
+    ],
+}
+
+PKEY_MLS_SINGLE_VAL = 'itest-selinuxusermap_MLS_single_val'
+DATA_MLS_SINGLE_VAL = {
+    'pkey': PKEY_MLS_SINGLE_VAL,
+    'add': [
+        ('textbox', 'cn', PKEY_MLS_SINGLE_VAL),
+        ('textbox', 'ipaselinuxuser', 'user_u:s0-s0:c0.c1023'),
+    ],
+}
+
+PKEY_NON_EXIST_SEUSER = 'itest-selinuxusermap_nonexistent_user'
+DATA_NON_EXIST_SEUSER = {
+    'pkey': PKEY_NON_EXIST_SEUSER,
+    'add': [
+        ('textbox', 'cn', PKEY_NON_EXIST_SEUSER),
+        ('textbox', 'ipaselinuxuser', 'abc:s0'),
+    ],
+}
+
+PKEY_INVALID_MCS = 'itest-selinuxusermap_invalid_MCS'
+DATA_INVALID_MCS = {
+    'pkey': PKEY_INVALID_MCS,
+    'add': [
+        ('textbox', 'cn', PKEY_INVALID_MCS),
+        ('textbox', 'ipaselinuxuser', 'user:s0:c'),
+    ],
+}
+
+PKEY_INVALID_MLS = 'itest-selinuxusermap_invalid_MLS'
+DATA_INVALID_MLS = {
+    'pkey': PKEY_INVALID_MLS,
+    'add': [
+        ('textbox', 'cn', PKEY_INVALID_MLS),
+        ('textbox', 'ipaselinuxuser', 'user'),
+    ],
+}
+
+PKEY_FIELD_REQUIRED = 'itest-selinuxusermap_without_SELinux_user'
+DATA_FIELD_REQUIRED = {
+    'pkey': PKEY_FIELD_REQUIRED,
+    'add': [
+        ('textbox', 'cn', PKEY_FIELD_REQUIRED),
+    ],
+}
diff --git a/ipatests/test_webui/test_netgroup.py b/ipatests/test_webui/test_netgroup.py
index bc29cfc587..069894af81 100644
--- a/ipatests/test_webui/test_netgroup.py
+++ b/ipatests/test_webui/test_netgroup.py
@@ -68,7 +68,7 @@ def test_basic_workflows(self):
                         delete=True)
 
         # add netgroup using enter
-        self.add_record(netgroup.ENTITY, netgroup.DATA, negative=True)
+        self.add_record(netgroup.ENTITY, netgroup.DATA, dialog_btn=None)
         actions = ActionChains(self.driver)
         actions.send_keys(Keys.ENTER).perform()
         self.wait_for_request()
@@ -331,7 +331,7 @@ def get_t_vals(t):
 
         for t in tables:
             table, keys, _exts = get_t_vals(t)
-            self.add_table_associations(table, [keys[0]], negative=True)
+            self.add_table_associations(table, [keys[0]], confirm_btn='cancel')
 
             # verifying members listed as links ticket#2670
             self.add_table_associations(table, [keys[0]])
diff --git a/ipatests/test_webui/test_selinuxusermap.py b/ipatests/test_webui/test_selinuxusermap.py
index 77216891d0..67e7c3cb91 100644
--- a/ipatests/test_webui/test_selinuxusermap.py
+++ b/ipatests/test_webui/test_selinuxusermap.py
@@ -25,10 +25,31 @@
 from ipatests.test_webui.ui_driver import screenshot
 import ipatests.test_webui.data_user as user
 import ipatests.test_webui.data_group as group
+import ipatests.test_webui.data_selinuxusermap as selinux
 import ipatests.test_webui.data_hostgroup as hostgroup
+import ipatests.test_webui.data_hbac as hbac
 from ipatests.test_webui.test_host import host_tasks, ENTITY as HOST_ENTITY
 import pytest
 
+try:
+    from selenium.webdriver.common.by import By
+    from selenium.webdriver.common.keys import Keys
+    from selenium.webdriver.common.action_chains import ActionChains
+except ImportError:
+    pass
+
+RULE_ALR_EXIST = 'SELinux User Map rule with name "{}" already exists'
+RULE_UPDATED = 'SELinux User Map {} updated'
+RULE_ADDED = 'SELinux User Map successfully added'
+INVALID_SEUSER = 'SELinux user {} not found in ordering list (in config)'
+INVALID_MCS = ("invalid 'selinuxuser': Invalid MCS value, must match c[0-1023]"
+              ".c[0-1023] and/or c[0-1023]-c[0-c0123]")
+INVALID_MLS = ("invalid 'selinuxuser': Invalid MLS value, must match "
+              "s[0-15](-s[0-15])")
+HBAC_DEL_ERR = ('{} cannot be deleted because SELinux User Map {} requires '
+               'it')
+HBAC_MEMBER_ERR = 'HBAC rule and local members cannot both be set'
+
 ENTITY = 'selinuxusermap'
 PKEY = 'itest-selinuxusermap'
 DATA = {
@@ -68,7 +89,9 @@ def test_mod(self):
         self.add_record(group.ENTITY, group.DATA)
         self.add_record(group.ENTITY, group.DATA2, navigate=False)
         self.add_record(HOST_ENTITY, host.data)
+        self.close_notifications()
         self.add_record(HOST_ENTITY, host.data2, navigate=False)
+        self.close_notifications()
         self.add_record(hostgroup.ENTITY, hostgroup.DATA)
         self.add_record(hostgroup.ENTITY, hostgroup.DATA2, navigate=False)
         self.add_record(ENTITY, DATA)
@@ -89,6 +112,19 @@ def test_mod(self):
 
         self.mod_rule_tables(tables, categories, [])
 
+        # add associations then cancel
+        def get_t_vals(t):
+            table = t[0]
+            k = t[1]
+            e = []
+            if len(t) > 2:
+                e = t[2]
+            return table, k, e
+
+        for t in tables:
+            table, keys, _exts = get_t_vals(t)
+            self.add_table_associations(table, [keys[0]], confirm_btn='cancel')
+
         # cleanup
         # -------
         self.delete(ENTITY, [DATA])
@@ -110,3 +146,230 @@ def test_actions(self):
         self.disable_action()
         self.enable_action()
         self.delete_action(ENTITY, PKEY)
+
+    @screenshot
+    def test_misc(self):
+
+        self.init_app()
+
+        # test add and add another record
+        self.add_record(selinux.ENTITY, [selinux.DATA, selinux.DATA2])
+
+        # test delete multiple records
+        self.delete_record([selinux.DATA, selinux.DATA2])
+
+        # test add and cancel adding record
+        self.add_record(selinux.ENTITY, selinux.DATA, dialog_btn='cancel')
+
+        # test add and edit record
+        self.add_record(selinux.ENTITY, selinux.DATA,
+                        dialog_btn='add_and_edit')
+
+        # test add duplicate rule (should FAIL)
+        self.add_record(selinux.ENTITY, selinux.DATA, negative=True,
+                        pre_delete=False)
+        self.assert_last_error_dialog(RULE_ALR_EXIST.format(selinux.PKEY))
+        self.close_all_dialogs()
+
+        # test add disabled HBAC rule to SElinux rule
+        self.add_record(hbac.RULE_ENTITY, hbac.RULE_DATA)
+        self.navigate_to_record(hbac.RULE_PKEY)
+        self.disable_action()
+        self.navigate_to_record(selinux.PKEY, entity=selinux.ENTITY)
+        self.facet_button_click('refresh')
+        self.select_combobox('seealso', hbac.RULE_PKEY)
+        self.facet_button_click('save')
+        self.wait_for_request()
+        self.assert_notification(assert_text=RULE_UPDATED.format(selinux.PKEY))
+        self.close_all_dialogs()
+
+        # test deleting HBAC rule used in SELinux user map (should FAIL)
+        self.delete(hbac.RULE_ENTITY, [hbac.RULE_DATA])
+        self.assert_last_error_dialog(
+            HBAC_DEL_ERR.format(hbac.RULE_PKEY, selinux.PKEY), details=True)
+        self.close_all_dialogs()
+        self.select_record(hbac.RULE_PKEY, unselect=True)
+
+        # test adding user to SELinux map together with HBAC rule (should FAIL)
+        self.navigate_to_record(selinux.PKEY, entity=selinux.ENTITY)
+        self.add_table_associations('memberuser_user', ['admin'],
+                                    negative=True)
+        self.assert_last_error_dialog(HBAC_MEMBER_ERR)
+        self.close_all_dialogs()
+
+        # test adding HBAC rule together with user (should FAIL)
+        self.add_record(selinux.ENTITY, selinux.DATA2)
+        self.navigate_to_record(selinux.PKEY2)
+        self.add_table_associations('memberuser_user', ['admin'],
+                                    negative=True)
+        self.select_combobox('seealso', hbac.RULE_PKEY)
+        self.facet_button_click('save')
+        self.assert_last_error_dialog(HBAC_MEMBER_ERR)
+        self.close_all_dialogs()
+
+        # test add rule without "SELinux user" (requires the field)
+        self.add_record(selinux.ENTITY, selinux.DATA_FIELD_REQUIRED,
+                        negative=True)
+        self.assert_field_validation_required(field='ipaselinuxuser')
+        self.close_all_dialogs()
+
+        # test add rule with non-existent SELinux user
+        self.add_record(selinux.ENTITY, selinux.DATA_NON_EXIST_SEUSER,
+                        negative=True)
+        self.assert_last_error_dialog(expected_err=INVALID_SEUSER.format(
+            selinux.DATA_NON_EXIST_SEUSER['add'][1][2]))
+        self.close_all_dialogs()
+
+        # test add invalid MCS
+        self.add_record(selinux.ENTITY, selinux.DATA_INVALID_MCS,
+                        negative=True)
+        self.assert_last_error_dialog(expected_err=INVALID_MCS)
+        self.close_all_dialogs()
+
+        # test add invalid MLS
+        self.add_record(selinux.ENTITY, selinux.DATA_INVALID_MLS,
+                        negative=True)
+        self.assert_last_error_dialog(expected_err=INVALID_MLS)
+        self.close_all_dialogs()
+
+        # test search SELinux usermap
+        self.find_record(selinux.ENTITY, selinux.DATA)
+
+        # test disable enable multiple SELinux rules
+        self.select_multiple_records([selinux.DATA, selinux.DATA2])
+        self.facet_button_click('disable')
+        self.dialog_button_click('ok')
+        self.assert_notification(assert_text='2 item(s) disabled')
+        self.close_notifications()
+        self.assert_record_value('Disabled', [selinux.PKEY, selinux.PKEY2],
+                                 'ipaenabledflag')
+        self.select_multiple_records([selinux.DATA, selinux.DATA2])
+        self.facet_button_click('enable')
+        self.dialog_button_click('ok')
+        self.assert_notification(assert_text='2 item(s) enabled')
+        self.close_notifications()
+        self.assert_record_value('Enabled', [selinux.PKEY, selinux.PKEY2],
+                                 'ipaenabledflag')
+
+        # test add / delete SELinux usermap confirming using ENTER key
+        self.add_record(selinux.ENTITY, selinux.DATA, dialog_btn=None)
+        actions = ActionChains(self.driver)
+        actions.send_keys(Keys.ENTER).perform()
+        self.wait()
+        self.assert_notification(assert_text=RULE_ADDED)
+        self.assert_record(selinux.PKEY)
+        self.close_notifications()
+        self.delete_record(selinux.PKEY, confirm_btn=None)
+        actions = ActionChains(self.driver)
+        actions.send_keys(Keys.ENTER).perform()
+        self.wait()
+        self.assert_notification(assert_text='1 item(s) deleted')
+        self.assert_record(selinux.PKEY, negative=True)
+        self.close_notifications()
+
+        # cleanup
+        self.delete(selinux.ENTITY, [selinux.DATA2])
+        self.delete(hbac.RULE_ENTITY, [hbac.RULE_DATA])
+
+    @screenshot
+    def test_add_different_rules(self):
+
+        self.init_app()
+
+        self.navigate_to_entity('config')
+        old_selinux_order = self.get_field_value('ipaselinuxusermaporder')
+        new_selinux_order = '{}${}${}${}${}'.format(
+            old_selinux_order,
+            selinux.DATA_MLS_RANGE['add'][1][2],
+            selinux.DATA_MCS_RANGE['add'][1][2],
+            selinux.DATA_MCS_COMMAS['add'][1][2],
+            selinux.DATA_MLS_SINGLE_VAL['add'][1][2])
+        self.fill_input('ipaselinuxusermaporder', new_selinux_order)
+        self.facet_button_click('save')
+
+        # test add MLS range rule
+        self.add_record(selinux.ENTITY, selinux.DATA_MLS_RANGE)
+        self.assert_record(selinux.PKEY_MLS_RANGE)
+
+        # test add MCS range rule
+        self.add_record(selinux.ENTITY, selinux.DATA_MCS_RANGE)
+        self.assert_record(selinux.PKEY_MCS_RANGE)
+
+        # test add MCS rule with commas
+        self.add_record(selinux.ENTITY, selinux.DATA_MCS_COMMAS)
+        self.assert_record(selinux.PKEY_MCS_COMMAS)
+
+        # test add MLS single value rule
+        self.add_record(selinux.ENTITY, selinux.DATA_MLS_SINGLE_VAL)
+        self.assert_record(selinux.PKEY_MLS_SINGLE_VAL)
+
+        # restore original SELinux user map order
+        self.navigate_to_entity('config')
+        self.fill_input('ipaselinuxusermaporder', old_selinux_order)
+        self.facet_button_click('save')
+
+        # cleanup
+        self.delete(selinux.ENTITY, [selinux.DATA_MLS_RANGE,
+                                     selinux.DATA_MCS_RANGE,
+                                     selinux.DATA_MCS_COMMAS,
+                                     selinux.DATA_MLS_SINGLE_VAL])
+
+    @screenshot
+    def test_undo_refresh_reset_update_cancel(self):
+
+        self.init_app()
+
+        mod_description = (selinux.DATA['mod'][0][2])
+
+        # test selinux usermap undo button
+        self.add_record(selinux.ENTITY, selinux.DATA)
+        self.navigate_to_record(selinux.PKEY)
+        self.fill_fields(selinux.DATA['mod'])
+        self.assert_undo_button('description')
+        desc_undo_btn_e = '.widget [name="description"] .btn.undo'
+        desc_undo_btn = self.find(desc_undo_btn_e, By.CSS_SELECTOR)
+        desc_undo_btn.click()
+        self.assert_undo_button('description', visible=False)
+        self.verify_btn_action(mod_description)
+
+        # test refresh button
+        self.fill_fields(selinux.DATA['mod'], undo=True)
+        self.facet_button_click('refresh')
+        self.verify_btn_action(mod_description)
+
+        # test reset button
+        self.mod_record(selinux.ENTITY, selinux.DATA, facet_btn='revert')
+        self.wait_for_request()
+        self.verify_btn_action(mod_description)
+
+        # test update button
+        self.fill_fields(selinux.DATA['mod'], undo=True)
+        self.facet_button_click('refresh')
+        self.verify_btn_action(mod_description)
+
+        # test reset button after trying to leave the details page
+        self.fill_fields(selinux.DATA2['mod'], undo=True)
+        self.click_on_link('SELinux User Maps')
+        self.dialog_button_click('revert')
+        self.navigate_to_record(selinux.PKEY)
+        self.verify_btn_action(mod_description)
+        self.wait_for_request(n=2)
+
+        # test update button after trying to leave the details page
+        self.fill_fields(selinux.DATA['mod'], undo=True)
+        self.click_on_link('SELinux User Maps')
+        self.dialog_button_click('save')
+        self.navigate_to_record(selinux.PKEY)
+        self.verify_btn_action(mod_description, negative=True)
+        self.wait_for_request(n=2)
+
+    def verify_btn_action(self, mod_description, negative=False):
+        """
+        camparing current description with modified description
+        """
+        current_description = self.get_field_value("description",
+                                                   element="textarea")
+        if negative:
+            assert current_description == mod_description
+        else:
+            assert current_description != mod_description
diff --git a/ipatests/test_webui/ui_driver.py b/ipatests/test_webui/ui_driver.py
index 34d21ae35d..0647b75cb7 100644
--- a/ipatests/test_webui/ui_driver.py
+++ b/ipatests/test_webui/ui_driver.py
@@ -1374,6 +1374,9 @@ def add_record(self, entity, data, facet='search', facet_btn='add',
             if record != last_element:
                 btn = add_another_btn
 
+            if not dialog_btn:
+                return
+
             self.dialog_button_click(btn)
             self.wait_for_request()
             self.wait_for_request()
@@ -1604,7 +1607,8 @@ def delete_associations(
             self.assert_record(key, negative=True)
 
     def add_table_associations(self, table_name, pkeys, parent=False,
-                               delete=False, negative=False):
+                               delete=False, confirm_btn='add',
+                               negative=False):
         """
         Add value to table (association|rule|...)
         """
@@ -1624,14 +1628,16 @@ def add_table_associations(self, table_name, pkeys, parent=False,
             self.button_click('add')
             self.wait()
 
-        if negative:
-            self.dialog_button_click('cancel')
+        self.dialog_button_click(confirm_btn)
+
+        if confirm_btn == 'cancel':
             self.assert_record(key, parent, table_name, negative=True)
             return
-        else:
-            self.dialog_button_click('add')
         self.wait_for_request(n=2)
 
+        if negative:
+            return
+
         for key in pkeys:
             self.assert_record(key, parent, table_name)
         if delete:

From 870337c4b40d96e556bf268a9e8a62bb5e4f4bd5 Mon Sep 17 00:00:00 2001
From: Michal Reznik <mrez...@redhat.com>
Date: Mon, 14 May 2018 13:48:38 +0200
Subject: [PATCH 2/2] TEMP_COMMIT: activate WebUI tests + other temp stuff

---
 .freeipa-pr-ci.yaml              | 174 +++++++--------------------------------
 ipatests/test_webui/ui_driver.py |  11 ++-
 2 files changed, 36 insertions(+), 149 deletions(-)

diff --git a/.freeipa-pr-ci.yaml b/.freeipa-pr-ci.yaml
index a16b388695..3130b52816 100644
--- a/.freeipa-pr-ci.yaml
+++ b/.freeipa-pr-ci.yaml
@@ -3,6 +3,9 @@ topologies:
     name: build
     cpu: 2
     memory: 3800
+  ipaserver: &ipaserver
+    name: ipaserver
+    cpu: 1
   master_1repl: &master_1repl
     name: master_1repl
     cpu: 4
@@ -27,183 +30,62 @@ jobs:
         timeout: 1800
         topology: *build
 
-  fedora-27/simple_replication:
+  fedora-27/test_webui_a_to_d:
     requires: [fedora-27/build]
     priority: 50
     job:
-      class: RunPytest
+      class: RunWebuiTests
       args:
         build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_simple_replication.py
+        test_suite: test_webui/test_automember.py test_webui/test_cert.py test_webui/test_config.py test_webui/test_delegation.py test_webui/test_dns.py
         template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
+        timeout: 7200
+        topology: *ipaserver
 
-  fedora-27/caless:
+  fedora-27/test_webui_g_to_m:
     requires: [fedora-27/build]
     priority: 50
     job:
-      class: RunPytest
+      class: RunWebuiTests
       args:
         build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_caless.py::TestServerReplicaCALessToCAFull
+        test_suite: test_webui/test_group.py test_webui/test_hbac.py test_webui/test_host.py test_webui/test_hostgroup.py test_webui/test_idviews.py test_webui/test_krbtpolicy.py test_webui/test_misc_cases.py
         template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
+        timeout: 7200
+        topology: *ipaserver
 
-  fedora-27/external_ca:
+  fedora-27/test_webui_n_to_r:
     requires: [fedora-27/build]
     priority: 50
     job:
-      class: RunPytest
+      class: RunWebuiTests
       args:
         build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_external_ca.py
+        test_suite: test_webui/test_navigation.py test_webui/test_netgroup.py test_webui/test_pwpolicy.py test_webui/test_range.py test_webui/test_rbac.py test_webui/test_realmdomains.py
         template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
+        timeout: 7200
+        topology: *ipaserver
 
-  fedora-27/test_topologies:
+  fedora-27/test_webui_s_to_z:
     requires: [fedora-27/build]
     priority: 50
     job:
-      class: RunPytest
+      class: RunWebuiTests
       args:
         build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_topologies.py
+        test_suite: test_webui/test_selfservice.py test_webui/test_selinuxusermap.py test_webui/test_service.py test_webui/test_sudo.py test_webui/test_trust.py test_webui/test_user.py test_webui/test_vault.py
         template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
+        timeout: 7200
+        topology: *ipaserver
 
-  fedora-27/test_sudo:
+  fedora-27/test_webui:
     requires: [fedora-27/build]
     priority: 50
     job:
-      class: RunPytest
+      class: RunWebuiTests
       args:
         build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_sudo.py
+        test_suite: test_webui/
         template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl_1client
-
-  fedora-27/test_ipa_cli:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_ipa_cli.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_kerberos_flags:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_kerberos_flags.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl_1client
-
-  fedora-27/test_http_kdc_proxy:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_http_kdc_proxy.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl_1client
-
-  fedora-27/test_forced_client_enrolment:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_forced_client_reenrollment.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl_1client
-
-  fedora-27/test_advise:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_advise.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_testconfig:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_testconfig.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_service_permissions:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_service_permissions.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_netgroup:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_netgroup.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_vault:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_vault.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl
-
-  fedora-27/test_authconfig:
-    requires: [fedora-27/build]
-    priority: 50
-    job:
-      class: RunPytest
-      args:
-        build_url: '{fedora-27/build_url}'
-        test_suite: test_integration/test_authselect.py
-        template: *ci-master-f27
-        timeout: 3600
-        topology: *master_1repl_1client
-
+        timeout: 16000
+        topology: *ipaserver
diff --git a/ipatests/test_webui/ui_driver.py b/ipatests/test_webui/ui_driver.py
index 0647b75cb7..c2c8337828 100644
--- a/ipatests/test_webui/ui_driver.py
+++ b/ipatests/test_webui/ui_driver.py
@@ -772,6 +772,7 @@ def fill_text(self, selector, value, parent=None):
         """
         if not parent:
             parent = self.get_form()
+
         tb = self.find(selector, By.CSS_SELECTOR, parent, strict=True)
         try:
             tb.clear()
@@ -2145,7 +2146,7 @@ def assert_action_list_action(self, action, visible=True, enabled=True,
             assert is_enabled == enabled, ('Invalid enabled state of action item %s. '
                                            'Expected: %s') % (action, str(visible))
 
-    def assert_field_validation(self, expect_error, parent=None):
+    def assert_field_validation(self, expect_error, parent=None, field=None):
         """
         Assert for error in field validation
         """
@@ -2153,14 +2154,18 @@ def assert_field_validation(self, expect_error, parent=None):
         if not parent:
             parent = self.get_form()
 
+        if field:
+            field_s = '.widget[name="{}"]'.format(field)
+            parent = self.find(field_s, By.CSS_SELECTOR, context=parent)
+
         req_field_css = '.help-block[name="error_link"]'
 
         res = self.find(req_field_css, By.CSS_SELECTOR, context=parent)
         assert expect_error in res.text, \
             'Expected error: {} not found'.format(expect_error)
 
-    def assert_field_validation_required(self, parent=None):
-        self.assert_field_validation('Required field', parent)
+    def assert_field_validation_required(self, parent=None, field=None):
+        self.assert_field_validation('Required field', parent, field)
 
     def assert_notification(self, type='success', assert_text=None):
         """
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to