-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathwebdriver.py
119 lines (94 loc) · 2.85 KB
/
webdriver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# SPDX-License-Identifier: BSD-3-Clause
#
# Copyright 2022 Marek Behún <[email protected]>
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
from selenium.common.exceptions import WebDriverException
from selenium.webdriver.remote.webelement import WebElement
from functools import wraps
from time import sleep
__all__ = ['ProfilerWebDriver']
def repeat_on_error(err=Exception, to_sleep=1, contains=None, repeats=5):
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for i in range(1, repeats + 1):
try:
return func(*args, **kwargs)
except err as e:
if contains is not None and str(e).find(contains) == -1:
raise e
if i == repeats:
raise e
sleep(to_sleep)
return wrapper
return decorator
repeat_on_unexpected = repeat_on_error(err=WebDriverException, contains='unexpected command response')
class ProfilerWebElement(WebElement):
@repeat_on_unexpected
def click(self, *args, **kwargs):
return super().click(*args, *kwargs)
def wrap_elements(func):
@wraps(func)
def wrapper(*args, **kwargs):
elems = func(*args, **kwargs)
for elem in elems:
elem.__class__ = ProfilerWebElement
return elems
return wrapper
def wrap_element(func):
@wraps(func)
def wrapper(*args, **kwargs):
elem = func(*args, **kwargs)
if elem is None:
return None
elif elem.__class__ == WebElement:
elem.__class__ = ProfilerWebElement
return elem
return wrapper
class ProfilerWebDriver(Chrome):
@repeat_on_unexpected
def get(self, *args, **kwargs):
return super().get(*args, *kwargs)
@repeat_on_unexpected
def back(self, *args, **kwargs):
return super().back(*args, *kwargs)
@wrap_elements
@repeat_on_unexpected
def find_elements_by_css_selector(self, *args, **kwargs):
return super().find_elements(By.CSS_SELECTOR, *args, *kwargs)
def find_elements_by_xpath(self, *args, **kwargs):
return super().find_elements(By.XPATH, *args, *kwargs)
def wait_for_javascript_condition(self, condition, time=10):
while time > 0:
if self.execute_script('return !!(%s);' % condition):
return True
time -= 1
sleep(1)
return False
@wrap_element
def wait_for_element(self, selector, time=10):
if selector.startswith('xpath='):
method = self.find_elements_by_xpath
selector = selector[6:]
else:
method = self.find_elements_by_css_selector
while time > 0:
elems = method(selector)
if len(elems) > 0:
return elems[0]
time -= 1
sleep(1)
return None
def wait_for_element_click(self, selector, time=10):
elem = self.wait_for_element(selector, time)
if elem:
elem.click()
return elem
def open_in_new_tab(self, url):
old_handles = set(self.window_handles)
self.execute_script('window.open("%s", "_blank");' % (url,))
new_handles = set(self.window_handles)
win = list(new_handles - old_handles)[0]
self.switch_to.window(win)
return win