From 580e705fa96b9f7c5573a3cde0f7a1e2784fe406 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 14:34:53 -0500
Subject: [PATCH 01/10] Add support for the newer chromedriver download origin
---
seleniumbase/console_scripts/sb_install.py | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/seleniumbase/console_scripts/sb_install.py b/seleniumbase/console_scripts/sb_install.py
index 7cc890d6fb9..2ee596cdaf2 100644
--- a/seleniumbase/console_scripts/sb_install.py
+++ b/seleniumbase/console_scripts/sb_install.py
@@ -498,6 +498,12 @@ def main(override=None, intel_for_uc=None, force_uc=None):
"https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/"
"%s/%s/%s" % (use_version, platform_code, file_name)
)
+ major_ch_ver = use_version.split(".")[0]
+ if major_ch_ver.isnumeric() and int(major_ch_ver) >= 121:
+ download_url = (
+ "https://storage.googleapis.com/chrome-for-testing-public/"
+ "%s/%s/%s" % (use_version, platform_code, file_name)
+ )
url_request = None
if not found_chromedriver:
url_req = requests_get(last)
From 916c789fb4e9b102e68b64e131bcf842242f9145 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 14:37:35 -0500
Subject: [PATCH 02/10] Add support for Beta and Dev builds of Chrome on macOS
---
seleniumbase/fixtures/constants.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/seleniumbase/fixtures/constants.py b/seleniumbase/fixtures/constants.py
index 42039222bd8..350ffb64ae0 100644
--- a/seleniumbase/fixtures/constants.py
+++ b/seleniumbase/fixtures/constants.py
@@ -409,6 +409,8 @@ class ValidBinaries:
"Google Chrome",
"Chromium",
"Google Chrome for Testing",
+ "Google Chrome Beta",
+ "Google Chrome Dev",
"Brave Browser",
"Opera",
]
From 26ca791c455f73d218d5ad429e677e1750792093 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 14:42:44 -0500
Subject: [PATCH 03/10] Add a pause as needed when typing text ending with "\n"
---
seleniumbase/fixtures/base_case.py | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py
index 1b9d1ab5d3f..d16f0edd2d6 100644
--- a/seleniumbase/fixtures/base_case.py
+++ b/seleniumbase/fixtures/base_case.py
@@ -951,6 +951,10 @@ def update_text(
self.wait_for_ready_state_complete()
else:
element.send_keys(text[:-1])
+ if self.slow_mode or self.demo_mode:
+ self.__demo_mode_pause_if_active(tiny=True)
+ else:
+ time.sleep(0.0135)
try:
element.send_keys(Keys.RETURN)
except WebDriverException as e:
@@ -976,6 +980,10 @@ def update_text(
element.send_keys(text)
else:
element.send_keys(text[:-1])
+ if self.slow_mode or self.demo_mode:
+ self.__demo_mode_pause_if_active(tiny=True)
+ else:
+ time.sleep(0.0135)
try:
element.send_keys(Keys.RETURN)
except WebDriverException as e:
@@ -1054,6 +1062,10 @@ def add_text(self, selector, text, by="css selector", timeout=None):
element.send_keys(text)
else:
element.send_keys(text[:-1])
+ if self.slow_mode or self.demo_mode:
+ self.__demo_mode_pause_if_active(tiny=True)
+ else:
+ time.sleep(0.0135)
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
@@ -1067,6 +1079,10 @@ def add_text(self, selector, text, by="css selector", timeout=None):
element.send_keys(text)
else:
element.send_keys(text[:-1])
+ if self.slow_mode or self.demo_mode:
+ self.__demo_mode_pause_if_active(tiny=True)
+ else:
+ time.sleep(0.0135)
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
self.wait_for_ready_state_complete()
@@ -1143,6 +1159,10 @@ def press_keys(self, selector, text, by="css selector", timeout=None):
for key in text:
element.send_keys(key)
if press_enter:
+ if self.slow_mode or self.demo_mode:
+ self.__demo_mode_pause_if_active(tiny=True)
+ else:
+ time.sleep(0.0135)
element.send_keys(Keys.RETURN)
if settings.WAIT_FOR_RSC_ON_PAGE_LOADS:
if not self.undetectable:
From f2dc88be62282dbf27111419ee4880dfa562f2d4 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 14:45:14 -0500
Subject: [PATCH 04/10] Update Recorder Mode
---
seleniumbase/extensions/recorder.zip | Bin 11896 -> 11900 bytes
seleniumbase/js_code/active_css_js.py | 5 ++---
seleniumbase/js_code/recorder_js.py | 5 ++---
3 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/seleniumbase/extensions/recorder.zip b/seleniumbase/extensions/recorder.zip
index eaaecaaa4f50b67083e2fa464d9e72eb56e147c6..dbae7aedf1f20b065177d2bcc889c2984832e87e 100644
GIT binary patch
delta 5663
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
diff --git a/seleniumbase/js_code/active_css_js.py b/seleniumbase/js_code/active_css_js.py
index 04ef165e86a..3a61770cafa 100644
--- a/seleniumbase/js_code/active_css_js.py
+++ b/seleniumbase/js_code/active_css_js.py
@@ -179,9 +179,8 @@
if (!selector_by_attr[i].includes(' > ') &&
((num_by_attr[i] == 1) || (el == all_by_attr[i][0])))
{
- if (n_i_attr == 'aria-label' || n_i_attr == 'for')
- if (hasDigit(selector_by_attr[i]))
- continue;
+ if (n_i_attr.startsWith('aria') || n_i_attr == 'for')
+ if (hasDigit(selector_by_attr[i])) continue;
return selector_by_attr[i];
}
child_count_by_attr[i] = ssOccurrences(selector_by_attr[i], ' > ');
diff --git a/seleniumbase/js_code/recorder_js.py b/seleniumbase/js_code/recorder_js.py
index 66405a6228c..67fe5c7af48 100644
--- a/seleniumbase/js_code/recorder_js.py
+++ b/seleniumbase/js_code/recorder_js.py
@@ -179,9 +179,8 @@
if (!selector_by_attr[i].includes(' > ') &&
((num_by_attr[i] == 1) || (el == all_by_attr[i][0])))
{
- if (n_i_attr == 'aria-label' || n_i_attr == 'for')
- if (hasDigit(selector_by_attr[i]))
- continue;
+ if (n_i_attr.startsWith('aria') || n_i_attr == 'for')
+ if (hasDigit(selector_by_attr[i])) continue;
return selector_by_attr[i];
}
child_count_by_attr[i] = ssOccurrences(selector_by_attr[i], ' > ');
From 010a2f033bcb653f5b50c7d1a7eaaed4bef74a21 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 15:55:07 -0500
Subject: [PATCH 05/10] Refactor code with the "ruff" Python linter
---
seleniumbase/behave/behave_sb.py | 4 +-
seleniumbase/console_scripts/sb_print.py | 12 +--
seleniumbase/core/browser_launcher.py | 26 ++---
seleniumbase/core/jqc_helper.py | 4 +-
seleniumbase/fixtures/base_case.py | 132 ++++++++++-------------
seleniumbase/fixtures/page_actions.py | 2 +-
seleniumbase/fixtures/shared_utils.py | 2 +-
seleniumbase/plugins/base_plugin.py | 4 +-
seleniumbase/plugins/sb_manager.py | 4 +-
seleniumbase/translate/translator.py | 12 +--
10 files changed, 89 insertions(+), 113 deletions(-)
diff --git a/seleniumbase/behave/behave_sb.py b/seleniumbase/behave/behave_sb.py
index c3208df0023..bd54740ee1f 100644
--- a/seleniumbase/behave/behave_sb.py
+++ b/seleniumbase/behave/behave_sb.py
@@ -367,7 +367,7 @@ def get_configured_sb(context):
# Handle: -D variables="{'KEY':'VALUE','KEY2':'VALUE2'}"
if low_key == "variables":
variables = userdata[key]
- if variables and type(variables) is str and len(variables) > 0:
+ if variables and isinstance(variables, str) and len(variables) > 0:
bad_input = False
if (
not variables.startswith("{")
@@ -377,7 +377,7 @@ def get_configured_sb(context):
else:
try:
variables = ast.literal_eval(variables)
- if not type(variables) is dict:
+ if not isinstance(variables, dict):
bad_input = True
except Exception:
bad_input = True
diff --git a/seleniumbase/console_scripts/sb_print.py b/seleniumbase/console_scripts/sb_print.py
index a4f6e7c47d1..7df43817acb 100644
--- a/seleniumbase/console_scripts/sb_print.py
+++ b/seleniumbase/console_scripts/sb_print.py
@@ -213,7 +213,7 @@ def main():
first_paren = line.find("(")
line1 = line[:first_paren + 1]
line2 = new_ws + line[first_paren + 1:]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count('", "') == 1:
@@ -353,7 +353,7 @@ def main():
new_ws = line[0:whitespace] + " "
line1 = line.split('("')[0] + "("
line2 = new_ws + '"' + line.split('("')[1]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count('" in self.') == 1:
@@ -382,7 +382,7 @@ def main():
new_ws = line[0:whitespace] + " "
line1 = line.split("('")[0] + "("
line2 = new_ws + "'" + line.split("('")[1]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count("' in self.") == 1:
@@ -444,7 +444,7 @@ def main():
continue
new_sb_lines.append(line2)
continue
- if line.count("(self.") == 1 and not ("):") in line:
+ if line.count("(self.") == 1 and ("):") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split("(self.")[0] + "("
@@ -500,7 +500,7 @@ def main():
else:
new_sb_lines.append(line2)
continue
- if line.count(" % ") == 1 and not ("):") in line:
+ if line.count(" % ") == 1 and ("):") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split(" % ")[0] + " \\"
@@ -509,7 +509,7 @@ def main():
new_sb_lines.append(line1)
new_sb_lines.append(line2)
continue
- if line.count(" = ") == 1 and not (" # ") in line:
+ if line.count(" = ") == 1 and (" # ") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split(" = ")[0] + " = ("
diff --git a/seleniumbase/core/browser_launcher.py b/seleniumbase/core/browser_launcher.py
index 218bebcda7a..d48626c8781 100644
--- a/seleniumbase/core/browser_launcher.py
+++ b/seleniumbase/core/browser_launcher.py
@@ -361,9 +361,9 @@ def uc_special_open_if_cf(
driver.switch_to.window(driver.window_handles[-1])
uc_metrics = {}
if (
- type(device_width) is int
- and type(device_height) is int
- and type(device_pixel_ratio) is int
+ isinstance(device_width, int)
+ and isinstance(device_height, int)
+ and isinstance(device_pixel_ratio, int)
):
uc_metrics["width"] = device_width
uc_metrics["height"] = device_height
@@ -847,9 +847,9 @@ def _set_chrome_options(
emulator_settings = {}
device_metrics = {}
if (
- type(device_width) is int
- and type(device_height) is int
- and type(device_pixel_ratio) is int
+ isinstance(device_width, int)
+ and isinstance(device_height, int)
+ and isinstance(device_pixel_ratio, int)
):
device_metrics["width"] = device_width
device_metrics["height"] = device_height
@@ -1389,7 +1389,7 @@ def get_driver(
headless = True
if (
binary_location
- and type(binary_location) is str
+ and isinstance(binary_location, str)
and (
browser_name == constants.Browser.GOOGLE_CHROME
or browser_name == constants.Browser.EDGE
@@ -2553,9 +2553,9 @@ def get_local_driver(
emulator_settings = {}
device_metrics = {}
if (
- type(device_width) is int
- and type(device_height) is int
- and type(device_pixel_ratio) is int
+ isinstance(device_width, int)
+ and isinstance(device_height, int)
+ and isinstance(device_pixel_ratio, int)
):
device_metrics["width"] = device_width
device_metrics["height"] = device_height
@@ -3703,9 +3703,9 @@ def get_local_driver(
if mobile_emulator:
uc_metrics = {}
if (
- type(device_width) is int
- and type(device_height) is int
- and type(device_pixel_ratio) is int
+ isinstance(device_width, int)
+ and isinstance(device_height, int)
+ and isinstance(device_pixel_ratio, int)
):
uc_metrics["width"] = device_width
uc_metrics["height"] = device_height
diff --git a/seleniumbase/core/jqc_helper.py b/seleniumbase/core/jqc_helper.py
index 79fe5554c00..49bcf8cc139 100644
--- a/seleniumbase/core/jqc_helper.py
+++ b/seleniumbase/core/jqc_helper.py
@@ -118,9 +118,7 @@ def jquery_confirm_text_dialog(driver, message, button=None, options=None):
if not message:
message = ""
if button:
- if not type(button) is list and not type(button) is tuple:
- raise Exception('"button" should be a (text, color) tuple!')
- if len(button) != 2:
+ if not isinstance(button, (list, tuple)) or len(button) != 2:
raise Exception('"button" should be a (text, color) tuple!')
else:
button = ("Submit", "blue")
diff --git a/seleniumbase/fixtures/base_case.py b/seleniumbase/fixtures/base_case.py
index d16f0edd2d6..c9204a82ad8 100644
--- a/seleniumbase/fixtures/base_case.py
+++ b/seleniumbase/fixtures/base_case.py
@@ -1368,7 +1368,7 @@ def open_start_page(self):
If the start_page is not set, then "about:blank" will be used."""
self.__check_scope()
start_page = self.start_page
- if type(start_page) is str:
+ if isinstance(start_page, str):
start_page = start_page.strip() # Remove extra whitespace
if start_page and len(start_page) >= 4:
if page_utils.is_valid_url(start_page):
@@ -3418,7 +3418,7 @@ def switch_to_frame(self, frame, timeout=None):
time.sleep(0.05)
if self.undetectable:
time.sleep(0.05)
- if type(frame) is str and self.is_element_visible(frame):
+ if isinstance(frame, str) and self.is_element_visible(frame):
try:
self.scroll_to(frame, timeout=1)
if self.__needs_minimum_wait():
@@ -6531,7 +6531,7 @@ def assert_no_404_errors(self, multithreaded=True, timeout=None):
):
links.append(link)
if timeout:
- if not type(timeout) is int and not type(timeout) is float:
+ if not isinstance(timeout, (int, float)):
raise Exception('Expecting a numeric value for "timeout"!')
if timeout < 0:
raise Exception('The "timeout" cannot be a negative number!')
@@ -6595,21 +6595,21 @@ def __get_type_checked_text(self, text):
"""Do type-checking on text. Then return it when valid.
If the text is acceptable, return the text or str(text).
If the text is not acceptable, raise a Python Exception."""
- if type(text) is str:
+ if isinstance(text, str):
return text
- elif type(text) is int or type(text) is float:
+ elif isinstance(text, (int, float)):
return str(text) # Convert num to string
- elif type(text) is bool:
+ elif isinstance(text, bool):
raise Exception("text must be a string! Boolean found!")
elif type(text).__name__ == "NoneType":
raise Exception("text must be a string! NoneType found!")
- elif type(text) is list:
+ elif isinstance(text, list):
raise Exception("text must be a string! List found!")
- elif type(text) is tuple:
+ elif isinstance(text, tuple):
raise Exception("text must be a string! Tuple found!")
- elif type(text) is set:
+ elif isinstance(text, set):
raise Exception("text must be a string! Set found!")
- elif type(text) is dict:
+ elif isinstance(text, dict):
raise Exception("text must be a string! Dict found!")
else:
return str(text)
@@ -6705,12 +6705,12 @@ def get_pdf_text(
raise Exception("%s is not a valid URL or file path!" % pdf)
file_path = os.path.abspath(pdf)
page_search = None # (Pages are delimited by '\x0c')
- if type(page) is list:
+ if isinstance(page, list):
pages = page
page_search = []
for page in pages:
page_search.append(page - 1)
- elif type(page) is int:
+ elif isinstance(page, int):
page = page - 1
if page < 0:
page = 0
@@ -6781,7 +6781,7 @@ def assert_pdf_text(
override=override,
caching=caching,
)
- if type(page) is int:
+ if isinstance(page, int):
if text not in pdf_text:
self.fail(
"PDF [%s] is missing expected text [%s] on "
@@ -6855,7 +6855,7 @@ def choose_file(
sele_file_path = [selector, file_path]
action = ["chfil", sele_file_path, origin, time_stamp]
self.__extra_actions.append(action)
- if type(abs_path) is int or type(abs_path) is float:
+ if isinstance(abs_path, (int, float)):
abs_path = str(abs_path)
try:
if self.browser == "safari":
@@ -6912,7 +6912,7 @@ def save_element_as_image_file(
with open(image_file_path, "wb") as file:
file.write(element_png)
# Add a text overlay if given
- if type(overlay_text) is str and len(overlay_text) > 0:
+ if isinstance(overlay_text, str) and len(overlay_text) > 0:
pip_find_lock = fasteners.InterProcessLock(
constants.PipInstall.FINDLOCK
)
@@ -7599,11 +7599,7 @@ def assert_no_js_errors(self, exclude=[]):
self.assert_no_js_errors(exclude=["Uncaught SyntaxError"])
self.assert_no_js_errors(exclude=["TypeError", "SyntaxE"]) """
self.__check_scope()
- if (
- exclude
- and not type(exclude) is list
- and not type(exclude) is tuple
- ):
+ if exclude and not isinstance(exclude, (list, tuple)):
exclude = str(exclude).replace(" ", "").split(",")
time.sleep(0.1) # May take a moment for errors to appear after loads.
try:
@@ -8218,7 +8214,7 @@ def set_default_timeout(self, timeout):
The maximum allowable default timeout is: 60.0 seconds.
(Test methods can still override timeouts outside that range.)"""
self.__check_scope()
- if not type(timeout) is int and not type(timeout) is float:
+ if not isinstance(timeout, (int, float)):
raise Exception('Expecting a numeric value for "timeout"!')
if timeout < 0:
raise Exception('The "timeout" cannot be a negative number!')
@@ -8778,7 +8774,7 @@ def _print(self, msg):
To print without the new-line character end, use: "sys.stdout.write()".
"""
if hasattr(sb_config, "_multithreaded") and sb_config._multithreaded:
- if type(msg) is not str:
+ if not isinstance(msg, str):
try:
msg = str(msg)
except Exception:
@@ -9012,7 +9008,7 @@ def generate_referral_chain(self, pages):
generation without increasing the bounce rate, you'll want to visit
at least one additional page on that site with a button click.)"""
self.__check_scope()
- if not type(pages) is tuple and not type(pages) is list:
+ if not isinstance(pages, (list, tuple)):
raise Exception(
"Exception: Expecting a list of website pages for chaining!"
)
@@ -9121,7 +9117,7 @@ def assert_element_present(
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
- if type(selector) is list:
+ if isinstance(selector, list):
self.assert_elements_present(selector, by=by, timeout=timeout)
return True
if self.__is_shadow_selector(selector):
@@ -9157,12 +9153,12 @@ def assert_elements_present(self, *args, **kwargs):
by = kwargs["by"]
elif kwarg == "selector":
selector = kwargs["selector"]
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
- elif type(selector) is list:
+ elif isinstance(selector, list):
selectors_list = selector
for selector in selectors_list:
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
else:
raise Exception('Unknown kwarg: "%s"!' % kwarg)
@@ -9171,11 +9167,11 @@ def assert_elements_present(self, *args, **kwargs):
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
for arg in args:
- if type(arg) is list:
+ if isinstance(arg, list):
for selector in arg:
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
- elif type(arg) is str:
+ elif isinstance(arg, str):
selectors.append(arg)
for selector in selectors:
if self.__is_shadow_selector(selector):
@@ -9198,7 +9194,7 @@ def assert_element(self, selector, by="css selector", timeout=None):
timeout = settings.SMALL_TIMEOUT
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
- if type(selector) is list:
+ if isinstance(selector, list):
self.assert_elements(selector, by=by, timeout=timeout)
return True
if self.__is_shadow_selector(selector):
@@ -9260,12 +9256,12 @@ def assert_elements(self, *args, **kwargs):
by = kwargs["by"]
elif kwarg == "selector":
selector = kwargs["selector"]
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
- elif type(selector) is list:
+ elif isinstance(selector, list):
selectors_list = selector
for selector in selectors_list:
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
else:
raise Exception('Unknown kwarg: "%s"!' % kwarg)
@@ -9274,11 +9270,11 @@ def assert_elements(self, *args, **kwargs):
if self.timeout_multiplier and timeout == settings.SMALL_TIMEOUT:
timeout = self.__get_new_timeout(timeout)
for arg in args:
- if type(arg) is list:
+ if isinstance(arg, list):
for selector in arg:
- if type(selector) is str:
+ if isinstance(selector, str):
selectors.append(selector)
- elif type(arg) is str:
+ elif isinstance(arg, str):
selectors.append(arg)
for selector in selectors:
if self.__is_shadow_selector(selector):
@@ -11119,7 +11115,7 @@ def save_presentation(
interval = 0
if interval == 0 and self.interval:
interval = float(self.interval)
- if not type(interval) is int and not type(interval) is float:
+ if not isinstance(interval, (int, float)):
raise Exception('Expecting a numeric value for "interval"!')
if interval < 0:
raise Exception('The "interval" cannot be a negative number!')
@@ -11208,7 +11204,7 @@ def begin_presentation(
interval = 0
if interval == 0 and self.interval:
interval = float(self.interval)
- if not type(interval) is int and not type(interval) is float:
+ if not isinstance(interval, (int, float)):
raise Exception('Expecting a numeric value for "interval"!')
if interval < 0:
raise Exception('The "interval" cannot be a negative number!')
@@ -11787,7 +11783,7 @@ def add_data_point(self, label, value, color=None, chart_name=None):
self.create_pie_chart(chart_name=chart_name)
if not value:
value = 0
- if not type(value) is int and not type(value) is float:
+ if not isinstance(value, (int, float)):
raise Exception('Expecting a numeric value for "value"!')
if not color:
color = ""
@@ -11898,7 +11894,7 @@ def display_chart(self, chart_name=None, filename=None, interval=0):
interval = 0
if interval == 0 and self.interval:
interval = float(self.interval)
- if not type(interval) is int and not type(interval) is float:
+ if not isinstance(interval, (int, float)):
raise Exception('Expecting a numeric value for "interval"!')
if interval < 0:
raise Exception('The "interval" cannot be a negative number!')
@@ -12664,7 +12660,7 @@ def set_jqc_theme(self, theme, color=None, width=None):
)
constants.JqueryConfirm.DEFAULT_COLOR = color.lower()
if width:
- if type(width) is int or type(width) is float:
+ if isinstance(width, (int, float)):
# Convert to a string if a number is given
width = str(width)
if width.isnumeric():
@@ -12719,30 +12715,24 @@ def get_jqc_button_input(self, message, buttons, options=None):
Width can be set using percent or pixels. Eg: "36.0%", "450px"."""
from seleniumbase.core import jqc_helper
- if message and type(message) is not str:
+ if message and not isinstance(message, str):
raise Exception('Expecting a string for arg: "message"!')
- if not type(buttons) is list and not type(buttons) is tuple:
+ if not isinstance(buttons, (list, tuple)):
raise Exception('Expecting a list or tuple for arg: "button"!')
if len(buttons) < 1:
raise Exception('List "buttons" requires at least one button!')
new_buttons = []
for button in buttons:
- if (
- (type(button) is list or type(button) is tuple)
- and (len(button) == 1)
- ):
+ if isinstance(button, (list, tuple)) and (len(button) == 1):
new_buttons.append(button[0])
- elif (
- (type(button) is list or type(button) is tuple)
- and (len(button) > 1)
- ):
+ elif isinstance(button, (list, tuple)) and (len(button) > 1):
new_buttons.append((button[0], str(button[1]).lower()))
else:
new_buttons.append((str(button), ""))
buttons = new_buttons
if options:
for option in options:
- if not type(option) is list and not type(option) is tuple:
+ if not isinstance(option, (list, tuple)):
raise Exception('"options" should be a list of tuples!')
if self.headless or self.headless2 or self.xvfb:
return buttons[-1][0]
@@ -12789,18 +12779,12 @@ def get_jqc_text_input(self, message, button=None, options=None):
Width can be set using percent or pixels. Eg: "36.0%", "450px"."""
from seleniumbase.core import jqc_helper
- if message and type(message) is not str:
+ if message and not isinstance(message, str):
raise Exception('Expecting a string for arg: "message"!')
if button:
- if (
- (type(button) is list or type(button) is tuple)
- and (len(button) == 1)
- ):
+ if isinstance(button, (list, tuple)) and (len(button) == 1):
button = (str(button[0]), "")
- elif (
- (type(button) is list or type(button) is tuple)
- and (len(button) > 1)
- ):
+ elif isinstance(button, (list, tuple)) and (len(button) > 1):
valid_colors = [
"blue",
"default",
@@ -12823,7 +12807,7 @@ def get_jqc_text_input(self, message, button=None, options=None):
button = ("Submit", "blue")
if options:
for option in options:
- if not type(option) is list and not type(option) is tuple:
+ if not isinstance(option, (list, tuple)):
raise Exception('"options" should be a list of tuples!')
if self.headless or self.headless2 or self.xvfb:
return ""
@@ -12870,30 +12854,24 @@ def get_jqc_form_inputs(self, message, buttons, options=None):
Width can be set using percent or pixels. Eg: "36.0%", "450px"."""
from seleniumbase.core import jqc_helper
- if message and type(message) is not str:
+ if message and not isinstance(message, str):
raise Exception('Expecting a string for arg: "message"!')
- if not type(buttons) is list and not type(buttons) is tuple:
+ if not isinstance(buttons, (list, tuple)):
raise Exception('Expecting a list or tuple for arg: "button"!')
if len(buttons) < 1:
raise Exception('List "buttons" requires at least one button!')
new_buttons = []
for button in buttons:
- if (
- (type(button) is list or type(button) is tuple)
- and (len(button) == 1)
- ):
+ if isinstance(button, (list, tuple)) and (len(button) == 1):
new_buttons.append(button[0])
- elif (
- (type(button) is list or type(button) is tuple)
- and (len(button) > 1)
- ):
+ elif isinstance(button, (list, tuple)) and (len(button) > 1):
new_buttons.append((button[0], str(button[1]).lower()))
else:
new_buttons.append((str(button), ""))
buttons = new_buttons
if options:
for option in options:
- if not type(option) is list and not type(option) is tuple:
+ if not isinstance(option, (list, tuple)):
raise Exception('"options" should be a list of tuples!')
if self.headless or self.headless2 or self.xvfb:
return ("", buttons[-1][0])
@@ -14244,7 +14222,7 @@ def setUp(self, masterqa_mode=False):
self.var2 = sb_config.var2
self.var3 = sb_config.var3
variables = sb_config.variables
- if variables and type(variables) is str and len(variables) > 0:
+ if variables and isinstance(variables, str) and len(variables) > 0:
import ast
bad_input = False
@@ -14256,7 +14234,7 @@ def setUp(self, masterqa_mode=False):
else:
try:
variables = ast.literal_eval(variables)
- if not type(variables) is dict:
+ if not isinstance(variables, dict):
bad_input = True
except Exception:
bad_input = True
@@ -14265,7 +14243,7 @@ def setUp(self, masterqa_mode=False):
'\nExpecting a Python dictionary for "variables"!'
"\nEg. --variables=\"{'KEY1':'VALUE', 'KEY2':123}\""
)
- elif type(variables) is dict:
+ elif isinstance(variables, dict):
pass # Already processed
else:
variables = {}
diff --git a/seleniumbase/fixtures/page_actions.py b/seleniumbase/fixtures/page_actions.py
index 56633e45e13..877874fae07 100644
--- a/seleniumbase/fixtures/page_actions.py
+++ b/seleniumbase/fixtures/page_actions.py
@@ -1412,7 +1412,7 @@ def switch_to_frame(driver, frame, timeout=settings.SMALL_TIMEOUT):
driver.switch_to.frame(frame)
return True
except Exception:
- if type(frame) is str:
+ if isinstance(frame, str):
by = None
if page_utils.is_xpath_selector(frame):
by = "xpath"
diff --git a/seleniumbase/fixtures/shared_utils.py b/seleniumbase/fixtures/shared_utils.py
index 19ccfa198a4..888e88cbb29 100644
--- a/seleniumbase/fixtures/shared_utils.py
+++ b/seleniumbase/fixtures/shared_utils.py
@@ -120,7 +120,7 @@ def format_exc(exception, message):
exc = exceptions.NoSuchOptionException
elif exception == "NoSuchOptionException":
exc = exceptions.NoSuchOptionException
- elif type(exception) is str:
+ elif isinstance(exception, str):
exc = Exception
message = "%s: %s" % (exception, message)
return exc, message
diff --git a/seleniumbase/plugins/base_plugin.py b/seleniumbase/plugins/base_plugin.py
index 4816d235d0c..61b6da01afe 100644
--- a/seleniumbase/plugins/base_plugin.py
+++ b/seleniumbase/plugins/base_plugin.py
@@ -219,14 +219,14 @@ def configure(self, options, conf):
def beforeTest(self, test):
sb_config._context_of_runner = False # Context Manager Compatibility
variables = self.options.variables
- if variables and type(variables) is str and len(variables) > 0:
+ if variables and isinstance(variables, str) and len(variables) > 0:
bad_input = False
if not variables.startswith("{") or not variables.endswith("}"):
bad_input = True
else:
try:
variables = ast.literal_eval(variables)
- if not type(variables) is dict:
+ if not isinstance(variables, dict):
bad_input = True
except Exception:
bad_input = True
diff --git a/seleniumbase/plugins/sb_manager.py b/seleniumbase/plugins/sb_manager.py
index 2fdcbd007b0..911de408dd8 100644
--- a/seleniumbase/plugins/sb_manager.py
+++ b/seleniumbase/plugins/sb_manager.py
@@ -409,7 +409,7 @@ def SB(
sb_config.proxy_driver = False
if "--proxy-driver" in sys_argv or "--proxy_driver" in sys_argv:
sb_config.proxy_driver = True
- if variables and type(variables) is str and len(variables) > 0:
+ if variables and isinstance(variables, str) and len(variables) > 0:
import ast
bad_input = False
if (
@@ -420,7 +420,7 @@ def SB(
else:
try:
variables = ast.literal_eval(variables)
- if not type(variables) is dict:
+ if not isinstance(variables, dict):
bad_input = True
except Exception:
bad_input = True
diff --git a/seleniumbase/translate/translator.py b/seleniumbase/translate/translator.py
index b52959af2c6..67e87167272 100644
--- a/seleniumbase/translate/translator.py
+++ b/seleniumbase/translate/translator.py
@@ -635,7 +635,7 @@ def main():
first_paren = line.find("(")
line1 = line[:first_paren + 1]
line2 = new_ws + line[first_paren + 1:]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count('", "') == 1:
@@ -773,7 +773,7 @@ def main():
new_ws = line[0:whitespace] + " "
line1 = line.split('("')[0] + "("
line2 = new_ws + '"' + line.split('("')[1]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count('" in self.') == 1:
@@ -802,7 +802,7 @@ def main():
new_ws = line[0:whitespace] + " "
line1 = line.split("('")[0] + "("
line2 = new_ws + "'" + line.split("('")[1]
- if not ("):") in line2:
+ if ("):") not in line2:
new_sb_lines.append(line1)
if get_width(line2) + w > console_width:
if line2.count("' in self.") == 1:
@@ -864,7 +864,7 @@ def main():
continue
new_sb_lines.append(line2)
continue
- if line.count("(self.") == 1 and not ("):") in line:
+ if line.count("(self.") == 1 and ("):") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split("(self.")[0] + "("
@@ -920,7 +920,7 @@ def main():
else:
new_sb_lines.append(line2)
continue
- if line.count(" % ") == 1 and not ("):") in line:
+ if line.count(" % ") == 1 and ("):") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split(" % ")[0] + " \\"
@@ -929,7 +929,7 @@ def main():
new_sb_lines.append(line1)
new_sb_lines.append(line2)
continue
- if line.count(" = ") == 1 and not (" # ") in line:
+ if line.count(" = ") == 1 and (" # ") not in line:
whitespace = line_length2 - len(line.lstrip())
new_ws = line[0:whitespace] + " "
line1 = line.split(" = ")[0] + " = ("
From c6236e25a9cd4b8753d5e7daefe1e3879e850cec Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 19:23:37 -0500
Subject: [PATCH 06/10] Refresh mkdocs dependencies
---
mkdocs_build/requirements.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mkdocs_build/requirements.txt b/mkdocs_build/requirements.txt
index ba2fb5034e6..624886a6dd9 100644
--- a/mkdocs_build/requirements.txt
+++ b/mkdocs_build/requirements.txt
@@ -3,7 +3,7 @@
regex>=2023.12.25
pymdown-extensions>=10.7
-pipdeptree>=2.13.2
+pipdeptree>=2.14.0
python-dateutil>=2.8.2
Markdown==3.5.2
markdown2==2.4.12
From f79822a2f65bf265999339c61ef57740eb70abaf Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 19:24:25 -0500
Subject: [PATCH 07/10] Refresh Python dependencies
---
requirements.txt | 2 +-
setup.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/requirements.txt b/requirements.txt
index ee49877abdb..97bfbf5f14f 100755
--- a/requirements.txt
+++ b/requirements.txt
@@ -42,7 +42,7 @@ pytest==7.4.4;python_version<"3.8"
pytest==8.0.0;python_version>="3.8"
pytest-html==2.0.1
pytest-metadata==3.0.0;python_version<"3.8"
-pytest-metadata==3.1.0;python_version>="3.8"
+pytest-metadata==3.1.1;python_version>="3.8"
pytest-ordering==0.6
pytest-rerunfailures==13.0
pytest-xdist==3.5.0
diff --git a/setup.py b/setup.py
index 6df3b8e2e88..47c81c58863 100755
--- a/setup.py
+++ b/setup.py
@@ -189,7 +189,7 @@
'pytest==8.0.0;python_version>="3.8"',
"pytest-html==2.0.1", # Newer ones had issues
'pytest-metadata==3.0.0;python_version<"3.8"',
- 'pytest-metadata==3.1.0;python_version>="3.8"',
+ 'pytest-metadata==3.1.1;python_version>="3.8"',
"pytest-ordering==0.6",
'pytest-rerunfailures==13.0',
'pytest-xdist==3.5.0',
From 302b9e9b8569c0a0076fe1a9791f0876058f229c Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 21:28:24 -0500
Subject: [PATCH 08/10] Update an example test
---
examples/dialog_boxes/dialog_box_tour.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/examples/dialog_boxes/dialog_box_tour.py b/examples/dialog_boxes/dialog_box_tour.py
index 4785511714c..2e061732cc7 100644
--- a/examples/dialog_boxes/dialog_box_tour.py
+++ b/examples/dialog_boxes/dialog_box_tour.py
@@ -87,7 +87,10 @@ def test_dialog_boxes(self):
self.open("https://seleniumbase.io/help_docs/ReadMe/")
self.highlight("h1")
- self.highlight_click('a:contains("Running Example Tests")')
+ self.slow_scroll_to('article p a[href*="/examples/ReadMe/"]')
+ zoom_in = 'article p a[href*="/examples/ReadMe/"]{zoom: 1.8;}'
+ self.add_css_style(zoom_in)
+ self.highlight_click('article p a[href*="/examples/ReadMe/"]')
self.highlight("h1")
self.set_jqc_theme("bootstrap", color="green", width="52%")
From 84b9ba88902eda1eda45b7580cecea3f9c14b8fe Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 21:30:31 -0500
Subject: [PATCH 09/10] Update ReadMe files
---
README.md | 12 ++++++------
examples/migration/raw_selenium/ReadMe.md | 4 ++--
help_docs/ReadMe.md | 16 ++++++++++------
seleniumbase/ReadMe.md | 2 +-
4 files changed, 19 insertions(+), 15 deletions(-)
diff --git a/README.md b/README.md
index 6f7e53c1c8f..ec897569ec5 100755
--- a/README.md
+++ b/README.md
@@ -63,7 +63,7 @@
pytest my_first_test.py
```
-
+
> ``pytest`` uses ``--chrome`` by default unless set differently.
@@ -361,10 +361,10 @@ COMMANDS:
▶️ Here's sample output from a chromedriver download. (click to expand)
```bash
-*** chromedriver to download = 116.0.5845.96 (Latest Stable)
+*** chromedriver to download = 121.0.6167.85 (Latest Stable)
Downloading chromedriver-mac-arm64.zip from:
-https://edgedl.me.gvt1.com/edgedl/chrome/chrome-for-testing/116.0.5845.96/mac-arm64/chromedriver-mac-arm64.zip ...
+https://storage.googleapis.com/chrome-for-testing-public/121.0.6167.85/mac-arm64/chromedriver-mac-arm64.zip ...
Download Complete!
Extracting ['chromedriver'] from chromedriver-mac-arm64.zip ...
@@ -373,8 +373,8 @@ Unzip Complete!
The file [chromedriver] was saved to:
/Users/michael/github/SeleniumBase/seleniumbase/drivers/chromedriver
-Making [chromedriver 116.0.5845.96] executable ...
-[chromedriver 116.0.5845.96] is now ready for use!
+Making [chromedriver 121.0.6167.85] executable ...
+[chromedriver 121.0.6167.85] is now ready for use!
```
@@ -392,7 +392,7 @@ cd examples/
pytest my_first_test.py
```
-
+
Here's the code for my_first_test.py:
diff --git a/examples/migration/raw_selenium/ReadMe.md b/examples/migration/raw_selenium/ReadMe.md
index 57a5459fd21..904d843bcf3 100644
--- a/examples/migration/raw_selenium/ReadMe.md
+++ b/examples/migration/raw_selenium/ReadMe.md
@@ -70,9 +70,9 @@ With raw Selenium, that requires more code:
💡 SeleniumBase has its own Recorder / Test Generator for creating tests from manual browser actions.
-💡 SeleniumBase comes with test case management software, ("CasePlans"), for organizing tests and step descriptions.
+💡 SeleniumBase comes with test case management software, ("Case Plans"), for organizing tests and step descriptions.
-💡 SeleniumBase includes tools for building data apps, ("ChartMaker"), which can generate JavaScript from Python.
+💡 SeleniumBase includes tools for building data apps, ("Chart Maker"), which can generate JavaScript from Python.
diff --git a/help_docs/ReadMe.md b/help_docs/ReadMe.md
index 885c2f9a54b..228431ef4da 100644
--- a/help_docs/ReadMe.md
+++ b/help_docs/ReadMe.md
@@ -1,6 +1,6 @@
-
+
## [
](https://github.com/seleniumbase/SeleniumBase/) Help Docs
@@ -33,10 +33,13 @@
🛂 Dialog Boxes
🔴 Recorder |
-🚝 Migrate
+💻 Device Farm
🎞️ Slides |
-📶 Charts
+📶 Chart Maker
+
+🎖️ GUI |
+👤 UC Mode
--------
@@ -57,19 +60,20 @@
+
-
+
-
+
-
+
diff --git a/seleniumbase/ReadMe.md b/seleniumbase/ReadMe.md
index 2b8f160fb62..a4827dc9a99 100644
--- a/seleniumbase/ReadMe.md
+++ b/seleniumbase/ReadMe.md
@@ -1,4 +1,4 @@
-
+
Framework Folders
From c22fcc2b9db8c0fee021732f4d8f716764dfe567 Mon Sep 17 00:00:00 2001
From: Michael Mintz
Date: Thu, 15 Feb 2024 21:31:13 -0500
Subject: [PATCH 10/10] Version 4.23.4
---
seleniumbase/__version__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/seleniumbase/__version__.py b/seleniumbase/__version__.py
index 6e641d13521..361c8bdcbf2 100755
--- a/seleniumbase/__version__.py
+++ b/seleniumbase/__version__.py
@@ -1,2 +1,2 @@
# seleniumbase package
-__version__ = "4.23.3"
+__version__ = "4.23.4"