Issue
I found these two topics:
Finding a given element in nested iframes *recursively*
Recursively locate element within nested iframes
But they are not selenium based or C#, below you may see what I have so far:
public static IWebElement FindWebElementByXPath(ChromeDriver chromeDriver, string xPath, string frameType = "iframe")
{
Console.WriteLine(" Searching for Element: " + xPath + "\n");
Console.WriteLine();
IWebElement element;
try
{
chromeDriver.SwitchTo().DefaultContent();
element = chromeDriver.FindElement(By.XPath(xPath));
if (element != null)
{
Console.WriteLine(" Found Element: " + xPath + " (" + element.Text + ")\n");
Console.WriteLine();
return element;
}
}
catch (Exception)
{
// ignored
}
var windowHandles = chromeDriver.WindowHandles;
foreach (var window in windowHandles)
{
chromeDriver.SwitchTo().Window(window);
var frames = chromeDriver.FindElements(By.TagName(frameType));
foreach (var frame in frames)
{
chromeDriver.SwitchTo().DefaultContent();
chromeDriver.SwitchTo().Frame(frame);
try
{
element = chromeDriver.FindElement(By.XPath(xPath));
if (element != null)
{
Console.WriteLine(" Found Element: " + xPath + " (" + element.Text + ")\n");
Console.WriteLine();
return element;
}
}
catch (Exception)
{
// ignored
}
var frameChildren = chromeDriver.FindElements(By.TagName(frameType));
foreach (var child in frameChildren)
{
chromeDriver.SwitchTo().DefaultContent();
chromeDriver.SwitchTo().Frame(frame);
chromeDriver.SwitchTo().Frame(child);
try
{
element = chromeDriver.FindElement(By.XPath(xPath));
if (element != null)
{
Console.WriteLine(" Found Element: " + xPath + " (" + element.Text + ")\n");
Console.WriteLine();
return element;
}
}
catch (Exception)
{
// ignored
}
}
}
}
Console.WriteLine("Failed to find Element: " + xPath + "\n");
Console.WriteLine();
return null;
}
My current code can only handle the 1 frame and the children of said frame, but not the children of children and so on.
My brain hurts because I can't figure out how to write a recursive function to crawl through all of this.
Solution
This is the solution I came up with:
public static IWebElement FindWebElementByXPath(ChromeDriver chromeDriver, string XPath, string FrameType = "iframe")
{
IWebElement element = null;
Console.WriteLine(" Searching for Element: " + XPath + "\n");
chromeDriver.SwitchTo().DefaultContent();
try
{
element = chromeDriver.FindElement(By.XPath(XPath));
if (element != null)
{
Console.WriteLine(" Found Element: " + XPath + " (" + element.Text + ")\n");
return element;
}
}
catch
{
}
var iframes = chromeDriver.FindElements(By.TagName(FrameType)).ToList<IWebElement>();
var index = 0;
Reset:
for (; index < iframes.Count; index++)
{
retry:
try
{
var item = iframes[index];
try
{
chromeDriver.SwitchTo().Frame(item);
try
{
element = chromeDriver.FindElement(By.XPath(XPath));
if (element != null)
{
Console.WriteLine(" Found Element: " + XPath + " (" + element.Text + ")\n");
return element;
}
}
catch
{
}
}
catch
{
chromeDriver.SwitchTo().ParentFrame();
goto retry;
}
var children = chromeDriver.FindElements(By.TagName(FrameType)).ToList();
if (children.Count > 0)
{
if (iframes.Any(x => children.Any(y => y.Equals(x))) == false)
{
iframes.InsertRange(index+1,children);
goto Reset;
}
}
}
catch
{
}
}
return element;
}
Here you go, literally the only hit on SO with a snippet for crawling through nested iframes in C# Selenium.
Answered By - Laurian Avrigeanu
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.