Path: blob/trunk/py/selenium/webdriver/support/relative_locator.py
1864 views
# Licensed to the Software Freedom Conservancy (SFC) under one1# or more contributor license agreements. See the NOTICE file2# distributed with this work for additional information3# regarding copyright ownership. The SFC licenses this file4# to you under the Apache License, Version 2.0 (the5# "License"); you may not use this file except in compliance6# with the License. You may obtain a copy of the License at7#8# http://www.apache.org/licenses/LICENSE-2.09#10# Unless required by applicable law or agreed to in writing,11# software distributed under the License is distributed on an12# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13# KIND, either express or implied. See the License for the14# specific language governing permissions and limitations15# under the License.16import warnings17from typing import NoReturn, Optional, Union, overload1819from selenium.common.exceptions import WebDriverException20from selenium.webdriver.common.by import By, ByType21from selenium.webdriver.remote.webelement import WebElement222324def with_tag_name(tag_name: str) -> "RelativeBy":25"""Start searching for relative objects using a tag name.2627Parameters:28-----------29tag_name : str30The DOM tag of element to start searching.3132Returns:33--------34RelativeBy35Use this object to create filters within a `find_elements` call.3637Raises:38-------39WebDriverException40If `tag_name` is None.4142Notes:43------44- This method is deprecated and may be removed in future versions.45- Please use `locate_with` instead.46"""47warnings.warn("This method is deprecated and may be removed in future versions. Please use `locate_with` instead.")48if not tag_name:49raise WebDriverException("tag_name can not be null")50return RelativeBy({By.CSS_SELECTOR: tag_name})515253def locate_with(by: ByType, using: str) -> "RelativeBy":54"""Start searching for relative objects your search criteria with By.5556Parameters:57-----------58by : ByType59The method to find the element.6061using : str62The value from `By` passed in.6364Returns:65--------66RelativeBy67Use this object to create filters within a `find_elements` call.6869Example:70--------71>>> lowest = driver.find_element(By.ID, "below")72>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").above(lowest))73"""74assert by is not None, "Please pass in a by argument"75assert using is not None, "Please pass in a using argument"76return RelativeBy({by: using})777879class RelativeBy:80"""Gives the opportunity to find elements based on their relative location81on the page from a root element. It is recommended that you use the helper82function to create it.8384Example:85--------86>>> lowest = driver.find_element(By.ID, "below")87>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").above(lowest))88>>> ids = [el.get_attribute("id") for el in elements]89>>> assert "above" in ids90>>> assert "mid" in ids91"""9293LocatorType = dict[ByType, str]9495def __init__(self, root: Optional[dict[ByType, str]] = None, filters: Optional[list] = None):96"""Creates a new RelativeBy object. It is preferred if you use the97`locate_with` method as this signature could change.9899Attributes:100-----------101root : Dict[By, str]102- A dict with `By` enum as the key and the search query as the value103104filters : List105- A list of the filters that will be searched. If none are passed106in please use the fluent API on the object to create the filters107"""108self.root = root109self.filters = filters or []110111@overload112def above(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...113114@overload115def above(self, element_or_locator: None = None) -> "NoReturn": ...116117def above(self, element_or_locator: Union[WebElement, LocatorType, None] = None) -> "RelativeBy":118"""Add a filter to look for elements above.119120Parameters:121-----------122element_or_locator : Union[WebElement, Dict, None]123Element to look above124125Returns:126--------127RelativeBy128129Raises:130-------131WebDriverException132If `element_or_locator` is None.133134Example:135--------136>>> lowest = driver.find_element(By.ID, "below")137>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").above(lowest))138"""139if not element_or_locator:140raise WebDriverException("Element or locator must be given when calling above method")141142self.filters.append({"kind": "above", "args": [element_or_locator]})143return self144145@overload146def below(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...147148@overload149def below(self, element_or_locator: None = None) -> "NoReturn": ...150151def below(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":152"""Add a filter to look for elements below.153154Parameters:155-----------156element_or_locator : Union[WebElement, Dict, None]157Element to look below158159Returns:160--------161RelativeBy162163Raises:164-------165WebDriverException166If `element_or_locator` is None.167168Example:169--------170>>> highest = driver.find_element(By.ID, "high")171>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").below(highest))172"""173if not element_or_locator:174raise WebDriverException("Element or locator must be given when calling below method")175176self.filters.append({"kind": "below", "args": [element_or_locator]})177return self178179@overload180def to_left_of(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...181182@overload183def to_left_of(self, element_or_locator: None = None) -> "NoReturn": ...184185def to_left_of(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":186"""Add a filter to look for elements to the left of.187188Parameters:189-----------190element_or_locator : Union[WebElement, Dict, None]191Element to look to the left of192193Returns:194--------195RelativeBy196197Raises:198-------199WebDriverException200If `element_or_locator` is None.201202Example:203--------204>>> right = driver.find_element(By.ID, "right")205>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").to_left_of(right))206"""207if not element_or_locator:208raise WebDriverException("Element or locator must be given when calling to_left_of method")209210self.filters.append({"kind": "left", "args": [element_or_locator]})211return self212213@overload214def to_right_of(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...215216@overload217def to_right_of(self, element_or_locator: None = None) -> "NoReturn": ...218219def to_right_of(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":220"""Add a filter to look for elements right of.221222Parameters:223-----------224element_or_locator : Union[WebElement, Dict, None]225Element to look right of226227Returns:228--------229RelativeBy230231Raises:232-------233WebDriverException234If `element_or_locator` is None.235236Example:237--------238>>> left = driver.find_element(By.ID, "left")239>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").to_right_of(left))240"""241if not element_or_locator:242raise WebDriverException("Element or locator must be given when calling to_right_of method")243244self.filters.append({"kind": "right", "args": [element_or_locator]})245return self246247@overload248def straight_above(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...249250@overload251def straight_above(self, element_or_locator: None = None) -> "NoReturn": ...252253def straight_above(self, element_or_locator: Union[WebElement, LocatorType, None] = None) -> "RelativeBy":254"""Add a filter to look for elements above.255256:Args:257- element_or_locator: Element to look above258"""259if not element_or_locator:260raise WebDriverException("Element or locator must be given when calling above method")261262self.filters.append({"kind": "straightAbove", "args": [element_or_locator]})263return self264265@overload266def straight_below(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...267268@overload269def straight_below(self, element_or_locator: None = None) -> "NoReturn": ...270271def straight_below(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":272"""Add a filter to look for elements below.273274:Args:275- element_or_locator: Element to look below276"""277if not element_or_locator:278raise WebDriverException("Element or locator must be given when calling below method")279280self.filters.append({"kind": "straightBelow", "args": [element_or_locator]})281return self282283@overload284def straight_left_of(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...285286@overload287def straight_left_of(self, element_or_locator: None = None) -> "NoReturn": ...288289def straight_left_of(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":290"""Add a filter to look for elements to the left of.291292:Args:293- element_or_locator: Element to look to the left of294"""295if not element_or_locator:296raise WebDriverException("Element or locator must be given when calling to_left_of method")297298self.filters.append({"kind": "straightLeft", "args": [element_or_locator]})299return self300301@overload302def straight_right_of(self, element_or_locator: Union[WebElement, LocatorType]) -> "RelativeBy": ...303304@overload305def straight_right_of(self, element_or_locator: None = None) -> "NoReturn": ...306307def straight_right_of(self, element_or_locator: Union[WebElement, dict, None] = None) -> "RelativeBy":308"""Add a filter to look for elements right of.309310:Args:311- element_or_locator: Element to look right of312"""313if not element_or_locator:314raise WebDriverException("Element or locator must be given when calling to_right_of method")315316self.filters.append({"kind": "straightRight", "args": [element_or_locator]})317return self318319@overload320def near(self, element_or_locator: Union[WebElement, LocatorType], distance: int = 50) -> "RelativeBy": ...321322@overload323def near(self, element_or_locator: None = None, distance: int = 50) -> "NoReturn": ...324325def near(self, element_or_locator: Union[WebElement, LocatorType, None] = None, distance: int = 50) -> "RelativeBy":326"""Add a filter to look for elements near.327328Parameters:329-----------330element_or_locator : Union[WebElement, Dict, None]331Element to look near by the element or within a distance332333distance : int334Distance in pixel335336Returns:337--------338RelativeBy339340Raises:341-------342WebDriverException343- If `element_or_locator` is None344- If `distance` is less than or equal to 0.345346Example:347--------348>>> near = driver.find_element(By.ID, "near")349>>> elements = driver.find_elements(locate_with(By.CSS_SELECTOR, "p").near(near, 50))350"""351if not element_or_locator:352raise WebDriverException("Element or locator must be given when calling near method")353if distance <= 0:354raise WebDriverException("Distance must be positive")355356self.filters.append({"kind": "near", "args": [element_or_locator, distance]})357return self358359def to_dict(self) -> dict:360"""Create a dict that will be passed to the driver to start searching361for the element."""362return {363"relative": {364"root": self.root,365"filters": self.filters,366}367}368369370