Skip to content

Add the ability to set custom Chromium args. And update downloads. #846

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ The code above will leave your browser window open in case there's a failure. (i
--agent=STRING # (Modify the web browser's User-Agent string.)
--mobile # (Use the mobile device emulator while running tests.)
--metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
--chromium-arg=ARG # (Add a Chromium arg for Chrome/Edge, comma-separated.)
--extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
--headless # (Run tests headlessly. Default mode on Linux OS.)
Expand Down
1 change: 1 addition & 0 deletions examples/raw_parameter_script.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
sb.remote_debug = False
sb.settings_file = None
sb.user_data_dir = None
sb.chromium_arg = None
sb.proxy_string = None
sb.swiftshader = False
sb.ad_block_on = False
Expand Down
18 changes: 14 additions & 4 deletions examples/test_shadow_dom.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,28 @@ def download_tar_file_from_pypi(self, package):
pkg_name = pkg_header.replace(" ", "-")
tar_file = pkg_name + ".tar.gz"
tar_selector = 'div#files a[href$="%s"]' % tar_file
self.delete_downloaded_file_if_present(tar_file)
self.delete_downloaded_file_if_present(tar_file, browser=True)
self.click(tar_selector)
return tar_file

def test_shadow_dom(self):
if self.browser != "chrome":
print("\n This test is for Google Chrome only!")
self.skip('This test is for Google Chrome only!')
self.skip("This test is for Google Chrome only!")
if self.headless:
print("\n This test does not run in headless mode!")
self.skip('This test does not run in headless mode!')
print("\n This test doesn't run in headless mode!")
self.skip("This test doesn't run in headless mode!")

# Download Python package files from PyPI
file_name_1 = self.download_tar_file_from_pypi("sbase")
file_name_2 = self.download_tar_file_from_pypi("tensorpy")
self.assert_downloaded_file(file_name_1, browser=True)
self.assert_downloaded_file(file_name_2, browser=True)

# Navigate to the Chrome downloads page.
self.open("chrome://downloads/")

