Skip to content

Commit

Permalink
Add wait_until_loaded method to page objects
Browse files Browse the repository at this point in the history
  • Loading branch information
rgonalo committed Mar 23, 2017
1 parent a35e27a commit 7379805
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Expand Up @@ -7,6 +7,7 @@ v1.2.5
*In development*

- Fix firefox initialization error using Selenium 2.X
- Add *wait_until_loaded* method to PageObject class to wait until all page elements with wait=True are visible

v1.2.4
------
Expand Down
2 changes: 1 addition & 1 deletion toolium/behave/environment.py
Expand Up @@ -204,7 +204,7 @@ def bdd_common_after_scenario(context_or_world, scenario, status):
context_or_world.logger.info("The scenario '%s' has passed", scenario.name)
else:
test_status = 'Fail'
test_comment = "The scenario '{0}' has failed".format(scenario.name)
test_comment = "The scenario '%s' has failed" % scenario.name
context_or_world.logger.error("The scenario '%s' has failed", scenario.name)
# Capture screenshot on error
DriverWrappersPool.capture_screenshots(scenario_file_name)
Expand Down
6 changes: 4 additions & 2 deletions toolium/pageelements/group_page_element.py
Expand Up @@ -24,7 +24,7 @@


class Group(PageObject, PageElement):
def __init__(self, by, value, parent=None, driver_wrapper=None, order=None):
def __init__(self, by, value, parent=None, driver_wrapper=None, order=None, wait=False):
"""Initialize the Group object with the given locator components.
If parent is not None, find_elements will be performed over it, instead of
Expand All @@ -33,13 +33,15 @@ def __init__(self, by, value, parent=None, driver_wrapper=None, order=None):
:param by: locator type
:param value: locator value
:param parent: parent element (WebElement, PageElement or locator tuple)
:param order: index value if the locator returns more than one element
:param driver_wrapper: driver wrapper instance
:param order: index value if the locator returns more than one element
:param wait: True if the page element must be loaded in wait_until_loaded method of the container page object
"""
self.logger = logging.getLogger(__name__) #: logger instance
self.locator = (by, value) #: tuple with locator type and locator value
self.parent = parent #: element from which to find actual elements
self.order = order #: index value if the locator returns more than one element
self.wait = wait #: True if it must be loaded in wait_until_loaded method of the container page object
self.driver_wrapper = driver_wrapper if driver_wrapper else \
DriverWrappersPool.get_default_wrapper() #: driver wrapper instance
self.init_page_elements()
Expand Down
4 changes: 3 additions & 1 deletion toolium/pageelements/page_element.py
Expand Up @@ -32,7 +32,7 @@ class PageElement(CommonObject):
or (selenium.webdriver.common.by.By or appium.webdriver.common.mobileby.MobileBy, str)
"""

def __init__(self, by, value, parent=None, order=None):
def __init__(self, by, value, parent=None, order=None, wait=False):
"""Initialize the PageElement object with the given locator components.
If parent is not None, find_element will be performed over it, instead of
Expand All @@ -42,11 +42,13 @@ def __init__(self, by, value, parent=None, order=None):
:param value: locator value
:param parent: parent element (WebElement, PageElement or locator tuple)
:param order: index value if the locator returns more than one element
:param wait: True if the page element must be loaded in wait_until_loaded method of the container page object
"""
super(PageElement, self).__init__()
self.locator = (by, value) #: tuple with locator type and locator value
self.parent = parent #: element from which to find actual elements
self.order = order #: index value if the locator returns more than one element
self.wait = wait #: True if it must be loaded in wait_until_loaded method of the container page object
self.driver_wrapper = DriverWrappersPool.get_default_wrapper() #: driver wrapper instance
self.reset_object(self.driver_wrapper)

Expand Down
22 changes: 21 additions & 1 deletion toolium/pageobjects/page_object.py
Expand Up @@ -26,12 +26,14 @@ class PageObject(CommonObject):
:type app_strings: str
"""

def __init__(self, driver_wrapper=None):
def __init__(self, driver_wrapper=None, wait=False):
"""Initialize page object properties and update their page elements
:param driver_wrapper: driver wrapper instance
:param wait: True if the page object must be loaded in wait_until_loaded method of the container page object
"""
super(PageObject, self).__init__()
self.wait = wait #: True if it must be loaded in wait_until_loaded method of the container page object
self.driver_wrapper = driver_wrapper if driver_wrapper else \
DriverWrappersPool.get_default_wrapper() #: driver wrapper instance
self.init_page_elements()
Expand Down Expand Up @@ -65,3 +67,21 @@ def _get_page_elements(self):
if attribute != 'parent' and isinstance(value, CommonObject):
page_elements.append(value)
return page_elements

def wait_until_loaded(self, timeout=10):
"""Wait until page object is loaded
Search all page elements configured with wait=True
:param timeout: max time to wait
:returns: this page object instance
"""
for element in self._get_page_elements():
if element.wait:
from toolium.pageelements.page_element import PageElement
if isinstance(element, PageElement):
# Pageelement and Group
element.wait_until_visible(timeout)
if isinstance(element, PageObject):
# PageObject and Group
element.wait_until_loaded(timeout)
return self
27 changes: 23 additions & 4 deletions toolium/test/pageobjects/test_page_object.py
Expand Up @@ -34,24 +34,25 @@ class MenuPageObject(PageObject):
register = PageElement(By.ID, 'register')

def init_page_elements(self):
self.logo = PageElement(By.ID, 'image')
self.logo = PageElement(By.ID, 'image', wait=True)


class MenuGroup(Group):
def init_page_elements(self):
self.logo = PageElement(By.ID, 'image')
self.logo_wait = PageElement(By.ID, 'image2', wait=True)


class RegisterPageObject(PageObject):
username = PageElement(By.XPATH, '//input[0]')
username = PageElement(By.XPATH, '//input[0]', wait=True)
password = PageElement(By.ID, 'password', username)

def init_page_elements(self):
self.language = PageElement(By.ID, 'language')
self.email = PageElement(By.ID, 'email', mock_element)
self.address = PageElement(By.ID, 'address', (By.ID, 'parent'))
self.menu = MenuPageObject()
self.menu_group = MenuGroup(By.ID, 'menu')
self.menu = MenuPageObject(wait=True)
self.menu_group = MenuGroup(By.ID, 'menu', wait=True)


@pytest.fixture
Expand Down Expand Up @@ -164,3 +165,21 @@ def test_reset_object(driver_wrapper):
assert page_object.menu.logo._web_element is None
assert page_object.menu_group._web_element is None
assert page_object.menu_group.logo._web_element is None


def test_wait_until_loaded(driver_wrapper):
page_object = RegisterPageObject(driver_wrapper).wait_until_loaded()

# Check that all page elements with wait=True have a web element
assert page_object.username._web_element is not None
assert page_object.menu.logo._web_element is not None
assert page_object.menu_group._web_element is not None
assert page_object.menu_group.logo_wait._web_element is not None

# Check that all page elements with wait=False have no web element value
assert page_object.password._web_element is None
assert page_object.language._web_element is None
assert page_object.email._web_element is None
assert page_object.address._web_element is None
assert page_object.menu.register._web_element is None
assert page_object.menu_group.logo._web_element is None

0 comments on commit 7379805

Please sign in to comment.