URL: https://github.com/freeipa/freeipa/pull/2414
Author: serg-cymbaluk
 Title: #2414: UI-Test Automate: ID Range
Action: opened

PR body:
"""
Web UI tests for "ID Ranges" functionality.

This PR doesn't include cases which require AD server for running. So task 
hasn't completed yet.

Ticket: https://pagure.io/freeipa/issue/7709
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/2414/head:pr2414
git checkout pr2414
From 844bfb302b1fa90cda19a40a9732ad525d22ec23 Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 24 Sep 2018 09:43:00 +0200
Subject: [PATCH 1/9] UI tests for "ID Range": check range name and base ID
 duplication

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py | 113 ++++++++++++++++++++++--------
 ipatests/test_webui/test_range.py |  87 ++++++++++++++++++-----
 ipatests/test_webui/test_trust.py |   6 +-
 3 files changed, 156 insertions(+), 50 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index b71285d1e6..bb156c37a6 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -21,16 +21,19 @@
 Range tasks
 """
 
+import uuid
+
 from ipatests.test_webui.ui_driver import UI_driver
 
+LOCAL_ID_RANGE = 'ipa-local'
+TRUSTED_ID_RANGE = 'ipa-ad-trust'
 
-class range_tasks(UI_driver):
 
-    def get_shifts(self, idranges=None):
+class range_tasks(UI_driver):
 
-        if not idranges:
-            result = self.execute_api_from_ui('idrange_find', [], {})
-            idranges = result['result']['result']
+    def get_shifts(self):
+        result = self.execute_api_from_ui('idrange_find', [], {})
+        idranges = result['result']['result']
 
         max_id = 0
         max_rid = 0
@@ -67,50 +70,100 @@ def get_domain(self):
             domain = trusts[0]['cn']
         return domain
 
-    def get_data(self, pkey, size=50, add_data=None):
+    def get_data(self, pkey=None, form_data=None, **kwargs):
 
-        if not add_data:
-            add_data = self.get_add_data(pkey, size=size)
+        if not pkey:
+            pkey = 'itest-range-{}'.format(uuid.uuid4().hex[:8])
+
+        if form_data:
+            form_data.cn = pkey
+        else:
+            form_data = self.get_add_form_data(pkey, **kwargs)
 
         data = {
             'pkey': pkey,
-            'add': add_data,
+            'add': form_data.serialize(),
             'mod': [
-                ('textbox', 'ipaidrangesize', str(size + 1)),
+                ('textbox', 'ipaidrangesize', str(form_data.size + 1)),
             ],
         }
         return data
 
-    def get_add_data(self, pkey, range_type='ipa-local', size=50, shift=100, domain=None):
+    def get_add_form_data(self, pkey, range_type=LOCAL_ID_RANGE, size=50,
+                          domain=None, **kwargs):
+        """
+        Generate RangeAddFormData instance with initial data based on existing
+        ID ranges.
+        """
 
-        base_id = self.max_id + shift
+        shift = 100
+        base_id = kwargs.get('base_id', self.max_id + shift)
         self.max_id = base_id + size
 
         base_rid = self.max_rid + shift
         self.max_rid = base_rid + size
 
-        add = [
-            ('textbox', 'cn', pkey),
-            ('textbox', 'ipabaseid', str(base_id)),
-            ('textbox', 'ipaidrangesize', str(size)),
-            ('textbox', 'ipabaserid', str(base_rid)),
-            ('radio', 'iparangetype', range_type),
-            ('callback', self.check_range_type_mod, range_type)
-        ]
-
+        secondary_base_rid = None
         if not domain:
-            base_rid = self.max_rid + shift
-            self.max_rid = base_rid + size
-            add.append(('textbox', 'ipasecondarybaserid', str(base_rid)))
-        if domain:
-            add.append(('textbox', 'ipanttrusteddomainname', domain))
-
-        return add
+            secondary_base_rid = base_rid + size + shift
+            self.max_rid = secondary_base_rid + size
+
+        return RangeAddFormData(
+            pkey, base_id, base_rid,
+            secondary_base_rid=secondary_base_rid,
+            range_type=range_type,
+            size=size,
+            domain=domain,
+            callback=self.check_range_type_mod
+        )
 
     def check_range_type_mod(self, range_type):
-        if range_type == 'ipa-local':
+        if range_type == LOCAL_ID_RANGE:
             self.assert_disabled("[name=ipanttrusteddomainname]")
             self.assert_disabled("[name=ipasecondarybaserid]", negative=True)
-        elif range_type == 'ipa-ad-trust':
+        elif range_type == TRUSTED_ID_RANGE:
             self.assert_disabled("[name=ipanttrusteddomainname]", negative=True)
             self.assert_disabled("[name=ipasecondarybaserid]")
