Improve mobile element highlighting and rectangle accuracy#4480
Conversation
Enhances reliability of UI element highlighting and rectangle drawing, especially for Android automation. Ensures up-to-date element details are used, validates and refreshes element bounds before drawing overlays, and preserves correct element identity for web highlights. Adds error handling and makes driver highlight requests more robust, addressing issues with invalid rectangles and incorrect element selection in live spy and mobile scenarios.
WalkthroughThe pull request enhances element handling in mobile and POM automation workflows. Key changes include capturing enriched element instances returned by Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Not up to standards ⛔
|
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Ginger/Ginger/AutomatePageLib/AddActionMenu/LiveSpy/LiveSpyPage.xaml.cs`:
- Line 269: The code calls LearnElementInfoDetails on
xWindowSelectionUC.mWindowExplorerDriver causing potential reference drift;
replace that call to use the active field mWindowExplorerDriver instead (i.e.,
call mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement)) so the single
source of truth is used; ensure the existing null/guard check around
mWindowExplorerDriver remains in place before invoking LearnElementInfoDetails.
In
`@Ginger/Ginger/AutomatePageLib/AddActionMenu/WindowExplorer/Common/WindowExplorerPage.xaml.cs`:
- Around line 1501-1504: The catch blocks currently logging exceptions with
Reporter.ToLog at eLogLevel.DEBUG are error paths and should be changed to
eLogLevel.ERROR; update the Reporter.ToLog calls inside
DrawElementRectangleAsync (the catch around UpdateElementInfoFields) and the
other two catch blocks referenced (around lines 1635–1644) to use
eLogLevel.ERROR instead of eLogLevel.DEBUG so failures are logged as errors;
keep the same message and exception parameter when replacing the log level for
Reporter.ToLog.
In
`@Ginger/GingerCoreNET/Drivers/CoreDrivers/Mobile/Appium/GenericAppiumDriver.cs`:
- Around line 1804-1814: The code is using ei.Properties.FirstOrDefault(...) to
read a cached "bounds" which can be stale; change the logic in
GenericAppiumDriver (where boundsAttr is set) and in
GetLocationAndSizeOfElement()/EnsureDeviceBounds() to prefer the live value from
the IWebElement: always call we.GetAttribute("bounds") when ei.ElementObject is
an IWebElement and use that result (falling back to ei.Properties only if
GetAttribute returns null/empty), then write the fresh bounds back into
ei.Properties["bounds"] (update existing key or add) so subsequent reads reflect
the latest rectangle and duplicate stale values are not preserved.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: b038127a-27da-4deb-937d-1bb86411ff69
📒 Files selected for processing (4)
Ginger/Ginger/ApplicationModelsLib/POMModels/PomAllElementsPage.xaml.csGinger/Ginger/AutomatePageLib/AddActionMenu/LiveSpy/LiveSpyPage.xaml.csGinger/Ginger/AutomatePageLib/AddActionMenu/WindowExplorer/Common/WindowExplorerPage.xaml.csGinger/GingerCoreNET/Drivers/CoreDrivers/Mobile/Appium/GenericAppiumDriver.cs
| // Learn details (fills properties/locators) | ||
| xWindowSelectionUC.mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement); | ||
| // Learn details (fills properties/locators) and keep enriched instance if returned | ||
| var learnedElement = xWindowSelectionUC.mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement); |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
Use the active driver field for element learning to avoid reference drift.
Line 269 calls LearnElementInfoDetails via xWindowSelectionUC.mWindowExplorerDriver while this flow is guarded by mWindowExplorerDriver. Prefer a single source of truth here to avoid null/out-of-sync edge failures.
Suggested change
- var learnedElement = xWindowSelectionUC.mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement);
+ var learnedElement = mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement);📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| var learnedElement = xWindowSelectionUC.mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement); | |
| var learnedElement = mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement); |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Ginger/Ginger/AutomatePageLib/AddActionMenu/LiveSpy/LiveSpyPage.xaml.cs` at
line 269, The code calls LearnElementInfoDetails on
xWindowSelectionUC.mWindowExplorerDriver causing potential reference drift;
replace that call to use the active field mWindowExplorerDriver instead (i.e.,
call mWindowExplorerDriver.LearnElementInfoDetails(mSpyElement)) so the single
source of truth is used; ensure the existing null/guard check around
mWindowExplorerDriver remains in place before invoking LearnElementInfoDetails.
| catch (Exception exUpd) | ||
| { | ||
| Reporter.ToLog(eLogLevel.DEBUG, "DrawElementRectangleAsync: UpdateElementInfoFields failed before rectangle draw: " + exUpd.Message, exUpd); | ||
| } |
There was a problem hiding this comment.
Use ERROR level in these exception paths.
Line 1503, Line 1637, and Line 1644 log caught failures with DEBUG. These are error paths and should use eLogLevel.ERROR for consistency and alerting fidelity.
Suggested change
- Reporter.ToLog(eLogLevel.DEBUG, "DrawElementRectangleAsync: UpdateElementInfoFields failed before rectangle draw: " + exUpd.Message, exUpd);
+ Reporter.ToLog(eLogLevel.ERROR, "DrawElementRectangleAsync: UpdateElementInfoFields failed before rectangle draw: " + exUpd.Message, exUpd);
- Reporter.ToLog(eLogLevel.DEBUG, "Driver HighLightElement failed", ex);
+ Reporter.ToLog(eLogLevel.ERROR, "Driver HighLightElement failed", ex);
- Reporter.ToLog(eLogLevel.DEBUG, "Request to driver highlight element failed", ex);
+ Reporter.ToLog(eLogLevel.ERROR, "Request to driver highlight element failed", ex);As per coding guidelines: **/*.cs: Use Reporter.ToLog(eLogLevel.ERROR, message) for logging errors.
Also applies to: 1635-1644
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@Ginger/Ginger/AutomatePageLib/AddActionMenu/WindowExplorer/Common/WindowExplorerPage.xaml.cs`
around lines 1501 - 1504, The catch blocks currently logging exceptions with
Reporter.ToLog at eLogLevel.DEBUG are error paths and should be changed to
eLogLevel.ERROR; update the Reporter.ToLog calls inside
DrawElementRectangleAsync (the catch around UpdateElementInfoFields) and the
other two catch blocks referenced (around lines 1635–1644) to use
eLogLevel.ERROR instead of eLogLevel.DEBUG so failures are logged as errors;
keep the same message and exception parameter when replacing the log level for
Reporter.ToLog.
| string boundsAttr = ei.Properties? | ||
| .FirstOrDefault(p => string.Equals(p.Name, "bounds", StringComparison.InvariantCultureIgnoreCase)) | ||
| ?.Value; | ||
| if (ei.ElementObject is IWebElement we) | ||
| { | ||
| try | ||
| { | ||
| boundsAttr = we.GetAttribute("bounds"); | ||
| if (string.IsNullOrEmpty(boundsAttr)) | ||
| { | ||
| boundsAttr = we.GetAttribute("bounds"); | ||
| } |
There was a problem hiding this comment.
Refresh bounds from the live element, not the first cached property.
This now prefers ei.Properties["bounds"], but EnsureDeviceBounds() also writes "bounds" back into ei.Properties. On a reused ElementInfo, FirstOrDefault() keeps returning the oldest rectangle, and GetLocationAndSizeOfElement() also keeps the first duplicate, so the highlight can stay stale after a refresh.
💡 Suggested fix
- string boundsAttr = ei.Properties?
- .FirstOrDefault(p => string.Equals(p.Name, "bounds", StringComparison.InvariantCultureIgnoreCase))
- ?.Value;
+ string boundsAttr = null;
if (ei.ElementObject is IWebElement we)
{
try
{
- if (string.IsNullOrEmpty(boundsAttr))
- {
- boundsAttr = we.GetAttribute("bounds");
- }
+ boundsAttr = we.GetAttribute("bounds");
}
catch { boundsAttr = null; }
}
+
+ if (string.IsNullOrEmpty(boundsAttr))
+ {
+ boundsAttr = ei.Properties?
+ .LastOrDefault(p => string.Equals(p.Name, "bounds", StringComparison.InvariantCultureIgnoreCase))
+ ?.Value;
+ }- if (ei.Properties == null) ei.Properties = new ObservableList<ControlProperty>();
- ei.Properties.Add(new ControlProperty() { Name = "bounds", Value = $"[{l},{t}][{r},{b}]" });
+ if (ei.Properties == null) ei.Properties = new ObservableList<ControlProperty>();
+ var existingBounds = ei.Properties
+ .FirstOrDefault(p => string.Equals(p.Name, "bounds", StringComparison.InvariantCultureIgnoreCase));
+ if (existingBounds != null)
+ {
+ existingBounds.Value = $"[{l},{t}][{r},{b}]";
+ }
+ else
+ {
+ ei.Properties.Add(new ControlProperty() { Name = "bounds", Value = $"[{l},{t}][{r},{b}]" });
+ }Also applies to: 1835-1837
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In
`@Ginger/GingerCoreNET/Drivers/CoreDrivers/Mobile/Appium/GenericAppiumDriver.cs`
around lines 1804 - 1814, The code is using ei.Properties.FirstOrDefault(...) to
read a cached "bounds" which can be stale; change the logic in
GenericAppiumDriver (where boundsAttr is set) and in
GetLocationAndSizeOfElement()/EnsureDeviceBounds() to prefer the live value from
the IWebElement: always call we.GetAttribute("bounds") when ei.ElementObject is
an IWebElement and use that result (falling back to ei.Properties only if
GetAttribute returns null/empty), then write the fresh bounds back into
ei.Properties["bounds"] (update existing key or add) so subsequent reads reflect
the latest rectangle and duplicate stale values are not preserved.
Enhances reliability of UI element highlighting and rectangle drawing, especially for Android automation. Ensures up-to-date element details are used, validates and refreshes element bounds before drawing overlays, and preserves correct element identity for web highlights. Adds error handling and makes driver highlight requests more robust, addressing issues with invalid rectangles and incorrect element selection in live spy and mobile scenarios.
Description
Type of Change
Checklist
[IsSerializedForLocalRepository]where neededReporter.ToLog()patternSummary by CodeRabbit
Release Notes
Bug Fixes