Skip to content

Commit bf807a7

Browse files
authored
Merge pull request #846 from seleniumbase/custom-chromium-args
Add the ability to set custom Chromium args. And update downloads.
2 parents c9c450e + 4ba5608 commit bf807a7

File tree

11 files changed

+112
-25
lines changed

11 files changed

+112
-25
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ The code above will leave your browser window open in case there's a failure. (i
357357
--agent=STRING # (Modify the web browser's User-Agent string.)
358358
--mobile # (Use the mobile device emulator while running tests.)
359359
--metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
360+
--chromium-arg=ARG # (Add a Chromium arg for Chrome/Edge, comma-separated.)
360361
--extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
361362
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
362363
--headless # (Run tests headlessly. Default mode on Linux OS.)

examples/raw_parameter_script.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
sb.remote_debug = False
7777
sb.settings_file = None
7878
sb.user_data_dir = None
79+
sb.chromium_arg = None
7980
sb.proxy_string = None
8081
sb.swiftshader = False
8182
sb.ad_block_on = False

examples/test_shadow_dom.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,28 @@ def download_tar_file_from_pypi(self, package):
1616
pkg_name = pkg_header.replace(" ", "-")
1717
tar_file = pkg_name + ".tar.gz"
1818
tar_selector = 'div#files a[href$="%s"]' % tar_file
19-
self.delete_downloaded_file_if_present(tar_file)
19+
self.delete_downloaded_file_if_present(tar_file, browser=True)
2020
self.click(tar_selector)
2121
return tar_file
2222

2323
def test_shadow_dom(self):
2424
if self.browser != "chrome":
2525
print("\n This test is for Google Chrome only!")
26-
self.skip('This test is for Google Chrome only!')
26+
self.skip("This test is for Google Chrome only!")
2727
if self.headless:
28-
print("\n This test does not run in headless mode!")
29-
self.skip('This test does not run in headless mode!')
28+
print("\n This test doesn't run in headless mode!")
29+
self.skip("This test doesn't run in headless mode!")
3030

31+
# Download Python package files from PyPI
3132
file_name_1 = self.download_tar_file_from_pypi("sbase")
3233
file_name_2 = self.download_tar_file_from_pypi("tensorpy")
34+
self.assert_downloaded_file(file_name_1, browser=True)
35+
self.assert_downloaded_file(file_name_2, browser=True)
3336