+
+
+class RangeAddFormData(object):
+    """
+    Class for ID Range form data storing and serializing.
+
+    Warning: Only for data transformation.
+             Do not put any additional logic here!
+    """
+
+    def __init__(self, cn, base_id, base_rid, secondary_base_rid=None,
+                 range_type=LOCAL_ID_RANGE, size=50, domain=None,
+                 callback=None):
+        self.cn = cn
+        self.base_id = base_id
+        self.base_rid = base_rid
+        self.secondary_base_rid = secondary_base_rid
+        self.range_type = range_type
+        self.size = size
+        self.domain = domain
+        self.callback = callback
+
+    def serialize(self):
+
+        serialized = [
+            ('textbox', 'cn', self.cn),
+            ('textbox', 'ipabaseid', str(self.base_id)),
+            ('textbox', 'ipaidrangesize', str(self.size)),
+            ('textbox', 'ipabaserid', str(self.base_rid)),
+            ('radio', 'iparangetype', self.range_type),
+            ('callback', self.callback, self.range_type),
+        ]
+
+        if self.domain:
+            serialized.append(('textbox',
+                               'ipanttrusteddomainname',
+                               self.domain))
+        else:
+            serialized.append(('textbox',
+                               'ipasecondarybaserid',
+                               str(self.secondary_base_rid)))
+
+        return serialized
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index 6ea0485f38..d9ab8fd785 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -21,10 +21,15 @@
 Range tests
 """
 
+import pytest
+
 import ipatests.test_webui.test_trust as trust_mod
 from ipatests.test_webui.ui_driver import screenshot
-from ipatests.test_webui.task_range import range_tasks
-import pytest
+from ipatests.test_webui.task_range import (
+    range_tasks,
+    LOCAL_ID_RANGE,
+    TRUSTED_ID_RANGE,
+)
 
 ENTITY = 'idrange'
 PKEY = 'itest-range'
@@ -33,13 +38,20 @@
 @pytest.mark.tier1
 class test_range(range_tasks):
 
+    def setup(self):
+        super().setup()
+        self.init_app()
+        self.get_shifts()
+
+        self.range_types = [LOCAL_ID_RANGE]
+        if self.has_trusts():
+            self.range_types.append(TRUSTED_ID_RANGE)
+
     @screenshot
     def test_crud(self):
         """
         Basic CRUD: range
         """
-        self.init_app()
-        self.get_shifts()
         self.basic_crud(ENTITY, self.get_data(PKEY), mod=False)
 
     @screenshot
@@ -48,16 +60,11 @@ def test_mod(self):
         Test mod operating in a new range
         """
 
-        self.init_app()
         self.navigate_to_entity(ENTITY)
-        self.get_shifts()
 
-        add = self.get_add_data(PKEY)
-        data = self.get_data(PKEY, add_data=add)
+        data = self.get_data(PKEY)
 
-        self.add_record(ENTITY, data, facet='search', navigate=False,
-                        facet_btn='add', dialog_name='add',
-                        dialog_btn='add')
+        self.add_record(ENTITY, data, navigate=False)
         self.navigate_to_record(PKEY)
 
         # changes idrange and tries to save it
