Path: blob/trunk/py/selenium/webdriver/remote/shadowroot.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.1617from hashlib import md5 as md5_hash1819from ..common.by import By20from .command import Command212223class ShadowRoot:24# TODO: We should look and see how we can create a search context like Java/.NET2526def __init__(self, session, id_) -> None:27self.session = session28self._id = id_2930def __eq__(self, other_shadowroot) -> bool:31return self._id == other_shadowroot._id3233def __hash__(self) -> int:34return int(md5_hash(self._id.encode("utf-8")).hexdigest(), 16)3536def __repr__(self) -> str:37return '<{0.__module__}.{0.__name__} (session="{1}", element="{2}")>'.format(38type(self), self.session.session_id, self._id39)4041@property42def id(self) -> str:43return self._id4445def find_element(self, by: str = By.ID, value: str = None):46"""Find an element inside a shadow root given a By strategy and47locator.4849Parameters:50-----------51by : selenium.webdriver.common.by.By52The locating strategy to use. Default is `By.ID`. Supported values include:53- By.ID: Locate by element ID.54- By.NAME: Locate by the `name` attribute.55- By.XPATH: Locate by an XPath expression.56- By.CSS_SELECTOR: Locate by a CSS selector.57- By.CLASS_NAME: Locate by the `class` attribute.58- By.TAG_NAME: Locate by the tag name (e.g., "input", "button").59- By.LINK_TEXT: Locate a link element by its exact text.60- By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.61- RelativeBy: Locate elements relative to a specified root element.6263Example:64--------65element = driver.find_element(By.ID, 'foo')6667Returns:68-------69WebElement70The first matching `WebElement` found on the page.71"""72if by == By.ID:73by = By.CSS_SELECTOR74value = f'[id="{value}"]'75elif by == By.CLASS_NAME:76by = By.CSS_SELECTOR77value = f".{value}"78elif by == By.NAME:79by = By.CSS_SELECTOR80value = f'[name="{value}"]'8182return self._execute(Command.FIND_ELEMENT_FROM_SHADOW_ROOT, {"using": by, "value": value})["value"]8384def find_elements(self, by: str = By.ID, value: str = None):85"""Find elements inside a shadow root given a By strategy and locator.8687Parameters:88-----------89by : selenium.webdriver.common.by.By90The locating strategy to use. Default is `By.ID`. Supported values include:91- By.ID: Locate by element ID.92- By.NAME: Locate by the `name` attribute.93- By.XPATH: Locate by an XPath expression.94- By.CSS_SELECTOR: Locate by a CSS selector.95- By.CLASS_NAME: Locate by the `class` attribute.96- By.TAG_NAME: Locate by the tag name (e.g., "input", "button").97- By.LINK_TEXT: Locate a link element by its exact text.98- By.PARTIAL_LINK_TEXT: Locate a link element by partial text match.99- RelativeBy: Locate elements relative to a specified root element.100101Example:102--------103element = driver.find_elements(By.ID, 'foo')104105Returns:106-------107List[WebElement]108list of `WebElements` matching locator strategy found on the page.109"""110if by == By.ID:111by = By.CSS_SELECTOR112value = f'[id="{value}"]'113elif by == By.CLASS_NAME:114by = By.CSS_SELECTOR115value = f".{value}"116elif by == By.NAME:117by = By.CSS_SELECTOR118value = f'[name="{value}"]'119120return self._execute(Command.FIND_ELEMENTS_FROM_SHADOW_ROOT, {"using": by, "value": value})["value"]121122# Private Methods123def _execute(self, command, params=None):124"""Executes a command against the underlying HTML element.125126Args:127command: The name of the command to _execute as a string.128params: A dictionary of named parameters to send with the command.129130Returns:131The command's JSON response loaded into a dictionary object.132"""133if not params:134params = {}135params["shadowId"] = self._id136return self.session.execute(command, params)137138139