Skip to content

Self healing operation refactoring#3637

Merged
Maheshkale447 merged 5 commits into
masterfrom
Feature/SelfHealingEnhancement
Apr 26, 2024
Merged

Self healing operation refactoring#3637
Maheshkale447 merged 5 commits into
masterfrom
Feature/SelfHealingEnhancement

Conversation

@Maheshkale447

@Maheshkale447 Maheshkale447 commented Apr 25, 2024

Copy link
Copy Markdown
Contributor
  1. Avoid learning html and Body tags during POM creation
  2. Update Auto Update of self healing to only trigger once during the single run for Automate tab run. Removed existing 5 hours check
  3. Avoid learning screenshots of unmapped elements during POM learn
  4. Convert Exact and Contains Text match to be case insensitive in case of auto learned element
  5. De-Select tag name locator in case friendly locators are not available for element and its not only locator.
  6. Changes to SeleniumDriver.cs file to improve readability, flexibility, and functionality.
  7. Changes in PluginsManager.cs to prevent potential NullReferenceExceptions and improve readability and performance.
  8. Changes in AgentOperations.cs to prevent a potential NullReferenceException.
  9. Changes in XPathHelper.cs to improve readability and performance, and to use new features introduced in C# 9.0.

Thank you for your contribution.
Before submitting this PR, please make sure:

  • PR description and commit message should describe the changes done in this PR
  • Verify the PR is pointing to correct branch i.e. Release or Beta branch if the code fix is for specific release , else point it to master
  • Latest Code from master or specific release branch is merged to your branch
  • No unwanted\commented\junk code is included
  • No new warning upon build solution
  • Code Summary\Comments are added to my code which explains what my code is doing
  • Existing unit test cases are passed
  • New Unit tests are added for your development
  • Sanity Tests are successfully executed for New and Existing Functionality
  • Verify that changes are compatible with all relevant browsers and platforms.
  • After creating pull request there should not be any conflicts
  • Resolve all Codacy comments
  • Builds and checks are passed before PR is sent for review
  • Resolve code review comments
  • Update the Help Library document to match any feature changes

Summary by CodeRabbit

  • Refactor
    • Improved efficiency in handling Page Object Model (POM) updates based on timing.
    • Enhanced readability and maintainability in web driver operations and element location methods.
    • Streamlined plugin retrieval and logging processes in plugin management.
    • Optimized agent readiness checks to handle potential null objects more gracefully.
    • Refined list operations and string handling in XPath helper for better performance and clarity.

1. Avoid learning html and Body tags during POM creation
2. Update Auto Update of self healing to only trigger once during single run for Automate tab run. Removed existing 5 hours check
3. Changes to SeleniumDriver.cs file to improve readability, flexibility, and functionality.
3. Changes in `PluginsManager.cs` to prevent potential NullReferenceExceptions and improve readability and performance.
4. Changes in `AgentOperations.cs` to prevent a potential NullReferenceException.
5. Changes in `XPathHelper.cs` to improve readability and performance, and to use new features introduced in C# 9.0.
6. Avoid learning screenshots of unmapped elements during POM learn
7. Convert Exact and Contains Text match to be case insensitive in case of auto learned element
8. De-Select tag name loctor in case friendly locators are not available for element and its not only locator.
@coderabbitai

coderabbitai Bot commented Apr 25, 2024

Copy link
Copy Markdown
Contributor

Walkthrough

The recent updates across various components in the Ginger software suite focus on refining and optimizing code efficiency and readability. These changes include enhancements in error handling, refactoring of core functionalities, and improved management of data structures and conditions, ensuring a smoother and more reliable operation of the software.

Changes

File Path Change Summary
.../Execution/POM/POMExecutionUtils.cs Refactored logic for updating POM elements based on RunSet or BusinessFlow start times.
.../Web/Selenium/SeleniumDriver.cs Added constants, refactored switch statements and element location methods for better readability.
.../PlugInsLib/PluginsManager.cs Enhanced retrieval of PluginPackage using lambda expressions and added null checks in logging.
.../RunLib/AgentOperations.cs Improved error handling in WaitForAgentToBeReady by safeguarding against null Driver objects.
.../RunLib/Common/XPathHelper.cs Optimized string checks and list operations, and utilized concise syntax for initializing lists and adjusting loop conditions.

