Skip to content

Commit

Permalink
fix chrome driver (#539)
Browse files Browse the repository at this point in the history
* fix chrome driver for version >= 115
---------

Co-authored-by: s.pirohov <[email protected]>
  • Loading branch information
SergeyPirogov and s.pirohov authored Jul 22, 2023
1 parent f3af8a5 commit 8f3ab07
Show file tree
Hide file tree
Showing 17 changed files with 303 additions and 233 deletions.
29 changes: 19 additions & 10 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,39 +70,48 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install software-properties-common apt-transport-https wget curl
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
wget -q https://packages.microsoft.com/keys/microsoft.asc -O- | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://packages.microsoft.com/repos/edge stable main"
sudo apt-get update && sudo apt install microsoft-edge-beta
microsoft-edge --version
wget -qO- https://deb.opera.com/archive.key | sudo apt-key add -
sudo add-apt-repository "deb [arch=i386,amd64] https://deb.opera.com/opera-stable/ stable non-free"
sudo apt-get update
sudo apt-get -y --no-install-recommends install opera-stable
opera --version
sudo apt-get install chromium-browser
chromium --version
sudo curl -fsSLo /usr/share/keyrings/brave-browser-archive-keyring.gpg https://brave-browser-apt-release.s3.brave.com/brave-browser-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg arch=amd64] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list
sudo apt-get update
sudo apt-get install brave-browser
echo "deb [signed-by=/usr/share/keyrings/brave-browser-archive-keyring.gpg] https://brave-browser-apt-release.s3.brave.com/ stable main"|sudo tee /etc/apt/sources.list.d/brave-browser-release.list
sudo apt update
sudo apt install brave-browser
- name: Check browser versions on Linux
if: runner.os == 'Linux'
run: |
google-chrome --version
microsoft-edge --version
opera --version
chromium --version
brave-browser --version
- name: Install browsers on Windows
if: runner.os == 'Windows'
shell: powershell
run: |
choco install chromium opera brave --no-progress -y --force
choco install chromium opera brave googlechrome --no-progress -y --force
- name: Install browsers on MacOS
if: startsWith(runner.os, 'macOS')
run: |
brew tap domt4/chromium
brew update
brew install --cask mac-chromium opera brave-browser
brew upgrade google-chrome
- name: Install Python dependencies
run: |
Expand Down
5 changes: 3 additions & 2 deletions .github/workflows/test_xdist.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,9 @@ jobs:
sudo apt-get update
sudo apt-get install software-properties-common apt-transport-https wget curl
sudo apt-get install chromium-browser
chromium --version
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
sudo dpkg -i google-chrome-stable_current_amd64.deb
google-chrome --version
- name: Install Python dependencies
run: |
Expand Down
373 changes: 189 additions & 184 deletions Pipfile.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 3.8.6
current_version = 3.9.0
commit = True
tag = True

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
long_description_content_type="text/markdown",
packages=setuptools.find_packages(include=['webdriver_manager*']),
include_package_data=True,
version='3.8.6',
version='3.9.0',
description='Library provides the way to automatically manage drivers for different browsers',
author='Sergey Pirogov',
author_email='[email protected]',
Expand Down
10 changes: 1 addition & 9 deletions tests/test_brave_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ def test_brave_manager_with_specific_version():
assert os.path.exists(bin_path)


@pytest.mark.skip(reason='Brave version is strange on CI')
def test_brave_manager_with_selenium():
binary_location = {
OSType.LINUX: "/usr/bin/brave-browser",
Expand All @@ -45,15 +46,6 @@ def test_brave_manager_with_selenium():
driver.close()


def test_driver_can_be_saved_to_custom_path():
custom_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), "custom")

path = ChromeDriverManager(version="87.0.4280.88", path=custom_path,
chrome_type=ChromeType.BRAVE).install()
assert os.path.exists(path)
assert custom_path in path


def test_brave_manager_with_wrong_version():
with pytest.raises(ValueError) as ex:
ChromeDriverManager("0.2", chrome_type=ChromeType.BRAVE).install()
Expand Down
23 changes: 13 additions & 10 deletions tests/test_chrome_driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,32 @@

from webdriver_manager.chrome import ChromeDriverManager
from webdriver_manager.core.constants import ROOT_FOLDER_NAME
from selenium.webdriver.chrome.service import Service as ChromeService

os.environ.setdefault("WDM_LOCAL", "true")


def test_chrome_manager_with_cache(delete_drivers_dir):
ChromeDriverManager().install()
bin = ChromeDriverManager().install()
assert os.path.exists(bin)
driver_binary = ChromeDriverManager().install()
assert os.path.exists(driver_binary)


def test_chrome_manager_with_specific_version(delete_drivers_dir):
bin = ChromeDriverManager("87.0.4280.88").install()
assert os.path.exists(bin)
driver_binary = ChromeDriverManager("87.0.4280.88").install()
assert os.path.exists(driver_binary)


