Skip to content

Commit 52da66f

Browse files
authored
Merge pull request #1592 from seleniumbase/python-3.11-official-support
Python 3.11 Official Support
2 parents 17a9082 + 08a8887 commit 52da66f

25 files changed

+619
-118
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,7 @@ pytest my_first_test.py --pdb
564564
--window-size=WIDTH,HEIGHT # (Set the browser's starting window size.)
565565
--maximize # (Start tests with the browser window maximized.)
566566
--screenshot # (Save a screenshot at the end of each test.)
567+
--no-screenshot # (No screenshots saved unless tests directly ask it.)
567568
--visual-baseline # (Set the visual baseline for Visual/Layout tests.)
568569
--wire # (Use selenium-wire's webdriver for replacing selenium webdriver.)
569570
--external-pdf # (Set Chromium "plugins.always_open_pdf_externally":True.)

examples/wordle_archive_test.py renamed to examples/old_wordle_script.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1-
""" Solve the Wordle game using SeleniumBase.
2-
This test runs on archived versions of Wordle, containing Shadow-DOM. """
1+
"""
2+
Solve the Wordle game using SeleniumBase.
3+
This test runs on archived versions of Wordle, containing Shadow-DOM.
4+
"""
35

46
import ast
57
import random
@@ -86,7 +88,7 @@ def test_wordle(self):
8688
keyboard_base = "game-app::shadow game-keyboard::shadow "
8789
word = random.choice(self.word_list)
8890
num_attempts = 0
89-
success = False
91+
found_word = False
9092
for attempt in range(6):
9193
num_attempts += 1
9294
word = random.choice(self.word_list)
@@ -105,13 +107,13 @@ def test_wordle(self):
105107
letter_eval = self.get_attribute(tile % str(i), "evaluation")
106108
letter_status.append(letter_eval)
107109
if letter_status.count("correct") == 5:
108-
success = True
110+
found_word = True
109111
break
110112
self.word_list.remove(word)
111113
self.modify_word_list(word, letter_status)
112114

113115
self.save_screenshot_to_logs()
114-
if success:
116+
if found_word:
115117
print('Word: "%s"\nAttempts: %s' % (word.upper(), num_attempts))
116118
else:
117119
print('Final guess: "%s" (Not the correct word!)' % word.upper())

examples/raw_parameter_script.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
sb.maximize_option = False
8181
sb._disable_beforeunload = False
8282
sb.save_screenshot_after_test = False
83+
sb.no_screenshot_after_test = False
8384
sb.page_load_strategy = None
8485
sb.timeout_multiplier = None
8586
sb.pytest_html_report = None

examples/test_apple_site.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@ def test_apple_developer_site_webdriver_instructions(self):
88
self.demo_mode = True
99
self.demo_sleep = 0.5
1010
self.message_duration = 2.0
11-
if self.headless and (
12-
self.browser == "chrome" or self.browser == "edge"
13-
):
14-
self.get_new_driver(browser=self.browser, headless2=True)
11+
if self.headless:
12+
if self._multithreaded:
13+
print("Skipping test in headless multi-threaded mode.")
14+
self.skip("Skipping test in headless multi-threaded mode.")
15+
elif self.undetectable:
16+
print("Skipping test in headless undetectable mode.")
17+
self.skip("Skipping test in headless undetectable mode.")
18+
elif self.browser == "chrome" or self.browser == "edge":
19+
self.get_new_driver(browser=self.browser, headless2=True)
1520
self.open("https://developer.apple.com/search/")
1621
title = "Testing with WebDriver in Safari"
1722
self.type('[placeholder*="developer.apple.com"]', title + "\n")

examples/test_get_locale_code.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
class LocaleTests(BaseCase):
55
def test_get_locale_code(self):
6-
self.open("data:,")
6+
self.open("about:blank")
77
locale_code = self.get_locale_code()
88
message = '\nLocale Code = "%s"' % locale_code
99
print(message)

examples/visual_testing/test_layout_fail.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def test_applitools_change(self):
2222
# Click a button that changes the text of an element
2323
self.click('a[href="?diff1"]')
2424
# Click a button that makes a hidden element visible
25-
self.click("button")
25+
self.slow_click("button")
2626
print("(This test should fail)") # due to image now seen
2727
self.check_window(name="helloworld", level=3)
2828