37+
# Navigate to the Chrome downloads page.
3438
self.open("chrome://downloads/")
39+
40+
# Shadow DOM selectors
3541
search_icon = (
3642
"downloads-manager::shadow downloads-toolbar::shadow"
3743
" cr-toolbar::shadow cr-toolbar-search-field::shadow"
@@ -64,3 +70,7 @@ def test_shadow_dom(self):
6470
self.assert_text("No search results found", no_downloads_area)
6571
self.click(clear_search_icon)
6672
self.assert_element(remove_button)
73+
74+
# Delete the downloaded files from the [Downloads Folder]
75+
self.delete_downloaded_file_if_present(file_name_1, browser=True)
76+
self.delete_downloaded_file_if_present(file_name_2, browser=True)

help_docs/customizing_test_runs.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,10 @@ SeleniumBase provides additional ``pytest`` command-line options for tests:
109109
--port=PORT # (The Selenium Grid port used by the test server.)
110110
--proxy=SERVER:PORT # (Connect to a proxy server:port for tests.)
111111
--proxy=USERNAME:PASSWORD@SERVER:PORT # (Use authenticated proxy server.)
112+
--agent=STRING # (Modify the web browser's User-Agent string.)
112113
--mobile # (Use the mobile device emulator while running tests.)
113114
--metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
115+
--chromium-arg=ARG # (Add a Chromium arg for Chrome/Edge, comma-separated.)
114116
--extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
115117
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
116118
--headless # (Run tests headlessly. Default mode on Linux OS.)

help_docs/shadow_dom.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
## Shadow DOM support / Shadow-root interaction
2+
3+
🔵 SeleniumBase lets you pierce through open Shadow DOM selectors (to interact with elements inside) by adding ``::shadow`` to CSS fragments that include a shadow-root element. For multi-layered shadow-roots, you must individually pierce through each shadow-root element that you want to get through.
4+
5+
🔵 Here are some examples of Shadow DOM selectors:
6+
7+
```python
8+
css_1 = "downloads-manager::shadow #no-downloads"
9+
10+
css_2 = "downloads-manager::shadow #downloadsList downloads-item::shadow #file-link"
11+
12+
css_3 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow cr-icon-button"
13+
14+
css_4 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #searchInput"
15+
16+
css_5 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #clearSearch"
17+
```
18+
19+
🔵 The shadow-root (``::shadow``) elements are transitional, and therefore cannot be the final part of your CSS selectors. Complete your CSS selectors by including an element that's inside a shadow-root.
20+
21+
🔵 Note that ``::shadow`` selectors only exist within SeleniumBase, and do not exist outside of it.
22+
23+
🔵 Here's an example test that interacts with Shadow DOM elements: [examples/test_shadow_dom.py](https://github.com/seleniumbase/SeleniumBase/blob/master/examples/test_shadow_dom.py)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ nav:
114114
- Desired Capabilities: help_docs/desired_capabilities.md
115115
- Docker Start Guide: integrations/docker/ReadMe.md
116116
- Using Safari Driver: help_docs/using_safari_driver.md
117+
- Shadow DOM Support: help_docs/shadow_dom.md
117118
- macOS Hidden Files: help_docs/hidden_files_info.md
118119
- MySQL Instructions: help_docs/mysql_installation.md
119120
- Demo Pages:

seleniumbase/__version__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
# seleniumbase package
2-
__version__ = "1.59.0"
2+
__version__ = "1.59.1"

seleniumbase/core/browser_launcher.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def _set_chrome_options(
133133
proxy_string, proxy_auth, proxy_user, proxy_pass,
134134
user_agent, disable_csp, enable_ws, enable_sync, use_auto_ext,
135135
no_sandbox, disable_gpu, incognito, guest_mode,
136-
devtools, remote_debug, swiftshader, block_images,
136+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
137137
user_data_dir, extension_zip, extension_dir, servername,
138138
mobile_emulator, device_width, device_height, device_pixel_ratio):
139139
chrome_options = webdriver.ChromeOptions()
@@ -298,6 +298,18 @@ def _set_chrome_options(
298298
chrome_options.add_argument("--disable-gpu")
299299
if "linux" in PLATFORM:
300300
chrome_options.add_argument("--disable-dev-shm-usage")
301+
if chromium_arg:
302+
# Can be a comma-separated list of Chromium args
303+
chromium_arg_list = chromium_arg.split(',')
304+
for chromium_arg_item in chromium_arg_list:
305+
chromium_arg_item = chromium_arg_item.strip()
306+
if not chromium_arg_item.startswith("--"):
307+
if chromium_arg_item.startswith("-"):
308+
chromium_arg_item = "-" + chromium_arg_item
309+
else:
310+
chromium_arg_item = "--" + chromium_arg_item
311+
if len(chromium_arg_item) >= 3:
312+
chrome_options.add_argument(chromium_arg_item)
301313
return chrome_options
302314

303315

@@ -459,7 +471,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
459471
use_auto_ext=None, no_sandbox=None, disable_gpu=None,
460472
incognito=None, guest_mode=None,
461473
devtools=None, remote_debug=None,
462-
swiftshader=None, block_images=None,
474+
swiftshader=None, block_images=None, chromium_arg=None,
463475
user_data_dir=None, extension_zip=None, extension_dir=None,
464476
test_id=None, mobile_emulator=False, device_width=None,
465477
device_height=None, device_pixel_ratio=None):
@@ -498,7 +510,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
498510
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
499511
cap_file, cap_string, disable_csp, enable_ws, enable_sync,
500512
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
501-
devtools, remote_debug, swiftshader, block_images,
513+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
502514
user_data_dir, extension_zip, extension_dir, test_id,
503515
mobile_emulator, device_width, device_height, device_pixel_ratio)
504516
else:
@@ -507,7 +519,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
507519
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
508520
disable_csp, enable_ws, enable_sync,
509521
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
510-
devtools, remote_debug, swiftshader, block_images,
522+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
511523
user_data_dir, extension_zip, extension_dir,
512524
mobile_emulator, device_width, device_height, device_pixel_ratio)
513525