def test_106_0_5249_61_chrome_version(delete_drivers_dir):
bin = ChromeDriverManager("106.0.5249.61").install()
assert os.path.exists(bin)
driver_binary = ChromeDriverManager("106.0.5249.61").install()
assert os.path.exists(driver_binary)


def test_chrome_manager_with_project_root_local_folder(delete_drivers_dir):
os.environ['WDM_LOCAL'] = "1"
bin = ChromeDriverManager("87.0.4280.88").install()
driver_binary = ChromeDriverManager("87.0.4280.88").install()
os.environ['WDM_LOCAL'] = "0"
assert os.path.exists(bin)
assert os.path.exists(driver_binary)


def test_driver_can_be_saved_to_custom_path():
Expand All @@ -46,7 +49,7 @@ def test_chrome_manager_with_wrong_version():

def test_chrome_manager_with_selenium():
driver_path = ChromeDriverManager().install()
driver = webdriver.Chrome(driver_path)
driver = webdriver.Chrome(service=ChromeService(driver_path))
driver.get("http://automation-remarks.com")
driver.close()

Expand Down Expand Up @@ -83,6 +86,6 @@ def test_chrome_manager_cached_driver_with_selenium():


@pytest.mark.parametrize('os_type', ['win32', 'win64', 'mac64', 'mac64_m1'])
def test_can_get_chrome_for_win(os_type):
def test_can_get_chrome_for_os(os_type):
path = ChromeDriverManager(os_type=os_type).install()
assert os.path.exists(path)
6 changes: 3 additions & 3 deletions tests/test_downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

def test_can_download_driver_as_zip_file(delete_drivers_dir):
file = download_manager.download_file("http://chromedriver.storage.googleapis.com/2.26/chromedriver_win32.zip")
assert file.filename == "driver.zip"
assert file.filename == "chromedriver_win32.zip"
archive = save_file(file, DEFAULT_PROJECT_ROOT_CACHE_PATH)
assert archive.file_path == f"{DEFAULT_PROJECT_ROOT_CACHE_PATH}{os.sep}{file.filename}"
assert archive.unpack(DEFAULT_PROJECT_ROOT_CACHE_PATH) == ["chromedriver.exe"]
Expand All @@ -28,14 +28,14 @@ def test_can_download_driver_as_tar_gz(delete_drivers_dir):
assert archive.unpack(DEFAULT_PROJECT_ROOT_CACHE_PATH) == ["geckodriver"]


@pytest.mark.parametrize('version', ["2.26", None])
@pytest.mark.parametrize('version', ["2.26"])
def test_can_download_chrome_driver(delete_drivers_dir, version):
driver = ChromeDriver(name="chromedriver", version=version, os_type="win32",
url="http://chromedriver.storage.googleapis.com",
latest_release_url="http://chromedriver.storage.googleapis.com/LATEST_RELEASE",
chrome_type=ChromeType.GOOGLE, http_client=WDMHttpClient())

file = download_manager.download_file(driver.get_driver_download_url())
assert file.filename == "driver.zip"
assert file.filename == "chromedriver_win32.zip"
archive = save_file(file, DEFAULT_PROJECT_ROOT_CACHE_PATH)
assert "chromedriver.exe" in archive.unpack(DEFAULT_PROJECT_ROOT_CACHE_PATH)
2 changes: 1 addition & 1 deletion webdriver_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "3.8.6"
__version__ = "3.9.0"
3 changes: 2 additions & 1 deletion webdriver_manager/chrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,6 @@ def __init__(

def install(self) -> str:
driver_path = self._get_driver_path(self.driver)
os.chmod(driver_path, 0o755)
if all(test_os not in driver_path for test_os in ["mac_arm64", "mac_x64"]):
os.chmod(driver_path, 0o755)
return driver_path
12 changes: 12 additions & 0 deletions webdriver_manager/core/archive.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,18 @@ def __extract_zip(self, to_directory):
"Permission denied",
]:
raise e
file_names = []
for n in archive.namelist():
if "/" not in n:
file_names.append(n)
else:
file_path, file_name = n.split("/")
full_file_path = os.path.join(to_directory, file_path)
source = os.path.join(full_file_path, file_name)
destination = os.path.join(to_directory, file_name)
os.rename(source, destination)
file_names.append(file_name)
return sorted(file_names, key=lambda x: x.lower())
return archive.namelist()

def __extract_tar_file(self, to_directory):
Expand Down
15 changes: 14 additions & 1 deletion webdriver_manager/core/download_manager.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
from abc import ABC

from webdriver_manager.core.http import WDMHttpClient
Expand Down Expand Up @@ -26,4 +27,16 @@ def __init__(self, http_client=None):
def download_file(self, url: str) -> File:
log(f"About to download new driver from {url}")
response = self._http_client.get(url)
return File(response)
log(f"Driver downloading response is {response.status_code}")
file_name = self.extract_filename_from_url(url)
return File(response, file_name)

