seleniumbase 4.24.10__py3-none-any.whl → 4.33.15__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sbase/__init__.py +1 -0
- sbase/steps.py +7 -0
- seleniumbase/__init__.py +16 -7
- seleniumbase/__version__.py +1 -1
- seleniumbase/behave/behave_sb.py +97 -32
- seleniumbase/common/decorators.py +16 -7
- seleniumbase/config/proxy_list.py +3 -3
- seleniumbase/config/settings.py +4 -0
- seleniumbase/console_scripts/logo_helper.py +47 -8
- seleniumbase/console_scripts/run.py +345 -335
- seleniumbase/console_scripts/sb_behave_gui.py +5 -12
- seleniumbase/console_scripts/sb_caseplans.py +6 -13
- seleniumbase/console_scripts/sb_commander.py +5 -12
- seleniumbase/console_scripts/sb_install.py +62 -54
- seleniumbase/console_scripts/sb_mkchart.py +13 -20
- seleniumbase/console_scripts/sb_mkdir.py +11 -17
- seleniumbase/console_scripts/sb_mkfile.py +69 -43
- seleniumbase/console_scripts/sb_mkpres.py +13 -20
- seleniumbase/console_scripts/sb_mkrec.py +88 -21
- seleniumbase/console_scripts/sb_objectify.py +30 -30
- seleniumbase/console_scripts/sb_print.py +5 -12
- seleniumbase/console_scripts/sb_recorder.py +16 -11
- seleniumbase/core/browser_launcher.py +1658 -221
- seleniumbase/core/detect_b_ver.py +7 -8
- seleniumbase/core/log_helper.py +42 -27
- seleniumbase/core/mysql.py +1 -4
- seleniumbase/core/proxy_helper.py +35 -30
- seleniumbase/core/recorder_helper.py +24 -5
- seleniumbase/core/sb_cdp.py +1951 -0
- seleniumbase/core/sb_driver.py +162 -8
- seleniumbase/core/settings_parser.py +6 -0
- seleniumbase/core/style_sheet.py +10 -0
- seleniumbase/extensions/recorder.zip +0 -0
- seleniumbase/fixtures/base_case.py +1234 -632
- seleniumbase/fixtures/constants.py +10 -1
- seleniumbase/fixtures/js_utils.py +171 -144
- seleniumbase/fixtures/page_actions.py +177 -13
- seleniumbase/fixtures/page_utils.py +25 -53
- seleniumbase/fixtures/shared_utils.py +97 -11
- seleniumbase/js_code/active_css_js.py +1 -1
- seleniumbase/js_code/recorder_js.py +1 -1
- seleniumbase/plugins/base_plugin.py +2 -3
- seleniumbase/plugins/driver_manager.py +340 -65
- seleniumbase/plugins/pytest_plugin.py +276 -47
- seleniumbase/plugins/sb_manager.py +412 -99
- seleniumbase/plugins/selenium_plugin.py +122 -17
- seleniumbase/translate/translator.py +0 -7
- seleniumbase/undetected/__init__.py +59 -52
- seleniumbase/undetected/cdp.py +0 -1
- seleniumbase/undetected/cdp_driver/__init__.py +1 -0
- seleniumbase/undetected/cdp_driver/_contradict.py +110 -0
- seleniumbase/undetected/cdp_driver/browser.py +829 -0
- seleniumbase/undetected/cdp_driver/cdp_util.py +458 -0
- seleniumbase/undetected/cdp_driver/config.py +334 -0
- seleniumbase/undetected/cdp_driver/connection.py +639 -0
- seleniumbase/undetected/cdp_driver/element.py +1168 -0
- seleniumbase/undetected/cdp_driver/tab.py +1323 -0
- seleniumbase/undetected/dprocess.py +4 -7
- seleniumbase/undetected/options.py +6 -8
- seleniumbase/undetected/patcher.py +11 -13
- seleniumbase/undetected/reactor.py +0 -1
- seleniumbase/undetected/webelement.py +16 -3
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/LICENSE +1 -1
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/METADATA +299 -252
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/RECORD +68 -70
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/WHEEL +1 -1
- sbase/ReadMe.txt +0 -2
- seleniumbase/ReadMe.md +0 -25
- seleniumbase/common/ReadMe.md +0 -71
- seleniumbase/console_scripts/ReadMe.md +0 -731
- seleniumbase/drivers/ReadMe.md +0 -27
- seleniumbase/extensions/ReadMe.md +0 -12
- seleniumbase/masterqa/ReadMe.md +0 -61
- seleniumbase/resources/ReadMe.md +0 -31
- seleniumbase/resources/favicon.ico +0 -0
- seleniumbase/utilities/selenium_grid/ReadMe.md +0 -84
- seleniumbase/utilities/selenium_ide/ReadMe.md +0 -111
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/entry_points.txt +0 -0
- {seleniumbase-4.24.10.dist-info → seleniumbase-4.33.15.dist-info}/top_level.txt +0 -0
seleniumbase/core/sb_driver.py
CHANGED
@@ -1,14 +1,21 @@
|
|
1
1
|
"""Add new methods to extend the driver"""
|
2
|
+
from contextlib import suppress
|
2
3
|
from selenium.webdriver.remote.webelement import WebElement
|
4
|
+
from seleniumbase.config import settings
|
3
5
|
from seleniumbase.fixtures import js_utils
|
4
6
|
from seleniumbase.fixtures import page_actions
|
5
7
|
from seleniumbase.fixtures import page_utils
|
8
|
+
from seleniumbase.fixtures import shared_utils
|
6
9
|
|
7
10
|
|
8
11
|
class DriverMethods():
|
9
12
|
def __init__(self, driver):
|
10
13
|
self.driver = driver
|
11
14
|
|
15
|
+
def __is_cdp_swap_needed(self):
|
16
|
+
"""If the driver is disconnected, use a CDP method when available."""
|
17
|
+
return shared_utils.is_cdp_swap_needed(self.driver)
|
18
|
+
|
12
19
|
def find_element(self, by=None, value=None):
|
13
20
|
if not value:
|
14
21
|
value = by
|
@@ -36,20 +43,29 @@ class DriverMethods():
|
|
36
43
|
selector, by = page_utils.swap_selector_and_by_if_reversed(
|
37
44
|
selector, by
|
38
45
|
)
|
39
|
-
|
46
|
+
with suppress(Exception):
|
40
47
|
return self.driver.default_find_element(by=by, value=selector)
|
41
|
-
except Exception:
|
42
|
-
pass
|
43
48
|
raise Exception('No such Element: {%s} (by="%s")!' % (selector, by))
|
44
49
|
|
45
50
|
def get_attribute(self, selector, attribute, by="css selector"):
|
46
51
|
element = self.locator(selector, by=by)
|
47
52
|
return element.get_attribute(attribute)
|
48
53
|
|
54
|
+
def get_current_url(self):
|
55
|
+
if self.__is_cdp_swap_needed():
|
56
|
+
current_url = self.driver.cdp.get_current_url()
|
57
|
+
else:
|
58
|
+
current_url = self.driver.current_url
|
59
|
+
return current_url
|
60
|
+
|
49
61
|
def get_page_source(self):
|
62
|
+
if self.__is_cdp_swap_needed():
|
63
|
+
return self.driver.cdp.get_page_source()
|
50
64
|
return self.driver.page_source
|
51
65
|
|
52
66
|
def get_title(self):
|
67
|
+
if self.__is_cdp_swap_needed():
|
68
|
+
return self.driver.cdp.get_title()
|
53
69
|
return self.driver.title
|
54
70
|
|
55
71
|
def open_url(self, *args, **kwargs):
|
@@ -94,6 +110,16 @@ class DriverMethods():
|
|
94
110
|
def assert_exact_text(self, *args, **kwargs):
|
95
111
|
page_actions.assert_exact_text(self.driver, *args, **kwargs)
|
96
112
|
|
113
|
+
def assert_non_empty_text(self, *args, **kwargs):
|
114
|
+
return page_actions.assert_non_empty_text(
|
115
|
+
self.driver, *args, **kwargs
|
116
|
+
)
|
117
|
+
|
118
|
+
def assert_text_not_visible(self, *args, **kwargs):
|
119
|
+
return page_actions.assert_text_not_visible(
|
120
|
+
self.driver, *args, **kwargs
|
121
|
+
)
|
122
|
+
|
97
123
|
def wait_for_element(self, *args, **kwargs):
|
98
124
|
return page_actions.wait_for_element(self.driver, *args, **kwargs)
|
99
125
|
|
@@ -112,6 +138,16 @@ class DriverMethods():
|
|
112
138
|
def wait_for_exact_text(self, *args, **kwargs):
|
113
139
|
return page_actions.wait_for_exact_text(self.driver, *args, **kwargs)
|
114
140
|
|
141
|
+
def wait_for_non_empty_text(self, *args, **kwargs):
|
142
|
+
return page_actions.wait_for_non_empty_text(
|
143
|
+
self.driver, *args, **kwargs
|
144
|
+
)
|
145
|
+
|
146
|
+
def wait_for_text_not_visible(self, *args, **kwargs):
|
147
|
+
return page_actions.wait_for_text_not_visible(
|
148
|
+
self.driver, *args, **kwargs
|
149
|
+
)
|
150
|
+
|
115
151
|
def wait_for_and_accept_alert(self, *args, **kwargs):
|
116
152
|
return page_actions.wait_for_and_accept_alert(
|
117
153
|
self.driver, *args, **kwargs
|
@@ -134,28 +170,111 @@ class DriverMethods():
|
|
134
170
|
def is_exact_text_visible(self, *args, **kwargs):
|
135
171
|
return page_actions.is_exact_text_visible(self.driver, *args, **kwargs)
|
136
172
|
|
137
|
-
def
|
138
|
-
return page_actions.
|
173
|
+
def is_attribute_present(self, *args, **kwargs):
|
174
|
+
return page_actions.has_attribute(self.driver, *args, **kwargs)
|
175
|
+
|
176
|
+
def is_non_empty_text_visible(self, *args, **kwargs):
|
177
|
+
return page_actions.is_non_empty_text_visible(
|
178
|
+
self.driver, *args, **kwargs
|
179
|
+
)
|
180
|
+
|
181
|
+
def is_valid_url(self, url):
|
182
|
+
"""Return True if the url is a valid url."""
|
183
|
+
return page_utils.is_valid_url(url)
|
184
|
+
|
185
|
+
def is_alert_present(self):
|
186
|
+
try:
|
187
|
+
self.driver.switch_to.alert
|
188
|
+
return True
|
189
|
+
except Exception:
|
190
|
+
return False
|
191
|
+
|
192
|
+
def is_online(self):
|
193
|
+
if self.__is_cdp_swap_needed():
|
194
|
+
return self.driver.cdp.evaluate("navigator.onLine;")
|
195
|
+
return self.driver.execute_script("return navigator.onLine;")
|
196
|
+
|
197
|
+
def is_connected(self):
|
198
|
+
"""
|
199
|
+
Return True if WebDriver is connected to the browser.
|
200
|
+
Note that the stealthy CDP-Driver isn't a WebDriver.
|
201
|
+
In CDP Mode, the CDP-Driver controls the web browser.
|
202
|
+
The CDP-Driver can be connected while WebDriver isn't.
|
203
|
+
"""
|
204
|
+
if shared_utils.is_windows():
|
205
|
+
return (
|
206
|
+
not hasattr(self.driver, "_is_connected")
|
207
|
+
or self.driver._is_connected
|
208
|
+
)
|
209
|
+
try:
|
210
|
+
self.driver.window_handles
|
211
|
+
return True
|
212
|
+
except Exception:
|
213
|
+
return False
|
214
|
+
|
215
|
+
def is_uc_mode_active(self):
|
216
|
+
"""Return True if the driver is using UC Mode. False otherwise."""
|
217
|
+
return (
|
218
|
+
hasattr(self.driver, "_is_using_uc")
|
219
|
+
and self.driver._is_using_uc
|
220
|
+
)
|
221
|
+
|
222
|
+
def is_cdp_mode_active(self):
|
223
|
+
"""CDP Mode is a special mode within UC Mode. Activated separately.
|
224
|
+
Return True if CDP Mode is loaded in the driver. False otherwise."""
|
225
|
+
return (
|
226
|
+
hasattr(self.driver, "_is_using_cdp")
|
227
|
+
and self.driver._is_using_cdp
|
228
|
+
)
|
139
229
|
|
140
230
|
def js_click(self, *args, **kwargs):
|
141
231
|
return page_actions.js_click(self.driver, *args, **kwargs)
|
142
232
|
|
143
|
-
def
|
144
|
-
return page_actions.
|
233
|
+
def get_text(self, *args, **kwargs):
|
234
|
+
return page_actions.get_text(self.driver, *args, **kwargs)
|
145
235
|
|
146
236
|
def get_active_element_css(self, *args, **kwargs):
|
237
|
+
if self.__is_cdp_swap_needed():
|
238
|
+
return self.driver.cdp.get_active_element_css()
|
147
239
|
return js_utils.get_active_element_css(self.driver, *args, **kwargs)
|
148
240
|
|
149
241
|
def get_locale_code(self, *args, **kwargs):
|
242
|
+
if self.__is_cdp_swap_needed():
|
243
|
+
return self.driver.cdp.get_locale_code()
|
150
244
|
return js_utils.get_locale_code(self.driver, *args, **kwargs)
|
151
245
|
|
246
|
+
def get_screen_rect(self, *args, **kwargs):
|
247
|
+
if self.__is_cdp_swap_needed():
|
248
|
+
return self.driver.cdp.get_screen_rect()
|
249
|
+
return js_utils.get_screen_rect(self.driver, *args, **kwargs)
|
250
|
+
|
152
251
|
def get_origin(self, *args, **kwargs):
|
252
|
+
if self.__is_cdp_swap_needed():
|
253
|
+
return self.driver.cdp.get_origin()
|
153
254
|
return js_utils.get_origin(self.driver, *args, **kwargs)
|
154
255
|
|
155
256
|
def get_user_agent(self, *args, **kwargs):
|
257
|
+
if self.__is_cdp_swap_needed():
|
258
|
+
return self.driver.cdp.get_user_agent()
|
156
259
|
return js_utils.get_user_agent(self.driver, *args, **kwargs)
|
157
260
|
|
261
|
+
def get_cookie_string(self, *args, **kwargs):
|
262
|
+
if self.__is_cdp_swap_needed():
|
263
|
+
return self.driver.cdp.get_cookie_string()
|
264
|
+
return js_utils.get_cookie_string(self.driver, *args, **kwargs)
|
265
|
+
|
158
266
|
def highlight(self, *args, **kwargs):
|
267
|
+
if self.__is_cdp_swap_needed():
|
268
|
+
selector = None
|
269
|
+
if "selector" in kwargs:
|
270
|
+
selector = kwargs["selector"]
|
271
|
+
else:
|
272
|
+
selector = args[0]
|
273
|
+
if ":contains(" not in selector:
|
274
|
+
self.driver.cdp.highlight(selector)
|
275
|
+
return
|
276
|
+
else:
|
277
|
+
self.driver.connect()
|
159
278
|
if "scroll" in kwargs:
|
160
279
|
kwargs.pop("scroll")
|
161
280
|
w_args = kwargs.copy()
|
@@ -182,13 +301,48 @@ class DriverMethods():
|
|
182
301
|
if self.is_element_visible(selector, by=by):
|
183
302
|
self.highlight(selector, by=by, loops=loops, scroll=scroll)
|
184
303
|
|
185
|
-
def
|
304
|
+
def switch_to_default_window(self):
|
305
|
+
self.driver.switch_to.window(self.driver.window_handles[0])
|
306
|
+
|
307
|
+
def switch_to_newest_window(self):
|
308
|
+
self.driver.switch_to.window(self.driver.window_handles[-1])
|
309
|
+
|
310
|
+
def open_new_window(self, switch_to=True):
|
311
|
+
if switch_to:
|
312
|
+
try:
|
313
|
+
self.driver.switch_to.new_window("tab")
|
314
|
+
except Exception:
|
315
|
+
self.driver.execute_script("window.open('');")
|
316
|
+
self.switch_to_newest_window()
|
317
|
+
else:
|
318
|
+
self.driver.execute_script("window.open('');")
|
319
|
+
|
320
|
+
def open_new_tab(self, switch_to=True):
|
321
|
+
self.open_new_window(switch_to=switch_to)
|
322
|
+
|
323
|
+
def switch_to_window(self, *args, **kwargs):
|
324
|
+
page_actions.switch_to_window(self.driver, *args, **kwargs)
|
325
|
+
|
326
|
+
def switch_to_tab(self, *args, **kwargs):
|
327
|
+
self.switch_to_window(*args, **kwargs)
|
328
|
+
|
329
|
+
def switch_to_frame(self, frame="iframe"):
|
186
330
|
if isinstance(frame, WebElement):
|
187
331
|
self.driver.switch_to.frame(frame)
|
188
332
|
else:
|
189
333
|
iframe = self.locator(frame)
|
190
334
|
self.driver.switch_to.frame(iframe)
|
191
335
|
|
336
|
+
def reset_window_size(self):
|
337
|
+
if self.__is_cdp_swap_needed():
|
338
|
+
self.driver.cdp.reset_window_size()
|
339
|
+
return
|
340
|
+
x = settings.WINDOW_START_X
|
341
|
+
y = settings.WINDOW_START_Y
|
342
|
+
width = settings.CHROME_START_WIDTH
|
343
|
+
height = settings.CHROME_START_HEIGHT
|
344
|
+
self.driver.set_window_rect(x, y, width, height)
|
345
|
+
|
192
346
|
def set_wire_proxy(self, string):
|
193
347
|
"""Set a proxy server for selenium-wire mode ("--wire")
|
194
348
|
Examples: (ONLY avilable if using selenium-wire mode!)
|
@@ -71,6 +71,8 @@ def set_settings(settings_file):
|
|
71
71
|
settings.LARGE_TIMEOUT = override_settings[key]
|
72
72
|
elif key == "EXTREME_TIMEOUT":
|
73
73
|
settings.EXTREME_TIMEOUT = override_settings[key]
|
74
|
+
elif key == "PAGE_LOAD_TIMEOUT":
|
75
|
+
settings.PAGE_LOAD_TIMEOUT = override_settings[key]
|
74
76
|
elif key == "ARCHIVE_EXISTING_LOGS":
|
75
77
|
settings.ARCHIVE_EXISTING_LOGS = override_settings[key]
|
76
78
|
elif key == "ARCHIVE_EXISTING_DOWNLOADS":
|
@@ -113,6 +115,10 @@ def set_settings(settings_file):
|
|
113
115
|
settings.RAISE_INVALID_PROXY_STRING_EXCEPTION = override_settings[
|
114
116
|
key
|
115
117
|
]
|
118
|
+
elif key == "WINDOW_START_X":
|
119
|
+
settings.WINDOW_START_X = override_settings[key]
|
120
|
+
elif key == "WINDOW_START_Y":
|
121
|
+
settings.WINDOW_START_Y = override_settings[key]
|
116
122
|
elif key == "CHROME_START_WIDTH":
|
117
123
|
settings.CHROME_START_WIDTH = override_settings[key]
|
118
124
|
elif key == "CHROME_START_HEIGHT":
|
seleniumbase/core/style_sheet.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import sys
|
2
|
+
import textwrap
|
2
3
|
from seleniumbase.fixtures import constants
|
3
4
|
|
4
5
|
|
@@ -116,6 +117,7 @@ def get_report_style():
|
|
116
117
|
}
|
117
118
|
</style>"""
|
118
119
|
)
|
120
|
+
style = textwrap.dedent(style)
|
119
121
|
Saved.report_style = style
|
120
122
|
return style
|
121
123
|
|
@@ -132,6 +134,7 @@ def get_bt_backdrop_style():
|
|
132
134
|
box-shadow: 0 0 0 88422px rgba(0, 0, 0, 0.42);
|
133
135
|
pointer-events: auto !important;
|
134
136
|
}"""
|
137
|
+
bt_backdrop_style = textwrap.dedent(bt_backdrop_style)
|
135
138
|
Saved.bt_backdrop_style = bt_backdrop_style
|
136
139
|
return bt_backdrop_style
|
137
140
|
|
@@ -150,6 +153,7 @@ def get_dt_backdrop_style():
|
|
150
153
|
button.driver-prev-btn.driver-disabled {
|
151
154
|
visibility: hidden;
|
152
155
|
}"""
|
156
|
+
dt_backdrop_style = textwrap.dedent(dt_backdrop_style)
|
153
157
|
Saved.dt_backdrop_style = dt_backdrop_style
|
154
158
|
return dt_backdrop_style
|
155
159
|
|
@@ -167,6 +171,7 @@ def get_messenger_style():
|
|
167
171
|
box-shadow: 2px 2px 9px 4px rgba(32, 142, 120, 0.28),
|
168
172
|
2px 2px 9px 4px rgba(200, 240, 80, 0.34) !important;
|
169
173
|
}""" % font_family
|
174
|
+
messenger_style = textwrap.dedent(messenger_style)
|
170
175
|
Saved.messenger_style = messenger_style
|
171
176
|
return messenger_style
|
172
177
|
|
@@ -181,6 +186,7 @@ def get_sh_style_test():
|
|
181
186
|
scrollTo: true
|
182
187
|
}
|
183
188
|
});"""
|
189
|
+
sh_style_test = textwrap.dedent(sh_style_test)
|
184
190
|
Saved.sh_style_test = sh_style_test
|
185
191
|
return sh_style_test
|
186
192
|
|
@@ -193,6 +199,7 @@ def get_hops_backdrop_style():
|
|
193
199
|
.hopscotch-bubble-container {
|
194
200
|
font-size: 110%;
|
195
201
|
}"""
|
202
|
+
hops_backdrop_style = textwrap.dedent(hops_backdrop_style)
|
196
203
|
Saved.hops_backdrop_style = hops_backdrop_style
|
197
204
|
return hops_backdrop_style
|
198
205
|
|
@@ -227,6 +234,7 @@ def get_introjs_style():
|
|
227
234
|
box-sizing: content-box;
|
228
235
|
position: absolute;
|
229
236
|
}"""
|
237
|
+
introjs_style = textwrap.dedent(introjs_style)
|
230
238
|
Saved.introjs_style = introjs_style
|
231
239
|
return introjs_style
|
232
240
|
|
@@ -261,6 +269,7 @@ def get_sh_backdrop_style():
|
|
261
269
|
body.shepherd-active {
|
262
270
|
pointer-events: none !important;
|
263
271
|
}"""
|
272
|
+
sh_backdrop_style = textwrap.dedent(sh_backdrop_style)
|
264
273
|
Saved.sh_backdrop_style = sh_backdrop_style
|
265
274
|
return sh_backdrop_style
|
266
275
|
|
@@ -387,5 +396,6 @@ def get_pytest_style():
|
|
387
396
|
.desc.active .sort-icon {
|
388
397
|
border-top: 8px solid #999;
|
389
398
|
}"""
|
399
|
+
pytest_style = textwrap.dedent(pytest_style)
|
390
400
|
Saved.pytest_style = pytest_style
|
391
401
|
return pytest_style
|
Binary file
|