Initial QSfera import
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
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']
|
||||
Reference in New Issue
Block a user