Repository: robocorp/rpaframework

Issue:
RPA.WINDOWS Click not successful but no error reported again
Ref to 901:
I have installed rpaframework 22.5.0 and repeated the robot but still i got the error

 
Start / End / Elapsed:	20230405 17:25:21.170 / 20230405 17:25:30.669 / 00:00:09.499
00:00:09.498ITERATION
Start / End / Elapsed:	20230405 17:25:21.170 / 20230405 17:25:30.668 / 00:00:09.498
00:00:09.491TRY
Start / End / Elapsed:	20230405 17:25:21.171 / 20230405 17:25:30.662 / 00:00:09.491
00:00:00.521KEYWORD RPA.Windows . Control Window ${Window}
00:00:00.005KEYWORD RPA.Windows . Click ${Group}
Documentation:	
Mouse click on element matching given locator.

Tags:	action, mouse
Start / End / Elapsed:	20230405 17:25:21.693 / 20230405 17:25:21.698 / 00:00:00.005
17:25:21.694	INFO	Getting element with locator: WindowsElement(item=<uiautomation.uiautomation.TreeItemControl object at 0x00000262E60FBCA0>, locator=None, name='SEMM03', automation_id='', control_type='TreeItemControl', class_name='', left=1151, right=1201, top=280, bottom=298, width=50, height=18, xcenter=1176, ycenter=289)	
17:25:21.695	INFO	Returning element: WindowsElement(item=<uiautomation.uiautomation.TreeItemControl object at 0x00000262E60FBCA0>, locator=None, name='SEMM03', automation_id='', control_type='TreeItemControl', class_name='', left=1151, right=1201, top=280, bottom=298, width=50, height=18, xcenter=1176, ycenter=289)	
17:25:21.697	INFO	2023-04-05 17:25:21.697 action.py[190] _ click_element -> Can not move cursor. TreeItemControl's 
                                                                                  ===================================
BoundingRectangle is (0,0,0,0)[0x0]. SearchProperties: {ControlType: TreeItemControl}	
00:00:01.916KEYWORD Output Tree Items ${Window}, ${Group}


What have I done wrong ?


Discussion:
Hi there @hhsem and thx for being so eager to test our latest library releases. Also your feedback provided so far was very valuable for us in order to develop the latest enhancements.

This "Can not move cursor." reported error in the logs is not something under our control and it is a known limitation expected to happen when using previously retrieved Windows elements after disturbing the automation or interacting with your keyboard/mouse during automation.
Luckily, you can use string locators and control the main app window before clicking elements in order to solve this. And as an extra safety measure, you can use a clicking helper which will test against this problem like so:
```robotframework
Click Group If Visible
    [Arguments]    ${name}

    ${group} =    Get Element    ${DATABASE} > name:"${name}"
    # Checks if the element is not visible (not having dimensions), thus not clickable
    #  for some reason. (when disturbing the automation)
    IF    ${group.width} <= ${0} or ${group.height} <= ${0}
        Fail    Group ${name} not clickable!
    END

    RPA.Windows.Click    ${group}    wait_time=${0.1}
```

Also, I enhanced your robot example automating KeePass in such a way it will avoid such issues by both using this helper and string locators. So please give it a try and let us know if it acts differently, even when you disturb the automation on purpose.

- Robot: https://github.com/cmin764/robots/tree/main/keepass-win
- Your enhanced task: `List Groups`
- Our newly added more robust task: `Iterate Groups`

#### Demo

<img width="1373" alt="Screenshot 2023-04-06 at 19 32 56" src="https://user-images.githubusercontent.com/709053/230352369-aecc07a8-ffc4-4b17-ab53-3f03bf738928.png">


https://user-images.githubusercontent.com/709053/230352460-cd7df00e-0658-4002-869e-da7398964b56.mov



