Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions optics_framework/api/action_keyword.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,14 @@ def _save_annotated_for_result(
return
element_source = getattr(result.strategy, "element_source", None)
if element_source is None or not hasattr(element_source, "get_bbox_for_element"):
internal_logger.warning(f"Element source {element_source} does not support get_bbox_for_element")
return
bbox = element_source.get_bbox_for_element(result.value)
if bbox is None:
internal_logger.debug(f"Could not get bbox for element {result.value} in {func_name}")
return
if screenshot_np is None:
internal_logger.debug(f"Could not get screenshot for element {result.value} in {func_name}")
return
framed = utils.annotate(screenshot_np.copy(), [bbox])
utils.save_screenshot(
Expand Down Expand Up @@ -207,7 +210,7 @@ def press_element(
self.driver.press_coordinates(
x + int(offset_x), y + int(offset_y), event_name)
else:
internal_logger.info(f"Pressing element '{element}'")
internal_logger.info(f"Pressing element '{element}' at {located}")
self.driver.press_element(located, int(repeat), event_name)

def press_by_percentage(self, percent_x: str, percent_y: str, repeat: str = "1", event_name: Optional[str] = None) -> None:
Expand Down Expand Up @@ -554,7 +557,7 @@ def press_keycode(self, keycode: str, event_name: Optional[str] = None) -> None:
except Exception as e:
internal_logger.error(f"Error capturing screenshot: {e}")

internal_logger.info(f"Pressing keycode: {keycode}")
internal_logger.info(f"Pressing keycode: {keycode}, {event_name}")
self.driver.press_keycode(keycode, event_name)


Expand Down
25 changes: 14 additions & 11 deletions optics_framework/common/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,10 @@

def get_timestamp():
try:
current_utc_time = datetime.now(timezone.utc)
desired_timezone = timezone(timedelta(hours=5, minutes=30))
current_time_in_desired_timezone = current_utc_time.astimezone(desired_timezone)
formatted_time = current_time_in_desired_timezone.strftime("%Y-%m-%dT%H:%M:%S.%f%z")
return formatted_time[:-2] + ":" + formatted_time[-2:]
ist = timezone(timedelta(hours=5, minutes=30))
now_ist = datetime.now(ist)
return now_ist.strftime("%Y-%m-%dT%H-%M-%S-%f")

except Exception as e:
internal_logger.error('Unable to get current time', exc_info=e)
return None
Expand Down Expand Up @@ -273,19 +272,23 @@
return
name = re.sub(r'[^a-zA-Z0-9\s_]', '', name)
if time_stamp is None:
time_stamp = str(datetime.now().astimezone().strftime('%Y-%m-%dT%H-%M-%S-%f'))
time_stamp = datetime.now().astimezone().strftime('%Y-%m-%dT%H-%M-%S-%f%z')

screenshot_file_path = os.path.join(output_dir, f"{time_stamp}-{name}.jpg")
try:
cv2.imwrite(screenshot_file_path, img)
internal_logger.debug(f'Screenshot saved as : {time_stamp}-{name}.jpg')
success = cv2.imwrite(screenshot_file_path, img)

if success:
internal_logger.debug(f"Screenshot saved as : {time_stamp}-{name}.jpg")
internal_logger.debug(f"Screenshot saved to :{screenshot_file_path}")
else:
internal_logger.error(f"cv2 returned FALSE. FAILED to save screenshot to : {screenshot_file_path}")
raise Exception(f"cv2 returned FALSE. FAILED to save screenshot to : {screenshot_file_path}")

Check warning on line 285 in optics_framework/common/utils.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Replace this generic exception class with a more specific one.

See more on https://sonarcloud.io/project/issues?id=mozarkai_optics-framework&issues=AZ0f2etUXafjTJA5U-7i&open=AZ0f2etUXafjTJA5U-7i&pullRequest=270

except Exception as e:
internal_logger.debug(f"Error writing screenshot to file : {e}")


def annotate(screenshot, bboxes):
# Iterate over each bounding box and annotate it on the image
internal_logger.debug(f"Bounding boxes {bboxes} to be annotated.")
for bbox in bboxes:
if bbox is None or len(bbox) != 2:
internal_logger.debug(f"Invalid bounding box: {bbox}")
Expand Down
11 changes: 8 additions & 3 deletions optics_framework/engines/drivers/appium.py
Original file line number Diff line number Diff line change
Expand Up @@ -910,9 +910,13 @@ def _flush_keyboard_buffer(self, driver: WebDriver, buffer: List[str]) -> None:

def _press_keycode_or_type_char(self, driver: WebDriver, ch: str, keycode: int) -> None:
"""Press keycode for char, or fall back to mobile:type on failure."""
internal_logger.debug(f"Pressing keycode for char '{ch}': {keycode}")
metastate = 1 if ch.isupper() else None
internal_logger.debug(f"Pressing keycode for char '{ch}': {keycode} (metastate={metastate})")
try:
driver.press_keycode(int(keycode))
if metastate is not None:
driver.press_keycode(int(keycode), metastate=metastate)
else:
driver.press_keycode(int(keycode))
except Exception:
internal_logger.debug(f"press_keycode failed for '{ch}', falling back to script typing")
driver.execute_script(
Expand Down Expand Up @@ -979,7 +983,8 @@ def get_char_as_keycode(self, char: str) -> Optional[int]:
"\n": 66, # Enter key
}

return mapping.get(char.lower()) # handle lowercase input
# Handle lowercase input so uppercase letters map to correct keycodes
return mapping.get(char.lower())

def get_text_element(self, element: Any) -> str:
text = element.get_attribute("text") or element.get_attribute("value")
Expand Down
Loading