2023-08-04 18:27:03 +00:00
|
|
|
import logging
|
|
|
|
import time
|
2023-09-05 06:22:44 +00:00
|
|
|
import typing
|
2023-08-04 18:27:03 +00:00
|
|
|
|
|
|
|
import allure
|
|
|
|
|
|
|
|
import configs
|
|
|
|
import driver
|
2023-10-31 10:53:49 +00:00
|
|
|
from gui import objects_map
|
2023-08-04 18:27:03 +00:00
|
|
|
from scripts.tools.image import Image
|
|
|
|
|
2023-12-01 13:58:22 +00:00
|
|
|
LOG = logging.getLogger(__name__)
|
2023-08-04 18:27:03 +00:00
|
|
|
|
|
|
|
|
2023-10-31 10:53:49 +00:00
|
|
|
class QObject:
|
2023-08-04 18:27:03 +00:00
|
|
|
|
2023-09-11 18:24:13 +00:00
|
|
|
def __init__(self, name, real_name: [str, dict] = None):
|
2023-10-31 10:53:49 +00:00
|
|
|
self.symbolic_name = name
|
|
|
|
if real_name:
|
|
|
|
self.real_name = real_name
|
|
|
|
else:
|
|
|
|
self.real_name = getattr(objects_map, name)
|
2023-08-04 18:27:03 +00:00
|
|
|
self._image = Image(self.real_name)
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f'{type(self).__qualname__}({self.symbolic_name})'
|
|
|
|
|
2023-10-31 10:53:49 +00:00
|
|
|
def __repr__(self):
|
|
|
|
return f'{type(self).__qualname__}({self.symbolic_name})'
|
|
|
|
|
2023-08-04 18:27:03 +00:00
|
|
|
@property
|
|
|
|
@allure.step('Get object {0}')
|
|
|
|
def object(self):
|
|
|
|
return driver.waitForObject(self.real_name, configs.timeouts.UI_LOAD_TIMEOUT_MSEC)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get object exists {0}')
|
|
|
|
def exists(self) -> bool:
|
|
|
|
return driver.object.exists(self.real_name)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get bounds {0}')
|
|
|
|
def bounds(self):
|
|
|
|
return driver.object.globalBounds(self.object)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get "x" coordinate {0}')
|
|
|
|
def x(self) -> int:
|
|
|
|
return self.bounds.x
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get "y" coordinate {0}')
|
|
|
|
def y(self) -> int:
|
|
|
|
return self.bounds.y
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get width {0}')
|
|
|
|
def width(self) -> int:
|
|
|
|
return int(self.bounds.width)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get height {0}')
|
|
|
|
def height(self) -> int:
|
|
|
|
return int(self.bounds.height)
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get central coordinate {0}')
|
|
|
|
def center(self):
|
|
|
|
return self.bounds.center()
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get enabled {0}')
|
|
|
|
def is_enabled(self) -> bool:
|
2023-11-15 08:42:17 +00:00
|
|
|
return getattr(self.object, 'enabled')
|
2023-08-04 18:27:03 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get selected {0}')
|
|
|
|
def is_selected(self) -> bool:
|
2023-11-15 08:42:17 +00:00
|
|
|
return getattr(self.object, 'selected')
|
2023-08-04 18:27:03 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get checked {0}')
|
|
|
|
def is_checked(self) -> bool:
|
2023-11-15 08:42:17 +00:00
|
|
|
return getattr(self.object, 'checked')
|
2023-08-04 18:27:03 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get visible {0}')
|
|
|
|
def is_visible(self) -> bool:
|
|
|
|
try:
|
2023-10-02 09:21:12 +00:00
|
|
|
return driver.waitForObject(self.real_name, 0).visible
|
2023-08-04 18:27:03 +00:00
|
|
|
except (AttributeError, LookupError, RuntimeError):
|
|
|
|
return False
|
|
|
|
|
|
|
|
@property
|
|
|
|
@allure.step('Get image {0}')
|
|
|
|
def image(self):
|
2023-08-29 14:43:00 +00:00
|
|
|
self._image.update_view()
|
2023-08-04 18:27:03 +00:00
|
|
|
return self._image
|
|
|
|
|
|
|
|
@allure.step('Click {0}')
|
|
|
|
def click(
|
|
|
|
self,
|
|
|
|
x: int = None,
|
|
|
|
y: int = None,
|
|
|
|
button=None
|
|
|
|
):
|
|
|
|
driver.mouseClick(
|
|
|
|
self.object,
|
|
|
|
x or self.width // 2,
|
|
|
|
y or self.height // 2,
|
|
|
|
button or driver.Qt.LeftButton
|
|
|
|
)
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.info('%s: clicked', self)
|
2023-08-04 18:27:03 +00:00
|
|
|
|
2023-12-05 13:23:02 +00:00
|
|
|
@allure.step('Native click {0}')
|
|
|
|
def native_click(
|
|
|
|
self,
|
|
|
|
x: typing.Union[int, driver.UiTypes.ScreenPoint] = None,
|
|
|
|
y: typing.Union[int, driver.UiTypes.ScreenPoint] = None,
|
|
|
|
button: driver.MouseButton = None
|
|
|
|
):
|
|
|
|
driver.nativeMouseClick(
|
|
|
|
x or self.bounds.x + self.width // 2,
|
|
|
|
y or self.bounds.y + self.height // 2,
|
|
|
|
button or driver.MouseButton.LeftButton
|
|
|
|
)
|
|
|
|
LOG.info(f'{self}: native clicked')
|
|
|
|
|
2023-08-04 18:27:03 +00:00
|
|
|
@allure.step('Hover {0}')
|
|
|
|
def hover(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC):
|
|
|
|
def _hover():
|
|
|
|
try:
|
|
|
|
driver.mouseMove(self.object)
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.info('%s: mouse hovered', self)
|
2023-08-04 18:27:03 +00:00
|
|
|
return getattr(self.object, 'hovered', True)
|
|
|
|
except RuntimeError as err:
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.error(err)
|
2023-08-04 18:27:03 +00:00
|
|
|
time.sleep(1)
|
|
|
|
return False
|
|
|
|
|
|
|
|
assert driver.waitFor(lambda: _hover(), timeout_msec)
|
2023-09-07 04:13:38 +00:00
|
|
|
return self
|
|
|
|
|
2023-09-05 06:22:44 +00:00
|
|
|
@allure.step('Open context menu')
|
|
|
|
def open_context_menu(
|
|
|
|
self,
|
|
|
|
x: typing.Union[int, driver.UiTypes.ScreenPoint] = None,
|
|
|
|
y: typing.Union[int, driver.UiTypes.ScreenPoint] = None,
|
|
|
|
):
|
|
|
|
self.click(
|
|
|
|
x or self.width // 2,
|
|
|
|
y or self.height // 2,
|
|
|
|
driver.Qt.RightButton
|
|
|
|
)
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.info('%s: clicked via Right Mouse Button', self)
|
2023-10-31 10:53:49 +00:00
|
|
|
|
|
|
|
@allure.step('Wait until appears {0}')
|
|
|
|
def wait_until_appears(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC):
|
|
|
|
assert driver.waitFor(lambda: self.is_visible, timeout_msec), f'Object {self} is not visible'
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.info('%s: is visible', self)
|
2023-10-31 10:53:49 +00:00
|
|
|
return self
|
|
|
|
|
|
|
|
@allure.step('Wait until hidden {0}')
|
|
|
|
def wait_until_hidden(self, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC):
|
|
|
|
assert driver.waitFor(lambda: not self.is_visible, timeout_msec), f'Object {self} is not hidden'
|
2023-12-04 18:16:52 +00:00
|
|
|
LOG.info('%s: is hidden', self)
|
2023-10-31 10:53:49 +00:00
|
|
|
|
|
|
|
@classmethod
|
|
|
|
def wait_for(cls, condition, timeout_msec: int = configs.timeouts.UI_LOAD_TIMEOUT_MSEC) -> bool:
|
|
|
|
return driver.waitFor(lambda: condition, timeout_msec)
|