🐰✨
In the land of code where the ginger roots grow,
A rabbit hopped in, with a refactor in tow.
"Switches to lambdas, lists neatly in line,
Errors caught softly, oh, how divine!"
With each hop and each leap, the code did shine bright,
A whiskered architect danced away into the night.
🌟🐇


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?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

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 as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

{
int Counter = 0;
while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver.ErrorMessageFromDriver))
while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver?.ErrorMessageFromDriver))

@coderabbitai coderabbitai Bot Apr 25, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use null-conditional operator for Driver in the entire condition.

- while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver?.ErrorMessageFromDriver))
+ while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver?.ErrorMessageFromDriver))

This change ensures that the entire condition is safe against null references, maintaining consistency in how Driver is accessed within the condition.


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.

Suggested change
while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver?.ErrorMessageFromDriver))
while (Status != Agent.eStatus.Running && String.IsNullOrEmpty(Driver?.ErrorMessageFromDriver))

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

null-conditional operator is used

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Maheshkale447, thank you for confirming the use of the null-conditional operator. If there's anything else you need, feel free to ask!


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines +226 to +234
// Get start time stamp of RunSet or BusinessFlow
DateTime? startTimeStamp = ExecutedFrom == eExecutedFrom.Run
? WorkSpace.Instance.RunsetExecutor.RunSetConfig?.StartTimeStamp
: ((GingerCore.Agent)currentAgent).BusinessFlow?.StartTimeStamp;