@@ -88,15 +95,12 @@ def test_types(self):
         - 'ipa-ad-winsync' and 'ipa-ipa-trust' and  are not supported yet
           https://fedorahosted.org/freeipa/ticket/4323
         """
-        self.init_app()
-        self.get_shifts()
 
         pkey_local = 'itest-local'
         pkey_ad = 'itest-ad'
         column = 'iparangetype'
 
-        add = self.get_add_data(pkey_local)
-        data = self.get_data(pkey_local, add_data=add)
+        data = self.get_data(pkey_local)
         self.add_record(ENTITY, data)
         self.assert_record_value('local domain range', pkey_local, column)
 
@@ -111,8 +115,7 @@ def test_types(self):
 
             self.navigate_to_entity(ENTITY)
 
-            add = self.get_add_data(pkey_ad, range_type='ipa-ad-trust', domain=domain)
-            data = self.get_data(pkey_ad, add_data=add)
+            data = self.get_data(pkey_ad, range_type=TRUSTED_ID_RANGE, domain=domain)
             self.add_record(ENTITY, data, navigate=False)
             self.assert_record_value('Active Directory domain range', pkey_ad, column)
 
@@ -121,3 +124,53 @@ def test_types(self):
             self.delete_record(pkey_ad)
 
         self.delete_record(pkey_local)
+
+    @screenshot
+    def test_add_range_with_existing_name(self):
+        """
+        Test creating ID Range with existing range name
+        """
+        self.navigate_to_entity(ENTITY)
+
+        for range_type in self.range_types:
+            pkey = 'itest-range-{}'.format(range_type)
+            data = self.get_data(pkey, range_type=range_type)
+
+            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, data, navigate=False, negative=True,
+                            pre_delete=False)
+
+            dialog = self.get_last_error_dialog()
+
+            try:
+                assert ('range with name "{}" already exists'.format(pkey)
+                        in dialog.text)
+            finally:
+                self.delete_record(pkey)
+
+    @screenshot
+    def test_add_range_with_existing_base_id(self):
+        """
+        Test creating ID Range with existing base ID
+        """
+        self.navigate_to_entity(ENTITY)
+
+        for range_type in self.range_types:
+            pkey = 'itest-range-original'
+            form_data = self.get_add_form_data(pkey)
+            data = self.get_data(pkey, form_data=form_data)
+            form_data.range_type = range_type
+            duplicated_data = self.get_data(form_data=form_data)
+
+            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
+                            pre_delete=False)
+
+            dialog = self.get_last_error_dialog()
+
+            try:
+                assert ('Constraint violation: '
+                        'New base range overlaps with existing base range.'
+                        in dialog.text)
+            finally:
+                self.delete_record(pkey)
diff --git a/ipatests/test_webui/test_trust.py b/ipatests/test_webui/test_trust.py
index 57d7e7aab7..65e23fbf86 100644
--- a/ipatests/test_webui/test_trust.py
+++ b/ipatests/test_webui/test_trust.py
@@ -127,9 +127,9 @@ def test_range_types(self):
         r_tasks.driver = self.driver
         r_tasks.config = self.config
         r_tasks.get_shifts()
-        range_add = r_tasks.get_add_data('')
-        base_id = range_add[2][2]
-        range_size = range_add[3][2]
+        range_form = r_tasks.get_add_form_data('')
+        base_id = range_form.base_id
+        range_size = range_form.size
         range_pkey = self.get_range_name()
         column = 'iparangetype'
 

From da29ad63ec4130346d94f751cf775bf88914c6fa Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 24 Sep 2018 16:03:02 +0200
Subject: [PATCH 2/9] UI tests for "ID Range": check adding range without
 primary and secondary RID bases

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py | 16 +++++++++-----
 ipatests/test_webui/test_range.py | 35 +++++++++++++++++++++++++++++++
 ipatests/test_webui/ui_driver.py  | 12 +++++++++++
 3 files changed, 58 insertions(+), 5 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index bb156c37a6..0d96875e3a 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -100,13 +100,19 @@ def get_add_form_data(self, pkey, range_type=LOCAL_ID_RANGE, size=50,
         base_id = kwargs.get('base_id', self.max_id + shift)
         self.max_id = base_id + size
 
-        base_rid = self.max_rid + shift
-        self.max_rid = base_rid + size
+        if 'base_rid' in kwargs:
+            base_rid = kwargs['base_rid']
+        else:
+            base_rid = self.max_rid + shift
+            self.max_rid = base_rid + size
 
         secondary_base_rid = None
         if not domain:
-            secondary_base_rid = base_rid + size + shift
-            self.max_rid = secondary_base_rid + size
+            if 'secondary_base_rid' in kwargs:
+                secondary_base_rid = kwargs['secondary_base_rid']
+            else:
+                secondary_base_rid = self.max_rid + shift
+                self.max_rid = secondary_base_rid + size
 
         return RangeAddFormData(
             pkey, base_id, base_rid,
@@ -134,7 +140,7 @@ class RangeAddFormData(object):
              Do not put any additional logic here!
     """
 
-    def __init__(self, cn, base_id, base_rid, secondary_base_rid=None,
+    def __init__(self, cn, base_id, base_rid=None, secondary_base_rid=None,
                  range_type=LOCAL_ID_RANGE, size=50, domain=None,
                  callback=None):
         self.cn = cn
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index d9ab8fd785..ec08785b41 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -174,3 +174,38 @@ def test_add_range_with_existing_base_id(self):
                         in dialog.text)
             finally:
                 self.delete_record(pkey)
