Files
Курнат Андрей 2315f25754 Initial QSfera import
2026-06-07 10:20:04 +03:00

120 lines
3.2 KiB
Python

import pyautogui
import psutil
import threading
from appium.webdriver import Remote, WebElement
from appium.options.common.base import AppiumOptions
from appium.webdriver.common.appiumby import AppiumBy as By
from selenium.common.exceptions import WebDriverException, NoSuchElementException
from helpers.ConfigHelper import get_config, get_app_env
from helpers.ElementHelper import get_element_center_xy
from helpers.keys.keys_map import get_key
def native_click(self, **kwargs):
x, y = get_element_center_xy(self)
win_x, win_y = get_window_location()
if x < win_x:
x = x + win_x
if y < win_y:
y = y + win_y
pyautogui.click(x, y, **kwargs)
def native_double_click(self, **kwargs):
x, y = get_element_center_xy(self)
win_x, win_y = get_window_location()
if x < win_x:
x = x + win_x
if y < win_y:
y = y + win_y
pyautogui.doubleClick(x, y, **kwargs)
def native_send_keys(self, key):
pyautogui.press(get_key(key))
def find_element(self, by, selector):
"""
Returns a visible element.
Throws if no elements are found or if multiple visible elements are found.
"""
elements = self.find_elements(by, selector)
elements_count = len(elements)
if elements_count > 1:
visible_elements = [el for el in elements if el.is_displayed()]
if len(visible_elements) == 1:
return visible_elements.pop()
raise WebDriverException(
f'Found {elements_count} elements using "{by}={selector}"'
)
if elements_count == 0:
raise NoSuchElementException(f'No element found for "{by}={selector}"')
return elements[0]
def pause(self):
threading.Event().wait()
# bind custom element methods
Remote.find_element = find_element
Remote.pause = pause
WebElement.native_click = native_click
WebElement.native_double_click = native_double_click
WebElement.native_send_keys = native_send_keys
WebElement.find_element = find_element
app_driver = None
def app():
return app_driver
def create_app_session():
global app_driver
logfile = get_config("currentAppLogFile")
command_args = f' --logfile {logfile}'
options = AppiumOptions()
options.set_capability(
'app',
f'{get_config("app_path")} -s {command_args} --logdebug',
)
options.set_capability('appium:environ', get_app_env())
app_driver = Remote(command_executor='http://localhost:4723', options=options)
app_driver.implicitly_wait = 10
def close_and_kill_app():
"""
Close Appium session and kill the desktop client process.
Use this for both mid-scenario and end-of-scenario cleanup.
"""
global app_driver
# Quit Appium session
if app_driver is not None:
app_driver.quit()
# Kill remaining process by exe path
app_path = get_config("app_path")
for process in psutil.process_iter(['pid', 'exe']):
if process.info['exe'] == app_path:
print("Closing desktop client...")
psutil.Process(process.info['pid']).kill()
break
# Reset driver for reuse
app_driver = None
def get_window_location():
window = (
app()
.find_element(By.XPATH, "//*[contains(@name,'КуСфера')]")
.location
)
return window['x'], window['y']