From 86fcb59abb8c79687a6be7ac37df9ade12b6d050 Mon Sep 17 00:00:00 2001 From: l02 Date: Thu, 5 Dec 2024 17:50:44 +0300 Subject: [PATCH 01/12] added generation url for windows system --- frameworks/desktop/package/url_config.json | 6 +++++- frameworks/desktop/package/url_generator.py | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/frameworks/desktop/package/url_config.json b/frameworks/desktop/package/url_config.json index 6275019..a758979 100644 --- a/frameworks/desktop/package/url_config.json +++ b/frameworks/desktop/package/url_config.json @@ -5,7 +5,8 @@ "os_family": { "debian": ["debian", "ubuntu", "linuxmint", "pop"], "rhel": ["centos", "redos", "altlinux", "fedora"], - "suse": ["opensuse"] + "suse": ["opensuse"], + "inno": ["windows"] }, "package_name": { "debian": { @@ -19,6 +20,9 @@ "suse": { "package_cef107": "onlyoffice-desktopeditors-[version]~cef107.suse12.x86_64.rpm", "package": "onlyoffice-desktopeditors-[version].suse12.x86_64.rpm" + }, + "inno": { + "package": "ONLYOFFICE-DesktopEditors-[version]-x64.exe" } } } diff --git a/frameworks/desktop/package/url_generator.py b/frameworks/desktop/package/url_generator.py index a05243d..1181c93 100644 --- a/frameworks/desktop/package/url_generator.py +++ b/frameworks/desktop/package/url_generator.py @@ -44,7 +44,7 @@ def _os_family(self) -> str: @property def _version_for_url(self): - if self._os == 'windows': + if HostInfo().os == 'windows': return self.version.version return f"{self.version.major}.{self.version.minor}-{self.version.build}" From da3aaabde61310507af7250e865fc8fdc51095b0 Mon Sep 17 00:00:00 2001 From: l02 Date: Thu, 5 Dec 2024 18:02:56 +0300 Subject: [PATCH 02/12] Added tests for opening desktops on windows --- frameworks/desktop/desktop_config.json | 2 +- frameworks/desktop/desktop_editor.py | 14 ++++++++------ frameworks/desktop/package/package.py | 3 +++ frameworks/host_control/FileUtils.py | 17 ++++++++++++++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/frameworks/desktop/desktop_config.json b/frameworks/desktop/desktop_config.json index 7781f2f..7ef7fa7 100644 --- a/frameworks/desktop/desktop_config.json +++ b/frameworks/desktop/desktop_config.json @@ -1,5 +1,5 @@ { "linux_run_command": "onlyoffice-desktopeditors", "mac_run_command": "/Applications/ONLYOFFICE.app/Contents/MacOS/ONLYOFFICE", - "windows_run_command": "" + "windows_run_command": "powershell.exe \"& 'C:\\Program Files\\ONLYOFFICE\\DesktopEditors\\DesktopEditors.exe'\"" } diff --git a/frameworks/desktop/desktop_editor.py b/frameworks/desktop/desktop_editor.py index 901e5b5..9f43639 100644 --- a/frameworks/desktop/desktop_editor.py +++ b/frameworks/desktop/desktop_editor.py @@ -22,7 +22,7 @@ def __init__(self, data: Data): self.log_file = join(self.tmp_dir, "desktop.log") self.create_log_file() self.debug_command = '--ascdesktop-support-debug-info' - self.log_out_cmd = f'--ascdesktop-log-file={"stdout" if HostInfo().os != "windows" else self.log_file}' + self.log_out_cmd = f'--ascdesktop-log-file="stdout"' def open(self, file_path: str = None, debug_mode: bool = False, log_out_mode: bool = False) -> Popen: command = ( @@ -54,10 +54,7 @@ def wait_until_open( ) def get_version(self) -> "str | None": - version = re.findall( - r"\d+\.\d+\.\d+\.\d+", - FileUtils.output_cmd(f'{self._generate_running_command()} --version') - ) + version = re.findall(r"\d+\.\d+\.\d+\.\d+", FileUtils.output_cmd(self._generate_get_version_cmd())) return version[0] if version else None def _read_log(self, wait_msg: str, stdout_process: Popen) -> str: @@ -70,7 +67,6 @@ def _read_log(self, wait_msg: str, stdout_process: Popen) -> str: self.create_log_file() return line.strip() - def create_log_file(self): FileUtils.create_dir(dirname(self.log_file), stdout=False) FileUtils.file_writer(self.log_file, '', mode='w') @@ -88,6 +84,12 @@ def _generate_running_command(self): return run_cmd raise ValueError(f"[red]|ERROR| Can't get running command, key: {HostInfo().os}_run_command") + def _generate_get_version_cmd(self) -> str: + if self.os.lower() == 'windows': + path = re.search(r"'(.*?)'", self._generate_running_command()) + return f"powershell.exe (Get-Item '{path.group(1) if path else None}').VersionInfo.FileVersion" + return f'{self._generate_running_command()} --version' + @staticmethod def _get_config(path): config_path = path if path and isfile(path) else join(dirname(realpath(__file__)), 'desktop_config.json') diff --git a/frameworks/desktop/package/package.py b/frameworks/desktop/package/package.py index 87100b2..dd9454b 100644 --- a/frameworks/desktop/package/package.py +++ b/frameworks/desktop/package/package.py @@ -56,6 +56,9 @@ def _get_install_command( apt_get_installer: bool = False, custom_installer: str = None ) -> str: + if self.path.lower().endswith('.exe'): + return f'powershell.exe Start-Process {self.path} -ArgumentList "/silent", "/norestart" -Wait' + if custom_installer: return f"sudo {custom_installer} {self.path}" diff --git a/frameworks/host_control/FileUtils.py b/frameworks/host_control/FileUtils.py index 03b6244..987dc75 100644 --- a/frameworks/host_control/FileUtils.py +++ b/frameworks/host_control/FileUtils.py @@ -1,7 +1,8 @@ # -*- coding: utf-8 -*- import json from os import makedirs, walk -from os.path import isfile, isdir, join, basename, getsize +from os.path import isfile, isdir, join, basename, getsize, exists +from shutil import copyfile from subprocess import getoutput, Popen, PIPE from codecs import open as codecs_open @@ -53,6 +54,20 @@ def get_headers(url: str, stderr: bool = False): return None + @staticmethod + def copy( + path_from: str, + path_to: str, + stderr: bool = True, + ) -> None: + if not exists(path_from): + return print(f"[red]|WARNING| Path not exist: {path_from}") if stderr else None + + if isfile(path_from): + copyfile(path_from, path_to) + else: + return print(f"[red] Cant copy dir: {path_from}") + @staticmethod def download( url: str, From e9220a460dde0c67ae8975f8dc6be5abd4a86e52 Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 9 Dec 2024 16:36:28 +0300 Subject: [PATCH 03/12] Added tests for opening desktops on windows --- tests/desktop_tests.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/desktop_tests.py b/tests/desktop_tests.py index b16e94d..fce986f 100644 --- a/tests/desktop_tests.py +++ b/tests/desktop_tests.py @@ -138,10 +138,12 @@ def _write_results(self, exit_code: str): ) def _create_display(self, visible: bool = False, size: tuple = (1920, 1080)): - if self.virtual_display: + if self.virtual_display and HostInfo().os != 'windows': print("[green]|INFO| The test is running on the virtual display") self.display = Display(visible=visible, size=size) - self.display.start() + return self.display.start() + + self.virtual_display = False @staticmethod def _create_desktop(version: str, custom_config: str, license_file_path: str): From 1a54126878e730e09668390b1ec9ae8a886b1d4e Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 9 Dec 2024 18:20:35 +0300 Subject: [PATCH 04/12] Added tests for opening desktops on windows --- install_requirements.py | 10 +++++++++- pyproject.toml | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/install_requirements.py b/install_requirements.py index 99697b3..93caa8b 100644 --- a/install_requirements.py +++ b/install_requirements.py @@ -3,6 +3,8 @@ import re import subprocess as sb +from frameworks.host_control import HostInfo + requirements_file = 'requirements.txt' poetry_requirements = 'pyproject.toml' exceptions = ['python'] @@ -28,11 +30,17 @@ def create_requirements(): if isinstance(version, dict): if 'git' in version: write(f"git+{version.get('git')}@{version.get('branch')}", 'a') - continue + continue + if package.lower() == 'pywin32' and HostInfo().os == 'windows': + version = version.get('version') elif int(platform.python_version().rsplit(".", 1)[0].replace('.', '')) < 39: version = old_system_package_version(package) else: version = re.sub(r'[*^]', '', version) + + if package.lower() == 'pywin32' and HostInfo().os != 'windows': + continue + write(f"{package}{('==' + version) if version else ''}\n", 'a') def upgrade_pip(): diff --git a/pyproject.toml b/pyproject.toml index 606cf54..55a5f7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,6 +17,7 @@ pyvirtualdisplay = "*" opencv-python = "*" urllib3 = '*' pillow = '*' +pywin32 = { version = "*", markers = "sys_platform == 'win32'" } [build-system] From 40c0f99f88c828e60072a09da965d9734dc20ec3 Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 9 Dec 2024 18:26:10 +0300 Subject: [PATCH 05/12] Added tests for opening desktops on windows --- install_requirements.py | 93 ++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 44 deletions(-) diff --git a/install_requirements.py b/install_requirements.py index 93caa8b..8c55297 100644 --- a/install_requirements.py +++ b/install_requirements.py @@ -3,59 +3,64 @@ import re import subprocess as sb -from frameworks.host_control import HostInfo - -requirements_file = 'requirements.txt' -poetry_requirements = 'pyproject.toml' -exceptions = ['python'] +try: + import tomlkit +except ImportError: + sb.call("pip install tomlkit==0.11.6", shell=True) + import tomlkit -Python36 = { +OS = platform.system().lower() +REQUIREMENTS_FILE = "requirements.txt" +POETRY_FILE = "pyproject.toml" +EXCEPTIONS = {"python"} +PYTHON36_VERSIONS = { "opencv-python": "4.3.0.38", "rich": "12.6.0" } -def write(text, mode='w'): - with open(requirements_file, mode) as f: - f.write(text) - -def old_system_package_version(package): - for pkg, version in Python36.items(): - if package.lower() == pkg.lower(): - return version - return '' - -def create_requirements(): - with open(poetry_requirements) as t: - for package, version in tomlkit.parse(t.read())['tool']['poetry']['dependencies'].items(): - if package.lower() not in exceptions: - if isinstance(version, dict): - if 'git' in version: - write(f"git+{version.get('git')}@{version.get('branch')}", 'a') - continue - if package.lower() == 'pywin32' and HostInfo().os == 'windows': - version = version.get('version') - elif int(platform.python_version().rsplit(".", 1)[0].replace('.', '')) < 39: - version = old_system_package_version(package) - else: - version = re.sub(r'[*^]', '', version) - - if package.lower() == 'pywin32' and HostInfo().os != 'windows': - continue - - write(f"{package}{('==' + version) if version else ''}\n", 'a') + +def write_to_file(content, mode="w"): + with open(REQUIREMENTS_FILE, mode) as f: + f.write(content) + +def get_version_for_old_python(package): + return PYTHON36_VERSIONS.get(package.lower(), "") + +def get_dependency_version(package, version_info, is_old_python): + if isinstance(version_info, dict): + if "git" in version_info: + return f"git+{version_info['git']}@{version_info.get('branch', 'main')}" + if package.lower() == "pywin32": + return version_info.get("version", "") + elif is_old_python: + return get_version_for_old_python(package) + else: + return re.sub(r"[*^]", "", version_info) + return "" + +def generate_requirements(): + is_old_python = int(platform.python_version_tuple()[1]) < 9 # Python < 3.9 + + with open(POETRY_FILE, "r") as f: + poetry_data = tomlkit.parse(f.read()) + + dependencies = poetry_data.get("tool", {}).get("poetry", {}).get("dependencies", {}) + for package, version_info in dependencies.items(): + if package.lower() in EXCEPTIONS: + continue + + version = get_dependency_version(package, version_info, is_old_python) + if package.lower() == "pywin32" and OS != "windows": + continue + write_to_file(f"{package}=={version}\n" if version else f"{package}\n", "a") def upgrade_pip(): - sb.call('python -m pip install --upgrade pip', shell=True) + sb.call("python -m pip install --upgrade pip", shell=True) def install_requirements(): - sb.call(f'pip install -r {requirements_file}', shell=True) - -def install_tomlkit(): - sb.call('pip install tomlkit==0.11.6', shell=True) + sb.call(f"pip install -r {REQUIREMENTS_FILE}", shell=True) if __name__ == "__main__": - install_tomlkit() - import tomlkit upgrade_pip() - write('# -*- coding: utf-8 -*-\n', 'w') - create_requirements() + write_to_file("# -*- coding: utf-8 -*-\n", "w") # Очистка файла + generate_requirements() install_requirements() From b360bb0a51cbf09c22a0010fd518b146aff19ebd Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 9 Dec 2024 18:31:48 +0300 Subject: [PATCH 06/12] Added tests for opening desktops on windows --- install_requirements.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/install_requirements.py b/install_requirements.py index 8c55297..c00b0fa 100644 --- a/install_requirements.py +++ b/install_requirements.py @@ -30,7 +30,7 @@ def get_dependency_version(package, version_info, is_old_python): if "git" in version_info: return f"git+{version_info['git']}@{version_info.get('branch', 'main')}" if package.lower() == "pywin32": - return version_info.get("version", "") + return re.sub(r"[*^]", "", version_info.get("version", "")) elif is_old_python: return get_version_for_old_python(package) else: From 0b5ea2e3a3385f738da6662ac1f25e9a8c1812b0 Mon Sep 17 00:00:00 2001 From: l02 Date: Tue, 10 Dec 2024 14:55:41 +0300 Subject: [PATCH 07/12] Added tests for opening desktops on windows --- frameworks/host_control/__init__.py | 1 + frameworks/host_control/windows/__init__.py | 7 +++ .../host_control/windows/linux_window.py | 19 ++++++++ frameworks/host_control/windows/window.py | 18 +++++++ .../host_control/windows/windows_window.py | 48 +++++++++++++++++++ frameworks/test_data.py | 10 ++-- tests/assets/warning_window_info.json | 8 ++++ tests/desktop_tests.py | 19 +++++++- 8 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 frameworks/host_control/windows/__init__.py create mode 100644 frameworks/host_control/windows/linux_window.py create mode 100644 frameworks/host_control/windows/window.py create mode 100644 frameworks/host_control/windows/windows_window.py create mode 100644 tests/assets/warning_window_info.json diff --git a/frameworks/host_control/__init__.py b/frameworks/host_control/__init__.py index bf478ba..0155756 100644 --- a/frameworks/host_control/__init__.py +++ b/frameworks/host_control/__init__.py @@ -1,3 +1,4 @@ # -*- coding: utf-8 -*- from .FileUtils import FileUtils from .host_info import HostInfo +from .windows import Window diff --git a/frameworks/host_control/windows/__init__.py b/frameworks/host_control/windows/__init__.py new file mode 100644 index 0000000..0e42072 --- /dev/null +++ b/frameworks/host_control/windows/__init__.py @@ -0,0 +1,7 @@ +# -*- coding: utf-8 -*- +from frameworks.host_control import HostInfo + +if HostInfo().os == 'windows': + from .windows_window import WindowsWindow as Window +else: + from .linux_window import LinuxWindow as Window diff --git a/frameworks/host_control/windows/linux_window.py b/frameworks/host_control/windows/linux_window.py new file mode 100644 index 0000000..cb4f277 --- /dev/null +++ b/frameworks/host_control/windows/linux_window.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +from typing import Optional + +from .window import Window + + +class LinuxWindow(Window): + + @staticmethod + def get_hwnd(class_name: str, text: str) -> Optional[int]: + pass + + @staticmethod + def get_child_window_hwnd(window_hwnd: int, child_window_title: str, child_window_text: str) -> Optional[int]: + pass + + @staticmethod + def click_on_button(button_hwnd: int): + pass diff --git a/frameworks/host_control/windows/window.py b/frameworks/host_control/windows/window.py new file mode 100644 index 0000000..d6637dc --- /dev/null +++ b/frameworks/host_control/windows/window.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- +from abc import ABC, abstractmethod +from typing import Optional + + +class Window(ABC): + + @staticmethod + @abstractmethod + def get_hwnd(class_name: str, text: str) -> Optional[int]: ... + + @staticmethod + @abstractmethod + def get_child_window_hwnd(window_hwnd: int, child_window_title: str, child_window_text: str) -> Optional[int]: ... + + @staticmethod + @abstractmethod + def click_on_button(button_hwnd: int): ... diff --git a/frameworks/host_control/windows/windows_window.py b/frameworks/host_control/windows/windows_window.py new file mode 100644 index 0000000..f8eba1d --- /dev/null +++ b/frameworks/host_control/windows/windows_window.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +from typing import Optional + +from .window import Window + +try: + import win32gui + import win32con +except ImportError: + pass + + +class WindowsWindow(Window): + + @staticmethod + def get_hwnd(class_name: str, text: str) -> Optional[int]: + + def enum_windows_callback(hwnd: int): + if win32gui.IsWindowVisible(hwnd): + if ( + class_name.strip() == win32gui.GetClassName(hwnd).strip() + and text.strip() == win32gui.GetWindowText(hwnd).strip() + ): + return hwnd + + win32gui.EnumWindows(enum_windows_callback) + return None + + @staticmethod + def get_child_window_hwnd(window_hwnd: int, child_window_title: str, child_window_text: str) -> Optional[int]: + + def find_button(hwnd): + cls_name, text = win32gui.GetClassName(hwnd), win32gui.GetWindowText(hwnd) + if cls_name in child_window_title and child_window_text in text: + return hwnd + + win32gui.EnumChildWindows(window_hwnd, find_button) + return None + + @staticmethod + def click_on_button(button_hwnd: int): + try: + win32gui.SendMessage(button_hwnd, win32con.BM_CLICK, 0, 0) + except Exception as ex: + print(ex) + + + diff --git a/frameworks/test_data.py b/frameworks/test_data.py index 0aabae0..99baf76 100644 --- a/frameworks/test_data.py +++ b/frameworks/test_data.py @@ -12,9 +12,11 @@ class TestData: project_dir: str = getcwd() tmp_dir: str = join(project_dir, 'tmp') reports_dir: str = join(project_dir, 'reports') - img_template: str = join(project_dir, 'tests', 'assets', 'image_template') - bad_files_dir: str = join(project_dir, 'tests', 'assets', 'bad_files') - good_files_dir: str = join(project_dir, 'tests', 'assets', 'good_files') - lic_file_path: str = join(project_dir, 'tests', 'assets', 'test_lic.lickey') + test_assets: str = join(project_dir, 'tests', 'assets') + img_template: str = join(test_assets, 'image_template') + bad_files_dir: str = join(test_assets, 'bad_files') + good_files_dir: str = join(test_assets, 'good_files') + lic_file_path: str = join(test_assets, 'test_lic.lickey') config: json = FileUtils.read_json(join(project_dir, 'config.json')) cache_dir: str = config.get("cache_dir", None) + warning_window_info: str = join(test_assets, "warning_window_info.json") diff --git a/tests/assets/warning_window_info.json b/tests/assets/warning_window_info.json new file mode 100644 index 0000000..eb32e50 --- /dev/null +++ b/tests/assets/warning_window_info.json @@ -0,0 +1,8 @@ +{ + "Default_app_window": { + "class_name": "#32770", + "window_text": "ONLYOFFICE Desktop Editors", + "button_class_name": "Button", + "button_text": "No" + } +} \ No newline at end of file diff --git a/tests/desktop_tests.py b/tests/desktop_tests.py index fce986f..1a0bc4b 100644 --- a/tests/desktop_tests.py +++ b/tests/desktop_tests.py @@ -9,7 +9,7 @@ from frameworks.desktop import DesktopEditor, DesktopData, DesktopException, UrlException, PackageException from frameworks.test_data import TestData -from frameworks.host_control import FileUtils, HostInfo +from frameworks.host_control import FileUtils, HostInfo, Window from frameworks.image_handler import Image from tests.tools.desktop_report import DesktopReport @@ -18,6 +18,8 @@ class TestException(Exception): ... class DesktopTests: + warning_window_info = FileUtils.read_json(TestData.warning_window_info) + def __init__( self, version: str, @@ -101,6 +103,7 @@ def check_correct_version(self): raise TestException(f"[red]|ERROR| The version is not correct: {version}") def check_error_on_screen(self): + self._close_warning_window() for error_img in FileUtils.get_paths(join(self.img_dir, 'errors')): if Image.is_present(error_img): Image.make_screenshot(join(self.report.dir, f'{self.version}_{self.host_name}_error_screen.png')) @@ -160,3 +163,17 @@ def _create_desktop(version: str, custom_config: str, license_file_path: str): def _report_path(self): title = self.config.get('title', 'Undefined_title') return join(TestData.reports_dir, title, self.version, f"{self.version}_{title}_report.csv") + + def _close_warning_window(self) -> None: + if HostInfo().os != 'windows': + return + + window = Window() + for info in self.warning_window_info.values(): + window_hwnd = window.get_hwnd(info.get('class_name', ''), info.get('window_text', '')) + if not window_hwnd: + continue + + button_hwnd = window.get_child_window_hwnd(window_hwnd, info.get('Button', ''), info.get('button_text', '')) + if button_hwnd: + window.click_on_button(button_hwnd) From c725f853f73fa19af7c6bafe5170942523d6d12c Mon Sep 17 00:00:00 2001 From: l02 Date: Tue, 10 Dec 2024 16:02:03 +0300 Subject: [PATCH 08/12] Added tests for opening desktops on windows --- .../host_control/windows/windows_window.py | 18 ++++++++++-------- tests/desktop_tests.py | 10 ++++++---- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/frameworks/host_control/windows/windows_window.py b/frameworks/host_control/windows/windows_window.py index f8eba1d..7d151e7 100644 --- a/frameworks/host_control/windows/windows_window.py +++ b/frameworks/host_control/windows/windows_window.py @@ -14,28 +14,30 @@ class WindowsWindow(Window): @staticmethod def get_hwnd(class_name: str, text: str) -> Optional[int]: + data = [] - def enum_windows_callback(hwnd: int): + def enum_windows_callback(hwnd: int, data: list): if win32gui.IsWindowVisible(hwnd): if ( class_name.strip() == win32gui.GetClassName(hwnd).strip() and text.strip() == win32gui.GetWindowText(hwnd).strip() ): - return hwnd + data.append(hwnd) - win32gui.EnumWindows(enum_windows_callback) - return None + win32gui.EnumWindows(enum_windows_callback, data) + return data[0] if data else None @staticmethod def get_child_window_hwnd(window_hwnd: int, child_window_title: str, child_window_text: str) -> Optional[int]: + data = [] - def find_button(hwnd): + def find_button(hwnd, data: list): cls_name, text = win32gui.GetClassName(hwnd), win32gui.GetWindowText(hwnd) if cls_name in child_window_title and child_window_text in text: - return hwnd + data.append(hwnd) - win32gui.EnumChildWindows(window_hwnd, find_button) - return None + win32gui.EnumChildWindows(window_hwnd, find_button, data) + return data[0] if data else None @staticmethod def click_on_button(button_hwnd: int): diff --git a/tests/desktop_tests.py b/tests/desktop_tests.py index 1a0bc4b..21d2d31 100644 --- a/tests/desktop_tests.py +++ b/tests/desktop_tests.py @@ -165,15 +165,17 @@ def _report_path(self): return join(TestData.reports_dir, title, self.version, f"{self.version}_{title}_report.csv") def _close_warning_window(self) -> None: - if HostInfo().os != 'windows': - return - window = Window() for info in self.warning_window_info.values(): window_hwnd = window.get_hwnd(info.get('class_name', ''), info.get('window_text', '')) if not window_hwnd: continue - button_hwnd = window.get_child_window_hwnd(window_hwnd, info.get('Button', ''), info.get('button_text', '')) + button_hwnd = window.get_child_window_hwnd( + window_hwnd, + info.get('button_class_name', ''), + info.get('button_text', '') + ) + if button_hwnd: window.click_on_button(button_hwnd) From b6902ea565e8a067a74c6f3280290ae1cb3eb03f Mon Sep 17 00:00:00 2001 From: l02 Date: Tue, 10 Dec 2024 16:02:46 +0300 Subject: [PATCH 09/12] Added tests for opening desktops on windows --- tests/desktop_tests.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/desktop_tests.py b/tests/desktop_tests.py index 21d2d31..3708aa5 100644 --- a/tests/desktop_tests.py +++ b/tests/desktop_tests.py @@ -166,8 +166,10 @@ def _report_path(self): def _close_warning_window(self) -> None: window = Window() + for info in self.warning_window_info.values(): window_hwnd = window.get_hwnd(info.get('class_name', ''), info.get('window_text', '')) + if not window_hwnd: continue From 5c3a9d412a929e08617bb63dd7730b66dce208b0 Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 16 Dec 2024 15:59:15 +0300 Subject: [PATCH 10/12] Added error_5.png --- tests/assets/image_template/errors/error_5.png | Bin 0 -> 3333 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/assets/image_template/errors/error_5.png diff --git a/tests/assets/image_template/errors/error_5.png b/tests/assets/image_template/errors/error_5.png new file mode 100644 index 0000000000000000000000000000000000000000..b79a3693fbdd77e27e6f22e3be8c49270c17ab52 GIT binary patch literal 3333 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 P00000NkvXXu0mjf-B*+M literal 0 HcmV?d00001 From 280e13c7684fc0e7595e904f832599cf3bb22363 Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 16 Dec 2024 16:00:05 +0300 Subject: [PATCH 11/12] Added error_5.png --- tests/assets/image_template/errors/error_5.png | Bin 3333 -> 460 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/assets/image_template/errors/error_5.png b/tests/assets/image_template/errors/error_5.png index b79a3693fbdd77e27e6f22e3be8c49270c17ab52..7bd670b7e9de5dcacb596e8edf430c3e128f573e 100644 GIT binary patch delta 428 zcmV;d0aN~k8q5QKiBL{Q4GJ0x0000DNk~Le0000h0000j2m$~A0JvraiU0rsb4f%& zR9J=Wm&;89K@33C0tBI4P((tc1rZ3^0w{n6=zz@06C+(Q9e;R%aXl>N-t znjnqk!~Vv8YkOuqgEF-YQUhdyOyEawd$V|$7ca%h>umIYF+KX49H3lq%R^rAffm8t z;tC()vS0a(k7E+>TTka>8{gadcyVeI4>JK)-p`I*-HS5N2w@<&zrNf|4*lGVG8`kG z1mFj{uOWIO(Mb>ze5Z7D5Jn8LW3VEwn_X%Mh5mi zUy12wWBL_IbyaS<+smD)+=ty6p`nQD-mOC^f2*O2*QHe+U7A3APKV*{G2+vyiqL2W zLNMIFTdyPGosOR1I}iwjM`1=gwbjC0vRo%t(NC@;+rn?Lvf_h1rp^u*-12a#dU{uq WOppmOfyfUh^CId4vetf+*$gZ$9>8z_ literal 3333 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 P00000NkvXXu0mjf-B*+M From 60a90b67a0592caad672dd84f305857a566317cf Mon Sep 17 00:00:00 2001 From: l02 Date: Mon, 16 Dec 2024 16:13:31 +0300 Subject: [PATCH 12/12] Added error_5.png --- frameworks/image_handler/image.py | 8 ++++++-- tests/desktop_tests.py | 3 ++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/frameworks/image_handler/image.py b/frameworks/image_handler/image.py index 57331f0..14be4df 100644 --- a/frameworks/image_handler/image.py +++ b/frameworks/image_handler/image.py @@ -29,9 +29,13 @@ def find_template_on_window( return None @staticmethod - def is_present(template_path: str, window_coordinates: tuple = None, threshold: "int | float" = 0.8) -> bool: + def is_present( + template: "str | cv2.imread", + window_coordinates: tuple = None, + threshold: "int | float" = 0.8 + ) -> bool: window = cv2.cvtColor(Image.grab_coordinate(window_coordinates), cv2.COLOR_BGR2GRAY) - template = cv2.cvtColor(cv2.imread(template_path), cv2.COLOR_BGR2GRAY) + template = cv2.cvtColor(cv2.imread(template) if isinstance(template, str) else template, cv2.COLOR_BGR2GRAY) _, max_val, _, _ = cv2.minMaxLoc(cv2.matchTemplate(window, template, cv2.TM_CCOEFF_NORMED)) return True if max_val >= threshold else False diff --git a/tests/desktop_tests.py b/tests/desktop_tests.py index 3708aa5..a63a3ea 100644 --- a/tests/desktop_tests.py +++ b/tests/desktop_tests.py @@ -42,6 +42,7 @@ def __init__( self.good_files = TestData.good_files_dir self.desktop = self._create_desktop(self.version, custom_config, license_file_path) self.old_desktop = self._create_desktop(update_from, custom_config, license_file_path) if update_from else None + self.error_images = [Image.read(img_path=path) for path in FileUtils.get_paths(join(self.img_dir, 'errors'))] FileUtils.create_dir(self.report.dir, stdout=False) def open_test(self): @@ -104,7 +105,7 @@ def check_correct_version(self): def check_error_on_screen(self): self._close_warning_window() - for error_img in FileUtils.get_paths(join(self.img_dir, 'errors')): + for error_img in self.error_images: if Image.is_present(error_img): Image.make_screenshot(join(self.report.dir, f'{self.version}_{self.host_name}_error_screen.png')) self._write_results('ERROR')