Skip to content

Commit d4df607

Browse files
committed
Add support for the "selenium-wire" library
1 parent 4bb3a0a commit d4df607

File tree

13 files changed

+139
-8
lines changed

13 files changed

+139
-8
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,8 @@ pytest my_first_test.py --pdb
565565
--maximize # (Start tests with the browser window maximized.)
566566
--screenshot # (Save a screenshot at the end of each test.)
567567
--visual-baseline # (Set the visual baseline for Visual/Layout tests.)
568-
--external-pdf # (Set Chrome "plugins.always_open_pdf_externally": True.)
568+
--wire # (Use selenium-wire's webdriver for replacing selenium webdriver.)
569+
--external-pdf # (Set Chromium "plugins.always_open_pdf_externally":True.)
569570
--timeout-multiplier=MULTIPLIER # (Multiplies the default timeout values.)
570571
--list-fail-page # (After each failing test, list the URL of the failure.)
571572
```

examples/raw_parameter_script.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
sb._reuse_session = False
7575
sb._crumbs = False
7676
sb._final_debug = False
77+
sb.use_wire = False
7778
sb.visual_baseline = False
7879
sb.window_size = None
7980
sb.maximize_option = False

help_docs/customizing_test_runs.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,8 @@ pytest my_first_test.py --settings-file=custom_settings.py
179179
--maximize # (Start tests with the browser window maximized.)
180180
--screenshot # (Save a screenshot at the end of each test.)
181181
--visual-baseline # (Set the visual baseline for Visual/Layout tests.)
182-
--external-pdf # (Set Chrome "plugins.always_open_pdf_externally": True.)
182+
--wire # (Use selenium-wire's webdriver for replacing selenium webdriver.)
183+
--external-pdf # (Set Chromium "plugins.always_open_pdf_externally":True.)
183184
--timeout-multiplier=MULTIPLIER # (Multiplies the default timeout values.)
184185
--list-fail-page # (After each failing test, list the URL of the failure.)
185186
```