# Shadow DOM selectors
search_icon = (
"downloads-manager::shadow downloads-toolbar::shadow"
" cr-toolbar::shadow cr-toolbar-search-field::shadow"
Expand Down Expand Up @@ -64,3 +70,7 @@ def test_shadow_dom(self):
self.assert_text("No search results found", no_downloads_area)
self.click(clear_search_icon)
self.assert_element(remove_button)

# Delete the downloaded files from the [Downloads Folder]
self.delete_downloaded_file_if_present(file_name_1, browser=True)
self.delete_downloaded_file_if_present(file_name_2, browser=True)
2 changes: 2 additions & 0 deletions help_docs/customizing_test_runs.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,10 @@ SeleniumBase provides additional ``pytest`` command-line options for tests:
--port=PORT # (The Selenium Grid port used by the test server.)
--proxy=SERVER:PORT # (Connect to a proxy server:port for tests.)
--proxy=USERNAME:PASSWORD@SERVER:PORT # (Use authenticated proxy server.)
--agent=STRING # (Modify the web browser's User-Agent string.)
--mobile # (Use the mobile device emulator while running tests.)
--metrics=STRING # (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
--chromium-arg=ARG # (Add a Chromium arg for Chrome/Edge, comma-separated.)
--extension-zip=ZIP # (Load a Chrome Extension .zip|.crx, comma-separated.)
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
--headless # (Run tests headlessly. Default mode on Linux OS.)
Expand Down
23 changes: 23 additions & 0 deletions help_docs/shadow_dom.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
## Shadow DOM support / Shadow-root interaction

🔵 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.

🔵 Here are some examples of Shadow DOM selectors:

```python
css_1 = "downloads-manager::shadow #no-downloads"

css_2 = "downloads-manager::shadow #downloadsList downloads-item::shadow #file-link"

css_3 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow cr-icon-button"

css_4 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #searchInput"

css_5 = "downloads-manager::shadow downloads-toolbar::shadow cr-toolbar::shadow cr-toolbar-search-field::shadow #clearSearch"
```

🔵 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.

🔵 Note that ``::shadow`` selectors only exist within SeleniumBase, and do not exist outside of it.

🔵 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)
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ nav:
- Desired Capabilities: help_docs/desired_capabilities.md
- Docker Start Guide: integrations/docker/ReadMe.md
- Using Safari Driver: help_docs/using_safari_driver.md
- Shadow DOM Support: help_docs/shadow_dom.md
- macOS Hidden Files: help_docs/hidden_files_info.md
- MySQL Instructions: help_docs/mysql_installation.md
- Demo Pages:
Expand Down
2 changes: 1 addition & 1 deletion seleniumbase/__version__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# seleniumbase package
__version__ = "1.59.0"
__version__ = "1.59.1"
46 changes: 35 additions & 11 deletions seleniumbase/core/browser_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ def _set_chrome_options(
proxy_string, proxy_auth, proxy_user, proxy_pass,
user_agent, disable_csp, enable_ws, enable_sync, use_auto_ext,
no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir, servername,
mobile_emulator, device_width, device_height, device_pixel_ratio):
chrome_options = webdriver.ChromeOptions()
Expand Down Expand Up @@ -298,6 +298,18 @@ def _set_chrome_options(
chrome_options.add_argument("--disable-gpu")
if "linux" in PLATFORM:
chrome_options.add_argument("--disable-dev-shm-usage")
if chromium_arg:
# Can be a comma-separated list of Chromium args
chromium_arg_list = chromium_arg.split(',')
for chromium_arg_item in chromium_arg_list:
chromium_arg_item = chromium_arg_item.strip()
if not chromium_arg_item.startswith("--"):
if chromium_arg_item.startswith("-"):
chromium_arg_item = "-" + chromium_arg_item
else:
chromium_arg_item = "--" + chromium_arg_item
if len(chromium_arg_item) >= 3:
chrome_options.add_argument(chromium_arg_item)
return chrome_options


Expand Down Expand Up @@ -459,7 +471,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
use_auto_ext=None, no_sandbox=None, disable_gpu=None,
incognito=None, guest_mode=None,
devtools=None, remote_debug=None,
swiftshader=None, block_images=None,
swiftshader=None, block_images=None, chromium_arg=None,
user_data_dir=None, extension_zip=None, extension_dir=None,
test_id=None, mobile_emulator=False, device_width=None,
device_height=None, device_pixel_ratio=None):
Expand Down Expand Up @@ -498,7 +510,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
cap_file, cap_string, disable_csp, enable_ws, enable_sync,
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir, test_id,
mobile_emulator, device_width, device_height, device_pixel_ratio)
else:
Expand All @@ -507,7 +519,7 @@ def get_driver(browser_name, headless=False, locale_code=None,
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
disable_csp, enable_ws, enable_sync,
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir,
mobile_emulator, device_width, device_height, device_pixel_ratio)