// Check if the POM was updated after the start time stamp, if yes, don't update the POM
if (startTimeStamp.HasValue && Convert.ToDateTime(GetCurrentPOMElementInfo().LastUpdatedTime).ToUniversalTime() > startTimeStamp.Value)
{
var pomLastUpdatedTimeSpan = (System.DateTime.Now - Convert.ToDateTime(GetCurrentPOMElementInfo().LastUpdatedTime)).TotalHours;
if (pomLastUpdatedTimeSpan < 5)
{
return null;
}
return null;

@coderabbitai coderabbitai Bot Apr 25, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider handling potential exceptions when converting LastUpdatedTime to DateTime.

- if (startTimeStamp.HasValue && Convert.ToDateTime(GetCurrentPOMElementInfo().LastUpdatedTime).ToUniversalTime() > startTimeStamp.Value)
+ if (startTimeStamp.HasValue && DateTime.TryParse(GetCurrentPOMElementInfo().LastUpdatedTime, out DateTime lastUpdatedTime) && lastUpdatedTime.ToUniversalTime() > startTimeStamp.Value)

This change ensures that the conversion does not throw an exception if LastUpdatedTime is not in a valid format.


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.

Suggested change
// Get start time stamp of RunSet or BusinessFlow
DateTime? startTimeStamp = ExecutedFrom == eExecutedFrom.Run
? WorkSpace.Instance.RunsetExecutor.RunSetConfig?.StartTimeStamp
: ((GingerCore.Agent)currentAgent).BusinessFlow?.StartTimeStamp;
// Check if the POM was updated after the start time stamp, if yes, don't update the POM
if (startTimeStamp.HasValue && Convert.ToDateTime(GetCurrentPOMElementInfo().LastUpdatedTime).ToUniversalTime() > startTimeStamp.Value)
{
var pomLastUpdatedTimeSpan = (System.DateTime.Now - Convert.ToDateTime(GetCurrentPOMElementInfo().LastUpdatedTime)).TotalHours;
if (pomLastUpdatedTimeSpan < 5)
{
return null;
}
return null;
// Get start time stamp of RunSet or BusinessFlow
DateTime? startTimeStamp = ExecutedFrom == eExecutedFrom.Run
? WorkSpace.Instance.RunsetExecutor.RunSetConfig?.StartTimeStamp
: ((GingerCore.Agent)currentAgent).BusinessFlow?.StartTimeStamp;
// Check if the POM was updated after the start time stamp, if yes, don't update the POM
if (startTimeStamp.HasValue && DateTime.TryParse(GetCurrentPOMElementInfo().LastUpdatedTime, out DateTime lastUpdatedTime) && lastUpdatedTime.ToUniversalTime() > startTimeStamp.Value)
{
return null;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LastUpdatedTime will always be correct DateTime

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Maheshkale447, thank you for confirming the reliability of the LastUpdatedTime format. I'll remember this detail for future reviews to ensure we maintain streamlined and efficient code.

   (\(\ 
   ( -.-)
   o_(")(")

This little bunny is thoughtful, remembering your guidance for future interactions!


New Learnings Added
User: Maheshkale447
PR: Ginger-Automation/Ginger#3637
File: Ginger/GingerCoreNET/Application Models/Execution/POM/POMExecutionUtils.cs:226-234
Timestamp: 2024-04-25T21:51:07.425Z
Learning: The `LastUpdatedTime` in the `POMExecutionUtils.cs` file of the Ginger project is always in the correct DateTime format, as confirmed by the user. This information is crucial for avoiding unnecessary error handling suggestions in future reviews.

Note: Learnings are effective only in the context of specific code segments. To apply general coding guidelines, please configure review instructions.

if (deltaElementInfos.Count > 0)
{
UpdateElementSelfHealingDetails(deltaElementInfos.ToList());
UpdateElementSelfHealingDetails([.. deltaElementInfos]);

@coderabbitai coderabbitai Bot Apr 25, 2024

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensure that deltaElementInfos is not null before calling UpdateElementSelfHealingDetails.

- UpdateElementSelfHealingDetails([.. deltaElementInfos]);
+ if (deltaElementInfos != null) UpdateElementSelfHealingDetails(deltaElementInfos);

This modification adds a null check to prevent potential null reference exceptions.


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.

Suggested change
UpdateElementSelfHealingDetails([.. deltaElementInfos]);
if (deltaElementInfos != null) UpdateElementSelfHealingDetails(deltaElementInfos);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its checked in if before this piece of code

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Maheshkale447, thank you for pointing that out. It's good practice to ensure that methods returning collections, like GetUpdatedVirtulPOM, do not return null but rather an empty collection if there are no elements to return. This approach avoids the need for null checks when the method is used.

If you're confident that GetUpdatedVirtulPOM is implemented this way, then the existing check using Any() should suffice to handle cases where there are no elements to update. However, if there's any uncertainty about this behavior, it might be beneficial to review the implementation of GetUpdatedVirtulPOM to confirm that it never returns null. This can help prevent potential issues in scenarios where the method might unexpectedly return null due to changes or exceptions within it.

Let me know if there's anything else you'd like to discuss or if you need further assistance!

@Maheshkale447
Maheshkale447 merged commit 94faa87 into master Apr 26, 2024
@Maheshkale447
Maheshkale447 deleted the Feature/SelfHealingEnhancement branch April 26, 2024 09:37

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Out of diff range and nitpick comments (1)
Ginger/GingerCoreNET/Run/RunListenerLib/LiteDBRepository.cs (1)

251-253: Ensure consistent naming conventions for dictionary keys.

The keys used in the dictionary for ChildExecutableItemsCount, ChildExecutedItemsCount, and ChildPassedItemsCount are derived from an enum using nameof. This is good for maintainability, but ensure that the enum values are consistent and meaningful across the application to avoid confusion.

Comment on lines +394 to +409
businessFlow.ChildExecutableItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Activities), out count);
ChildExecutableItemsCountActivity = ChildExecutableItemsCountActivity + count;

businessFlow.ChildExecutedItemsCount.TryGetValue(HTMLReportConfiguration.eExecutionStatisticsCountBy.Activities.ToString(), out count);
businessFlow.ChildExecutedItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Activities), out count);
ChildExecutedItemsCountActivity = ChildExecutedItemsCountActivity + count;

businessFlow.ChildPassedItemsCount.TryGetValue(HTMLReportConfiguration.eExecutionStatisticsCountBy.Activities.ToString(), out count);
businessFlow.ChildPassedItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Activities), out count);
ChildPassedItemsCountActivity = ChildPassedItemsCountActivity + count;

businessFlow.ChildExecutableItemsCount.TryGetValue(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions.ToString(), out count);
businessFlow.ChildExecutableItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions), out count);
ChildExecutableItemsCountAction = ChildExecutableItemsCountAction + count;

businessFlow.ChildExecutedItemsCount.TryGetValue(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions.ToString(), out count);
businessFlow.ChildExecutedItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions), out count);
ChildExecutedItemsCountAction = ChildExecutedItemsCountAction + count;

businessFlow.ChildPassedItemsCount.TryGetValue(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions.ToString(), out count);
businessFlow.ChildPassedItemsCount.TryGetValue(nameof(HTMLReportConfiguration.eExecutionStatisticsCountBy.Actions), out count);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review the use of TryGetValue for performance optimization.

The repeated use of TryGetValue in a loop can be optimized. Consider caching the results or restructuring the data access patterns to reduce the overhead of dictionary lookups in a tight loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant