Skip to content

Commit 02dfba7

Browse files
committed
Integrate Chromium's new headless mode into SeleniumBase
1 parent 7e654af commit 02dfba7

File tree

8 files changed

+170
-49
lines changed

8 files changed

+170
-49
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -480,7 +480,8 @@ The code above will leave your browser window open in case there's a failure. (i
480480
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
481481
--pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
482482
--headless # (Run tests in headless mode. The default arg on Linux OS.)
483-
--headed # (Run tests in headed/GUI mode on Linux OS.)
483+
--headless2 # (Use the new headless mode, which supports extensions.)
484+
--headed # (Run tests in headed/GUI mode on Linux OS, where not default.)
484485
--xvfb # (Run tests using the Xvfb virtual display server on Linux OS.)
485486
--locale=LOCALE_CODE # (Set the Language Locale Code for the web browser.)
486487
--interval=SECONDS # (The autoplay interval for presentations & tour steps)

examples/raw_parameter_script.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
sb.browser = "chrome"
3434
sb.is_behave = False
3535
sb.headless = False
36+
sb.headless2 = False
3637
sb.headed = False
3738
sb.xvfb = False
3839
sb.start_page = None

help_docs/customizing_test_runs.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,8 @@ pytest my_first_test.py --settings-file=custom_settings.py
134134
--extension-dir=DIR # (Load a Chrome Extension directory, comma-separated.)
135135
--pls=PLS # (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
136136
--headless # (Run tests in headless mode. The default arg on Linux OS.)
137-
--headed # (Run tests in headed/GUI mode on Linux OS.)
137+
--headless2 # (Use the new headless mode, which supports extensions.)
138+
--headed # (Run tests in headed/GUI mode on Linux OS, where not default.)
138139
--xvfb # (Run tests using the Xvfb virtual display server on Linux OS.)
139140
--locale=LOCALE_CODE # (Set the Language Locale Code for the web browser.)
140141
--interval=SECONDS # (The autoplay interval for presentations & tour steps)

seleniumbase/behave/behave_sb.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@
4343
-D extension-dir=DIR (Load a Chrome Extension directory, comma-separated.)
4444
-D pls=PLS (Set pageLoadStrategy on Chrome: "normal", "eager", or "none".)
4545
-D headless (Run tests in headless mode. The default arg on Linux OS.)
46-
-D headed (Run tests in headed/GUI mode on Linux OS.)
46+
-D headless2 (Use the new headless mode, which supports extensions.)
47+
-D headed (Run tests in headed/GUI mode on Linux OS, where not default.)
4748
-D xvfb (Run tests using the Xvfb virtual display server on Linux OS.)
4849
-D locale=LOCALE_CODE (Set the Language Locale Code for the web browser.)
4950
-D pdb (Activate Post Mortem Debug Mode if a test fails.)
@@ -131,6 +132,7 @@ def get_configured_sb(context):
131132
sb.browser = "chrome"
132133
sb.is_behave = True
133134
sb.headless = False
135+
sb.headless2 = False
134136
sb.headless_active = False
135137
sb.headed = False
136138
sb.xvfb = False
@@ -262,6 +264,10 @@ def get_configured_sb(context):
262264
if low_key == "headless":
263265
sb.headless = True
264266
continue
267+
# Handle: -D headless2
268+
if low_key == "headless2":
269+
sb.headless2 = True
270+
continue
265271
# Handle: -D headed / gui
266272
if low_key in ["headed", "gui"]:
267273
sb.headed = True
@@ -733,36 +739,41 @@ def get_configured_sb(context):
733739
"\nOnly ONE default browser is allowed!\n"
734740
"%s browsers were selected: %s" % (len(browsers), browsers)
735741
)
736-
# Recorder Mode does not support headless browser runs.
737-
# Chromium does not allow extensions in Headless Mode.
742+
# Recorder Mode can still optimize scripts in "-D headless2" mode.
738743
if sb.recorder_ext and sb.headless:
739-
raise Exception(
740-
"\n\n Recorder Mode does NOT support Headless Mode!"
741-
'\n (DO NOT combine "-D rec" with "-D headless"!)\n'
742-
)
744+
sb.headless = False
745+
sb.headless2 = True
746+
if sb.browser not in ["chrome", "edge"]:
747+
sb.headless2 = False # Only for Chromium browsers
743748
# Recorder Mode only supports Chromium browsers.
744749
if sb.recorder_ext and (sb.browser not in ["chrome", "edge"]):
745750
raise Exception(
746751
"\n\n Recorder Mode ONLY supports Chrome and Edge!"
747752
'\n (Your browser choice was: "%s")\n' % sb.browser
748753
)
754+
# Recorder Mode can still optimize scripts in --headless2 mode.
755+
if sb.recorder_mode and sb.headless:
756+
sb.headless = False
757+
sb.headless2 = True
749758
# The Xvfb virtual display server is for Linux OS Only.
750759
if sb.xvfb and "linux" not in sys.platform:
751760
sb.xvfb = False
752761
if (
753762
"linux" in sys.platform
754763
and not sb.headed
755764
and not sb.headless
765+
and not sb.headless2
756766
and not sb.xvfb
757767
):
758768
print(
759769
'(Linux uses "-D headless" by default. '
760770
'To override, use "-D headed" / "-D gui". '
761771
'For Xvfb mode instead, use "-D xvfb". '
762-
'Or hide this info with "-D headless".)'
772+
'Or hide this info with "-D headless",'
773+
'or by calling the new "-D headless2".)'
763774
)
764775
sb.headless = True
765-
if not sb.headless:
776+
if not sb.headless and not sb.headless2:
766777
sb.headed = True
767778
if sb.servername != "localhost":
768779
# Using Selenium Grid

