Skip to content
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

Enhancement - Playwright Window Explorer And Visual Testing Action Support #3850

Merged
merged 7 commits into from
Aug 12, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@ public override void RunAction(Act act)
ActGotoURLHandler actGotoURLHandler = new(actGotoURL, _browser);
actGotoURLHandler.HandleAsync().Wait();
break;
case ActVisualTesting actVisualTesting:
actVisualTesting.Execute(this);
break;
default:
act.Error = $"This Action is not supported for Playwright driver";
break;
Expand All @@ -172,7 +175,7 @@ public bool IsActionSupported(Act act, out string message)
{
message = string.Empty;

if (act is ActWithoutDriver)
if (act is ActWithoutDriver or ActScreenShot or ActVisualTesting)
{
return true;
}
Expand Down Expand Up @@ -219,10 +222,6 @@ public bool IsActionSupported(Act act, out string message)
}
return isLocatorSupported && isOperationSupported;
}
else if (act is ActScreenShot)
{
return true;
}
else
{
message = $"'{act.ActionType}' is not supported by Playwright driver, use Selenium driver instead.";
Expand Down Expand Up @@ -731,13 +730,14 @@ public List<ElementInfo> GetElementChildren(ElementInfo elementInfo)
{
await SwitchToFrameOfElementAsync(elementInfo);
string xpath = GenerateXPathFromHTMLElementInfo(htmlElementInfo);
IEnumerable<IBrowserElement> browserElements = await _browser.CurrentWindow.CurrentTab.GetElementsAsync(eLocateBy.ByXPath, xpath);
string childrenXPath = GenerateChildrenXPath(xpath);
IEnumerable<IBrowserElement> browserElements = await _browser.CurrentWindow.CurrentTab.GetElementsAsync(eLocateBy.ByXPath, childrenXPath);
List<HTMLElementInfo> htmlElements = [];
foreach (IBrowserElement browserElement in browserElements)
{
HTMLElementInfo newHtmlElement = await CreateHtmlElementAsync(browserElement);

if (string.IsNullOrEmpty(newHtmlElement.ID))
if (string.IsNullOrEmpty(newHtmlElement.ID) && htmlElementInfo.HTMLElementObject != null)
{
newHtmlElement.ID = htmlElementInfo.HTMLElementObject.Id;
}
Expand Down Expand Up @@ -767,6 +767,27 @@ public List<ElementInfo> GetElementChildren(ElementInfo elementInfo)
}).Result;
}

private string GenerateChildrenXPath(string parentXPath)
{
string[] parentXPathSegments = parentXPath.Split("/", StringSplitOptions.RemoveEmptyEntries);
string elementType = parentXPathSegments[^1];

int index = elementType.IndexOf('[');
if (index != -1)
{
elementType = elementType.AsSpan(0, index).ToString();
}

if (string.Equals(elementType, "iframe") || string.Equals(elementType, "frame"))
{
return "/html/*";
}
else
{
return parentXPath + "/*";
}
}
Comment on lines +782 to +801
Copy link
Contributor

Choose a reason for hiding this comment

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

Optimize the XPath generation logic.

The method generates XPath for child elements but can be optimized for readability and performance.

-  string[] parentXPathSegments = parentXPath.Split("/", StringSplitOptions.RemoveEmptyEntries);
-  string elementType = parentXPathSegments[^1];
-  int index = elementType.IndexOf('[');
-  if (index != -1)
-  {
-    elementType = elementType.AsSpan(0, index).ToString();
-  }
-  if (string.Equals(elementType, "iframe") || string.Equals(elementType, "frame"))
-  {
-    return "/html/*";
-  }
-  else
-  {
-    return parentXPath + "/*";
-  }
+  var elementType = parentXPath.Split("/", StringSplitOptions.RemoveEmptyEntries).Last().Split('[').First();
+  return (elementType.Equals("iframe", StringComparison.OrdinalIgnoreCase) || elementType.Equals("frame", StringComparison.OrdinalIgnoreCase)) 
+    ? "/html/*" 
+    : $"{parentXPath}/*";
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.

Suggested change
private string GenerateChildrenXPath(string parentXPath)
{
string[] parentXPathSegments = parentXPath.Split("/", StringSplitOptions.RemoveEmptyEntries);
string elementType = parentXPathSegments[^1];
int index = elementType.IndexOf('[');
if (index != -1)
{
elementType = elementType.AsSpan(0, index).ToString();
}
if (string.Equals(elementType, "iframe") || string.Equals(elementType, "frame"))
{
return "/html/*";
}
else
{
return parentXPath + "/*";
}
}
private string GenerateChildrenXPath(string parentXPath)
{
var elementType = parentXPath.Split("/", StringSplitOptions.RemoveEmptyEntries).Last().Split('[').First();
return (elementType.Equals("iframe", StringComparison.OrdinalIgnoreCase) || elementType.Equals("frame", StringComparison.OrdinalIgnoreCase))
? "/html/*"
: $"{parentXPath}/*";
}


public ObservableList<ControlProperty> GetElementProperties(ElementInfo elementInfo)
{
if (elementInfo is not HTMLElementInfo htmlElementInfo)
Expand Down
Loading