+
+    @screenshot
+    def test_add_range_without_rid(self):
+        """
+        Test creating ID Range without giving rid-base or/and
+        secondary-rid-base values
+        """
+        self.navigate_to_entity(ENTITY)
+
+        pkey = 'itest-range-without-rid'
+
+        # Without primary RID base
+        data = self.get_data(pkey, base_rid='')
+        self.add_record(ENTITY, data, navigate=False, negative=True)
+        try:
+            assert self.has_form_error('ipabaserid')
+        finally:
+            self.delete_record(pkey)
+
+        self.dialog_button_click('cancel')
+
+        # Without secondary RID base
+        data = self.get_data(pkey, secondary_base_rid='')
+        self.add_record(ENTITY, data, navigate=False, negative=True)
+        try:
+            assert self.has_form_error('ipasecondarybaserid')
+        finally:
+            self.delete_record(pkey)
+
+        self.dialog_button_click('cancel')
+
+        # Without primary and secondary RID bases
+        data = self.get_data(pkey, base_rid='', secondary_base_rid='')
+        self.add_record(ENTITY, data, navigate=False)
+        self.delete_record(pkey)
diff --git a/ipatests/test_webui/ui_driver.py b/ipatests/test_webui/ui_driver.py
index b99adffbac..68c0518d1a 100644
--- a/ipatests/test_webui/ui_driver.py
+++ b/ipatests/test_webui/ui_driver.py
@@ -1905,6 +1905,18 @@ def has_class(self, el, cls):
         class_attr = el.get_attribute("class")
         return bool(class_attr) and cls in class_attr.split()
 
+    def has_form_error(self, name):
+        """
+        Check if form field has error
+        TODO: Move to some mixin class
+        """
+        form_group = self.find(
+            '//input[@name="{}"]/ancestor'
+            '::div[contains(@class, "form-group")]'.format(name),
+            By.XPATH
+        )
+        return self.has_class(form_group, 'has-error')
+
     def skip(self, reason):
         """
         Skip tests

From badd4260a2a4eeacf53cbf1955eac4c9e46f922f Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 24 Sep 2018 16:23:35 +0200
Subject: [PATCH 3/9] UI tests for "ID Range": check primary RID base
 duplication

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/test_range.py | 26 ++++++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index ec08785b41..c16e4c621a 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -175,6 +175,32 @@ def test_add_range_with_existing_base_id(self):
             finally:
                 self.delete_record(pkey)
 
+    @screenshot
+    def test_add_range_with_existing_base_rid(self):
+        """
+        Test creating ID Range with existing primary RID base
+        """
+        self.navigate_to_entity(ENTITY)
+
+        pkey = 'itest-range-original'
+        form_data = self.get_add_form_data(pkey)
+        data = self.get_data(pkey, form_data=form_data)
+        # Get RID base from previous form
+        duplicated_data = self.get_data(base_rid=form_data.base_rid)
+
+        self.add_record(ENTITY, data, navigate=False)
+        self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
+                        pre_delete=False)
+
+        dialog = self.get_last_error_dialog()
+
+        try:
+            assert ('Constraint violation: '
+                    'New primary rid range overlaps with existing primary rid range.'
+                    in dialog.text)
+        finally:
+            self.delete_record(pkey)
+
     @screenshot
     def test_add_range_without_rid(self):
         """

From cd4c1ee4edd4ce5df539517fe36233028357c70e Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Wed, 26 Sep 2018 09:12:52 +0200
Subject: [PATCH 4/9] UI tests for "ID Range": check adding range with
 overlapping of existing local range

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py | 10 ++++++++
 ipatests/test_webui/test_range.py | 39 ++++++++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index 0d96875e3a..e2f8724236 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -31,6 +31,16 @@
 
 class range_tasks(UI_driver):
 
+    BASE_RANGE_OVERLAPS_ERROR = (
+        'Constraint violation: '
+        'New base range overlaps with existing base range.'
+    )
+
+    PRIMARY_RID_RANGE_OVERLAPS_ERROR = (
+        'Constraint violation: '
+        'New primary rid range overlaps with existing primary rid range.'
+    )
+
     def get_shifts(self):
         result = self.execute_api_from_ui('idrange_find', [], {})
         idranges = result['result']['result']
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index c16e4c621a..900af85505 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -169,9 +169,38 @@ def test_add_range_with_existing_base_id(self):
             dialog = self.get_last_error_dialog()
 
             try:
-                assert ('Constraint violation: '
-                        'New base range overlaps with existing base range.'
-                        in dialog.text)
+                assert self.BASE_RANGE_OVERLAPS_ERROR in dialog.text
+            finally:
+                self.delete_record(pkey)
+
+    @screenshot
+    def test_add_range_overlaps_with_existing(self):
+        """
+        Test creating ID Range with overlapping of existing range
+        """
+        self.navigate_to_entity(ENTITY)
+
+        for range_type in self.range_types:
+            pkey = 'itest-range'
+            pkey_overlaps = 'itest-range-overlaps'
+
+            form_data = self.get_add_form_data(pkey)
+            data = self.get_data(pkey, form_data=form_data)
+            form_data_overlaps = self.get_add_form_data(
+                pkey_overlaps,
+                base_id=form_data.base_id + form_data.size - 1,
+                range_type=range_type
+            )
+            data_overlaps = self.get_data(form_data=form_data_overlaps)
+
+            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, data_overlaps, navigate=False,
+                            negative=True, pre_delete=False)
+
+            dialog = self.get_last_error_dialog()
+
+            try:
+                assert self.BASE_RANGE_OVERLAPS_ERROR in dialog.text
             finally:
                 self.delete_record(pkey)
 