seleniumbase/core/browser_launcher.py

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ def _set_chrome_options(
333333
undetectable,
334334
no_sandbox,
335335
disable_gpu,
336+
headless2,
336337
incognito,
337338
guest_mode,
338339
devtools,
@@ -505,7 +506,9 @@ def _set_chrome_options(
505506
"--disable-blink-features=AutomationControlled"
506507
)
507508
chrome_options.add_experimental_option("useAutomationExtension", False)
508-
if headless:
509+
if headless2:
510+
chrome_options.add_argument("--headless=chrome")
511+
elif headless:
509512
chrome_options.add_argument("--headless")
510513
if (settings.DISABLE_CSP_ON_CHROME or disable_csp) and not headless:
511514
# Headless Chrome does not support extensions, which are required
@@ -865,6 +868,7 @@ def get_driver(
865868
undetectable=False,
866869
no_sandbox=False,
867870
disable_gpu=False,
871+
headless2=False,
868872
incognito=False,
869873
guest_mode=False,
870874
devtools=False,
@@ -943,20 +947,43 @@ def get_driver(
943947
raise Exception('The proxy PAC URL must end with ".pac"!')
944948
if proxy_pac_url and proxy_user and proxy_pass:
945949
proxy_auth = True
950+
if (
951+
is_using_uc(undetectable, browser_name)
952+
and "linux" not in PLATFORM
953+
and headless
954+
):
955+
headless = False
956+
headless2 = True
946957
if (
947958
headless
948-
and proxy_auth
959+
and (
960+
proxy_auth
961+
or ad_block_on
962+
or disable_csp
963+
or recorder_ext
964+
or extension_zip
965+
or extension_dir
966+
)
949967
and (
950968
browser_name == constants.Browser.GOOGLE_CHROME
951969
or browser_name == constants.Browser.EDGE
952970
)
953971
):
954972
# Headless Chrome/Edge doesn't support extensions, which are
955-
# required when using a proxy server that has authentication.
973+
# required when using a proxy server that has authentication,
974+
# or when using other SeleniumBase extensions (eg: Recorder).
956975
# Instead, base_case.py will use the SBVirtualDisplay when not
957976
# using Chrome's built-in headless mode. See link for details:
958977
# https://bugs.chromium.org/p/chromium/issues/detail?id=706008
959978
headless = False
979+
if "linux" not in PLATFORM:
980+
# Use the new headless mode on Chrome if not using Linux:
981+
# bugs.chromium.org/p/chromium/issues/detail?id=706008#c36
982+
# Although Linux is technically supported, there are a lot
983+
# of old versions of Chrome on Linux server machines, and
984+
# this mode requires a recent version of Chrome to work.
985+
# Specify "--headless2" as a pytest arg to use on Linux.
986+
headless2 = True
960987
if (
961988
browser_name == constants.Browser.GOOGLE_CHROME
962989
and user_data_dir
@@ -990,6 +1017,7 @@ def get_driver(
9901017
undetectable,
9911018
no_sandbox,
9921019
disable_gpu,
1020+
headless2,
9931021
incognito,
9941022
guest_mode,
9951023
devtools,
@@ -1033,6 +1061,7 @@ def get_driver(
10331061
undetectable,
10341062
no_sandbox,
10351063
disable_gpu,
1064+
headless2,
10361065
incognito,
10371066
guest_mode,
10381067
devtools,
@@ -1080,6 +1109,7 @@ def get_remote_driver(
10801109
undetectable,
10811110
no_sandbox,
10821111
disable_gpu,
1112+
headless2,
10831113
incognito,
10841114
guest_mode,
10851115
devtools,
@@ -1177,6 +1207,7 @@ def get_remote_driver(
11771207
undetectable,
11781208
no_sandbox,
11791209
disable_gpu,
1210+
headless2,
11801211
incognito,
11811212
guest_mode,
11821213
devtools,
@@ -1402,6 +1433,7 @@ def get_remote_driver(
14021433
undetectable,
14031434
no_sandbox,
14041435
disable_gpu,
1436+
headless2,
14051437
incognito,
14061438
guest_mode,
14071439
devtools,
@@ -1594,6 +1626,7 @@ def get_local_driver(
15941626
undetectable,
15951627
no_sandbox,
15961628
disable_gpu,
1629+
headless2,
15971630
incognito,
15981631
guest_mode,
15991632
devtools,
@@ -1893,7 +1926,9 @@ def get_local_driver(
18931926
edge_options.add_argument("--disable-sync")
18941927
if guest_mode:
18951928
edge_options.add_argument("--guest")
1896-
if headless:
1929+
if headless2:
1930+
edge_options.add_argument("--headless=chrome")
1931+
elif headless:
18971932
edge_options.add_argument("--headless")
18981933
if mobile_emulator:
18991934
emulator_settings = {}
@@ -2177,6 +2212,7 @@ def get_local_driver(
21772212
undetectable,
21782213
no_sandbox,
21792214
disable_gpu,
2215+
headless2,
21802216
incognito,
21812217
guest_mode,
21822218
devtools,
@@ -2237,6 +2273,7 @@ def get_local_driver(
22372273
undetectable,
22382274
no_sandbox,
22392275
disable_gpu,
2276+
headless2,
22402277
incognito,
22412278
guest_mode,
22422279
devtools,
@@ -2551,6 +2588,7 @@ def get_local_driver(
25512588
undetectable,
25522589
no_sandbox,
25532590
disable_gpu,
2591+
headless2,
25542592
incognito,
25552593
guest_mode,
25562594
devtools,

0 commit comments

Comments
 (0)