-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Smart sync Action Playwright support #4044
base: master
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request introduces a new Changes
Possibly related PRs
Suggested reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (7)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (6)
10-16
: Consider clarifying comment or renaming private fields.
Your constructor sets internal fields_actSmartSync
,_browserTab
, and_elementLocator
. It might be clearer to rename these fields or add short doc comments that indicate their purpose and responsibilities.
40-53
: Address possible race condition when element becomes unavailable.
In theWaitUntilDisplay
loop, you repeatedly retrieve the element and checkIsVisibleAsync()
andIsEnabledAsync()
. If the element is removed between these checks, you could see unexpected exceptions or incomplete waits. Consider handling the scenario where the element might disappear mid-loop.
45-49
: Improve error specificity.
When the timeout is exceeded, the error message is quite generic. Consider expanding the message or providing more contextual information (e.g., the locator used) to help troubleshoot.
52-52
: Use short-circuit evaluation.
The conditionselement == null || !await element.IsVisibleAsync() || !await element.IsEnabledAsync()
are checked every cycle. You might consider evaluating each separately to clarify which condition failed.
55-67
: Typo inWaitUntilDisapear
.
Recommend renamingWaitUntilDisapear
toWaitUntilDisappear
to match standard spelling and improve readability.-case ActSmartSync.eSmartSyncAction.WaitUntilDisapear: +case ActSmartSync.eSmartSyncAction.WaitUntilDisappear:
79-84
: Potential performance optimization via caching.
GetFirstMatchingElementAsync()
fetches all matching elements and returns only the first one. If you frequently need only the first match, consider adding a dedicatedFindFirstElementAsync()
method to theIBrowserElementLocator
interface to avoid fetching all.Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
254-268
: Be mindful of synchronous blocking while calling asynchronous APIs.
Wrapping everything inTask.Run(...).Wait()
can create thread-pool consumption or potential deadlocks, especially if called in certain synchronization contexts. This approach is acceptable if you must maintain a synchronousRunAction
as per your codebase constraints, but consider documenting these implications.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
(1 hunks)Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs
(2 hunks)Ginger/GingerCoreNET/RunLib/DriverBase.cs
(2 hunks)
🧰 Additional context used
📓 Learnings (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
Learnt from: IamRanjeetSingh
PR: Ginger-Automation/Ginger#3783
File: Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs:129-129
Timestamp: 2024-11-12T02:45:14.501Z
Learning: User IamRanjeetSingh has indicated that the `RunAction` method in the `PlaywrightDriver` class should remain synchronous due to current constraints in the codebase.
🔇 Additional comments (4)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (1)
29-33
: Validate or handle negative timeouts.
Before starting the synchronization loop, consider validating that MaxTimeout
is non-negative; otherwise, you may want to bail early or handle it as an error.
Ginger/GingerCoreNET/RunLib/DriverBase.cs (2)
303-304
: Good use of compiled Regex.
Using RegexOptions.Compiled
is beneficial for performance, especially if you rely on these regexes heavily and repeatedly.
382-382
: Validate default wait time alignment.
The GetMaxTimeout
method defaults to 5
seconds if none is provided. Ensure that 5
seconds aligns with your driver or environment defaults (some test frameworks use 30 seconds by default). If there's a mismatch, it could cause unexpected action timeouts.
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
280-280
: Good approach to broaden support for additional actions.
Adding ActSmartSync
to the supported actions ensures the driver handles new synchronization logic. Be sure to maintain alignment with any future ActSmartSync
updates or new actions requiring special validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (2)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (2)
12-15
: Maintain consistent naming conventions for private fieldsThe field
mAct
uses a different naming convention (Hungarian notation) compared to other private fields which use underscore prefix. Consider renaming it to_act
for consistency.- private Act mAct; + private Act _act;
76-81
: Simplify GetFirstMatchingElementAsync methodThe method can be simplified by removing the intermediate variable and directly returning the result of FirstOrDefault().
private async Task<IBrowserElement> GetFirstMatchingElementAsync() { - IEnumerable<IBrowserElement> elements = await _elementLocator.FindMatchingElements(mAct.LocateBy, mAct.LocateValue); - IBrowserElement? firstElement = elements.FirstOrDefault(); - return firstElement; + return (await _elementLocator.FindMatchingElements(_act.LocateBy, _act.LocateValue)).FirstOrDefault(); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
(1 hunks)
🔇 Additional comments (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (1)
10-10
: Verify integration with PlaywrightDriver
Let's verify how this handler is integrated with PlaywrightDriver.
✅ Verification successful
Let me gather more context about the integration.
Let me check the ActSmartSync class and handler implementation.
Integration with PlaywrightDriver is properly implemented
The verification shows that ActSmartSyncHandler is correctly integrated:
- It's properly instantiated in PlaywrightDriver with required dependencies (browser tab and element locator)
- The class is internal which matches its usage scope within the Web drivers
- It's part of the action handling system alongside other handlers like accessibility testing
- The implementation follows the same pattern as other action handlers in the codebase
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for usage of ActSmartSyncHandler in PlaywrightDriver
rg -A 5 "ActSmartSyncHandler" "Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/"
Length of output: 878
Script:
#!/bin/bash
# Get the context around the usage
rg -B 10 -A 10 "ActSmartSyncHandler" "Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs"
# Check the implementation of ActSmartSync
ast-grep --pattern 'class ActSmartSync {
$$$
}'
Length of output: 7265
Script:
#!/bin/bash
# Find ActSmartSync class definition
rg -B 5 -A 10 "class ActSmartSync"
# Find ActSmartSyncHandler implementation
rg -B 5 -A 10 "class ActSmartSyncHandler" "Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/"
Length of output: 7064
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Outdated
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Outdated
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Outdated
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Outdated
Show resolved
Hide resolved
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (2)
30-34
: Standardize field naming conventionThe field
mAct
doesn't follow the same naming convention as other fields which use the underscore prefix. Consider renaming for consistency.- private Act mAct; + private Act _act;
96-101
: Simplify element retrieval logicThe
FirstOrDefault()
call is redundant as the elements are already enumerable.private async Task<IBrowserElement> GetFirstMatchingElementAsync() { IEnumerable<IBrowserElement> elements = await _elementLocator.FindMatchingElements(mAct.LocateBy, mAct.LocateValue); - IBrowserElement? firstElement = elements.FirstOrDefault(); - return firstElement; + return elements.FirstOrDefault(); }Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
269-286
: Improve timeout handlingThe timeout handling could be improved:
- Store the original timeout before modification
- Ensure timeout is always restored in finally block
- Use TimeSpan for clearer time unit handling
- float? driverDefaultTimeout = browserOptions.Timeout; + var originalTimeout = browserOptions.Timeout; try { - int smartSyncTimeout = DriverBase.GetMaxTimeout(actSmartSync) * 1000; - if (smartSyncTimeout != browserOptions.Timeout) + var smartSyncTimeout = TimeSpan.FromSeconds(DriverBase.GetMaxTimeout(actSmartSync)); + var timeoutMilliseconds = (int)smartSyncTimeout.TotalMilliseconds; + if (timeoutMilliseconds != browserOptions.Timeout) { - browserOptions.Timeout = smartSyncTimeout; + browserOptions.Timeout = timeoutMilliseconds; } - actSmartSyncHandler.HandleAsync(act, smartSyncTimeout).Wait(); + actSmartSyncHandler.HandleAsync(act, timeoutMilliseconds).Wait(); } catch (Exception ex) { act.Error = ex.Message; } finally { - browserOptions.Timeout = driverDefaultTimeout; + browserOptions.Timeout = originalTimeout; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
(1 hunks)Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs
(4 hunks)
🧰 Additional context used
📓 Learnings (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
Learnt from: IamRanjeetSingh
PR: Ginger-Automation/Ginger#3783
File: Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs:129-129
Timestamp: 2024-11-12T02:45:14.501Z
Learning: User IamRanjeetSingh has indicated that the `RunAction` method in the `PlaywrightDriver` class should remain synchronous due to current constraints in the codebase.
🔇 Additional comments (3)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs (2)
35-40
: 🛠️ Refactor suggestion
Add parameter validation in constructor
The constructor should validate input parameters to prevent null reference exceptions.
internal ActSmartSyncHandler(ActSmartSync actSmartSync, IBrowserTab browserTab, IBrowserElementLocator elementLocator)
{
+ ArgumentNullException.ThrowIfNull(actSmartSync);
+ ArgumentNullException.ThrowIfNull(browserTab);
+ ArgumentNullException.ThrowIfNull(elementLocator);
+
_actSmartSync = actSmartSync;
_browserTab = browserTab;
_elementLocator = elementLocator;
}
Likely invalid or redundant comment.
47-91
: 🛠️ Refactor suggestion
Refactor duplicate timeout logic and add cancellation support
The timeout and delay logic is duplicated between the two sync actions. Consider:
- Extracting common timeout logic
- Adding cancellation support
- Making the delay interval configurable
+ private const int DEFAULT_POLLING_INTERVAL = 100; // milliseconds
+
+ internal async Task HandleAsync(Act act, CancellationToken cancellationToken = default)
{
- mAct = act;
+ _act = act;
- Stopwatch st = new Stopwatch();
+ var stopwatch = Stopwatch.StartNew();
try
{
- st.Start();
IBrowserElement element;
+ var pollingInterval = TimeSpan.FromMilliseconds(DEFAULT_POLLING_INTERVAL);
if (_actSmartSync.SmartSyncAction == ActSmartSync.eSmartSyncAction.WaitUntilDisplay)
{
do
{
- if (st.ElapsedMilliseconds > timeout)
+ cancellationToken.ThrowIfCancellationRequested();
+ if (stopwatch.ElapsedMilliseconds > timeout)
{
- mAct.Error = "Smart Sync of WaitUntilDisplay is timeout";
+ _act.Error = "Smart Sync of WaitUntilDisplay timed out";
break;
}
- await Task.Delay(100);
+ await Task.Delay(pollingInterval, cancellationToken);
element = await GetFirstMatchingElementAsync();
} while (element == null || !await element.IsVisibleAsync() || !await element.IsEnabledAsync());
}
else if (_actSmartSync.SmartSyncAction == ActSmartSync.eSmartSyncAction.WaitUntilDisapear)
{
do
{
- if (st.ElapsedMilliseconds > timeout)
+ cancellationToken.ThrowIfCancellationRequested();
+ if (stopwatch.ElapsedMilliseconds > timeout)
{
- mAct.Error = "Smart Sync of WaitUntilDisapear is timeout";
+ _act.Error = "Smart Sync of WaitUntilDisappear timed out";
break;
}
- await Task.Delay(100);
+ await Task.Delay(pollingInterval, cancellationToken);
element = await GetFirstMatchingElementAsync();
} while (element != null);
}
}
Likely invalid or redundant comment.
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
299-299
: LGTM: ActSmartSync support added to IsActionSupported
The addition of ActSmartSync
to the supported actions list is correct.
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/ActionHandlers/ActSmartSyncHandler.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
269-283
: Enhance timeout handling and error handlingConsider the following improvements:
- Document the milliseconds conversion for better maintainability
- Use more specific exception handling to provide better error messages
float? driverDefaultTimeout = browserOptions.Timeout; try { - int smartSyncTimeout = DriverBase.GetMaxTimeout(actSmartSync) * 1000; + // Convert timeout from seconds to milliseconds + int smartSyncTimeout = DriverBase.GetMaxTimeout(actSmartSync) * 1000; browserOptions.Timeout = smartSyncTimeout; actSmartSyncHandler.HandleAsync(act, smartSyncTimeout).Wait(); } -catch (Exception ex) +catch (AggregateException ex) when (ex.InnerException != null) { - act.Error = ex.Message; + act.Error = $"Smart sync action failed: {ex.InnerException.Message}"; +} +catch (Exception ex) +{ + act.Error = $"Unexpected error during smart sync: {ex.Message}"; } finally { browserOptions.Timeout = driverDefaultTimeout; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs
(4 hunks)
🧰 Additional context used
📓 Learnings (1)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (1)
Learnt from: IamRanjeetSingh
PR: Ginger-Automation/Ginger#3783
File: Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs:129-129
Timestamp: 2024-11-12T02:45:14.501Z
Learning: User IamRanjeetSingh has indicated that the `RunAction` method in the `PlaywrightDriver` class should remain synchronous due to current constraints in the codebase.
🔇 Additional comments (3)
Ginger/GingerCoreNET/Drivers/CoreDrivers/Web/Playwright/PlaywrightDriver.cs (3)
34-34
: LGTM!
The added import is necessary for accessing the DriverBase
class used in the smart sync implementation.
256-284
: LGTM - Smart sync action handling maintains synchronous execution
The implementation correctly maintains synchronous execution as required, while properly managing the browser context, timeouts, and cleanup.
296-296
: LGTM!
The addition of ActSmartSync
to the list of supported actions is correct and follows the existing pattern.
Thank you for your contribution.
Before submitting this PR, please make sure:
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Chores