@@ -195,9 +224,7 @@ def test_add_range_with_existing_base_rid(self):
         dialog = self.get_last_error_dialog()
 
         try:
-            assert ('Constraint violation: '
-                    'New primary rid range overlaps with existing primary rid range.'
-                    in dialog.text)
+            assert self.PRIMARY_RID_RANGE_OVERLAPS_ERROR in dialog.text
         finally:
             self.delete_record(pkey)
 

From ab3b7ec75075be357cd77e0d69f3760926b4e431 Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Thu, 27 Sep 2018 14:42:44 +0200
Subject: [PATCH 5/9] UI tests for "ID Range": check modifying ID range with
 invalid or missing values

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py | 33 +++++++++++++++++++++-
 ipatests/test_webui/test_range.py | 47 +++++++++++++++++++++++++++++++
 ipatests/test_webui/ui_driver.py  |  3 +-
 3 files changed, 81 insertions(+), 2 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index e2f8724236..f1d7b2b90d 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -133,6 +133,9 @@ def get_add_form_data(self, pkey, range_type=LOCAL_ID_RANGE, size=50,
             callback=self.check_range_type_mod
         )
 
+    def get_mod_form_data(self, **kwargs):
+        return RangeModifyFormData(**kwargs)
+
     def check_range_type_mod(self, range_type):
         if range_type == LOCAL_ID_RANGE:
             self.assert_disabled("[name=ipanttrusteddomainname]")
@@ -144,7 +147,7 @@ def check_range_type_mod(self, range_type):
 
 class RangeAddFormData(object):
     """
-    Class for ID Range form data storing and serializing.
+    Class for storing and serializing of new ID Range form data.
 
     Warning: Only for data transformation.
              Do not put any additional logic here!
@@ -183,3 +186,31 @@ def serialize(self):
                                str(self.secondary_base_rid)))
 
         return serialized
+
+
+class RangeModifyFormData(object):
+    """
+    Class for storing and serializing of modified ID Range form data.
+    """
+
+    def __init__(self, base_id=None, base_rid=None, secondary_base_rid=None, size=None):
+        self.base_id = base_id
+        self.base_rid = base_rid
+        self.secondary_base_rid = secondary_base_rid
+        self.size = size
+
+    def serialize(self):
+        serialized = []
+
+        if self.base_id is not None:
+            serialized.append(('textbox', 'ipabaseid', str(self.base_id)))
+        if self.size is not None:
+            serialized.append(('textbox', 'ipaidrangesize', str(self.size)))
+        if self.base_rid is not None:
+            serialized.append(('textbox', 'ipabaserid', str(self.base_rid)))
+        if self.secondary_base_rid is not None:
+            serialized.append(('textbox',
+                               'ipasecondarybaserid',
+                               str(self.secondary_base_rid)))
+
+        return serialized
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index 900af85505..b104156b7e 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -262,3 +262,50 @@ def test_add_range_without_rid(self):
         data = self.get_data(pkey, base_rid='', secondary_base_rid='')
         self.add_record(ENTITY, data, navigate=False)
         self.delete_record(pkey)
+
+    @screenshot
+    def test_modify_range_with_invalid_or_missing_values(self):
+        """
+        Test modification ID range with empty values of options
+        """
+        cases = [
+            # Empty values
+            {
+                'base_id': '',
+                'base_rid': '',
+                'secondary_base_rid': '',
+                'size': '',
+            },
+            # Out of range
+            {'base_id': 2 ** 32},
+            {'size': 2 ** 32},
+            {'base_rid': 2 ** 32},
+            {'secondary_base_rid': 2 ** 32},
+            # Invalid value
+            {'base_id': 1.1},
+            {'size': 1.1},
+            {'base_rid': 1.1},
+            {'secondary_base_rid': 1.1},
+        ]
+
+        self.navigate_to_entity(ENTITY)
+
+        data = self.get_data(PKEY)
+        self.add_record(ENTITY, data, navigate=False)
+        self.navigate_to_record(PKEY)
+
+        for values in cases:
+            form_data = self.get_mod_form_data(**values)
+
+            self.fill_fields(form_data.serialize(), undo=True)
+            self.assert_facet_button_enabled('save')
+            self.facet_button_click('save')
+
+            self.assert_notification(
+                type='danger',
+                assert_text='Input form contains invalid or missing values.'
+            )
+            self.close_notifications()
+            self.facet_button_click('revert')
+
+        self.delete_record(PKEY)
diff --git a/ipatests/test_webui/ui_driver.py b/ipatests/test_webui/ui_driver.py
index 68c0518d1a..0d6a33e108 100644
--- a/ipatests/test_webui/ui_driver.py
+++ b/ipatests/test_webui/ui_driver.py
@@ -769,7 +769,8 @@ def fill_text(self, selector, value, parent=None):
             parent = self.get_form()
         tb = self.find(selector, By.CSS_SELECTOR, parent, strict=True)
         try:
-            tb.clear()
+            tb.send_keys(Keys.CONTROL + 'a')
+            tb.send_keys(Keys.DELETE)
             tb.send_keys(value)
         except InvalidElementStateException as e:
             msg = "Invalid Element State, el: %s, value: %s, error: %s" % (selector, value, e)

From 3c9060e454d3f5c0534f7c2432f3e5a6205de65c Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 1 Oct 2018 10:01:47 +0200
Subject: [PATCH 6/9] UI tests for "ID Range": - check creating ID range with
 special characters in name - check modifying ID range with existing secondary
 RID base

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py |  5 ++++
 ipatests/test_webui/test_range.py | 40 +++++++++++++++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index f1d7b2b90d..27d58ee10e 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -41,6 +41,11 @@ class range_tasks(UI_driver):
         'New primary rid range overlaps with existing primary rid range.'
     )
 
+    SECONDARY_RID_RANGE_OVERLAPS_ERROR = (
+        'Constraint violation: '
+        'New secondary rid range overlaps with existing secondary rid range.'
+    )
+
     def get_shifts(self):
         result = self.execute_api_from_ui('idrange_find', [], {})
         idranges = result['result']['result']
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index b104156b7e..eb192117c2 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -125,6 +125,14 @@ def test_types(self):
 
         self.delete_record(pkey_local)
 
+    @screenshot
+    def test_add_range_with_special_characters_in_name(self):
+        """
+        Test creating ID Range with special characters in name
+        """
+        data = self.get_data('itest-range-!@#$%^&*')
+        self.add_record(ENTITY, data, delete=True)
+
     @screenshot
     def test_add_range_with_existing_name(self):
         """
