Skip to content

Commit

Permalink
#42 Element not found and Element found handling restructuring
Browse files Browse the repository at this point in the history
  • Loading branch information
Nepitwin committed Jan 30, 2022
1 parent a2ac8a0 commit d1c1659
Show file tree
Hide file tree
Showing 5 changed files with 135 additions and 46 deletions.
40 changes: 39 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 12 additions & 6 deletions atests/Element.robot
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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}
Expand Down
5 changes: 2 additions & 3 deletions atests/ErrorHandling.robot
Original file line number Diff line number Diff line change
Expand Up @@ -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}
Expand Down Expand Up @@ -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}
56 changes: 45 additions & 11 deletions src/FlaUILibrary/flaui/module/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Container(ValueContainer):
"""
xpath: Optional[str]
name: Optional[str]
use_exception: Optional[bool]
retries: Optional[int]

class Action(Enum):
Expand All @@ -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"
Expand All @@ -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.
Expand All @@ -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):
Expand Down Expand Up @@ -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"]
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -226,25 +237,48 @@ 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.
Args:
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
Expand Down
62 changes: 37 additions & 25 deletions src/FlaUILibrary/keywords/element.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from robotlibcore import keyword

from FlaUILibrary.flaui.module.element import Element


Expand All @@ -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 <XPATH> |
Example for custom result handling:
| ${RESULT} Element Should Exist <XPATH> ${FALSE} |
| Run Keyword If ${RESULT} == ${False} |
Example if element will be shown after a click and takes a few seconds to open:
| Click <XPATH> |
| Wait Until Keyword Succeeds 5x 10ms Element Should Exist <XPATH> |
"""
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 <XPATH> |
Example for custom result handling:
| ${RESULT} Element Should Not Exist <XPATH> ${FALSE} |
| Run Keyword If ${RESULT} == ${False} |
Example if element will be shown after a click and takes a few seconds to open:
| Click <XPATH> |
| Wait Until Keyword Succeeds 5x 10ms Element Should Not Exist <XPATH> |
"""
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):
Expand Down Expand Up @@ -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`.
Expand All @@ -251,7 +264,6 @@ def wait_until_element_is_hidden(self, identifier, retries=10, msg=None):
| Wait Until Element Is Hidden <XPATH> <RETRIES=10> |
| Wait Until Element Is Hidden <XPATH> <RETRIES=10> <MSG> |
"""
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)
Expand Down

0 comments on commit d1c1659

Please sign in to comment.