If possible, how can I use selenium to identify elements that reside in nested frames?

后端 未结 1 367
醉梦人生
醉梦人生 2021-01-16 16:50

So in helping another user troubleshoot a Selenium/selector issue, I believe I ran in to a larger issue for which I\'m wondering if there is any solution.

Basically,

相关标签:
1条回答
  • 2021-01-16 17:14

    So this is ultimately the perfect use case for an extension I made. Here is the most important part of it:

      /// <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;
    
            }
    

    With this logic, you can pass a Jquery selector into your browser via javascript executor. JQuery has no problems finding elements nested within iframes. Try something like this:

    driver.FindElement(By.XPath(GetFullyQualifiedXPathToElement("#MyDeeplyNestedElement")).Click();
    

    https://gist.github.com/tsibiski/04410e9646ee9ced9f3794266d6c5a82

    Feel free to remove whatever is in that method/class that does not apply to your situation.

    Why/How does this suddenly make an element findable to Selenium????

    You may have noticed that if you tell selenium to find an iframe html element, and then explicitly search within the WebElement of the iframe, that you can find child elements under it. However, without first finding each child iframe, Selenium does not seem to look inside the iframes without you explicitly helping it through the DOM.

    JQuery does not have this limitation. It sees every registered DOM element just fine, and will grab it normally. Once you have the element as a JQuery object, you can build out a path of tags, parent by parent, all the way up the DOM. When the logic is complete, you will have a fully-qualified XPath from the top of the DOM down to the nested child element. Then, once this explicit XPath is supplied to Selenium, you are holding its hand down the rabbit hole through one or more iframes until it runs into the object you want.

    0 讨论(0)
提交回复
热议问题