@@ -211,9 +219,8 @@ def test_add_range_with_existing_base_rid(self):
         """
         self.navigate_to_entity(ENTITY)
 
-        pkey = 'itest-range-original'
-        form_data = self.get_add_form_data(pkey)
-        data = self.get_data(pkey, form_data=form_data)
+        form_data = self.get_add_form_data(PKEY)
+        data = self.get_data(PKEY, form_data=form_data)
         # Get RID base from previous form
         duplicated_data = self.get_data(base_rid=form_data.base_rid)
 
@@ -226,7 +233,32 @@ def test_add_range_with_existing_base_rid(self):
         try:
             assert self.PRIMARY_RID_RANGE_OVERLAPS_ERROR in dialog.text
         finally:
-            self.delete_record(pkey)
+            self.delete_record(PKEY)
+
+    @screenshot
+    def test_add_range_with_existing_secondary_rid(self):
+        """
+        Test creating ID Range with existing secondary RID base
+        """
+        self.navigate_to_entity(ENTITY)
+
+        form_data = self.get_add_form_data(PKEY)
+        data = self.get_data(PKEY, form_data=form_data)
+        # Get RID base from previous form
+        duplicated_data = self.get_data(
+            secondary_base_rid=form_data.secondary_base_rid
+        )
+
+        self.add_record(ENTITY, data, navigate=False)
+        self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
+                        pre_delete=False)
+
+        dialog = self.get_last_error_dialog()
+
+        try:
+            assert self.SECONDARY_RID_RANGE_OVERLAPS_ERROR in dialog.text
+        finally:
+            self.delete_record(PKEY)
 
     @screenshot
     def test_add_range_without_rid(self):

From d2ef6f2253d08b5f104b2e22b1c5ae4a224520ad Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 1 Oct 2018 10:55:44 +0200
Subject: [PATCH 7/9] UI tests for "ID Range": check creating ID Range with
 overlapping of primary and secondary RID base

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py |  5 +++++
 ipatests/test_webui/test_range.py | 17 +++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index 27d58ee10e..9220248488 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -46,6 +46,11 @@ class range_tasks(UI_driver):
         'New secondary rid range overlaps with existing secondary rid range.'
     )
 
+    PRIMARY_AND_SECONDARY_RID_OVERLAP_ERROR = (
+        "invalid 'ID Range setup': "
+        "Primary RID range and secondary RID range cannot overlap"
+    )
+
     def get_shifts(self):
         result = self.execute_api_from_ui('idrange_find', [], {})
         idranges = result['result']['result']
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index eb192117c2..dc7fb750ee 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -212,6 +212,23 @@ def test_add_range_overlaps_with_existing(self):
             finally:
                 self.delete_record(pkey)
 
+    @screenshot
+    def test_add_range_with_overlapping_primary_and_secondary_rid(self):
+        """
+        Test creating ID Range with overlapping of primary and secondary RID
+        """
+        form_data = self.get_add_form_data(PKEY)
+        form_data.secondary_base_rid = form_data.base_rid
+        data = self.get_data(PKEY, form_data=form_data)
+
+        self.add_record(ENTITY, data, negative=True)
+        dialog = self.get_last_error_dialog()
+
+        try:
+            assert self.PRIMARY_AND_SECONDARY_RID_OVERLAP_ERROR in dialog.text
+        finally:
+            self.delete_record(PKEY)
+
     @screenshot
     def test_add_range_with_existing_base_rid(self):
         """