examples/wordle_test.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def test_wordle(self):
6464
self.initialize_word_list()
6565
word = random.choice(self.word_list)
6666
num_attempts = 0
67-
success = False
67+
found_word = False
6868
for attempt in range(6):
6969
num_attempts += 1
7070
word = random.choice(self.word_list)
@@ -74,25 +74,27 @@ def test_wordle(self):
7474
button = 'button[data-key="%s"]' % letter
7575
self.click(button)
7676
button = 'button[class*="oneAndAHalf"]'
77+
self.wait_for_ready_state_complete()
7778
self.click(button)
7879
row = (
7980
'div[class*="lbzlf"] div[class*="Row-module"]:nth-of-type(%s) '
8081
% num_attempts
8182
)
8283
tile = row + 'div:nth-child(%s) div[class*="module_tile__3ayIZ"]'
8384
self.wait_for_element(tile % "5" + '[data-state*="e"]')
85+
self.wait_for_ready_state_complete()
8486
letter_status = []
8587
for i in range(1, 6):
8688
letter_eval = self.get_attribute(tile % str(i), "data-state")
8789
letter_status.append(letter_eval)
8890
if letter_status.count("correct") == 5:
89-
success = True
91+
found_word = True
9092
break
9193
self.word_list.remove(word)
9294
self.modify_word_list(word, letter_status)
9395

9496
self.save_screenshot_to_logs()
95-
if success:
97+
if found_word:
9698
print('\nWord: "%s"\nAttempts: %s' % (word.upper(), num_attempts))
9799
else:
98100
print('Final guess: "%s" (Not the correct word!)' % word.upper())

help_docs/customizing_test_runs.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ pytest my_first_test.py --settings-file=custom_settings.py
178178
--window-size=WIDTH,HEIGHT # (Set the browser's starting window size.)
179179
--maximize # (Start tests with the browser window maximized.)
180180
--screenshot # (Save a screenshot at the end of each test.)
181+
--no-screenshot # (No screenshots saved unless tests directly ask it.)
181182
--visual-baseline # (Set the visual baseline for Visual/Layout tests.)
182183
--wire # (Use selenium-wire's webdriver for replacing selenium webdriver.)
183184
--external-pdf # (Set Chromium "plugins.always_open_pdf_externally":True.)

mkdocs_build/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# mkdocs dependencies for generating the seleniumbase.io website
22
# Minimum Python version: 3.7
33

4-
regex>=2022.9.13
4+
regex>=2022.10.31
55
docutils==0.19
66
python-dateutil==2.8.2
77
livereload==2.6.3
@@ -14,7 +14,7 @@ Jinja2==3.1.2
1414
click==8.1.3
1515
zipp==3.10.0
1616
ghp-import==2.1.0
17-
readme-renderer==37.2
17+
readme-renderer==37.3
1818
pymdown-extensions==9.7
1919
importlib-metadata==5.0.0
2020
bleach==5.0.1
@@ -28,7 +28,7 @@ cairosvg==2.5.2
2828
cssselect2==0.7.0
2929
tinycss2==1.2.1
3030
defusedxml==0.7.1
31-
mkdocs==1.4.1
31+
mkdocs==1.4.2
3232
mkdocs-material==8.5.7
3333
mkdocs-exclude-search==0.6.4
3434
mkdocs-simple-hooks==0.1.5

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pytest-html==1.22.1;python_version<"3.6"
8080
pytest-html==2.0.1;python_version>="3.6"
8181
pytest-metadata==1.8.0;python_version<"3.6"
8282
pytest-metadata==1.11.0;python_version>="3.6" and python_version<"3.7"
83-
pytest-metadata==2.0.3;python_version>="3.7"
83+
pytest-metadata==2.0.4;python_version>="3.7"
8484
pytest-ordering==0.6
8585
pytest-rerunfailures==8.0;python_version<"3.6"
8686
pytest-rerunfailures==10.2;python_version>="3.6"
@@ -98,7 +98,7 @@ beautifulsoup4==4.9.3;python_version<"3.6"
9898
beautifulsoup4==4.11.1;python_version>="3.6"
9999
cryptography==2.9.2;python_version<"3.6"
100100
cryptography==36.0.2;python_version>="3.6" and python_version<"3.7"
101-
cryptography==38.0.1;python_version>="3.7"
101+
cryptography==38.0.3;python_version>="3.7"
102102
pygments==2.5.2;python_version<"3.6"
103103
pygments==2.13.0;python_version>="3.6"
104104
prompt-toolkit==1.0.18;python_version<"3.6"

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__ = "4.7.0"
2+
__version__ = "4.7.1"