Expand All @@ -517,7 +529,7 @@ def get_remote_driver(
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
cap_file, cap_string, disable_csp, enable_ws, enable_sync,
use_auto_ext, no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir, test_id,
mobile_emulator, device_width, device_height, device_pixel_ratio):
downloads_path = download_helper.get_downloads_folder()
Expand Down Expand Up @@ -549,7 +561,7 @@ def get_remote_driver(
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
disable_csp, enable_ws, enable_sync, use_auto_ext, no_sandbox,
disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir,
servername, mobile_emulator,
device_width, device_height, device_pixel_ratio)
Expand Down Expand Up @@ -677,7 +689,7 @@ def get_local_driver(
proxy_string, proxy_auth, proxy_user, proxy_pass, user_agent,
disable_csp, enable_ws, enable_sync, use_auto_ext, no_sandbox,
disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
devtools, remote_debug, swiftshader, block_images, chromium_arg,
user_data_dir, extension_zip, extension_dir,
mobile_emulator, device_width, device_height, device_pixel_ratio):
'''
Expand Down Expand Up @@ -765,8 +777,8 @@ def get_local_driver(
disable_csp, enable_ws, enable_sync, use_auto_ext,
no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
user_data_dir, extension_zip, extension_dir, servername,
mobile_emulator, device_width, device_height,
chromium_arg, user_data_dir, extension_zip, extension_dir,
servername, mobile_emulator, device_width, device_height,
device_pixel_ratio)
if LOCAL_EDGEDRIVER and os.path.exists(LOCAL_EDGEDRIVER):
try:
Expand Down Expand Up @@ -910,6 +922,18 @@ def get_local_driver(
edge_options.add_argument("--disable-gpu")
if "linux" in PLATFORM:
edge_options.add_argument("--disable-dev-shm-usage")
if chromium_arg:
# Can be a comma-separated list of Chromium args
chromium_arg_list = chromium_arg.split(',')
for chromium_arg_item in chromium_arg_list:
chromium_arg_item = chromium_arg_item.strip()
if not chromium_arg_item.startswith("--"):
if chromium_arg_item.startswith("-"):
chromium_arg_item = "-" + chromium_arg_item
else:
chromium_arg_item = "--" + chromium_arg_item
if len(chromium_arg_item) >= 3:
edge_options.add_argument(chromium_arg_item)
capabilities = edge_options.to_capabilities()
capabilities["platform"] = ''
return Edge(
Expand All @@ -935,7 +959,7 @@ def get_local_driver(
disable_csp, enable_ws, enable_sync, use_auto_ext,
no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
user_data_dir, extension_zip, extension_dir,
chromium_arg, user_data_dir, extension_zip, extension_dir,
servername, mobile_emulator,
device_width, device_height, device_pixel_ratio)
opera_options.headless = False # No support for headless Opera
Expand All @@ -955,7 +979,7 @@ def get_local_driver(
disable_csp, enable_ws, enable_sync, use_auto_ext,
no_sandbox, disable_gpu, incognito, guest_mode,
devtools, remote_debug, swiftshader, block_images,
user_data_dir, extension_zip, extension_dir,
chromium_arg, user_data_dir, extension_zip, extension_dir,
servername, mobile_emulator,
device_width, device_height, device_pixel_ratio)
if LOCAL_CHROMEDRIVER and os.path.exists(LOCAL_CHROMEDRIVER):
Expand Down
20 changes: 11 additions & 9 deletions seleniumbase/fixtures/base_case.py
Original file line number Diff line number Diff line change
Expand Up @@ -1899,9 +1899,9 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
switch_to=True, cap_file=None, cap_string=None,
disable_csp=None, enable_ws=None, enable_sync=None,
use_auto_ext=None, no_sandbox=None, disable_gpu=None,
incognito=None, guest_mode=None,
devtools=None, remote_debug=None,
swiftshader=None, block_images=None, user_data_dir=None,
incognito=None, guest_mode=None, devtools=None,
remote_debug=None, swiftshader=None, block_images=None,
chromium_arg=None, user_data_dir=None,
extension_zip=None, extension_dir=None, is_mobile=False,
d_width=None, d_height=None, d_p_r=None):
""" This method spins up an extra browser for tests that require
Expand Down Expand Up @@ -1930,6 +1930,7 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
remote_debug - the option to enable Chrome's Remote Debugger
swiftshader - the option to use Chrome's swiftshader (Chrome-only)
block_images - the option to block images from loading (Chrome)
chromium_arg - the option to add a Chromium arg to Chrome/Edge
user_data_dir - Chrome's User Data Directory to use (Chrome-only)
extension_zip - A Chrome Extension ZIP file to use (Chrome-only)
extension_dir - A Chrome Extension folder to use (Chrome-only)
Expand Down Expand Up @@ -2005,6 +2006,8 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
swiftshader = self.swiftshader
if block_images is None:
block_images = self.block_images
if chromium_arg is None:
chromium_arg = self.chromium_arg
if user_data_dir is None:
user_data_dir = self.user_data_dir
if extension_zip is None:
Expand Down Expand Up @@ -2052,6 +2055,7 @@ def get_new_driver(self, browser=None, headless=None, locale_code=None,
remote_debug=remote_debug,
swiftshader=swiftshader,
block_images=block_images,
chromium_arg=chromium_arg,
user_data_dir=user_data_dir,
extension_zip=extension_zip,
extension_dir=extension_dir,
Expand Down Expand Up @@ -3095,12 +3099,8 @@ def get_downloads_folder(self):
any clicks that download files will also use this folder
rather than using the browser's default "downloads/" path. """
self.__check_scope()
if self.is_chromium() and self.guest_mode and not self.headless:
# Guest Mode (non-headless) can force the default downloads path
return os.path.join(os.path.expanduser('~'), 'downloads')
else:
from seleniumbase.core import download_helper
return download_helper.get_downloads_folder()
from seleniumbase.core import download_helper
return download_helper.get_downloads_folder()

def get_browser_downloads_folder(self):
""" Returns the path that is used when a click initiates a download.
Expand Down Expand Up @@ -7075,6 +7075,7 @@ def setUp(self, masterqa_mode=False):
self.js_checking_on = sb_config.js_checking_on
self.ad_block_on = sb_config.ad_block_on
self.block_images = sb_config.block_images
self.chromium_arg = sb_config.chromium_arg
self.verify_delay = sb_config.verify_delay
self.disable_csp = sb_config.disable_csp
self.disable_ws = sb_config.disable_ws
Expand Down Expand Up @@ -7278,6 +7279,7 @@ def setUp(self, masterqa_mode=False):
remote_debug=self.remote_debug,
swiftshader=self.swiftshader,
block_images=self.block_images,
chromium_arg=self.chromium_arg,
user_data_dir=self.user_data_dir,
extension_zip=self.extension_zip,
extension_dir=self.extension_dir,
Expand Down
11 changes: 11 additions & 0 deletions seleniumbase/plugins/pytest_plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ def pytest_addoption(parser):
--agent=STRING (Modify the web browser's User-Agent string.)
--mobile (Use the mobile device emulator while running tests.)
--metrics=STRING (Set mobile metrics: "CSSWidth,CSSHeight,PixelRatio".)
--chromium-arg=ARG (Add a Chromium arg for Chrome/Edge, comma-separated.)
--extension-zip=ZIP (Load a Chrome Extension .zip|.crx, comma-separated.)
--extension-dir=DIR (Load a Chrome Extension directory, comma-separated.)
--headless (Run tests headlessly. Default mode on Linux OS.)
Expand Down Expand Up @@ -311,6 +312,15 @@ def pytest_addoption(parser):
Format: A comma-separated string with the 3 values.
Example: "375,734,3"
Default: None. (Will use default values if None)""")
parser.addoption('--chromium_arg', '--chromium-arg',
action='store',
dest='chromium_arg',
default=None,
help="""Add a Chromium argument for Chrome/Edge browsers.
Format: A comma-separated list of Chromium args.
If an arg doesn't start with "--", that will be
added to the beginning of the arg automatically.
Default: None.""")
parser.addoption('--extension_zip', '--extension-zip', '--crx',
action='store',
dest='extension_zip',
Expand Down Expand Up @@ -671,6 +681,7 @@ def pytest_configure(config):
sb_config.locale_code = config.getoption('locale_code')
sb_config.interval = config.getoption('interval')
sb_config.start_page = config.getoption('start_page')
sb_config.chromium_arg = config.getoption('chromium_arg')
sb_config.extension_zip = config.getoption('extension_zip')
sb_config.extension_dir = config.getoption('extension_dir')
sb_config.with_testing_base = config.getoption('with_testing_base')
Expand Down
Loading