@@ -517,7 +529,7 @@ def get_remote_driver(
517529
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
518530
cap_file, cap_string, disable_csp, enable_ws, enable_sync,
519531
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
520-
devtools, remote_debug, swiftshader, block_images,
532+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
521533
user_data_dir, extension_zip, extension_dir, test_id,
522534
mobile_emulator, device_width, device_height, device_pixel_ratio):
523535
downloads_path = download_helper.get_downloads_folder()
@@ -549,7 +561,7 @@ def get_remote_driver(
549561
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
550562
disable_csp, enable_ws, enable_sync, use_auto_ext, no_sandbox,
551563
disable_gpu, incognito, guest_mode,
552-
devtools, remote_debug, swiftshader, block_images,
564+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
553565
user_data_dir, extension_zip, extension_dir,
554566
servername, mobile_emulator,
555567
device_width, device_height, device_pixel_ratio)
@@ -677,7 +689,7 @@ def get_local_driver(
677689
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
678690
disable_csp, enable_ws, enable_sync, use_auto_ext, no_sandbox,
679691
disable_gpu, incognito, guest_mode,
680-
devtools, remote_debug, swiftshader, block_images,
692+
devtools, remote_debug, swiftshader, block_images, chromium_arg,
681693
user_data_dir, extension_zip, extension_dir,
682694
mobile_emulator, device_width, device_height, device_pixel_ratio):
683695
'''
@@ -765,8 +777,8 @@ def get_local_driver(
765777
disable_csp, enable_ws, enable_sync, use_auto_ext,
766778
no_sandbox, disable_gpu, incognito, guest_mode,
767779
devtools, remote_debug, swiftshader, block_images,
768-
user_data_dir, extension_zip, extension_dir, servername,
769-
mobile_emulator, device_width, device_height,
780+
chromium_arg, user_data_dir, extension_zip, extension_dir,
781+
servername, mobile_emulator, device_width, device_height,
770782
device_pixel_ratio)
771783
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
772784
try:
@@ -910,6 +922,18 @@ def get_local_driver(
910922
edge_options.add_argument("--disable-gpu")
911923
if "linux" in PLATFORM:
912924
edge_options.add_argument("--disable-dev-shm-usage")
925+
if chromium_arg:
926+
# Can be a comma-separated list of Chromium args
927+
chromium_arg_list = chromium_arg.split(',')
928+
for chromium_arg_item in chromium_arg_list:
929+
chromium_arg_item = chromium_arg_item.strip()
930+
if not chromium_arg_item.startswith("--"):
931+
if chromium_arg_item.startswith("-"):
932+
chromium_arg_item = "-" + chromium_arg_item
933+
else:
934+
chromium_arg_item = "--" + chromium_arg_item
935+
if len(chromium_arg_item) >= 3:
936+
edge_options.add_argument(chromium_arg_item)
913937
capabilities = edge_options.to_capabilities()
914938
capabilities["platform"] = ''
915939
return Edge(
@@ -935,7 +959,7 @@ def get_local_driver(
935959
disable_csp, enable_ws, enable_sync, use_auto_ext,
936960
no_sandbox, disable_gpu, incognito, guest_mode,
937961
devtools, remote_debug, swiftshader, block_images,
938-
user_data_dir, extension_zip, extension_dir,
962+
chromium_arg, user_data_dir, extension_zip, extension_dir,
939963
servername, mobile_emulator,
940964
device_width, device_height, device_pixel_ratio)
941965
opera_options.headless = False # No support for headless Opera
@@ -955,7 +979,7 @@ def get_local_driver(
955979
disable_csp, enable_ws, enable_sync, use_auto_ext,
956980
no_sandbox, disable_gpu, incognito, guest_mode,
957981
devtools, remote_debug, swiftshader, block_images,
958-
user_data_dir, extension_zip, extension_dir,
982+
chromium_arg, user_data_dir, extension_zip, extension_dir,
959983
servername, mobile_emulator,
960984
device_width, device_height, device_pixel_ratio)
961985
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):

seleniumbase/fixtures/base_case.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1899,9 +1899,9 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
18991899
switch_to=True, cap_file=None, cap_string=None,
19001900
disable_csp=None, enable_ws=None, enable_sync=None,
19011901
use_auto_ext=None, no_sandbox=None, disable_gpu=None,
1902-
incognito=None, guest_mode=None,
1903-
devtools=None, remote_debug=None,
1904-
swiftshader=None, block_images=None, user_data_dir=None,
1902+
incognito=None, guest_mode=None, devtools=None,
1903+
remote_debug=None, swiftshader=None, block_images=None,
1904+
chromium_arg=None, user_data_dir=None,
19051905
extension_zip=None, extension_dir=None, is_mobile=False,
19061906
d_width=None, d_height=None, d_p_r=None):
19071907
""" This method spins up an extra browser for tests that require
@@ -1930,6 +1930,7 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
19301930
remote_debug - the option to enable Chrome's Remote Debugger
19311931
swiftshader - the option to use Chrome's swiftshader (Chrome-only)
19321932
block_images - the option to block images from loading (Chrome)
1933+
chromium_arg - the option to add a Chromium arg to Chrome/Edge
19331934
user_data_dir - Chrome's User Data Directory to use (Chrome-only)
19341935
extension_zip - A Chrome Extension ZIP file to use (Chrome-only)
19351936
extension_dir - A Chrome Extension folder to use (Chrome-only)
@@ -2005,6 +2006,8 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
20052006
swiftshader = self.swiftshader
20062007
if block_images is None:
20072008
block_images = self.block_images
2009+
if chromium_arg is None:
2010+
chromium_arg = self.chromium_arg
20082011
if user_data_dir is None:
20092012
user_data_dir = self.user_data_dir
20102013
if extension_zip is None:
@@ -2052,6 +2055,7 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
20522055
remote_debug=remote_debug,
20532056
swiftshader=swiftshader,
20542057
block_images=block_images,
2058+
chromium_arg=chromium_arg,
20552059
user_data_dir=user_data_dir,
20562060
extension_zip=extension_zip,
20572061
extension_dir=extension_dir,
@@ -3095,12 +3099,8 @@ def get_downloads_folder(self):
30953099
any clicks that download files will also use this folder
30963100
rather than using the browser's default "downloads/" path. """
30973101
self.__check_scope()
3098-
if self.is_chromium() and self.guest_mode and not self.headless:
3099-
# Guest Mode (non-headless) can force the default downloads path
3100-
return os.path.join(os.path.expanduser('~'), 'downloads')
3101-
else:
3102-
from seleniumbase.core import download_helper
3103-
return download_helper.get_downloads_folder()
3102+
from seleniumbase.core import download_helper
3103+
return download_helper.get_downloads_folder()
31043104

31053105
def get_browser_downloads_folder(self):
31063106
""" Returns the path that is used when a click initiates a download.
@@ -7075,6 +7075,7 @@ def setUp(self, masterqa_mode=False):
70757075
self.js_checking_on = sb_config.js_checking_on
70767076
self.ad_block_on = sb_config.ad_block_on
70777077
self.block_images = sb_config.block_images
7078+
self.chromium_arg = sb_config.chromium_arg
70787079
self.verify_delay = sb_config.verify_delay
70797080
self.disable_csp = sb_config.disable_csp
70807081
self.disable_ws = sb_config.disable_ws
@@ -7278,6 +7279,7 @@ def setUp(self, masterqa_mode=False):
72787279
remote_debug=self.remote_debug,
72797280
swiftshader=self.swiftshader,
72807281
block_images=self.block_images,
7282+
chromium_arg=self.chromium_arg,
72817283
user_data_dir=self.user_data_dir,
72827284
extension_zip=self.extension_zip,
72837285
extension_dir=self.extension_dir,

seleniumbase/plugins/pytest_plugin.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def pytest_addoption(parser):
4141
--agent=STRING (Modify the web browser's User-Agent string.)
4242
--mobile (Use the mobile device emulator while running tests.)
4343
--metrics=STRING (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
44+
--chromium-arg=ARG (Add a Chromium arg for Chrome/Edge, comma-separated.)
4445
--extension-zip=ZIP (Load a Chrome Extension .zip|.crx, comma-separated.)
4546
--extension-dir=DIR (Load a Chrome Extension directory, comma-separated.)
4647
--headless (Run tests headlessly. Default mode on Linux OS.)
@@ -311,6 +312,15 @@ def pytest_addoption(parser):
311312
Format: A comma-separated string with the 3 values.
312313
Example: "375,734,3"
313314
Default: None. (Will use default values if None)""")
315+
parser.addoption('--chromium_arg', '--chromium-arg',
316+
action='store',
317+
dest='chromium_arg',
318+
default=None,
319+
help="""Add a Chromium argument for Chrome/Edge browsers.
320+
Format: A comma-separated list of Chromium args.
321+
If an arg doesn't start with "--", that will be
322+
added to the beginning of the arg automatically.
323+
Default: None.""")
314324
parser.addoption('--extension_zip', '--extension-zip', '--crx',
315325
action='store',
316326
dest='extension_zip',
@@ -671,6 +681,7 @@ def pytest_configure(config):
671681
sb_config.locale_code = config.getoption('locale_code')
672682
sb_config.interval = config.getoption('interval')
673683
sb_config.start_page = config.getoption('start_page')
684+
sb_config.chromium_arg = config.getoption('chromium_arg')
674685
sb_config.extension_zip = config.getoption('extension_zip')
675686
sb_config.extension_dir = config.getoption('extension_dir')
676687
sb_config.with_testing_base = config.getoption('with_testing_base')

0 commit comments

Comments
 (0)