seleniumbase/behave/behave_sb.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,10 @@
8888
-D window-size=WIDTH,HEIGHT (Set the browser's starting window size.)
8989
-D maximize (Start tests with the browser window maximized.)
9090
-D screenshot (Save a screenshot at the end of each test.)
91+
-D no-screenshot (No screenshots saved unless tests directly ask it.)
9192
-D visual-baseline (Set the visual baseline for Visual/Layout tests.)
9293
-D wire (Use selenium-wire's webdriver for replacing selenium webdriver.)
93-
-D external-pdf (Set Chromium "plugins.always_open_pdf_externally": True.)
94+
-D external-pdf (Set Chromium "plugins.always_open_pdf_externally":True.)
9495
-D timeout-multiplier=MULTIPLIER (Multiplies the default timeout values.)
9596
"""
9697

@@ -185,6 +186,7 @@ def get_configured_sb(context):
185186
sb.maximize_option = False
186187
sb.is_context_manager = False
187188
sb.save_screenshot_after_test = False
189+
sb.no_screenshot_after_test = False
188190
sb.timeout_multiplier = None
189191
sb.pytest_html_report = None
190192
sb.with_db_reporting = False
@@ -565,6 +567,10 @@ def get_configured_sb(context):
565567
]:
566568
sb.save_screenshot_after_test = True
567569
continue
570+
# Handle: -D no-screenshot / no_screenshot / ns
571+
if low_key in ["no-screenshot", "no_screenshot", "ns"]:
572+
sb.no_screenshot_after_test = True
573+
continue
568574
# Handle: -D timeout-multiplier=FLOAT / timeout_multiplier=FLOAT
569575
if low_key in ["timeout-multiplier", "timeout_multiplier"]:
570576
timeout_multiplier = userdata[key]
@@ -848,6 +854,7 @@ def get_configured_sb(context):
848854
sb_config.maximize_option = sb.maximize_option
849855
sb_config.xvfb = sb.xvfb
850856
sb_config.save_screenshot = sb.save_screenshot_after_test
857+
sb_config.no_screenshot = sb.no_screenshot_after_test
851858
sb_config._has_logs = False
852859
sb_config.variables = sb.variables
853860
sb_config.dashboard = sb.dashboard

seleniumbase/config/settings.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@
107107
# (Headless resolutions take priority, and include all browsers.)
108108
# (Firefox starts maximized by default when running in GUI Mode.)
109109
CHROME_START_WIDTH = 1250
110-
CHROME_START_HEIGHT = 840
110+
CHROME_START_HEIGHT = 825
111111
HEADLESS_START_WIDTH = 1440
112-
HEADLESS_START_HEIGHT = 1880
112+
HEADLESS_START_HEIGHT = 1875
113113

114114
# #####>>>>>----- MasterQA SETTINGS -----<<<<<#####
115115
# ##### (Used when importing MasterQA as the parent class)

seleniumbase/core/browser_launcher.py

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from selenium.webdriver.chrome.service import Service as ChromeService
1313
from selenium.webdriver.edge.service import Service as EdgeService
1414
from selenium.webdriver.firefox.service import Service as FirefoxService
15+
from selenium.webdriver.safari.service import Service as SafariService
1516
from seleniumbase.config import settings
1617
from seleniumbase.core import download_helper
1718
from seleniumbase.core import proxy_helper
@@ -477,6 +478,18 @@ def _set_chrome_options(
477478
chrome_options.add_experimental_option(
478479
"mobileEmulation", emulator_settings
479480
)
481+
if headless or headless2:
482+
chrome_options.add_argument(
483+
"--window-size=%s,%s" % (
484+
settings.HEADLESS_START_WIDTH, settings.HEADLESS_START_HEIGHT
485+
)
486+
)
487+
else:
488+
chrome_options.add_argument(
489+
"--window-size=%s,%s" % (
490+
settings.CHROME_START_WIDTH, settings.CHROME_START_HEIGHT
491+
)
492+
)
480493
if (
481494
not proxy_auth
482495
and not disable_csp
@@ -498,7 +511,7 @@ def _set_chrome_options(
498511
chrome_options.add_argument("--guest")
499512
else:
500513
pass
501-
if user_data_dir and not undetectable:
514+
if user_data_dir and not is_using_uc(undetectable, browser_name):
502515
abs_path = os.path.abspath(user_data_dir)
503516
chrome_options.add_argument("user-data-dir=%s" % abs_path)
504517
if extension_zip:
@@ -527,13 +540,6 @@ def _set_chrome_options(
527540
):
528541
# Only change it if not "normal", which is the default.
529542
chrome_options.page_load_strategy = settings.PAGE_LOAD_STRATEGY.lower()
530-
if servername != "localhost":
531-
use_auto_ext = True # Use Automation Extension
532-
if not use_auto_ext: # Disable Automation Extension. (Default)
533-
if browser_name != constants.Browser.OPERA:
534-
chrome_options.add_argument(
535-
"--disable-blink-features=AutomationControlled"
536-
)
537543
if headless2:
538544
chrome_options.add_argument("--headless=chrome")
539545
elif headless:
@@ -591,10 +597,11 @@ def _set_chrome_options(
591597
chrome_options.add_argument("--proxy-pac-url=%s" % proxy_pac_url)
592598
if browser_name != constants.Browser.OPERA:
593599
# Opera Chromium doesn't support these switches
594-
chrome_options.add_argument("--ignore-certificate-errors")
600+
if not is_using_uc(undetectable, browser_name) or not enable_ws:
601+
chrome_options.add_argument("--ignore-certificate-errors")
595602
if not enable_ws:
596603
chrome_options.add_argument("--disable-web-security")
597-
if "linux" in PLATFORM or not undetectable:
604+
if "linux" in PLATFORM or not is_using_uc(undetectable, browser_name):
598605
chrome_options.add_argument("--no-sandbox")
599606
else:
600607
# Opera Chromium only!
@@ -940,7 +947,7 @@ def get_driver(
940947
headless = True
941948
if uc_subprocess and not undetectable:
942949
undetectable = True
943-
if undetectable and mobile_emulator:
950+
if is_using_uc(undetectable, browser_name) and mobile_emulator:
944951
mobile_emulator = False
945952
user_agent = None
946953
proxy_auth = False
@@ -2060,7 +2067,21 @@ def get_local_driver(
20602067
edge_options.add_experimental_option(
20612068
"mobileEmulation", emulator_settings
20622069
)
2063-
if user_data_dir and not undetectable:
2070+
if headless or headless2:
2071+
edge_options.add_argument(
2072+
"--window-size=%s,%s" % (
2073+
settings.HEADLESS_START_WIDTH,
2074+
settings.HEADLESS_START_HEIGHT,
2075+
)
2076+
)
2077+
else:
2078+
edge_options.add_argument(
2079+
"--window-size=%s,%s" % (
2080+
settings.CHROME_START_WIDTH,
2081+
settings.CHROME_START_HEIGHT,
2082+
)
2083+
)
2084+
if user_data_dir and not is_using_uc(undetectable, browser_name):
20642085
abs_path = os.path.abspath(user_data_dir)
20652086
edge_options.add_argument("user-data-dir=%s" % abs_path)
20662087
if extension_zip:
@@ -2144,7 +2165,7 @@ def get_local_driver(
21442165
edge_options.add_argument("--allow-running-insecure-content")
21452166
if user_agent:
21462167
edge_options.add_argument("--user-agent=%s" % user_agent)
2147-
if "linux" in PLATFORM or not undetectable:
2168+
if "linux" in PLATFORM or not is_using_uc(undetectable, browser_name):
21482169
edge_options.add_argument("--no-sandbox")
21492170
if remote_debug:
21502171
# To access the Remote Debugger, go to: http://localhost:9222
@@ -2298,7 +2319,8 @@ def get_local_driver(
22982319
# Skip if multithreaded
22992320
raise Exception("Can't run Safari tests in multithreaded mode!")
23002321
warnings.simplefilter("ignore", category=DeprecationWarning)
2301-
return webdriver.safari.webdriver.WebDriver(quiet=False)
2322+
service = SafariService(quiet=False)
2323+
return webdriver.safari.webdriver.WebDriver(service=service)
23022324
elif browser_name == constants.Browser.OPERA:
23032325
try:
23042326
if LOCAL_OPERADRIVER and os.path.exists(LOCAL_OPERADRIVER):
@@ -2635,7 +2657,7 @@ def get_local_driver(
26352657
if selenium4_or_newer:
26362658
if headless and "linux" not in PLATFORM:
26372659
undetectable = False # No support for headless
2638-
if undetectable:
2660+
if is_using_uc(undetectable, browser_name):
26392661
from seleniumbase import undetected
26402662
from urllib.error import URLError
26412663

0 commit comments

Comments
 (0)