From 1ea301aab8e41aed66d1deef4a071071d0fd2dad Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 1 Oct 2018 11:32:58 +0200
Subject: [PATCH 8/9] UI tests for "ID Range": check deleting primary local
 range

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/task_range.py | 17 +++++++++++------
 ipatests/test_webui/test_range.py | 16 ++++++++++++++++
 2 files changed, 27 insertions(+), 6 deletions(-)

diff --git a/ipatests/test_webui/task_range.py b/ipatests/test_webui/task_range.py
index 9220248488..27821a57be 100644
--- a/ipatests/test_webui/task_range.py
+++ b/ipatests/test_webui/task_range.py
@@ -32,18 +32,18 @@
 class range_tasks(UI_driver):
 
     BASE_RANGE_OVERLAPS_ERROR = (
-        'Constraint violation: '
-        'New base range overlaps with existing base range.'
+        "Constraint violation: "
+        "New base range overlaps with existing base range."
     )
 
     PRIMARY_RID_RANGE_OVERLAPS_ERROR = (
-        'Constraint violation: '
-        'New primary rid range overlaps with existing primary rid range.'
+        "Constraint violation: "
+        "New primary rid range overlaps with existing primary rid range."
     )
 
     SECONDARY_RID_RANGE_OVERLAPS_ERROR = (
-        'Constraint violation: '
-        'New secondary rid range overlaps with existing secondary rid range.'
+        "Constraint violation: "
+        "New secondary rid range overlaps with existing secondary rid range."
     )
 
     PRIMARY_AND_SECONDARY_RID_OVERLAP_ERROR = (
@@ -51,6 +51,11 @@ class range_tasks(UI_driver):
         "Primary RID range and secondary RID range cannot overlap"
     )
 
+    DELETE_PRIMARY_LOCAL_RANGE_ERROR = (
+        "invalid 'ipabaseid,ipaidrangesize': range modification "
+        "leaving objects with ID out of the defined range is not allowed"
+    )
+
     def get_shifts(self):
         result = self.execute_api_from_ui('idrange_find', [], {})
         idranges = result['result']['result']
diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index dc7fb750ee..63cfca865f 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -358,3 +358,19 @@ def test_modify_range_with_invalid_or_missing_values(self):
             self.facet_button_click('revert')
 
         self.delete_record(PKEY)
+
+    @screenshot
+    def test_delete_primary_local_range(self):
+        """
+        Test deleting primary local ID range
+        """
+        ipa_realm = self.config.get('ipa_realm')
+        pkey = '{}_id_range'.format(ipa_realm)
+
+        self.navigate_to_entity(ENTITY)
+        self.delete_record(pkey)
+
+        self.assert_last_error_dialog(
+            self.DELETE_PRIMARY_LOCAL_RANGE_ERROR,
+            details=True
+        )

From e27f9d04d4e0cea12377aae4537ffd8a5fdd2372 Mon Sep 17 00:00:00 2001
From: Serhii Tsymbaliuk <stsym...@redhat.com>
Date: Mon, 1 Oct 2018 13:09:31 +0200
Subject: [PATCH 9/9] UI tests for "ID Range": delete some boilerplate code

https://pagure.io/freeipa/issue/7709
---
 ipatests/test_webui/test_range.py | 36 +++++++++----------------------
 1 file changed, 10 insertions(+), 26 deletions(-)

