diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fc198d..c731122 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,11 +11,49 @@ This document follows the conventions laid out in [Keep a CHANGELOG][]. - Python.Net 3.0 Support -### Fixxed +### Fixed - Converter bugfix for wrong value convert - Tree module refactoring +### Changed + +- Keyword behaviour changed for Element Should Exist and Element Should Not Exist + - Keywords contains now a use_exceptions flag to decide if an exception should be called or a return value. + - Exception handling will be used in general to check if a ui element is closing or opened + - If you want to check it by your own use_exception flag should be set to ${FALSE} + - Wait Until Keyword Succeeds combination does not work anymore to check if an ui is displaying after amount of time + - Returns now always True or False + +#### Old Syntax +``` +# This throws a flaui exception and stop test exeuction +Element Should Exist /WRONG/XPATH +``` + +#### New Syntax + +- You can now decide to use the old syntax or new style by using the flag parameter use_exceptions. +- This is by default ${TRUE} to avoid this breaks for checkups if a ui element is displaying delayed. + +``` +# This throws a flaui exception and stop test exeuction +Element Should Exist /WRONG/XPATH +Element Should Not Exist /VALID_XPATH + +# Usage with Wait Until Keyword Succeeds +Wait Until Keyword Succeeds Element Should Exist /VALID_XPATH +Wait Until Keyword Succeeds Element Should Not Exist /VALID_XPATH + +# If you want to check the return value by your own syntax. +# Wait Until Keyword Succeeds will not work anymore because this keyword will always Return True or False now +${RESULT} Element Should Exist /VALID_XPATH ${FALSE} +${RESULT} Element Should Not Exist /WRONG/XPATH ${FALSE} +``` + +- Wait Until Element Is Hidden does not check anymore if element exists + - No xpath not found exception is called anymore to avoid break tests + ## [Release][1.6.6] [1.6.6][1.6.5-1.6.6] - 2021-09-01 ### Added diff --git a/atests/Element.robot b/atests/Element.robot index 5e5ac24..922a6e3 100644 --- a/atests/Element.robot +++ b/atests/Element.robot @@ -27,16 +27,22 @@ Get Name From Element By XPath Should Be Equal Test Label ${TEXT} Element Should Exist - Element Should Exist ${XPATH_ELEMENT} + ${EXISTS} Element Should Exist ${XPATH_ELEMENT} + Should Be Equal ${EXISTS} ${True} -Element Should Not Exist - Element Should Not Exist ${XPATH_NOT_EXISTS} +Element Should Exist Xpath Not Exists + ${EXISTS} Element Should Exist ${XPATH_NOT_EXISTS} ${FALSE} + Should Be Equal ${EXISTS} ${False} -Element Should Not Exist Error +Element Should Not Exist ${EXP_ERR_MSG} Format String ${EXP_ERR_MSG_ELEMENT_EXISTS} ${XPATH_ELEMENT} - ${ERR_MSG} Run Keyword And Expect Error * Element Should Not Exist ${XPATH_ELEMENT} + ${ERR_MSG} Run Keyword And Expect Error * Element Should Not Exist ${XPATH_ELEMENT} Should Be Equal As Strings ${EXP_ERR_MSG} ${ERR_MSG} +Element Should Not Exist Xpath Not Exists + ${NOT_EXISTS} Element Should Not Exist ${XPATH_NOT_EXISTS} ${FALSE} + Should Be Equal ${NOT_EXISTS} ${TRUE} + Name Should Be Name Should Be ${EXP_WINDOW_TITLE} ${MAIN_WINDOW} @@ -65,7 +71,7 @@ Is Element Visible ${IS_VISIBLE} Is Element Visible ${XPATH_ELEMENT} Should Be True ${IS_VISIBLE} -Is Element Offscreen And Not Visible +Is Element Visible When Element Is Offscreen And Not Visible ${IS_VISIBLE} Is Element Visible ${XPATH_OFFSCREEN_ELEMENT} Should Be Equal ${IS_VISIBLE} ${False} diff --git a/atests/ErrorHandling.robot b/atests/ErrorHandling.robot index 3f926ae..e489dfb 100644 --- a/atests/ErrorHandling.robot +++ b/atests/ErrorHandling.robot @@ -28,7 +28,6 @@ Double Click Double Click ${EXP_ERR_MSG_XPATH_NOT_FOUND} Element Should Be Visible Element Should Be Visible ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} Element Should Exist Element Should Exist ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} Element Should Not Be Visible Element Should Not Be Visible ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} -Element Should Not Exist Element Should Not Be Visible ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} Expand TreeItem Expand TreeItem ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} No Such Item Focus Focus ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} Get Checkbox State Get Checkbox State ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} @@ -69,12 +68,12 @@ Select TreeItem Select TreeItem ${EXP_ERR_MSG_XPATH_NOT_FOUND Select Visible TreeItem By Name Select Visible TreeItem By Name ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} No Such Item Set Checkbox State Set Checkbox State ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} ${False} Set Text To Textbox Set Text To Textbox ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} ${XPATH_NOT_EXISTS} -Wait Until Element Is Hidden Wait Until Element Is Hidden ${EXP_ERR_MSG_XPATH_NOT_FOUND} ${XPATH_NOT_EXISTS} 10 Wait Until Element Is Visible Wait Until Element Is Visible ${EXP_ERR_MSG_ELEMENT_NOT_VISIBLE} ${XPATH_NOT_EXISTS} 10 *** Keywords *** Execute Keyword And Expect Error Message [Arguments] ${keyword} ${expected_default_error_msg} @{args} + Log ${args} ${EXP_ERR_MSG} Format String ${expected_default_error_msg} ${XPATH_NOT_EXISTS} Run Keyword And Expect Error ${EXP_ERR_MSG} Run Keyword ${keyword} @{args} - Run Keyword And Expect Error ${EXP_CUSTOM_ERR_MSG} Run Keyword ${keyword} @{args} ${CUSTOM_ERR_MSG} + Run Keyword And Expect Error ${EXP_CUSTOM_ERR_MSG} Run Keyword ${keyword} @{args} msg=${CUSTOM_ERR_MSG} diff --git a/src/FlaUILibrary/flaui/module/element.py b/src/FlaUILibrary/flaui/module/element.py index 3dbe3e0..e379e8d 100644 --- a/src/FlaUILibrary/flaui/module/element.py +++ b/src/FlaUILibrary/flaui/module/element.py @@ -19,6 +19,7 @@ class Container(ValueContainer): """ xpath: Optional[str] name: Optional[str] + use_exception: Optional[bool] retries: Optional[int] class Action(Enum): @@ -31,6 +32,7 @@ class Action(Enum): IS_ELEMENT_ENABLED = "IS_ELEMENT_ENABLED" NAME_SHOULD_BE = "NAME_SHOULD_BE" NAME_SHOULD_CONTAINS = "NAME_SHOULD_CONTAINS" + ELEMENT_SHOULD_EXIST = "ELEMENT_SHOULD_EXIST" ELEMENT_SHOULD_NOT_EXIST = "ELEMENT_SHOULD_NOT_EXIST" IS_ELEMENT_VISIBLE = "IS_ELEMENT_VISIBLE" ELEMENT_SHOULD_BE_VISIBLE = "ELEMENT_SHOULD_BE_VISIBLE" @@ -51,7 +53,7 @@ def __init__(self, automation: Any, timeout: int = 1000): self._timeout = timeout @staticmethod - def create_value_container(name=None, xpath=None, retries=None, msg=None): + def create_value_container(name=None, xpath=None, retries=None, use_exception=None, msg=None): """ Helper to create container object. @@ -62,10 +64,12 @@ def create_value_container(name=None, xpath=None, retries=None, msg=None): name (String): Name from element xpath (String): Searched element as xpath retries (Number): Retry counter to repeat calls as number + use_exception (Bool) : Indicator to ignore exception handling by flaui msg (String): Optional error message """ return Element.Container(name=Converter.cast_to_string(name), xpath=Converter.cast_to_string(xpath), + use_exception=Converter.cast_to_bool(use_exception), retries=Converter.cast_to_int(retries, msg)) def execute_action(self, action: Action, values: Container): @@ -110,9 +114,13 @@ def execute_action(self, action: Action, values: Container): * Values ["xpath"] * Returns : None + * Action.ELEMENT_SHOULD_EXIST + * Values ["xpath", "use_exception"] + * Returns : True if element exists otherwise False + * Action.ELEMENT_SHOULD_NOT_EXIST - * Values ["xpath"] - * Returns : None + * Values ["xpath", "use_exception"] + * Returns : True if element not exists otherwise False * Action.WAIT_UNTIL_ELEMENT_IS_HIDDEN * Values ["xpath", "retries"] @@ -140,7 +148,10 @@ def execute_action(self, action: Action, values: Container): self.Action.IS_ELEMENT_VISIBLE: lambda: self._get_element(values["xpath"]).IsOffscreen, self.Action.ELEMENT_SHOULD_BE_VISIBLE: lambda: self._element_should_be_visible(values["xpath"]), self.Action.ELEMENT_SHOULD_NOT_BE_VISIBLE: lambda: self._element_should_not_be_visible(values["xpath"]), - self.Action.ELEMENT_SHOULD_NOT_EXIST: lambda: self._element_should_not_exist(values["xpath"]), + self.Action.ELEMENT_SHOULD_EXIST: lambda: self._element_should_exist(values["xpath"], + values["use_exception"]), + self.Action.ELEMENT_SHOULD_NOT_EXIST: lambda: self._element_should_not_exist(values["xpath"], + values["use_exception"]), self.Action.WAIT_UNTIL_ELEMENT_IS_HIDDEN: lambda: self._wait_until_element_is_hidden( values["xpath"], values["retries"]), self.Action.WAIT_UNTIL_ELEMENT_IS_VISIBLE: lambda: self._wait_until_element_is_visible( @@ -226,10 +237,29 @@ def _get_element_by_xpath(self, xpath: str): Args: xpath (string): XPath identifier from element. """ - desktop = self._automation.GetDesktop() - return desktop.FindFirstByXPath(xpath) + return self._automation.GetDesktop().FindFirstByXPath(xpath) + + def _element_should_exist(self, xpath: str, use_exception: bool): + """ + Checks if element exists. + + Args: + xpath (string): XPath identifier from element. + use_exception (bool): Indicator if to throw an FlaUI error + + Raises: + FlaUiError: If element could not be found + """ + try: + if self._get_element(xpath): + return True + except FlaUiError as ex: + if use_exception: + raise ex from None - def _element_should_not_exist(self, xpath: str): + return False + + def _element_should_not_exist(self, xpath: str, use_exception: bool): """ Try to get element from xpath. @@ -237,14 +267,18 @@ def _element_should_not_exist(self, xpath: str): xpath (string): XPath identifier from element. Raises: - FlaUiError: If node could found by xpath. + FlaUiError: If element could be found """ - desktop = self._automation.GetDesktop() - component = desktop.FindFirstByXPath(xpath) + try: + component = self._get_element(xpath) + except FlaUiError: + return True - if component: + if component and use_exception: raise FlaUiError(FlaUiError.ElementExists.format(xpath)) + return False + def _element_should_be_visible(self, xpath: str): """ Checks if the element with the given xpath is visible diff --git a/src/FlaUILibrary/keywords/element.py b/src/FlaUILibrary/keywords/element.py index 6485bc3..3c9d2e2 100644 --- a/src/FlaUILibrary/keywords/element.py +++ b/src/FlaUILibrary/keywords/element.py @@ -1,5 +1,4 @@ from robotlibcore import keyword - from FlaUILibrary.flaui.module.element import Element @@ -17,48 +16,63 @@ def __init__(self, module): self._module = module @keyword - def element_should_exist(self, identifier, msg=None): + def element_should_exist(self, identifier, use_exception=True, msg=None): """ Checks if element exists. If element exists True will be returned otherwise False. + If element could not be found by xpath False will be returned. XPath syntax is explained in `XPath locator`. - If element could not be found by xpath an error message will be thrown. - Arguments: - | Argument | Type | Description | - | identifier | string | XPath identifier from element | - | msg | string | Custom error message | + | Argument | Type | Description | + | identifier | string | XPath identifier from element | + | use_exception | bool | Indicator if an FlaUI exception should be called if element + could not be found by xpath | + | msg | string | Custom error message | - Example: - | Element Should Exist | + Example for custom result handling: + | ${RESULT} Element Should Exist ${FALSE} | + | Run Keyword If ${RESULT} == ${False} | + + Example if element will be shown after a click and takes a few seconds to open: + | Click | + | Wait Until Keyword Succeeds 5x 10ms Element Should Exist | """ - self._module.action(Element.Action.GET_ELEMENT, - Element.create_value_container(xpath=identifier, msg=msg), - msg) + return self._module.action(Element.Action.ELEMENT_SHOULD_EXIST, + Element.create_value_container(xpath=identifier, + use_exception=use_exception, + msg=msg), msg) @keyword - def element_should_not_exist(self, identifier, msg=None): + def element_should_not_exist(self, identifier, use_exception=True, msg=None): """ Checks if element exists. If element exists False will be returned otherwise True. + If element could not be found by xpath True will be returned. XPath syntax is explained in `XPath locator`. - If element could not be found by xpath an error message will be thrown. - Arguments: - | Argument | Type | Description | - | identifier | string | XPath identifier from element | - | msg | string | Custom error message | + | Argument | Type | Description | + | identifier | string | XPath identifier from element | + | use_exception | bool | Indicator if an FlaUI exception should be called if element + could not be found by xpath | + | msg | string | Custom error message | - Example: - | Element Should Exist | + + Example for custom result handling: + | ${RESULT} Element Should Not Exist ${FALSE} | + | Run Keyword If ${RESULT} == ${False} | + + Example if element will be shown after a click and takes a few seconds to open: + | Click | + | Wait Until Keyword Succeeds 5x 10ms Element Should Not Exist | """ - self._module.action(Element.Action.ELEMENT_SHOULD_NOT_EXIST, - Element.create_value_container(xpath=identifier, msg=msg), - msg) + return self._module.action(Element.Action.ELEMENT_SHOULD_NOT_EXIST, + Element.create_value_container(xpath=identifier, + use_exception=use_exception, + msg=msg), msg) @keyword def focus(self, identifier, msg=None): @@ -237,7 +251,6 @@ def element_should_not_be_visible(self, identifier, msg=None): def wait_until_element_is_hidden(self, identifier, retries=10, msg=None): """ Waits until element is hidden or timeout was reached. If timeout was reached an FlaUIError occurred. - Checks if element exists before Wait Until Element Is Hidden is called. XPath syntax is explained in `XPath locator`. @@ -251,7 +264,6 @@ def wait_until_element_is_hidden(self, identifier, retries=10, msg=None): | Wait Until Element Is Hidden | | Wait Until Element Is Hidden | """ - self.element_should_exist(identifier, msg) self._module.action(Element.Action.WAIT_UNTIL_ELEMENT_IS_HIDDEN, Element.create_value_container(xpath=identifier, retries=retries), msg)