Refactoring
This commit is contained in:
parent
5fd88b1fd8
commit
e6d35b478e
|
@ -1,6 +1,7 @@
|
|||
""" SeleniumBase Exceptions
|
||||
NoSuchFileException => Called when self.assert_downloaded_file(...) fails.
|
||||
NotUsingChromeException => Used by Chrome-only methods if not using Chrome.
|
||||
NotUsingChromiumException => Used by Chromium-only methods if not Chromium.
|
||||
OutOfScopeException => Used by BaseCase methods when setUp() is skipped.
|
||||
TextNotVisibleException => Called when expected text fails to appear.
|
||||
TimeLimitExceededException => Called when exceeding "--time-limit=SECONDS".
|
||||
|
@ -16,6 +17,10 @@ class NotUsingChromeException(Exception):
|
|||
pass
|
||||
|
||||
|
||||
class NotUsingChromiumException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class OutOfScopeException(Exception):
|
||||
pass
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import sys
|
|||
import time
|
||||
import urllib3
|
||||
import warnings
|
||||
import zipfile
|
||||
from selenium import webdriver
|
||||
from selenium.webdriver.chrome.service import Service as ChromeService
|
||||
from selenium.webdriver.edge.service import Service as EdgeService
|
||||
|
@ -351,8 +352,6 @@ def _unzip_to_new_folder(zip_file, folder):
|
|||
proxy_dir_lock = fasteners.InterProcessLock(PROXY_DIR_LOCK)
|
||||
with proxy_dir_lock:
|
||||
if not os.path.exists(folder):
|
||||
import zipfile
|
||||
|
||||
zip_ref = zipfile.ZipFile(zip_file, "r")
|
||||
os.makedirs(folder)
|
||||
zip_ref.extractall(folder)
|
||||
|
|
|
@ -61,6 +61,12 @@ from selenium.webdriver.remote.remote_connection import LOGGER
|
|||
from seleniumbase import config as sb_config
|
||||
from seleniumbase.__version__ import __version__
|
||||
from seleniumbase.common import decorators
|
||||
from seleniumbase.common.exceptions import (
|
||||
NotUsingChromeException,
|
||||
NotUsingChromiumException,
|
||||
OutOfScopeException,
|
||||
VisualException,
|
||||
)
|
||||
from seleniumbase.config import settings
|
||||
from seleniumbase.core import download_helper
|
||||
from seleniumbase.core import log_helper
|
||||
|
@ -6493,6 +6499,12 @@ class BaseCase(unittest.TestCase):
|
|||
and self.headless
|
||||
):
|
||||
return os.path.join(os.path.expanduser("~"), "downloads")
|
||||
elif (
|
||||
self.driver.capabilities["browserName"].lower() == "chrome"
|
||||
and int(self.get_chromedriver_version().split(".")[0]) >= 110
|
||||
and self.headless
|
||||
):
|
||||
return os.path.abspath(".")
|
||||
else:
|
||||
return download_helper.get_downloads_folder()
|
||||
return os.path.join(os.path.expanduser("~"), "downloads")
|
||||
|
@ -7092,17 +7104,27 @@ class BaseCase(unittest.TestCase):
|
|||
if browser_name.lower() == "chrome":
|
||||
chrome = True
|
||||
if not chrome:
|
||||
from seleniumbase.common.exceptions import NotUsingChromeException
|
||||
|
||||
message = (
|
||||
'Error: "%s" should only be called '
|
||||
'by tests running with self.browser == "chrome"! '
|
||||
'Error: "%s" should only be called by tests '
|
||||
'running with "--browser=chrome" / "--chrome"! '
|
||||
'You should add an "if" statement to your code before calling '
|
||||
"this method if using browsers that are Not Chrome! "
|
||||
'The browser detected was: "%s".' % (method, browser_name)
|
||||
)
|
||||
raise NotUsingChromeException(message)
|
||||
|
||||
def __fail_if_not_using_chromium(self, method):
|
||||
browser_name = self.driver.capabilities["browserName"]
|
||||
if not self.is_chromium():
|
||||
message = (
|
||||
'Error: "%s" should only be called by tests '
|
||||
'running with a Chromium browser! (Chrome or Edge) '
|
||||
'You should add an "if" statement to your code before calling '
|
||||
"this method if using browsers that are Not Chromium! "
|
||||
'The browser detected was: "%s".' % (method, browser_name)
|
||||
)
|
||||
raise NotUsingChromiumException(message)
|
||||
|
||||
def get_chrome_version(self):
|
||||
self.__check_scope()
|
||||
self.__fail_if_not_using_chrome("get_chrome_version()")
|
||||
|
@ -7113,6 +7135,11 @@ class BaseCase(unittest.TestCase):
|
|||
chrome_version = driver_capabilities["browserVersion"]
|
||||
return chrome_version
|
||||
|
||||
def get_chromium_version(self):
|
||||
self.__check_scope()
|
||||
self.__fail_if_not_using_chromium("get_chromium_version()")
|
||||
return self.__get_major_browser_version()
|
||||
|
||||
def get_chromedriver_version(self):
|
||||
self.__check_scope()
|
||||
self.__fail_if_not_using_chrome("get_chromedriver_version()")
|
||||
|
@ -7121,14 +7148,19 @@ class BaseCase(unittest.TestCase):
|
|||
chromedriver_version = chromedriver_version.split(" ")[0]
|
||||
return chromedriver_version
|
||||
|
||||
def is_chromedriver_too_old(self):
|
||||
"""Before chromedriver 73, there was no version check, which
|
||||
means it's possible to run a new Chrome with old drivers."""
|
||||
def get_chromium_driver_version(self):
|
||||
self.__check_scope()
|
||||
self.__fail_if_not_using_chrome("is_chromedriver_too_old()")
|
||||
if int(self.get_chromedriver_version().split(".")[0]) < 73:
|
||||
return True # chromedriver is too old! Please upgrade!
|
||||
return False
|
||||
self.__fail_if_not_using_chromium("get_chromium_version()")
|
||||
driver_version = None
|
||||
if "chrome" in self.driver.capabilities:
|
||||
chrome_dict = self.driver.capabilities["chrome"]
|
||||
driver_version = chrome_dict["chromedriverVersion"]
|
||||
driver_version = driver_version.split(" ")[0]
|
||||
elif "msedge" in self.driver.capabilities:
|
||||
edge_dict = self.driver.capabilities["msedge"]
|
||||
driver_version = edge_dict["msedgedriverVersion"]
|
||||
driver_version = driver_version.split(" ")[0]
|
||||
return driver_version
|
||||
|
||||
def get_mfa_code(self, totp_key=None):
|
||||
"""Same as get_totp_code() and get_google_auth_password().
|
||||
|
@ -9307,8 +9339,6 @@ class BaseCase(unittest.TestCase):
|
|||
elif line.strip().startswith("*"):
|
||||
minified_exception += line + "\n"
|
||||
if minified_exception:
|
||||
from seleniumbase.common.exceptions import VisualException
|
||||
|
||||
raise VisualException(minified_exception)
|
||||
|
||||
def _process_visual_baseline_logs(self):
|
||||
|
@ -9688,8 +9718,6 @@ class BaseCase(unittest.TestCase):
|
|||
if hasattr(self, "browser"): # self.browser stores the type of browser
|
||||
return # All good: setUp() already initialized variables in "self"
|
||||
else:
|
||||
from seleniumbase.common.exceptions import OutOfScopeException
|
||||
|
||||
message = (
|
||||
"\n It looks like you are trying to call a SeleniumBase method"
|
||||
"\n from outside the scope of your test class's `self` object,"
|
||||
|
@ -12734,9 +12762,18 @@ class BaseCase(unittest.TestCase):
|
|||
|
||||
############
|
||||
|
||||
@decorators.deprecated("The Driver Manager prevents old drivers.")
|
||||
def is_chromedriver_too_old(self):
|
||||
"""Before chromedriver 73, there was no version check, which
|
||||
means it's possible to run a new Chrome with old drivers."""
|
||||
self.__fail_if_not_using_chrome("is_chromedriver_too_old()")
|
||||
if int(self.get_chromedriver_version().split(".")[0]) < 73:
|
||||
return True # chromedriver is too old! Please upgrade!
|
||||
return False
|
||||
|
||||
@decorators.deprecated("You should use re.escape() instead.")
|
||||
def jq_format(self, code):
|
||||
# DEPRECATED - re.escape() already performs the intended action.
|
||||
# DEPRECATED - re.escape() already performs this action.
|
||||
return js_utils._jq_format(code)
|
||||
|
||||
############
|
||||
|
|
|
@ -24,9 +24,7 @@ def get_domain_url(url):
|
|||
|
||||
|
||||
def is_xpath_selector(selector):
|
||||
"""
|
||||
A basic method to determine if a selector is an xpath selector.
|
||||
"""
|
||||
"""Determine if a selector is an xpath selector."""
|
||||
if (
|
||||
selector.startswith("/")
|
||||
or selector.startswith("./")
|
||||
|
@ -37,9 +35,7 @@ def is_xpath_selector(selector):
|
|||
|
||||
|
||||
def is_link_text_selector(selector):
|
||||
"""
|
||||
A basic method to determine if a selector is a link text selector.
|
||||
"""
|
||||
"""Determine if a selector is a link text selector."""
|
||||
if (
|
||||
selector.startswith("link=")
|
||||
or selector.startswith("link_text=")
|
||||
|
@ -50,9 +46,7 @@ def is_link_text_selector(selector):
|
|||
|
||||
|
||||
def is_partial_link_text_selector(selector):
|
||||
"""
|
||||
A basic method to determine if a selector is a partial link text selector.
|
||||
"""
|
||||
"""Determine if a selector is a partial link text selector."""
|
||||
if (
|
||||
selector.startswith("partial_link=")
|
||||
or selector.startswith("partial_link_text=")
|
||||
|
@ -66,18 +60,14 @@ def is_partial_link_text_selector(selector):
|
|||
|
||||
|
||||
def is_name_selector(selector):
|
||||
"""
|
||||
A basic method to determine if a selector is a name selector.
|
||||
"""
|
||||
"""Determine if a selector is a name selector."""
|
||||
if selector.startswith("name=") or selector.startswith("&"):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def get_link_text_from_selector(selector):
|
||||
"""
|
||||
A basic method to get the link text from a link text selector.
|
||||
"""
|
||||
"""Get the link text from a link text selector."""
|
||||
if selector.startswith("link="):
|
||||
return selector[len("link="):]
|
||||
elif selector.startswith("link_text="):
|
||||
|
@ -88,9 +78,7 @@ def get_link_text_from_selector(selector):
|
|||
|
||||
|
||||
def get_partial_link_text_from_selector(selector):
|
||||
"""
|
||||
A basic method to get the partial link text from a partial link selector.
|
||||
"""
|
||||
"""Get the partial link text from a partial link selector."""
|
||||
if selector.startswith("partial_link="):
|
||||
return selector[len("partial_link="):]
|
||||
elif selector.startswith("partial_link_text="):
|
||||
|
@ -107,9 +95,7 @@ def get_partial_link_text_from_selector(selector):
|
|||
|
||||
|
||||
def get_name_from_selector(selector):
|
||||
"""
|
||||
A basic method to get the name from a name selector.
|
||||
"""
|
||||
"""Get the name from a name selector."""
|
||||
if selector.startswith("name="):
|
||||
return selector[len("name="):]
|
||||
if selector.startswith("&"):
|
||||
|
@ -143,8 +129,7 @@ def is_valid_url(url):
|
|||
|
||||
|
||||
def _get_unique_links(page_url, soup):
|
||||
"""
|
||||
Returns all unique links.
|
||||
"""Returns all unique links.
|
||||
Includes:
|
||||
"a"->"href", "img"->"src", "link"->"href", and "script"->"src" links.
|
||||
"""
|
||||
|
@ -225,8 +210,7 @@ def _get_link_status_code(
|
|||
If the timeout is exceeded, will return a 404.
|
||||
If "verify" is False, will ignore certificate errors.
|
||||
For a list of available status codes, see:
|
||||
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
|
||||
"""
|
||||
https://en.wikipedia.org/wiki/List_of_HTTP_status_codes """
|
||||
status_code = None
|
||||
try:
|
||||
response = requests.head(
|
||||
|
@ -246,8 +230,7 @@ def _print_unique_links_with_status_codes(page_url, soup):
|
|||
and then prints out those links with their status codes.
|
||||
Format: ["link" -> "status_code"] (per line)
|
||||
Page links include those obtained from:
|
||||
"a"->"href", "img"->"src", "link"->"href", and "script"->"src".
|
||||
"""
|
||||
"a"->"href", "img"->"src", "link"->"href", and "script"->"src". """
|
||||
links = _get_unique_links(page_url, soup)
|
||||
for link in links:
|
||||
status_code = _get_link_status_code(link)
|
||||
|
|
|
@ -7,6 +7,7 @@ import re
|
|||
import string
|
||||
import sys
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
IS_POSIX = sys.platform.startswith(("darwin", "cygwin", "linux"))
|
||||
|
@ -137,8 +138,6 @@ class Patcher(object):
|
|||
"""
|
||||
:return: path to unpacked executable
|
||||
"""
|
||||
import zipfile
|
||||
|
||||
logger.debug("unzipping %s" % fp)
|
||||
try:
|
||||
os.unlink(self.zip_path)
|
||||
|
@ -147,12 +146,19 @@ class Patcher(object):
|
|||
os.makedirs(self.zip_path, mode=0o755, exist_ok=True)
|
||||
with zipfile.ZipFile(fp, mode="r") as zf:
|
||||
zf.extract(self.exe_name, self.zip_path)
|
||||
os.rename(
|
||||
os.path.join(self.zip_path, self.exe_name), self.executable_path
|
||||
)
|
||||
os.remove(fp)
|
||||
os.rmdir(self.zip_path)
|
||||
os.chmod(self.executable_path, 0o755)
|
||||
try:
|
||||
os.rename(
|
||||
os.path.join(self.zip_path, self.exe_name),
|
||||
self.executable_path,
|
||||
)
|
||||
os.remove(fp)
|
||||
except PermissionError:
|
||||
pass
|
||||
try:
|
||||
os.rmdir(self.zip_path)
|
||||
os.chmod(self.executable_path, 0o755)
|
||||
except PermissionError:
|
||||
pass
|
||||
return self.executable_path
|
||||
|
||||
@staticmethod
|
||||
|
@ -170,8 +176,6 @@ class Patcher(object):
|
|||
|
||||
@staticmethod
|
||||
def gen_random_cdc():
|
||||
import string
|
||||
|
||||
cdc = random.choices(string.ascii_lowercase, k=26)
|
||||
cdc[-6:-4] = map(str.upper, cdc[-6:-4])
|
||||
cdc[2] = cdc[0]
|
||||
|
@ -220,32 +224,40 @@ class Patcher(object):
|
|||
fh.write(file_bin)
|
||||
return True
|
||||
|
||||
def is_binary_patched_new(self, executable_path=None):
|
||||
executable_path = executable_path or self.executable_path
|
||||
with io.open(executable_path, "rb") as fh:
|
||||
return fh.read().find(b"undetected chromedriver") != -1
|
||||
@staticmethod
|
||||
def gen_random_cdc_beta():
|
||||
cdc = random.choices(string.ascii_letters, k=27)
|
||||
return "".join(cdc).encode()
|
||||
|
||||
def patch_exe_new(self):
|
||||
logger.info("patching driver executable %s" % self.executable_path)
|
||||
def is_binary_patched_beta(self, executable_path=None):
|
||||
executable_path = executable_path or self.executable_path
|
||||
try:
|
||||
with io.open(executable_path, "rb") as fh:
|
||||
return fh.read().find(b"undetected chromedriver") != -1
|
||||
except FileNotFoundError:
|
||||
return False
|
||||
|
||||
def patch_exe_beta(self):
|
||||
with io.open(self.executable_path, "r+b") as fh:
|
||||
content = fh.read()
|
||||
match_injected_codeblock = re.search(rb"{window.*;}", content)
|
||||
match_injected_codeblock = re.search(
|
||||
rb"\{window\.cdc.*?;\}", content
|
||||
)
|
||||
target_bytes = None
|
||||
if match_injected_codeblock:
|
||||
target_bytes = match_injected_codeblock[0]
|
||||
new_target_bytes = (
|
||||
b'{console.log("undetected chromedriver 1337!")}'.ljust(
|
||||
b'{console.log("chromedriver is undetectable!")}'.ljust(
|
||||
len(target_bytes), b" "
|
||||
)
|
||||
)
|
||||
if target_bytes:
|
||||
new_content = content.replace(target_bytes, new_target_bytes)
|
||||
if new_content == content:
|
||||
pass # Failure to patch driver
|
||||
pass # Unable to patch driver
|
||||
else:
|
||||
# Patch now
|
||||
fh.seek(0)
|
||||
fh.write(new_content)
|
||||
else:
|
||||
pass # Already patched
|
||||
|
||||
def __repr__(self):
|
||||
return "{0:s}({1:s})".format(
|
||||
|
|
Loading…
Reference in New Issue