diff --git a/ipatests/test_webui/test_range.py b/ipatests/test_webui/test_range.py
index 63cfca865f..874a5b849b 100644
--- a/ipatests/test_webui/test_range.py
+++ b/ipatests/test_webui/test_range.py
@@ -59,12 +59,9 @@ def test_mod(self):
         """
         Test mod operating in a new range
         """
-
-        self.navigate_to_entity(ENTITY)
-
         data = self.get_data(PKEY)
 
-        self.add_record(ENTITY, data, navigate=False)
+        self.add_record(ENTITY, data)
         self.navigate_to_record(PKEY)
 
         # changes idrange and tries to save it
@@ -138,13 +135,11 @@ def test_add_range_with_existing_name(self):
         """
         Test creating ID Range with existing range name
         """
-        self.navigate_to_entity(ENTITY)
-
         for range_type in self.range_types:
             pkey = 'itest-range-{}'.format(range_type)
             data = self.get_data(pkey, range_type=range_type)
 
-            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, data)
             self.add_record(ENTITY, data, navigate=False, negative=True,
                             pre_delete=False)
 
@@ -161,8 +156,6 @@ def test_add_range_with_existing_base_id(self):
         """
         Test creating ID Range with existing base ID
         """
-        self.navigate_to_entity(ENTITY)
-
         for range_type in self.range_types:
             pkey = 'itest-range-original'
             form_data = self.get_add_form_data(pkey)
@@ -170,7 +163,7 @@ def test_add_range_with_existing_base_id(self):
             form_data.range_type = range_type
             duplicated_data = self.get_data(form_data=form_data)
 
-            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, data)
             self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
                             pre_delete=False)
 
@@ -186,8 +179,6 @@ def test_add_range_overlaps_with_existing(self):
         """
         Test creating ID Range with overlapping of existing range
         """
-        self.navigate_to_entity(ENTITY)
-
         for range_type in self.range_types:
             pkey = 'itest-range'
             pkey_overlaps = 'itest-range-overlaps'
@@ -201,7 +192,7 @@ def test_add_range_overlaps_with_existing(self):
             )
             data_overlaps = self.get_data(form_data=form_data_overlaps)
 
-            self.add_record(ENTITY, data, navigate=False)
+            self.add_record(ENTITY, data)
             self.add_record(ENTITY, data_overlaps, navigate=False,
                             negative=True, pre_delete=False)
 
@@ -234,14 +225,13 @@ def test_add_range_with_existing_base_rid(self):
         """
         Test creating ID Range with existing primary RID base
         """
-        self.navigate_to_entity(ENTITY)
-
         form_data = self.get_add_form_data(PKEY)
         data = self.get_data(PKEY, form_data=form_data)
+
         # Get RID base from previous form
         duplicated_data = self.get_data(base_rid=form_data.base_rid)
 
-        self.add_record(ENTITY, data, navigate=False)
+        self.add_record(ENTITY, data)
         self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
                         pre_delete=False)
 
@@ -257,8 +247,6 @@ def test_add_range_with_existing_secondary_rid(self):
         """
         Test creating ID Range with existing secondary RID base
         """
-        self.navigate_to_entity(ENTITY)
-
         form_data = self.get_add_form_data(PKEY)
         data = self.get_data(PKEY, form_data=form_data)
         # Get RID base from previous form
@@ -266,7 +254,7 @@ def test_add_range_with_existing_secondary_rid(self):
             secondary_base_rid=form_data.secondary_base_rid
         )
 
-        self.add_record(ENTITY, data, navigate=False)
+        self.add_record(ENTITY, data)
         self.add_record(ENTITY, duplicated_data, navigate=False, negative=True,
                         pre_delete=False)
 
@@ -283,13 +271,11 @@ def test_add_range_without_rid(self):
         Test creating ID Range without giving rid-base or/and
         secondary-rid-base values
         """
-        self.navigate_to_entity(ENTITY)
-
         pkey = 'itest-range-without-rid'
 
         # Without primary RID base
         data = self.get_data(pkey, base_rid='')
-        self.add_record(ENTITY, data, navigate=False, negative=True)
+        self.add_record(ENTITY, data, negative=True)
         try:
             assert self.has_form_error('ipabaserid')
         finally:
@@ -336,11 +322,9 @@ def test_modify_range_with_invalid_or_missing_values(self):
             {'base_rid': 1.1},
             {'secondary_base_rid': 1.1},
         ]
-
-        self.navigate_to_entity(ENTITY)
-
         data = self.get_data(PKEY)
-        self.add_record(ENTITY, data, navigate=False)
+
+        self.add_record(ENTITY, data)
         self.navigate_to_record(PKEY)
 
         for values in cases:
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: https://getfedora.org/code-of-conduct.html
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to