Skip to content

[py] Support RelativeBy in type annotations #15050

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions py/selenium/webdriver/remote/webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.bidi.script import Script
from selenium.webdriver.common.by import By
from selenium.webdriver.common.by import ByType
from selenium.webdriver.common.options import ArgOptions
from selenium.webdriver.common.options import BaseOptions
from selenium.webdriver.common.print_page_options import PrintOptions
Expand Down Expand Up @@ -861,7 +862,7 @@ def timeouts(self, timeouts) -> None:
"""
_ = self.execute(Command.SET_TIMEOUTS, timeouts._to_json())["value"]

def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:
def find_element(self, by: Union[ByType, RelativeBy] = By.ID, value: Optional[str] = None) -> WebElement:
"""Find an element given a By strategy and locator.

Parameters:
Expand Down Expand Up @@ -897,7 +898,7 @@ def find_element(self, by=By.ID, value: Optional[str] = None) -> WebElement:

return self.execute(Command.FIND_ELEMENT, {"using": by, "value": value})["value"]

def find_elements(self, by=By.ID, value: Optional[str] = None) -> List[WebElement]:
def find_elements(self, by: Union[ByType, RelativeBy] = By.ID, value: Optional[str] = None) -> List[WebElement]:
"""Find elements given a By strategy and locator.

Parameters:
Expand Down
8 changes: 6 additions & 2 deletions py/selenium/webdriver/support/event_firing_webdriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@

from typing import Any
from typing import List
from typing import Optional
from typing import Tuple
from typing import Union

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.by import ByType
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webelement import WebElement

from .abstract_event_listener import AbstractEventListener
from .relative_locator import RelativeBy


def _wrap_elements(result, ef_driver):
Expand Down Expand Up @@ -185,10 +189,10 @@ def clear(self) -> None:
def send_keys(self, *value) -> None:
self._dispatch("change_value_of", (self._webelement, self._driver), "send_keys", value)

def find_element(self, by=By.ID, value=None) -> WebElement:
def find_element(self, by: Union[ByType, RelativeBy] = By.ID, value: Optional[str] = None) -> WebElement:
return self._dispatch("find", (by, value, self._driver), "find_element", (by, value))

def find_elements(self, by=By.ID, value=None) -> List[WebElement]:
def find_elements(self, by: Union[ByType, RelativeBy] = By.ID, value: Optional[str] = None) -> List[WebElement]:
return self._dispatch("find", (by, value, self._driver), "find_elements", (by, value))

def _dispatch(self, l_call, l_args, d_call, d_args):
Expand Down
35 changes: 18 additions & 17 deletions py/selenium/webdriver/support/expected_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
from selenium.common.exceptions import StaleElementReferenceException
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.common.alert import Alert
from selenium.webdriver.common.by import ByType
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver.remote.webdriver import WebElement
from selenium.webdriver.support.relative_locator import RelativeBy

"""
* Canned "Expected Conditions" which are generally useful within webdriver
Expand All @@ -43,6 +45,7 @@
T = TypeVar("T")

WebDriverOrWebElement = Union[WebDriver, WebElement]
LocatorType = Union[Tuple[ByType, str], Tuple[RelativeBy, None]]


def title_is(title: str) -> Callable[[WebDriver], bool]:
Expand Down Expand Up @@ -84,7 +87,7 @@ def _predicate(driver: WebDriver):
return _predicate