Good luck and please close this Issue if it solves the problem!
Also replied on your Forum post [here](https://forum.robocorp.com/t/print-tree-with-return-structure-reports-an-error/2438/28?u=cosmin).

Resolving patch:
diff --git a/packages/windows/src/RPA/Windows/__init__.py b/packages/windows/src/RPA/Windows/__init__.py
--- a/packages/windows/src/RPA/Windows/__init__.py
+++ b/packages/windows/src/RPA/Windows/__init__.py
@@ -428,7 +428,7 @@ class           ClassName
     Check our Portal example in order to learn more abot the `path:` strategy in
     locators and how to record elements displaying their paths:
     https://robocorp.com/portal/robot/robocorp/example-windows-element-path
-    
+
     Video recorded demo on how to run the recorder script from VSCode:
     https://www.loom.com/share/2807372359f34b9cbe1bc2df9194ec68
 
@@ -461,18 +461,18 @@ class           ClassName
         *** Tasks ***
         Do some calculations
             [Setup]  Windows Run   calc.exe
-            
+
             Control Window    name:Calculator
             Click    id:clearButton
             Send Keys   keys=96+4=
             ${result} =    Get Attribute    id:CalculatorResults    Name
             Log To Console    ${result}
-            
+
             @{buttons} =  Get Elements  type:Group and name:"Number pad" > type:Button
             FOR  ${button}  IN  @{buttons}
                 Log To Console   ${button}
             END
-            
+
             [Teardown]   Close Current Window
 
     **Example: Python**
diff --git a/packages/windows/src/RPA/Windows/keywords/action.py b/packages/windows/src/RPA/Windows/keywords/action.py
--- a/packages/windows/src/RPA/Windows/keywords/action.py
+++ b/packages/windows/src/RPA/Windows/keywords/action.py
@@ -158,6 +158,14 @@ def _click_element(
             raise ActionNotPossible(
                 f"Element {element!r} does not have {click_type!r} attribute"
             )
+        # Get a new fresh bounding box each time, since the element might have been
+        #  moved from its initial spot.
+        rect = item.BoundingRectangle
+        if not rect or rect.width() == 0 or rect.height() == 0:
+            raise ActionNotPossible(
+                f"Element {element!r} is not visible for clicking, use a string"
+                " locator and ensure the root window is in focus"
+            )
 
         # Attribute added in `RPA.core.windows.locators.LocatorMethods`.
         offset: Optional[str] = getattr(item, "robocorp_click_offset", None)
@@ -165,9 +173,6 @@ def _click_element(
         offset_y: Optional[int] = None
         log_message = f"{click_type}-ing element"
         if offset:
-            # Get a new fresh bounding box each time, since the element might have been
-            #  moved from its initial spot.
-            rect = item.BoundingRectangle
             # Now compute the new coordinates starting from the element center.
             dist_x, dist_y = (int(dist.strip()) for dist in offset.split(","))
             pos_x, pos_y = rect.xcenter() + dist_x, rect.ycenter() + dist_y
@@ -196,20 +201,34 @@ def _click_element(
 
     @keyword(tags=["action"])
     def select(self, locator: Locator, value: str) -> WindowsElement:
-        """Select value on Control element if action is supported.
+        """Select a value on the passed element if such action is supported.
 
-        Exception ``ActionNotPossible`` is raised if element does not
-        allow Select action.
+        The ``ActionNotPossible`` exception is raised when the element does not allow
+        the `Select` action. This is usually used with combo box elements.
 
         :param locator: String locator or element object.
-        :param value: string value to select on Control element
-        :return: WindowsElement object
+        :param value: String value to select on Control element
+        :returns: The controlled Windows element.
 
-        Example:
+        **Example: Robot Framework**
 
-        .. code-block:: robotframework
+            *** Settings ***
+            Library     RPA.Windows
+
+            *** Tasks ***
+            Set Notepad Size
+                Select    id:FontSizeComboBox    22
+
+        **Example: Python**
+
+        .. code-block:: python
+
+            from RPA.Windows import Windows
+
+            lib = Windows()
 
-            Select  type:SelectControl   option2
+            def set_notepad_size():
+                lib.select("id:FontSizeComboBox", "22")
         """
         element = self.ctx.get_element(locator)
         if hasattr(element.item, "Select"):
@@ -221,7 +240,8 @@ def select(self, locator: Locator, value: str) -> WindowsElement:
             )
         else:
             raise ActionNotPossible(
-                f"Element {locator!r} does not support selection (try with `Set Value`)"
+                f"Element {locator!r} does not support selection (try with"
+                " `Set Value` instead)"
             )
         return element
 


Test patch:
diff --git a/packages/windows/tests/robot/test_windows.robot b/packages/windows/tests/robot/test_windows.robot
--- a/packages/windows/tests/robot/test_windows.robot
+++ b/packages/windows/tests/robot/test_windows.robot
@@ -236,21 +236,27 @@ Resize window with Spotify
     [Teardown]    Close Current Window
 
 Notepad write text into a file
-    Windows Run    notepad
+    [Setup]     Windows Run    notepad
+
     Control Window    ${LOC_NOTEPAD}
     ${ver} =    Get OS Version
     IF    "${ver}" == "11"
         Click    Edit    wait_time=0.5
         Click    Font    wait_time=0.5    # for some reason this only highlitghts the button
         Click    Font    wait_time=2    # and this finally clicks it
+
         Click    id:FontFamilyComboBox
         Send Keys   keys={DOWN}
         Send Keys   keys={Ctrl}a{Del}
         Send Keys   keys=Lucida Sans Unicode    send_enter=${True}    wait_time=0.5
-        Click    id:FontSizeComboBox
-        Send Keys   keys={DOWN}
-        Send Keys   keys={Ctrl}a{Del}
-        Send Keys   keys=26     send_enter=${True}    wait_time=0.5
+
+        Select  id:FontSizeComboBox     22
+        # If the Select above doesn't work.
+#        Click    id:FontSizeComboBox
+#        Send Keys   keys={DOWN}
+#        Send Keys   keys={Ctrl}a{Del}
+#        Send Keys   keys=22     send_enter=${True}    wait_time=0.5
+
         Click    name:"Back"
     ELSE
         Control Window    Font
@@ -278,6 +284,7 @@ Notepad write text into a file
         Click    Yes    wait_time=0.3
     END
     Minimize Window    ${LOC_NOTEPAD}
+
     [Teardown]    Close Current Window
 
 Control Window by handle