Вот мой ответ на предыдущий вопрос по этому вопросу . (Копировать / Вставить). Это работает 100% времени (при условии, что у вас есть JQuery на странице; если нет, мы можем сделать альтернативу):
Так что в конечном итоге это идеальный вариант использования расширения, которое я сделал. Вот самая важная часть этого:
/// <summary>
/// Selenium sometimes has trouble finding elements on the page. Give it some help by using JQuery to grab the full qualified xpath to that element.
/// </summary>
/// <param name="cssSelector"></param>
/// <returns></returns>
public static string GetFullyQualifiedXPathToElement(string cssSelector, bool isFullJQuery = false, bool noWarn = false)
{
if (cssSelector.Contains("$(") && !isFullJQuery) {
isFullJQuery = true;
}
string finder_method = @"
function getPathTo(element) {
if(typeof element == 'undefined') return '';
if (element.tagName == 'HTML')
return '/HTML[1]';
if (element===document.body)
return '/HTML[1]/BODY[1]';
var ix= 0;
var siblings = element.parentNode.childNodes;
for (var i= 0; i< siblings.length; i++) {
var sibling= siblings[i];
if (sibling===element)
return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
if (sibling.nodeType===1 && sibling.tagName===element.tagName)
ix++;
}
}
";
if(isFullJQuery) {
cssSelector = cssSelector.TrimEnd(';');
}
string executable = isFullJQuery ? string.Format("{0} return getPathTo({1}[0]);", finder_method, cssSelector) : string.Format("{0} return getPathTo($('{1}')[0]);", finder_method, cssSelector.Replace("'", "\""));
string xpath = string.Empty;
try {
xpath = BaseTest.Driver.ExecuteJavaScript<string>(executable);
} catch (Exception e) {
if (!noWarn) {
Check.Warn(string.Format("Exception occurred while building a dynamic Xpath. Css selector supplied to locate element is \"{0}\". Exception [{1}].", cssSelector, e.Message));
}
}
if (!noWarn && string.IsNullOrEmpty(xpath)) {
Check.Warn(string.Format("Supplied cssSelector did not point to an element. Selector is \"{0}\".", cssSelector));
}
return xpath;
}
С помощью этой логики вы можете передать селектор Jquery в ваш браузер через javascript executor. У JQuery нет проблем с поиском элементов, вложенных в iframes. Попробуйте что-то вроде этого:
driver.FindElement(By.XPath(GetFullyQualifiedXPathToElement("#MyDeeplyNestedElement")).Click();
https://gist.github.com/tsibiski/04410e9646ee9ced9f3794266d6c5a82
Не стесняйтесь удалять из этого метода / класса все, что не относится к вашей ситуации.
Почему / Как это внезапно делает элемент доступным для селена ????
Возможно, вы заметили, что если вы скажете selenium найти html-элемент iframe, а затем явно выполните поиск в WebElement iframe, вы сможете найти под ним дочерние элементы. Однако, предварительно не найдя каждый дочерний iframe, Selenium, похоже, не заглядывает внутрь iframe, если вы явно не помогаете ему через DOM.
JQuery не имеет этого ограничения. Он видит каждый зарегистрированный элемент DOM просто отлично, и будет нормально захватывать его. Получив элемент в виде объекта JQuery, вы можете создать путь тегов, родитель за родителем, вплоть до DOM. Когда логика будет завершена, у вас будет полностью квалифицированный XPath от вершины DOM до вложенного дочернего элемента. Затем, когда этот явный XPath передается в Selenium, вы удерживаете его руку в кроличьей норе через один или несколько фреймов, пока не натолкнетесь на нужный объект.