diff --git a/src/SeleniumLibrary/__init__.py b/src/SeleniumLibrary/__init__.py index 6945eae7f..5bdd14b12 100644 --- a/src/SeleniumLibrary/__init__.py +++ b/src/SeleniumLibrary/__init__.py @@ -202,7 +202,7 @@ class SeleniumLibrary(DynamicCore): used to specify multiple locators. This is useful, is some part of locator would match as the locator separator but it should not. Or if there is need to existing WebElement as locator. - Although all locators support chaining, some locator strategies do not abey the chaining. This is because + Although all locators support chaining, some locator strategies do not obey the chaining. This is because some locator strategies use JavaScript to find elements and JavaScript is executed for the whole browser context and not for the element found be the previous locator. Chaining is supported by locator strategies which are based on Selenium API, like `xpath` or `css`, but example chaining is not supported by `sizzle` or `jquery diff --git a/src/SeleniumLibrary/keywords/element.py b/src/SeleniumLibrary/keywords/element.py index 831ebfaf2..d103e3c7c 100644 --- a/src/SeleniumLibrary/keywords/element.py +++ b/src/SeleniumLibrary/keywords/element.py @@ -29,7 +29,7 @@ class ElementKeywords(LibraryComponent): @keyword(name="Get WebElement") - def get_webelement(self, locator: Union[WebElement, str]) -> WebElement: + def get_webelement(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> WebElement: """Returns the first WebElement matching the given ``locator``. See the `Locating elements` section for details about the locator @@ -38,7 +38,7 @@ def get_webelement(self, locator: Union[WebElement, str]) -> WebElement: return self.find_element(locator) @keyword(name="Get WebElements") - def get_webelements(self, locator: Union[WebElement, str]) -> List[WebElement]: + def get_webelements(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> List[WebElement]: """Returns a list of WebElement objects matching the ``locator``. See the `Locating elements` section for details about the locator @@ -53,7 +53,7 @@ def get_webelements(self, locator: Union[WebElement, str]) -> List[WebElement]: @keyword def element_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: Union[None, str], message: Optional[str] = None, ignore_case: bool = False, @@ -91,7 +91,7 @@ def element_should_contain( @keyword def element_should_not_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: Union[None, str], message: Optional[str] = None, ignore_case: bool = False, @@ -209,7 +209,7 @@ def page_should_not_contain(self, text: str, loglevel: str = "TRACE"): @keyword def page_should_not_contain_element( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -224,7 +224,7 @@ def page_should_not_contain_element( self.assert_page_not_contains(locator, message=message, loglevel=loglevel) @keyword - def assign_id_to_element(self, locator: Union[WebElement, str], id: str): + def assign_id_to_element(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], id: str): """Assigns a temporary ``id`` to the element specified by ``locator``. This is mainly useful if the locator is complicated and/or slow XPath @@ -243,7 +243,7 @@ def assign_id_to_element(self, locator: Union[WebElement, str], id: str): self.driver.execute_script(f"arguments[0].id = '{id}';", element) @keyword - def element_should_be_disabled(self, locator: Union[WebElement, str]): + def element_should_be_disabled(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies that element identified by ``locator`` is disabled. This keyword considers also elements that are read-only to be @@ -256,7 +256,7 @@ def element_should_be_disabled(self, locator: Union[WebElement, str]): raise AssertionError(f"Element '{locator}' is enabled.") @keyword - def element_should_be_enabled(self, locator: Union[WebElement, str]): + def element_should_be_enabled(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies that element identified by ``locator`` is enabled. This keyword considers also elements that are read-only to be @@ -269,7 +269,7 @@ def element_should_be_enabled(self, locator: Union[WebElement, str]): raise AssertionError(f"Element '{locator}' is disabled.") @keyword - def element_should_be_focused(self, locator: Union[WebElement, str]): + def element_should_be_focused(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies that element identified by ``locator`` is focused. See the `Locating elements` section for details about the locator @@ -287,7 +287,7 @@ def element_should_be_focused(self, locator: Union[WebElement, str]): @keyword def element_should_be_visible( - self, locator: Union[WebElement, str], message: Optional[str] = None + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None ): """Verifies that the element identified by ``locator`` is visible. @@ -310,7 +310,7 @@ def element_should_be_visible( @keyword def element_should_not_be_visible( - self, locator: Union[WebElement, str], message: Optional[str] = None + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None ): """Verifies that the element identified by ``locator`` is NOT visible. @@ -330,7 +330,7 @@ def element_should_not_be_visible( @keyword def element_text_should_be( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: Union[None, str], message: Optional[str] = None, ignore_case: bool = False, @@ -366,7 +366,7 @@ def element_text_should_be( @keyword def element_text_should_not_be( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], not_expected: Union[None, str], message: Optional[str] = None, ignore_case: bool = False, @@ -399,7 +399,7 @@ def element_text_should_not_be( @keyword def get_element_attribute( - self, locator: Union[WebElement, str], attribute: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], attribute: str ) -> str: """Returns the value of ``attribute`` from the element ``locator``. @@ -417,7 +417,7 @@ def get_element_attribute( @keyword def get_dom_attribute( - self, locator: Union[WebElement, str], attribute: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], attribute: str ) -> str: """Returns the value of ``attribute`` from the element ``locator``. `Get DOM Attribute` keyword only returns attributes declared within the element's HTML markup. If the requested attribute @@ -434,7 +434,7 @@ def get_dom_attribute( @keyword def get_property( - self, locator: Union[WebElement, str], property: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], property: str ) -> str: """Returns the value of ``property`` from the element ``locator``. @@ -450,7 +450,7 @@ def get_property( @keyword def element_attribute_value_should_be( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], attribute: str, expected: Union[None, str], message: Optional[str] = None, @@ -479,7 +479,7 @@ def element_attribute_value_should_be( ) @keyword - def get_horizontal_position(self, locator: Union[WebElement, str]) -> int: + def get_horizontal_position(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> int: """Returns the horizontal position of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -493,7 +493,7 @@ def get_horizontal_position(self, locator: Union[WebElement, str]) -> int: return self.find_element(locator).location["x"] @keyword - def get_element_size(self, locator: Union[WebElement, str]) -> Tuple[int, int]: + def get_element_size(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> Tuple[int, int]: """Returns width and height of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -508,7 +508,7 @@ def get_element_size(self, locator: Union[WebElement, str]) -> Tuple[int, int]: return element.size["width"], element.size["height"] @keyword - def cover_element(self, locator: Union[WebElement, str]): + def cover_element(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Will cover elements identified by ``locator`` with a blue div without breaking page layout. See the `Locating elements` section for details about the locator @@ -540,7 +540,7 @@ def cover_element(self, locator: Union[WebElement, str]): self.driver.execute_script(script, element) @keyword - def get_value(self, locator: Union[WebElement, str]) -> str: + def get_value(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> str: """Returns the value attribute of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -549,7 +549,7 @@ def get_value(self, locator: Union[WebElement, str]) -> str: return self.get_element_attribute(locator, "value") @keyword - def get_text(self, locator: Union[WebElement, str]) -> str: + def get_text(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> str: """Returns the text value of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -558,7 +558,7 @@ def get_text(self, locator: Union[WebElement, str]) -> str: return self.find_element(locator).text @keyword - def clear_element_text(self, locator: Union[WebElement, str]): + def clear_element_text(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Clears the value of the text-input-element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -567,7 +567,7 @@ def clear_element_text(self, locator: Union[WebElement, str]): self.find_element(locator).clear() @keyword - def get_vertical_position(self, locator: Union[WebElement, str]) -> int: + def get_vertical_position(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> int: """Returns the vertical position of the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -582,7 +582,7 @@ def get_vertical_position(self, locator: Union[WebElement, str]) -> int: @keyword def click_button( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], modifier: Union[bool, str] = False ): """Clicks the button identified by ``locator``. @@ -606,7 +606,7 @@ def click_button( @keyword def click_image( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], modifier: Union[bool, str] = False ): """Clicks an image identified by ``locator``. @@ -631,7 +631,7 @@ def click_image( @keyword def click_link( - self, locator: Union[WebElement, str], modifier: Union[bool, str] = False + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], modifier: Union[bool, str] = False ): """Clicks a link identified by ``locator``. @@ -653,7 +653,7 @@ def click_link( @keyword def click_element( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], modifier: Union[bool, str] = False, action_chain: bool = False, ): @@ -694,7 +694,7 @@ def click_element( self.info(f"Clicking element '{locator}'.") self.find_element(locator).click() - def _click_with_action_chain(self, locator: Union[WebElement, str]): + def _click_with_action_chain(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): self.info(f"Clicking '{locator}' using an action chain.") action = ActionChains(self.driver, duration=self.ctx.action_chain_delay) element = self.find_element(locator) @@ -720,7 +720,7 @@ def _click_with_modifier(self, locator, tag, modifier): @keyword def click_element_at_coordinates( - self, locator: Union[WebElement, str], xoffset: int, yoffset: int + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], xoffset: int, yoffset: int ): """Click the element ``locator`` at ``xoffset/yoffset``. @@ -741,7 +741,7 @@ def click_element_at_coordinates( action.perform() @keyword - def double_click_element(self, locator: Union[WebElement, str]): + def double_click_element(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Double clicks the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -753,7 +753,7 @@ def double_click_element(self, locator: Union[WebElement, str]): action.double_click(element).perform() @keyword - def set_focus_to_element(self, locator: Union[WebElement, str]): + def set_focus_to_element(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Sets the focus to the element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -765,7 +765,7 @@ def set_focus_to_element(self, locator: Union[WebElement, str]): self.driver.execute_script("arguments[0].focus();", element) @keyword - def scroll_element_into_view(self, locator: Union[WebElement, str]): + def scroll_element_into_view(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Scrolls the element identified by ``locator`` into view. See the `Locating elements` section for details about the locator @@ -778,7 +778,7 @@ def scroll_element_into_view(self, locator: Union[WebElement, str]): @keyword def drag_and_drop( - self, locator: Union[WebElement, str], target: Union[WebElement, str] + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], target: Union[WebElement, str, List[Union[WebElement,str]]] ): """Drags the element identified by ``locator`` into the ``target`` element. @@ -796,7 +796,7 @@ def drag_and_drop( @keyword def drag_and_drop_by_offset( - self, locator: Union[WebElement, str], xoffset: int, yoffset: int + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], xoffset: int, yoffset: int ): """Drags the element identified with ``locator`` by ``xoffset/yoffset``. @@ -815,7 +815,7 @@ def drag_and_drop_by_offset( action.perform() @keyword - def mouse_down(self, locator: Union[WebElement, str]): + def mouse_down(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates pressing the left mouse button on the element ``locator``. See the `Locating elements` section for details about the locator @@ -832,7 +832,7 @@ def mouse_down(self, locator: Union[WebElement, str]): action.click_and_hold(element).perform() @keyword - def mouse_out(self, locator: Union[WebElement, str]): + def mouse_out(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates moving the mouse away from the element ``locator``. See the `Locating elements` section for details about the locator @@ -849,7 +849,7 @@ def mouse_out(self, locator: Union[WebElement, str]): action.perform() @keyword - def mouse_over(self, locator: Union[WebElement, str]): + def mouse_over(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates hovering the mouse over the element ``locator``. See the `Locating elements` section for details about the locator @@ -861,7 +861,7 @@ def mouse_over(self, locator: Union[WebElement, str]): action.move_to_element(element).perform() @keyword - def mouse_up(self, locator: Union[WebElement, str]): + def mouse_up(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates releasing the left mouse button on the element ``locator``. See the `Locating elements` section for details about the locator @@ -872,14 +872,14 @@ def mouse_up(self, locator: Union[WebElement, str]): ActionChains(self.driver, duration=self.ctx.action_chain_delay).release(element).perform() @keyword - def open_context_menu(self, locator: Union[WebElement, str]): + def open_context_menu(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Opens the context menu on the element identified by ``locator``.""" element = self.find_element(locator) action = ActionChains(self.driver, duration=self.ctx.action_chain_delay) action.context_click(element).perform() @keyword - def simulate_event(self, locator: Union[WebElement, str], event: str): + def simulate_event(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], event: str): """Simulates ``event`` on the element identified by ``locator``. This keyword is useful if element has ``OnEvent`` handler that @@ -904,7 +904,7 @@ def simulate_event(self, locator: Union[WebElement, str], event: str): self.driver.execute_script(script, element, event) @keyword - def press_key(self, locator: Union[WebElement, str], key: str): + def press_key(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], key: str): """Simulates user pressing key on element identified by ``locator``. See the `Locating elements` section for details about the locator @@ -930,7 +930,7 @@ def press_key(self, locator: Union[WebElement, str], key: str): element.send_keys(key) @keyword - def press_keys(self, locator: Union[WebElement, None, str] = None, *keys: str): + def press_keys(self, locator: Union[WebElement, None, str, List[Union[WebElement,str]]] = None, *keys: str): """Simulates the user pressing key(s) to an element or on the active browser. If ``locator`` evaluates as false, see `Boolean arguments` for more @@ -1033,7 +1033,7 @@ def get_all_links(self) -> List[str]: return [link.get_attribute("id") for link in links] @keyword - def mouse_down_on_link(self, locator: Union[WebElement, str]): + def mouse_down_on_link(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates a mouse down event on a link identified by ``locator``. See the `Locating elements` section for details about the locator @@ -1047,7 +1047,7 @@ def mouse_down_on_link(self, locator: Union[WebElement, str]): @keyword def page_should_contain_link( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -1065,7 +1065,7 @@ def page_should_contain_link( @keyword def page_should_not_contain_link( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -1081,7 +1081,7 @@ def page_should_not_contain_link( self.assert_page_not_contains(locator, "link", message, loglevel) @keyword - def mouse_down_on_image(self, locator: Union[WebElement, str]): + def mouse_down_on_image(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Simulates a mouse down event on an image identified by ``locator``. See the `Locating elements` section for details about the locator @@ -1095,7 +1095,7 @@ def mouse_down_on_image(self, locator: Union[WebElement, str]): @keyword def page_should_contain_image( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -1113,7 +1113,7 @@ def page_should_contain_image( @keyword def page_should_not_contain_image( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -1129,7 +1129,7 @@ def page_should_not_contain_image( self.assert_page_not_contains(locator, "image", message, loglevel) @keyword - def get_element_count(self, locator: Union[WebElement, str]) -> int: + def get_element_count(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> int: """Returns the number of elements matching ``locator``. If you wish to assert the number of matching elements, use diff --git a/src/SeleniumLibrary/keywords/formelement.py b/src/SeleniumLibrary/keywords/formelement.py index 15ef61256..a98ded910 100644 --- a/src/SeleniumLibrary/keywords/formelement.py +++ b/src/SeleniumLibrary/keywords/formelement.py @@ -15,7 +15,7 @@ # limitations under the License. import os -from typing import Optional, Union +from typing import Optional, Union, List from robot.libraries.BuiltIn import BuiltIn from selenium.webdriver.remote.webelement import WebElement @@ -26,7 +26,7 @@ class FormElementKeywords(LibraryComponent): @keyword - def submit_form(self, locator: Union[WebElement, None, str] = None): + def submit_form(self, locator: Union[WebElement, None, str, List[Union[WebElement,str]]] = None): """Submits a form identified by ``locator``. If ``locator`` is not given, first form on the page is submitted. @@ -41,7 +41,7 @@ def submit_form(self, locator: Union[WebElement, None, str] = None): element.submit() @keyword - def checkbox_should_be_selected(self, locator: Union[WebElement, str]): + def checkbox_should_be_selected(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies checkbox ``locator`` is selected/checked. See the `Locating elements` section for details about the locator @@ -55,7 +55,7 @@ def checkbox_should_be_selected(self, locator: Union[WebElement, str]): ) @keyword - def checkbox_should_not_be_selected(self, locator: Union[WebElement, str]): + def checkbox_should_not_be_selected(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies checkbox ``locator`` is not selected/checked. See the `Locating elements` section for details about the locator @@ -69,7 +69,7 @@ def checkbox_should_not_be_selected(self, locator: Union[WebElement, str]): @keyword def page_should_contain_checkbox( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -86,7 +86,7 @@ def page_should_contain_checkbox( @keyword def page_should_not_contain_checkbox( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -101,7 +101,7 @@ def page_should_not_contain_checkbox( self.assert_page_not_contains(locator, "checkbox", message, loglevel) @keyword - def select_checkbox(self, locator: Union[WebElement, str]): + def select_checkbox(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Selects the checkbox identified by ``locator``. Does nothing if checkbox is already selected. @@ -115,7 +115,7 @@ def select_checkbox(self, locator: Union[WebElement, str]): element.click() @keyword - def unselect_checkbox(self, locator: Union[WebElement, str]): + def unselect_checkbox(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Removes the selection of checkbox identified by ``locator``. Does nothing if the checkbox is not selected. @@ -131,7 +131,7 @@ def unselect_checkbox(self, locator: Union[WebElement, str]): @keyword def page_should_contain_radio_button( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -149,7 +149,7 @@ def page_should_contain_radio_button( @keyword def page_should_not_contain_radio_button( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -213,7 +213,7 @@ def select_radio_button(self, group_name: str, value: str): element.click() @keyword - def choose_file(self, locator: Union[WebElement, str], file_path: str): + def choose_file(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], file_path: str): """Inputs the ``file_path`` into the file input field ``locator``. This keyword is most often used to input files into upload forms. @@ -240,7 +240,7 @@ def choose_file(self, locator: Union[WebElement, str], file_path: str): @keyword def input_password( - self, locator: Union[WebElement, str], password: str, clear: bool = True + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], password: str, clear: bool = True ): """Types the given password into the text field identified by ``locator``. @@ -270,7 +270,7 @@ def input_password( @keyword def input_text( - self, locator: Union[WebElement, str], text: str, clear: bool = True + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], text: str, clear: bool = True ): """Types the given ``text`` into the text field identified by ``locator``. @@ -299,7 +299,7 @@ def input_text( @keyword def page_should_contain_textfield( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -316,7 +316,7 @@ def page_should_contain_textfield( @keyword def page_should_not_contain_textfield( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -333,7 +333,7 @@ def page_should_not_contain_textfield( @keyword def textfield_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, message: Optional[str] = None, ): @@ -357,7 +357,7 @@ def textfield_should_contain( @keyword def textfield_value_should_be( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, message: Optional[str] = None, ): @@ -381,7 +381,7 @@ def textfield_value_should_be( @keyword def textarea_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, message: Optional[str] = None, ): @@ -405,7 +405,7 @@ def textarea_should_contain( @keyword def textarea_value_should_be( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, message: Optional[str] = None, ): @@ -429,7 +429,7 @@ def textarea_value_should_be( @keyword def page_should_contain_button( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -450,7 +450,7 @@ def page_should_contain_button( @keyword def page_should_not_contain_button( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -469,7 +469,7 @@ def page_should_not_contain_button( def _get_value(self, locator, tag): return self.find_element(locator, tag).get_attribute("value") - def _get_checkbox(self, locator: Union[WebElement, str]): + def _get_checkbox(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): return self.find_element(locator, tag="checkbox") def _get_radio_buttons(self, group_name): diff --git a/src/SeleniumLibrary/keywords/frames.py b/src/SeleniumLibrary/keywords/frames.py index 296b1ee6b..1967286ec 100644 --- a/src/SeleniumLibrary/keywords/frames.py +++ b/src/SeleniumLibrary/keywords/frames.py @@ -13,7 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union +from typing import Union, List from selenium.webdriver.remote.webelement import WebElement @@ -22,7 +22,7 @@ class FrameKeywords(LibraryComponent): @keyword - def select_frame(self, locator: Union[WebElement, str]): + def select_frame(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Sets frame identified by ``locator`` as the current frame. See the `Locating elements` section for details about the locator @@ -82,7 +82,7 @@ def current_frame_should_not_contain(self, text: str, loglevel: str = "TRACE"): @keyword def frame_should_contain( - self, locator: Union[WebElement, str], text: str, loglevel: str = "TRACE" + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], text: str, loglevel: str = "TRACE" ): """Verifies that frame identified by ``locator`` contains ``text``. @@ -99,7 +99,7 @@ def frame_should_contain( ) self.info(f"Frame '{locator}' contains text '{text}'.") - def _frame_contains(self, locator: Union[WebElement, str], text: str): + def _frame_contains(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], text: str): element = self.find_element(locator) self.driver.switch_to.frame(element) self.info(f"Searching for text from frame '{locator}'.") diff --git a/src/SeleniumLibrary/keywords/screenshot.py b/src/SeleniumLibrary/keywords/screenshot.py index 11308af85..2adc2df98 100644 --- a/src/SeleniumLibrary/keywords/screenshot.py +++ b/src/SeleniumLibrary/keywords/screenshot.py @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. import os -from typing import Optional, Union +from typing import Optional, Union, List from base64 import b64decode from robot.utils import get_link_path @@ -146,7 +146,7 @@ def _capture_page_screen_to_log(self, return_val): @keyword def capture_element_screenshot( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], filename: str = DEFAULT_FILENAME_ELEMENT, ) -> str: """Captures a screenshot from the element identified by ``locator`` and embeds it into log file. diff --git a/src/SeleniumLibrary/keywords/selectelement.py b/src/SeleniumLibrary/keywords/selectelement.py index 910fb081e..a4c8ce32b 100644 --- a/src/SeleniumLibrary/keywords/selectelement.py +++ b/src/SeleniumLibrary/keywords/selectelement.py @@ -25,7 +25,7 @@ class SelectElementKeywords(LibraryComponent): @keyword def get_list_items( - self, locator: Union[WebElement, str], values: bool = False + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], values: bool = False ) -> List[str]: """Returns all labels or values of selection list ``locator``. @@ -49,7 +49,7 @@ def get_list_items( return self._get_labels(options) @keyword - def get_selected_list_label(self, locator: Union[WebElement, str]) -> str: + def get_selected_list_label(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> str: """Returns the label of selected option from selection list ``locator``. If there are multiple selected options, the label of the first option @@ -62,7 +62,7 @@ def get_selected_list_label(self, locator: Union[WebElement, str]) -> str: return select.first_selected_option.text @keyword - def get_selected_list_labels(self, locator: Union[WebElement, str]) -> List[str]: + def get_selected_list_labels(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> List[str]: """Returns labels of selected options from selection list ``locator``. Starting from SeleniumLibrary 3.0, returns an empty list if there @@ -75,7 +75,7 @@ def get_selected_list_labels(self, locator: Union[WebElement, str]) -> List[str] return self._get_labels(options) @keyword - def get_selected_list_value(self, locator: Union[WebElement, str]) -> str: + def get_selected_list_value(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> str: """Returns the value of selected option from selection list ``locator``. If there are multiple selected options, the value of the first option @@ -88,7 +88,7 @@ def get_selected_list_value(self, locator: Union[WebElement, str]) -> str: return select.first_selected_option.get_attribute("value") @keyword - def get_selected_list_values(self, locator: Union[WebElement, str]) -> List[str]: + def get_selected_list_values(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]) -> List[str]: """Returns values of selected options from selection list ``locator``. Starting from SeleniumLibrary 3.0, returns an empty list if there @@ -101,7 +101,7 @@ def get_selected_list_values(self, locator: Union[WebElement, str]) -> List[str] return self._get_values(options) @keyword - def list_selection_should_be(self, locator: Union[WebElement, str], *expected: str): + def list_selection_should_be(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *expected: str): """Verifies selection list ``locator`` has ``expected`` options selected. It is possible to give expected options both as visible labels and @@ -138,7 +138,7 @@ def _format_selection(self, labels, values): return " | ".join(f"{label} ({value})" for label, value in zip(labels, values)) @keyword - def list_should_have_no_selections(self, locator: Union[WebElement, str]): + def list_should_have_no_selections(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Verifies selection list ``locator`` has no options selected. See the `Locating elements` section for details about the locator @@ -158,7 +158,7 @@ def list_should_have_no_selections(self, locator: Union[WebElement, str]): @keyword def page_should_contain_list( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -175,7 +175,7 @@ def page_should_contain_list( @keyword def page_should_not_contain_list( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], message: Optional[str] = None, loglevel: str = "TRACE", ): @@ -190,7 +190,7 @@ def page_should_not_contain_list( self.assert_page_not_contains(locator, "list", message, loglevel) @keyword - def select_all_from_list(self, locator: Union[WebElement, str]): + def select_all_from_list(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Selects all options from multi-selection list ``locator``. See the `Locating elements` section for details about the locator @@ -206,7 +206,7 @@ def select_all_from_list(self, locator: Union[WebElement, str]): select.select_by_index(index) @keyword - def select_from_list_by_index(self, locator: Union[WebElement, str], *indexes: str): + def select_from_list_by_index(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *indexes: str): """Selects options from selection list ``locator`` by ``indexes``. Indexes of list options start from 0. @@ -231,7 +231,7 @@ def select_from_list_by_index(self, locator: Union[WebElement, str], *indexes: s select.select_by_index(int(index)) @keyword - def select_from_list_by_value(self, locator: Union[WebElement, str], *values: str): + def select_from_list_by_value(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *values: str): """Selects options from selection list ``locator`` by ``values``. If more than one option is given for a single-selection list, @@ -253,7 +253,7 @@ def select_from_list_by_value(self, locator: Union[WebElement, str], *values: st select.select_by_value(value) @keyword - def select_from_list_by_label(self, locator: Union[WebElement, str], *labels: str): + def select_from_list_by_label(self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *labels: str): """Selects options from selection list ``locator`` by ``labels``. If more than one option is given for a single-selection list, @@ -275,7 +275,7 @@ def select_from_list_by_label(self, locator: Union[WebElement, str], *labels: st select.select_by_visible_text(label) @keyword - def unselect_all_from_list(self, locator: Union[WebElement, str]): + def unselect_all_from_list(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): """Unselects all options from multi-selection list ``locator``. See the `Locating elements` section for details about the locator @@ -293,7 +293,7 @@ def unselect_all_from_list(self, locator: Union[WebElement, str]): @keyword def unselect_from_list_by_index( - self, locator: Union[WebElement, str], *indexes: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *indexes: str ): """Unselects options from selection list ``locator`` by ``indexes``. @@ -320,7 +320,7 @@ def unselect_from_list_by_index( @keyword def unselect_from_list_by_value( - self, locator: Union[WebElement, str], *values: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *values: str ): """Unselects options from selection list ``locator`` by ``values``. @@ -345,7 +345,7 @@ def unselect_from_list_by_value( @keyword def unselect_from_list_by_label( - self, locator: Union[WebElement, str], *labels: str + self, locator: Union[WebElement, str, List[Union[WebElement,str]]], *labels: str ): """Unselects options from selection list ``locator`` by ``labels``. @@ -368,14 +368,14 @@ def unselect_from_list_by_label( for label in labels: select.deselect_by_visible_text(label) - def _get_select_list(self, locator: Union[WebElement, str]): + def _get_select_list(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): el = self.find_element(locator, tag="list") return Select(el) - def _get_options(self, locator: Union[WebElement, str]): + def _get_options(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): return self._get_select_list(locator).options - def _get_selected_options(self, locator: Union[WebElement, str]): + def _get_selected_options(self, locator: Union[WebElement, str, List[Union[WebElement,str]]]): return self._get_select_list(locator).all_selected_options def _get_labels(self, options): diff --git a/src/SeleniumLibrary/keywords/tableelement.py b/src/SeleniumLibrary/keywords/tableelement.py index e054e9d77..47519ff42 100644 --- a/src/SeleniumLibrary/keywords/tableelement.py +++ b/src/SeleniumLibrary/keywords/tableelement.py @@ -13,7 +13,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from typing import Union +from typing import Union, List from selenium.webdriver.common.by import By from selenium.webdriver.remote.webelement import WebElement @@ -25,7 +25,7 @@ class TableElementKeywords(LibraryComponent): @keyword def get_table_cell( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], row: int, column: int, loglevel: str = "TRACE", @@ -89,7 +89,7 @@ def _get_rows(self, locator, count): @keyword def table_cell_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], row: int, column: int, expected: str, @@ -112,7 +112,7 @@ def table_cell_should_contain( @keyword def table_column_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], column: int, expected: str, loglevel: str = "TRACE", @@ -143,7 +143,7 @@ def table_column_should_contain( @keyword def table_footer_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, loglevel: str = "TRACE", ): @@ -168,7 +168,7 @@ def table_footer_should_contain( @keyword def table_header_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, loglevel: str = "TRACE", ): @@ -193,7 +193,7 @@ def table_header_should_contain( @keyword def table_row_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], row: int, expected: str, loglevel: str = "TRACE", @@ -224,7 +224,7 @@ def table_row_should_contain( @keyword def table_should_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], expected: str, loglevel: str = "TRACE", ): diff --git a/src/SeleniumLibrary/keywords/waiting.py b/src/SeleniumLibrary/keywords/waiting.py index eeec6756e..7dd38e0e6 100644 --- a/src/SeleniumLibrary/keywords/waiting.py +++ b/src/SeleniumLibrary/keywords/waiting.py @@ -16,7 +16,7 @@ import time from datetime import timedelta -from typing import Optional, Union +from typing import Optional, Union, List from selenium.common.exceptions import StaleElementReferenceException from selenium.webdriver.remote.webelement import WebElement @@ -222,7 +222,7 @@ def wait_until_page_does_not_contain( @keyword def wait_until_page_contains_element( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], timeout: Optional[timedelta] = None, error: Optional[str] = None, limit: Optional[int] = None, @@ -260,7 +260,7 @@ def wait_until_page_contains_element( @keyword def wait_until_page_does_not_contain_element( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], timeout: Optional[timedelta] = None, error: Optional[str] = None, limit: Optional[int] = None, @@ -298,7 +298,7 @@ def wait_until_page_does_not_contain_element( @keyword def wait_until_element_is_visible( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], timeout: Optional[timedelta] = None, error: Optional[str] = None, ): @@ -321,7 +321,7 @@ def wait_until_element_is_visible( @keyword def wait_until_element_is_not_visible( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], timeout: Optional[timedelta] = None, error: Optional[str] = None, ): @@ -344,7 +344,7 @@ def wait_until_element_is_not_visible( @keyword def wait_until_element_is_enabled( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], timeout: Optional[timedelta] = None, error: Optional[str] = None, ): @@ -372,7 +372,7 @@ def wait_until_element_is_enabled( @keyword def wait_until_element_contains( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], text: str, timeout: Optional[timedelta] = None, error: Optional[str] = None, @@ -396,7 +396,7 @@ def wait_until_element_contains( @keyword def wait_until_element_does_not_contain( self, - locator: Union[WebElement, str], + locator: Union[WebElement, str, List[Union[WebElement,str]]], text: str, timeout: Optional[timedelta] = None, error: Optional[str] = None,