78 lines
3.0 KiB
Python
78 lines
3.0 KiB
Python
import random
|
|
import string
|
|
import typing
|
|
|
|
from selenium.webdriver.remote.webdriver import WebDriver
|
|
from selenium.webdriver.remote.webelement import WebElement
|
|
from selenium.webdriver.common.by import By
|
|
from selenium.webdriver.support import expected_conditions as EC
|
|
from selenium.webdriver.support.wait import WebDriverWait
|
|
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException
|
|
|
|
driver: WebDriver|None = None
|
|
attempts, timeout, interval, identity = int(), float(), float(), None
|
|
|
|
def until(condition: typing.Callable[[WebDriver], bool], watch=True):
|
|
try:
|
|
WebDriverWait(driver, timeout).until(condition)
|
|
except (TimeoutException, StaleElementReferenceException):
|
|
pass
|
|
if watch: WebDriverWait(driver, timeout).until_not(condition)
|
|
|
|
def sleep(seconds: float):
|
|
from common.jsonrpc2.server import connection
|
|
assert connection is not None and connection.closed is None
|
|
|
|
try: WebDriverWait(driver, seconds, seconds).until(lambda _: False)
|
|
except: pass
|
|
|
|
def locate(selector: str, wait=True, condition=True) -> WebElement:
|
|
while True:
|
|
try:
|
|
locator = (By.CSS_SELECTOR, selector)
|
|
if not wait: return driver.find_element(*locator)
|
|
|
|
presence = EC.presence_of_element_located(locator)
|
|
element = WebDriverWait(driver, timeout).until(presence, 'Timeout')
|
|
driver.execute_script("arguments[0].scrollIntoView({ block: 'center', inline: 'nearest' });", element)
|
|
|
|
if condition is not None and condition != False:
|
|
predicate = condition if callable(condition) else EC.visibility_of_element_located
|
|
element = WebDriverWait(driver, timeout).until(predicate(locator), 'Timeout')
|
|
|
|
return element
|
|
except StaleElementReferenceException:
|
|
pass
|
|
|
|
def click(selector: str|WebElement, wait=True, condition=False):
|
|
predicate = None if condition is None else condition or EC.element_to_be_clickable
|
|
error = False
|
|
|
|
element = locate(selector, wait, predicate) if isinstance(selector, str) else selector
|
|
counter = lambda: int(element.get_attribute(identity) or 0)
|
|
value = counter()
|
|
driver.execute_script("arguments[0].addEventListener('click', () => arguments[0].setAttribute(arguments[1], arguments[2] + 1));", element, identity, value)
|
|
|
|
for _ in range(attempts):
|
|
try:
|
|
if not error: element.click()
|
|
else: driver.execute_script("arguments[0].click();", element)
|
|
except StaleElementReferenceException:
|
|
break
|
|
except:
|
|
error = True
|
|
continue
|
|
try:
|
|
WebDriverWait(driver, interval).until(lambda _: counter() > value)
|
|
break
|
|
except TimeoutException: continue
|
|
except: break
|
|
|
|
def setup(a: WebDriver, b: int, c: float, d: float):
|
|
global identity, driver, attempts, timeout, interval
|
|
identity = ''.join(random.choices(string.ascii_uppercase + string.digits, k=8))
|
|
driver = a
|
|
attempts = b
|
|
timeout = c
|
|
interval = d
|