Если возможно, как я могу использовать селен для идентификации элементов, которые находятся во вложенных фреймах? - PullRequest
0 голосов
/ 12 марта 2019

Поэтому, помогая другому пользователю устранить проблему с селенином / селектором, я считаю, что столкнулся с более крупной проблемой, для которой мне интересно, есть ли какое-либо решение.

По сути, я наткнулся на (i) рамочный ад. Извините, что включил снимок экрана консоли разработчика, но я не смог найти хороший способ скопировать его.

too many frames

Итак, как вы можете видеть, если вы любезно щелкните по изображению выше, HTML-код этой страницы содержит кадры внутри наборов кадров внутри кадров внутри ....

Мне удалось идентифицировать первый уровень фреймов, но, конечно, элемент, который мы хотели найти, находился в середине всех этих фреймов.

Я обнаружил, что, используя xpath, cssSelector, ID, Name, любой тип локатора, я никогда не смог найти ни одного элемента мимо и включая все, что вложено в элемент #document. Я читал на нескольких сайтах, что это либо очень сложно, либо невозможно, но я никогда не сталкивался с решением, которое подойдет для этой страницы.

Возможно ли это, и если да, то как можно преодолеть эти #document элементы?

P.S. дайте мне знать, если есть простой способ скопировать фактический текст, как на картинке с консоли, и я сделаю это для всей страницы.

Это , а не , дубликат этого вопроса, потому что это касается нескольких вложенных фреймов с #document элементами, которые Selenium, очевидно, не может пройти. Все представленные примеры имеют только один (i) кадр . Я знаю, как переключиться на iFrame, но, кажется, невозможно переключиться на элемент или фрейм во вложенных фреймах, которые содержат #document, используя только Selenium; JQuery является решением этой проблемы, поэтому я принял ответ ниже.

Мне действительно все равно, если он будет ошибочно закрыт как дубликат, так как я получил решение, но я на 100% уверен, что это отдельная проблема от простого перехода на iFrame.

1 Ответ

1 голос
/ 12 марта 2019

Так что в конечном итоге это идеальный вариант использования расширения, которое я сделал. Вот самая важная часть этого:

  /// <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, вы удерживаете его руку в кроличьей норе через один или несколько фреймов, пока не натолкнетесь на нужный объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...