help_docs/features_list.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* Can run tests with a customized browser user agent. (``--agent=USER_AGENT_STRING``)
2525
* Can set a Chromium User Data Directory/Profile to load. (``--user-data-dir=DIR``)
2626
* Can avoid detection by sites that try to block Selenium. (``--undetected``/``--uc``)
27+
* Can integrate with [selenium-wire](https://github.com/wkeeling/selenium-wire) for inspecting browser requests. (``--wire``)
2728
* Can load Chrome Extension ZIP files. (``--extension-zip=ZIP``)
2829
* Can load Chrome Extension folders. (``--extension-dir=DIR``)
2930
* Powerful [console scripts](https://github.com/seleniumbase/SeleniumBase/blob/master/seleniumbase/console_scripts/ReadMe.md). (Type **``seleniumbase``** or **``sbase``** to use.)

help_docs/method_summary.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ self.get_session_storage_items()
536536

537537
############
538538

539+
self.set_wire_proxy(string) # Requires "--wire"!
540+
541+
############
542+
539543
self.add_css_link(css_link)
540544

541545
self.add_js_link(js_link)

help_docs/syntax_formats.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ class BaseTestCase(BaseCase):
7373
# <<< Run custom setUp() code for tests AFTER the super().setUp() >>>
7474

7575
def tearDown(self):
76-
self.save_teardown_screenshot() # If test fails, or if "--screenshot"
76+
self.save_teardown_screenshot() # On failure or "--screenshot"
7777
if self.has_exception():
7878
# <<< Run custom code if the test failed. >>>
7979
pass
@@ -255,7 +255,7 @@ class OverrideDriverTest(BaseCase):
255255

256256
(From <a href="https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_override_driver.py">examples/test_override_driver.py</a>)
257257

258-
The above format can let you use [selenium-wire](https://github.com/wkeeling/selenium-wire) to intercept & inspect requests and responses during SeleniumBase tests. Here's how the ``selenium-wire`` integration may look:
258+
The above format lets you customize [selenium-wire](https://github.com/wkeeling/selenium-wire) for intercepting and inspecting requests and responses during SeleniumBase tests. Here's how a ``selenium-wire`` integration may look:
259259

260260
```python
261261
from seleniumbase import BaseCase
@@ -277,6 +277,8 @@ class WireTestCase(BaseCase):
277277
print(request.url)
278278
```
279279

280+
(NOTE: The ``selenium-wire`` integration is now included with ``seleniumbase``: Add ``--wire`` as a ``pytest`` command-line option to activate. If you need both ``--wire`` with ``--undetected`` together, you'll still need to override ``get_new_driver()``.)
281+
280282
<a id="sb_sf_10"></a>
281283
<h3><img src="https://seleniumbase.github.io/img/logo3b.png" title="SeleniumBase" width="32" /> 10. Overriding the driver via "sb" fixture</h3>
282284

@@ -297,7 +299,7 @@ def sb(request):
297299
super(BaseClass, self).setUp()
298300

299301
def tearDown(self):
300-
self.save_teardown_screenshot()
302+
self.save_teardown_screenshot() # On failure or "--screenshot"
301303
super(BaseClass, self).tearDown()
302304

303305
def base_method(self):
@@ -352,7 +354,7 @@ def sb(request):
352354
super(BaseClass, self).setUp()
353355

354356
def tearDown(self):
355-
self.save_teardown_screenshot()
357+
self.save_teardown_screenshot() # On failure or "--screenshot"
356358
super(BaseClass, self).tearDown()
357359

358360
def base_method(self):
@@ -390,6 +392,8 @@ class TestWire:
390392
print(request.url)
391393
```
392394

395+
(NOTE: The ``selenium-wire`` integration is now included with ``seleniumbase``: Add ``--wire`` as a ``pytest`` command-line option to activate. If you need both ``--wire`` with ``--undetected`` together, you'll still need to override ``get_new_driver()``.)
396+
393397
<a id="sb_sf_11"></a>
394398
<h3><img src="https://seleniumbase.github.io/img/logo3b.png" title="SeleniumBase" width="32" /> 11. BaseCase with Chinese translations</h3>
395399

seleniumbase/behave/behave_sb.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@
8989
-D maximize (Start tests with the browser window maximized.)
9090
-D screenshot (Save a screenshot at the end of each test.)
9191
-D visual-baseline (Set the visual baseline for Visual/Layout tests.)
92+
-D wire (Use selenium-wire's webdriver for replacing selenium webdriver.)
9293
-D external-pdf (Set Chromium "plugins.always_open_pdf_externally": True.)
9394
-D timeout-multiplier=MULTIPLIER (Multiplies the default timeout values.)
9495
"""
@@ -179,6 +180,7 @@ def get_configured_sb(context):
179180
sb._crumbs = False
180181
sb._disable_beforeunload = False
181182
sb.visual_baseline = False
183+
sb.use_wire = False
182184
sb.window_size = None
183185
sb.maximize_option = False
184186
sb.is_context_manager = False
@@ -540,6 +542,10 @@ def get_configured_sb(context):
540542
if low_key in ["visual-baseline", "visual_baseline"]:
541543
sb.visual_baseline = True
542544
continue
545+
# Handle: -D wire
546+
if low_key == "wire":
547+
sb.use_wire = True
548+
continue
543549
# Handle: -D window-size=Width,Height / window_size=Width,Height
544550
if low_key in ["window-size", "window_size"]:
545551
window_size = userdata[key]

seleniumbase/core/browser_launcher.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from seleniumbase.core import download_helper
1717
from seleniumbase.core import proxy_helper
1818
from seleniumbase.fixtures import constants
19+
from seleniumbase.fixtures import shared_utils
1920
from seleniumbase import drivers # webdriver storage folder for SeleniumBase
2021
from seleniumbase import extensions # browser extensions storage folder
2122

@@ -372,6 +373,7 @@ def _set_chrome_options(
372373
extension_zip,
373374
extension_dir,
374375
page_load_strategy,
376+
use_wire,
375377
external_pdf,
376378
servername,
377379
mobile_emulator,
@@ -918,6 +920,7 @@ def get_driver(
918920
extension_zip=None,
919921
extension_dir=None,
920922
page_load_strategy=None,
923+
use_wire=False,
921924
external_pdf=False,
922925
test_id=None,
923926
mobile_emulator=False,
@@ -1083,6 +1086,7 @@ def get_driver(
10831086
extension_zip,
10841087
extension_dir,
10851088
page_load_strategy,
1089+
use_wire,
10861090
external_pdf,
10871091
test_id,
10881092
mobile_emulator,
@@ -1130,6 +1134,7 @@ def get_driver(
11301134
extension_zip,
11311135
extension_dir,
11321136
page_load_strategy,
1137+
use_wire,
11331138
external_pdf,
11341139
mobile_emulator,
11351140
device_width,
@@ -1181,13 +1186,29 @@ def get_remote_driver(
11811186
extension_zip,
11821187
extension_dir,
11831188
page_load_strategy,
1189+
use_wire,
11841190
external_pdf,
11851191
test_id,
11861192
mobile_emulator,
11871193
device_width,
11881194
device_height,
11891195
device_pixel_ratio,
11901196
):
1197+
if use_wire and selenium4_or_newer:
1198+
driver_fixing_lock = fasteners.InterProcessLock(
1199+
constants.MultiBrowser.DRIVER_FIXING_LOCK
1200+
)
1201+
with driver_fixing_lock: # Prevent multi-processes mode issues
1202+
try:
1203+
from seleniumwire import webdriver
1204+
except Exception:
1205+
shared_utils.pip_install(
1206+
"selenium-wire", version=constants.SeleniumWire.VER
1207+
)
1208+
from seleniumwire import webdriver
1209+
else:
1210+
from selenium import webdriver
1211+
11911212
# Construct the address for connecting to a Selenium Grid
11921213
if servername.startswith("https://"):
11931214
protocol = "https"
@@ -1280,6 +1301,7 @@ def get_remote_driver(
12801301
extension_zip,
12811302
extension_dir,
12821303
page_load_strategy,
1304+
use_wire,
12831305
external_pdf,
12841306
servername,
12851307
mobile_emulator,
@@ -1510,6 +1532,7 @@ def get_remote_driver(
15101532
extension_zip,
15111533
extension_dir,
15121534
page_load_strategy,
1535+
use_wire,
15131536
external_pdf,
15141537
servername,
15151538
mobile_emulator,
@@ -1708,6 +1731,7 @@ def get_local_driver(
17081731
extension_zip,
17091732
extension_dir,
17101733
page_load_strategy,
1734+
use_wire,
17111735
external_pdf,
17121736
mobile_emulator,
17131737
device_width,
@@ -1719,6 +1743,20 @@ def get_local_driver(
17191743
Can also be used to spin up additional browsers for the same test.
17201744
"""
17211745
downloads_path = DOWNLOADS_FOLDER
1746+
if use_wire and selenium4_or_newer:
1747+
driver_fixing_lock = fasteners.InterProcessLock(
1748+
constants.MultiBrowser.DRIVER_FIXING_LOCK
1749+
)
1750+
with driver_fixing_lock: # Prevent multi-processes mode issues
1751+
try:
1752+
from seleniumwire import webdriver
1753+
except Exception:
1754+
shared_utils.pip_install(
1755+
"selenium-wire", version=constants.SeleniumWire.VER
1756+
)
1757+
from seleniumwire import webdriver
1758+
else:
1759+
from selenium import webdriver
17221760

17231761
if browser_name == constants.Browser.FIREFOX:
17241762
firefox_options = _set_firefox_options(
@@ -2308,6 +2346,7 @@ def get_local_driver(
23082346
extension_zip,
23092347
extension_dir,
23102348
page_load_strategy,
2349+
use_wire,
23112350
external_pdf,
23122351
servername,
23132352
mobile_emulator,
@@ -2372,6 +2411,7 @@ def get_local_driver(
23722411
extension_zip,
23732412
extension_dir,
23742413
page_load_strategy,
2414+
use_wire,
23752415
external_pdf,
23762416
servername,
23772417
mobile_emulator,
@@ -2754,6 +2794,7 @@ def get_local_driver(
27542794
extension_zip,
27552795
extension_dir,
27562796
page_load_strategy,
2797+
use_wire,
27572798
external_pdf,
27582799
servername,
27592800
mobile_emulator,

seleniumbase/fixtures/base_case.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,6 +3201,7 @@ def get_new_driver(
32013201
extension_zip=None,
32023202
extension_dir=None,
32033203
page_load_strategy=None,
3204+
use_wire=None,
32043205
external_pdf=None,
32053206
is_mobile=None,
32063207
d_width=None,
@@ -3251,6 +3252,7 @@ def get_new_driver(
32513252
extension_zip - A Chrome Extension ZIP file to use (Chrome-only)
32523253
extension_dir - A Chrome Extension folder to use (Chrome-only)
32533254
page_load_strategy - the option to change pageLoadStrategy (Chrome)
3255+
use_wire - Use selenium-wire webdriver instead of the selenium one
32543256
external_pdf - "plugins.always_open_pdf_externally": True. (Chrome)
32553257
is_mobile - the option to use the mobile emulator (Chrome-only)
32563258
d_width - the device width of the mobile emulator (Chrome-only)
@@ -3367,6 +3369,8 @@ def get_new_driver(
33673369
extension_dir = self.extension_dir
33683370
if page_load_strategy is None:
33693371
page_load_strategy = self.page_load_strategy
3372+
if use_wire is None:
3373+
use_wire = self.use_wire
33703374
if external_pdf is None:
33713375
external_pdf = self.external_pdf
33723376
test_id = self.__get_test_id()
@@ -3432,6 +3436,7 @@ def get_new_driver(
34323436
extension_zip=extension_zip,
34333437
extension_dir=extension_dir,
34343438
page_load_strategy=page_load_strategy,
3439+
use_wire=use_wire,
34353440
external_pdf=external_pdf,
34363441
test_id=test_id,
34373442
mobile_emulator=is_mobile,
@@ -7773,6 +7778,36 @@ def get_session_storage_items(self):
77737778

77747779
############
77757780

7781+
# Methods ONLY for the selenium-wire integration ("--wire")
7782+
7783+
def set_wire_proxy(self, string):
7784+
"""Set a proxy server for selenium-wire mode ("--wire")
7785+
NOTE: This method ONLY works while using "--wire" mode!
7786+
Examples:
7787+
self.set_wire_proxy("SERVER:PORT")
7788+
self.set_wire_proxy("socks5://SERVER:PORT")
7789+
self.set_wire_proxy("USERNAME:PASSWORD@SERVER:PORT")
7790+
"""
7791+
if not string:
7792+
self.driver.proxy = {}
7793+
return
7794+
the_http = "http"
7795+
the_https = "https"
7796+
if string.startswith("socks4://"):
7797+
the_http = "socks4"
7798+
the_https = "socks4"
7799+
elif string.startswith("socks5://"):
7800+
the_http = "socks5"
7801+
the_https = "socks5"
7802+
string = string.split("//")[-1]
7803+
self.driver.proxy = {
7804+
"http": "%s://%s" % (the_http, string),
7805+
"https": "%s://%s" % (the_https, string),
7806+
"no_proxy": "localhost,127.0.0.1",
7807+
}
7808+
7809+
############
7810+
77767811
# Duplicates (Avoids name confusion when migrating from other frameworks.)
77777812

77787813
def open_url(self, url):
@@ -12804,6 +12839,7 @@ def setUp(self, masterqa_mode=False):
1280412839
self.extension_zip = sb_config.extension_zip
1280512840
self.extension_dir = sb_config.extension_dir
1280612841
self.page_load_strategy = sb_config.page_load_strategy
12842+
self.use_wire = sb_config.use_wire
1280712843
self.external_pdf = sb_config.external_pdf
1280812844
self._final_debug = sb_config.final_debug
1280912845
self.window_size = sb_config.window_size
@@ -13091,6 +13127,7 @@ def setUp(self, masterqa_mode=False):
1309113127
extension_zip=self.extension_zip,
1309213128
extension_dir=self.extension_dir,
1309313129
page_load_strategy=self.page_load_strategy,
13130+
use_wire=self.use_wire,
1309413131
external_pdf=self.external_pdf,
1309513132
is_mobile=self.mobile_emulator,
1309613133
d_width=self.__device_width,

seleniumbase/fixtures/constants.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ class Tether:
293293
)
294294

295295

296+
class SeleniumWire:
297+
# The version installed if selenium-wire is not installed
298+
VER = "5.1.0"
299+
300+
296301
class ValidBrowsers:
297302
valid_browsers = [
298303
"chrome",

0 commit comments

Comments
 (0)