@staticmethod
def extract_filename_from_url(url):
# Split the URL by '/'
url_parts = url.split('/')
# Get the last part of the URL, which should be the filename
filename = url_parts[-1]
# Decode the URL-encoded filename
filename = os.path.basename(filename)
return filename
3 changes: 2 additions & 1 deletion webdriver_manager/core/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ def get_driver_version_to_download(self):
Downloads determined browser version driver in all other ways as a bonus fallback for lazy users.
"""
if not self._driver_to_download_version:
self._driver_to_download_version = self._version if self._version not in (None, "latest") else self.get_latest_release_version()
self._driver_to_download_version = self._version if self._version not in (None, "latest") \
else self.get_latest_release_version()
return self._driver_to_download_version

def get_latest_release_version(self):
Expand Down
5 changes: 5 additions & 0 deletions webdriver_manager/core/driver_cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,15 @@ def save_file_to_cache(self, driver: Driver, file: File):
return binary_path

def __get_binary(self, files, driver_name):
if not files:
raise Exception(f"Can't find binary for {driver_name} among {files}")

if len(files) == 1:
return files[0]

for f in files:
if 'LICENSE' in f:
continue
if driver_name in f:
return f

Expand Down
2 changes: 0 additions & 2 deletions webdriver_manager/core/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,5 @@ def get(self, url, **kwargs) -> Response:
except exceptions.ConnectionError:
raise ConnectionError(f"Could not reach host. Are you offline?")
self.validate_response(resp)
if wdm_progress_bar():
show_download_progress(resp)
return resp

16 changes: 10 additions & 6 deletions webdriver_manager/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,23 @@


class File(object):
def __init__(self, stream):
def __init__(self, stream, file_name):
self.content = stream.content
self.__stream = stream
self.file_name = file_name
self.__temp_name = "driver"
self.__regex_filename = r"""filename.+"(.+)"|filename.+''(.+)"""
self.__regex_filename = r"""filename.+"(.+)"|filename.+''(.+)|filename=([\w.-]+)"""

@property
def filename(self) -> str:
if self.file_name:
return self.file_name
try:
# filename = re.findall('filename.*"(.+)"', self.__stream.headers["content-disposition"])[0] # TODO delete this commented code after testing new block
content = self.__stream.headers["content-disposition"]

content_disposition_list = re.split(";", content)
filenames = [re.findall(self.__regex_filename, element) for element in content_disposition_list]
filename = next(filter(None, next(filter(None, next(filter(None, filenames)))))) # type: ignore
filename = next(filter(None, next(filter(None, next(filter(None, filenames))))))
except KeyError:
filename = f"{self.__temp_name}.zip"
except (IndexError, StopIteration):
Expand Down Expand Up @@ -61,9 +65,9 @@ class ChromeType(object):

PATTERN = {
ChromeType.CHROMIUM: r"\d+\.\d+\.\d+",
ChromeType.GOOGLE: r"\d+\.\d+\.\d+",
ChromeType.GOOGLE: r"\d+\.\d+\.\d+(\.\d+)?",
ChromeType.MSEDGE: r"\d+\.\d+\.\d+",
"brave-browser": r"(\d+)",
"brave-browser": r"\d+\.\d+\.\d+(\.\d+)?",
"firefox": r"(\d+.\d+)",
}

Expand Down
28 changes: 27 additions & 1 deletion webdriver_manager/drivers/chrome.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,45 @@ def get_driver_download_url(self):
if version.parse(driver_version_to_download) < version.parse("106.0.5249.61"):
os_type = os_type.replace("mac_arm64", "mac64_m1")

if version.parse(driver_version_to_download) >= version.parse("113"):
if os_type == "mac64":
os_type = "mac-x64"
if os_type in ["mac_64", "mac64_m1", "mac_arm64"]:
os_type = "mac-arm64"

modern_version_url = self.get_url_for_version_and_platform(driver_version_to_download, os_type)
log(f"Modern chrome version {modern_version_url}")
return modern_version_url

return f"{self._url}/{driver_version_to_download}/{self.get_name()}_{os_type}.zip"

def get_browser_type(self):
return self._browser_type

def get_latest_release_version(self):
determined_browser_version = self.get_browser_version_from_os()

log(f"Get LATEST {self._name} version for {self._browser_type}")
if version.parse(determined_browser_version) >= version.parse("113"):

This comment has been minimized.

Copy link
@david-engelmann

david-engelmann Jul 22, 2023

my testing broken when trying to use determined_browser_version with 113

return determined_browser_version

latest_release_url = (
self._latest_release_url
if (self._version == "latest" or determined_browser_version is None)
else f"{self._latest_release_url}_{determined_browser_version}"
)
resp = self._http_client.get(url=latest_release_url)
return resp.text.rstrip()

def get_url_for_version_and_platform(self, browser_version, platform):
url = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json"
response = self._http_client.get(url)
data = response.json()
versions = data["versions"]
for v in versions:
if v["version"] == browser_version:
downloads = v["downloads"]["chromedriver"]
for d in downloads:
if d["platform"] == platform:
return d["url"]

raise Exception(f"No such driver version {browser_version} for {platform}")

0 comments on commit 8f3ab07

Please sign in to comment.