Skip to content

Commit

Permalink
added open test for windows 10 (#33)
Browse files Browse the repository at this point in the history
* added generation url for windows system

* Added tests for opening desktops on windows

* Added error_5.png
  • Loading branch information
l8556 authored Dec 17, 2024
1 parent 19830be commit 75e0089
Show file tree
Hide file tree
Showing 18 changed files with 227 additions and 56 deletions.
2 changes: 1 addition & 1 deletion frameworks/desktop/desktop_config.json
Original file line number Diff line number Diff line change
@@ -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'\""
}
14 changes: 8 additions & 6 deletions frameworks/desktop/desktop_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = (
Expand Down Expand Up @@ -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:
Expand All @@ -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')
Expand All @@ -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')
Expand Down
3 changes: 3 additions & 0 deletions frameworks/desktop/package/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

Expand Down
6 changes: 5 additions & 1 deletion frameworks/desktop/package/url_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand All @@ -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"
}
}
}
2 changes: 1 addition & 1 deletion frameworks/desktop/package/url_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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}"

Expand Down
17 changes: 16 additions & 1 deletion frameworks/host_control/FileUtils.py
Original file line number Diff line number Diff line change
@@ -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

Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions frameworks/host_control/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
from .FileUtils import FileUtils
from .host_info import HostInfo
from .windows import Window
7 changes: 7 additions & 0 deletions frameworks/host_control/windows/__init__.py
Original file line number Diff line number Diff line change
@@ -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
19 changes: 19 additions & 0 deletions frameworks/host_control/windows/linux_window.py
Original file line number Diff line number Diff line change
@@ -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
18 changes: 18 additions & 0 deletions frameworks/host_control/windows/window.py
Original file line number Diff line number Diff line change
@@ -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): ...
50 changes: 50 additions & 0 deletions frameworks/host_control/windows/windows_window.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# -*- 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]:
data = []

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()
):
data.append(hwnd)

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, data: list):
cls_name, text = win32gui.GetClassName(hwnd), win32gui.GetWindowText(hwnd)
if cls_name in child_window_title and child_window_text in text:
data.append(hwnd)

win32gui.EnumChildWindows(window_hwnd, find_button, data)
return data[0] if data else 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)



8 changes: 6 additions & 2 deletions frameworks/image_handler/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 6 additions & 4 deletions frameworks/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
85 changes: 49 additions & 36 deletions install_requirements.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,51 +3,64 @@
import re
import subprocess as sb

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
elif int(platform.python_version().rsplit(".", 1)[0].replace('.', '')) < 39:
version = old_system_package_version(package)
else:
version = re.sub(r'[*^]', '', version)
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 re.sub(r"[*^]", "", 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()
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pyvirtualdisplay = "*"
opencv-python = "*"
urllib3 = '*'
pillow = '*'
pywin32 = { version = "*", markers = "sys_platform == 'win32'" }


[build-system]
Expand Down
Binary file added tests/assets/image_template/errors/error_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions tests/assets/warning_window_info.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Default_app_window": {
"class_name": "#32770",
"window_text": "ONLYOFFICE Desktop Editors",
"button_class_name": "Button",
"button_text": "No"
}
}
Loading

0 comments on commit 75e0089

Please sign in to comment.