def presence_of_element_located(locator: Tuple[str, str]) -> Callable[[WebDriverOrWebElement], WebElement]:
def presence_of_element_located(locator: LocatorType) -> Callable[[WebDriverOrWebElement], WebElement]:
"""An expectation for checking that an element is present on the DOM of a
page. This does not necessarily mean that the element is visible.

Expand Down Expand Up @@ -195,7 +198,7 @@ def _predicate(driver: WebDriver):


def visibility_of_element_located(
locator: Tuple[str, str]
locator: LocatorType,
) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]:
"""An expectation for checking that an element is present on the DOM of a
page and visible. Visibility means that the element is not only displayed
Expand Down Expand Up @@ -280,7 +283,7 @@ def _element_if_visible(element: WebElement, visibility: bool = True) -> Union[L
return element if element.is_displayed() == visibility else False


def presence_of_all_elements_located(locator: Tuple[str, str]) -> Callable[[WebDriverOrWebElement], List[WebElement]]:
def presence_of_all_elements_located(locator: LocatorType) -> Callable[[WebDriverOrWebElement], List[WebElement]]:
"""An expectation for checking that there is at least one element present
on a web page.

Expand Down Expand Up @@ -308,7 +311,7 @@ def _predicate(driver: WebDriverOrWebElement):
return _predicate


def visibility_of_any_elements_located(locator: Tuple[str, str]) -> Callable[[WebDriverOrWebElement], List[WebElement]]:
def visibility_of_any_elements_located(locator: LocatorType) -> Callable[[WebDriverOrWebElement], List[WebElement]]:
"""An expectation for checking that there is at least one element visible
on a web page.

Expand Down Expand Up @@ -337,7 +340,7 @@ def _predicate(driver: WebDriverOrWebElement):


def visibility_of_all_elements_located(
locator: Tuple[str, str]
locator: LocatorType,
) -> Callable[[WebDriverOrWebElement], Union[List[WebElement], Literal[False]]]:
"""An expectation for checking that all elements are present on the DOM of
a page and visible. Visibility means that the elements are not only
Expand Down Expand Up @@ -374,7 +377,7 @@ def _predicate(driver: WebDriverOrWebElement):
return _predicate


def text_to_be_present_in_element(locator: Tuple[str, str], text_: str) -> Callable[[WebDriverOrWebElement], bool]:
def text_to_be_present_in_element(locator: LocatorType, text_: str) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation for checking if the given text is present in the
specified element.

Expand Down Expand Up @@ -408,9 +411,7 @@ def _predicate(driver: WebDriverOrWebElement):
return _predicate


def text_to_be_present_in_element_value(
locator: Tuple[str, str], text_: str
) -> Callable[[WebDriverOrWebElement], bool]:
def text_to_be_present_in_element_value(locator: LocatorType, text_: str) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation for checking if the given text is present in the
element's value.

Expand Down Expand Up @@ -445,7 +446,7 @@ def _predicate(driver: WebDriverOrWebElement):


def text_to_be_present_in_element_attribute(
locator: Tuple[str, str], attribute_: str, text_: str
locator: LocatorType, attribute_: str, text_: str
) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation for checking if the given text is present in the
element's attribute.
Expand Down Expand Up @@ -485,7 +486,7 @@ def _predicate(driver: WebDriverOrWebElement):
return _predicate


def frame_to_be_available_and_switch_to_it(locator: Union[Tuple[str, str], str]) -> Callable[[WebDriver], bool]:
def frame_to_be_available_and_switch_to_it(locator: Union[LocatorType, str]) -> Callable[[WebDriver], bool]:
"""An expectation for checking whether the given frame is available to
switch to.

Expand Down Expand Up @@ -525,7 +526,7 @@ def _predicate(driver: WebDriver):


def invisibility_of_element_located(
locator: Union[WebElement, Tuple[str, str]]
locator: Union[WebElement, LocatorType]
) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]:
"""An Expectation for checking that an element is either invisible or not
present on the DOM.
Expand Down Expand Up @@ -574,7 +575,7 @@ def _predicate(driver: WebDriverOrWebElement):


def invisibility_of_element(
element: Union[WebElement, Tuple[str, str]]
element: Union[WebElement, LocatorType]
) -> Callable[[WebDriverOrWebElement], Union[WebElement, bool]]:
"""An Expectation for checking that an element is either invisible or not
present on the DOM.
Expand All @@ -600,7 +601,7 @@ def invisibility_of_element(


def element_to_be_clickable(
mark: Union[WebElement, Tuple[str, str]]
mark: Union[WebElement, LocatorType]
) -> Callable[[WebDriverOrWebElement], Union[Literal[False], WebElement]]:
"""An Expectation for checking an element is visible and enabled such that
you can click it.
Expand Down Expand Up @@ -696,7 +697,7 @@ def _predicate(_):
return _predicate


def element_located_to_be_selected(locator: Tuple[str, str]) -> Callable[[WebDriverOrWebElement], bool]:
def element_located_to_be_selected(locator: LocatorType) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation for the element to be located is selected.

Parameters:
Expand Down Expand Up @@ -752,7 +753,7 @@ def _predicate(_):


def element_located_selection_state_to_be(
locator: Tuple[str, str], is_selected: bool
locator: LocatorType, is_selected: bool
) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation to locate an element and check if the selection state
specified is in that state.
Expand Down Expand Up @@ -868,7 +869,7 @@ def _predicate(driver: WebDriver):
return _predicate


def element_attribute_to_include(locator: Tuple[str, str], attribute_: str) -> Callable[[WebDriverOrWebElement], bool]:
def element_attribute_to_include(locator: LocatorType, attribute_: str) -> Callable[[WebDriverOrWebElement], bool]:
"""An expectation for checking if the given attribute is included in the
specified element.

Expand Down
Loading