@@ -1733,6 +1733,69 @@ def click_active_element(self):
1733
1733
elif self.slow_mode:
1734
1734
self.__slow_mode_pause_if_active()
1735
1735
1736
+ def click_with_offset(
1737
+ self, selector, x, y, by=By.CSS_SELECTOR, mark=False, timeout=None
1738
+ ):
1739
+ """
1740
+ Click an element at an {X,Y}-offset location.
1741
+ {0,0} is the top-left corner of the element.
1742
+ If mark==True, will draw a dot at location. (Useful for debugging)
1743
+ """
1744
+ from selenium.webdriver.common.action_chains import ActionChains
1745
+
1746
+ self.__check_scope()
1747
+ if not timeout:
1748
+ timeout = settings.SMALL_TIMEOUT
1749
+ if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
1750
+ timeout = self.__get_new_timeout(timeout)
1751
+ selector, by = self.__recalculate_selector(selector, by)
1752
+ element = page_actions.wait_for_element_visible(
1753
+ self.driver, selector, by, timeout
1754
+ )
1755
+ self.__demo_mode_highlight_if_active(selector, by)
1756
+ if mark:
1757
+ selector = self.convert_to_css_selector(selector, by=by)
1758
+ selector = re.escape(selector)
1759
+ selector = self.__escape_quotes_if_needed(selector)
1760
+ px = x - 2
1761
+ if px < 0:
1762
+ px = 0
1763
+ py = y - 2
1764
+ if py < 0:
1765
+ py = 0
1766
+ script = (
1767
+ "var canvas = document.querySelector('%s');"
1768
+ "var ctx = canvas.getContext('2d');"
1769
+ "ctx.fillStyle = '#F80808';"
1770
+ "ctx.fillRect(%s, %s, 5, 5);"
1771
+ % (selector, px, py)
1772
+ )
1773
+ self.execute_script(script)
1774
+ try:
1775
+ element_location = element.location["y"]
1776
+ element_location = element_location - 130 + y
1777
+ if element_location < 0:
1778
+ element_location = 0
1779
+ scroll_script = "window.scrollTo(0, %s);" % element_location
1780
+ self.driver.execute_script(scroll_script)
1781
+ self.sleep(0.1)
1782
+ except Exception:
1783
+ pass
1784
+ try:
1785
+ action_chains = ActionChains(self.driver)
1786
+ action_chains.move_to_element_with_offset(element, x, y)
1787
+ action_chains.click().perform()
1788
+ except MoveTargetOutOfBoundsException:
1789
+ message = (
1790
+ "Target coordinates for click are out-of-bounds!\n"
1791
+ "The offset must stay inside the target element!"
1792
+ )
1793
+ raise Exception(message)
1794
+ if self.demo_mode:
1795
+ self.__demo_mode_pause_if_active()
1796
+ elif self.slow_mode:
1797
+ self.__slow_mode_pause_if_active()
1798
+
1736
1799
def is_checked(self, selector, by=By.CSS_SELECTOR, timeout=None):
1737
1800
"""Determines if a checkbox or a radio button element is checked.
1738
1801
Returns True if the element is checked.
0 commit comments