简体   繁体   中英

Why can't I access some Salesforce DOM elements with (C#) Selenium By.CssSelector(), when I can 'see' them under their 'distant' ancestor nodes

I am attempting to write E2E UI tests over a Salesforce implementation which has Lightning Components (LWC). I am using Selenium with C# to automate the tests. I have been successful in locating my target elements using XPaths, but have read that CSS Selectors are recommended (for auto-test speed and robustness), so I'm attempting to convert my By calls from By.XPath() to By.CssSelector() .

However I am seeing strange behaviour when using CSS Selectors with Salesforce, and I'm finding it impossible to access some elements in the DOM, even though I can 'see' them when I access their (distant) ancestors.

This code...

var cssSel = "body";
var element = wait.Until(ExpectedConditions.ElementExists(By.CssSelector(cssSel)));
Console.WriteLine(element.GetAttribute("outerHTML"));

gives me every element under the <body> node in the DOM. That's all good, I can see the whole DOM structure - including the elements I want to target.

I can then refine the search down to say...

var cssSel = "body>div.desktop div.slds-no-print";

and I get something like...

<div class="slds-no-print oneAppNavContainer" data-aura-rendered-by="299:0;p" data-aura-class="oneAppNavContainer" style="top: 83px;">
    <one-appnav data-data-rendering-service-uid="138" data-aura-rendered-by="244:0">
        <div class="slds-context-bar">
            <div class="slds-context-bar__primary navLeft">
                <div class="slds-context-bar__item slds-context-bar_dropdown-trigger slds-dropdown-trigger slds-dropdown-trigger--click slds-no-hover">
                    <div class="appLauncher slds-context-bar__icon-action" role="navigation" aria-label="App">
                        <one-app-launcher-header class="slds-icon-waffle_container">
                            <button class="slds-button slds-show" aria-haspopup="dialog">
                                <div class="slds-icon-waffle">
                                    <div class="slds-r1"/>
                                    .
                                    .
                                    <div class="slds-r9"/>
                                    <span class="slds-assistive-text">App Launcher</span>
                                </div>
                            </button>
                        </one-app-launcher-header>
                    </div>
                    <span class="appName slds-context-bar__label-action slds-context-bar__app-name">
                        <span class="slds-truncate" title="Critical Indicators – Sales">Critical Indicators – Sales</span>
                    </span>
                </div>
            </div>
            <one-app-nav-bar class="slds-grid slds-has-flexi-truncate" one-appnavbar_appnavbar-host="">
                <span one-appnavbar_appnavbar="" class="slds-assistive-text" id="operationId-5">Press Spacebar to reorder.</span>
                <span one-appnavbar_appnavbar="" class="slds-assistive-text keyboardDnd" id="dndAssistiveText-5" aria-live="assertive"/>
                <nav one-appnavbar_appnavbar="" class="slds-context-bar__secondary navCenter" role="navigation" aria-label="Global">
                    <div one-appnavbar_appnavbar="" class="slds-grid slds-has-flexi-truncate navUL" role="list" aria-describedby="operationId-5">
                        <one-app-nav-bar-item-root one-appnavbar_appnavbar="" class="navItem slds-context-bar__item slds-shrink-none slds-is-active" data-id="home" data-assistive-id="operationId" aria-hidden="false" draggable="true" role="listitem">
                            <a class="slds-context-bar__label-action dndItem" href="/lightning/page/home" title="Home" tabindex="0" draggable="false" aria-current="page">
                                <span class="slds-truncate">Home</span>
                            </a>
                        </one-app-nav-bar-item-root>
   .
   .
 <!-- hundreds of lines of elements cut out -->
   .
   .
                    </div>
                </nav>
            </one-app-nav-bar>
        </div>
    </one-appnav>
    <!--render facet: 301:0;p-->
</div>

Still good - my target elements are still in that DOM structure. But if I now get the next element down, with any of these...

var cssSel = "body>div.desktop div.slds-no-print>one-appnav";
// or
var cssSel = "body>div.desktop div.slds-no-print one-appnav";
// or
var cssSel = "one-appnav";

I only get that single element back, and it doesn't contain any children...

<one-appnav data-data-rendering-service-uid="138" data-aura-rendered-by="244:0"></one-appnav>

The elements I am targeting are below this <one-appnav> element. But if I try to access them with something like...

var cssSel = "body>div.desktop div.slds-no-print>one-appnav>div.slds-context-bar";
// or
var cssSel = "body>div.desktop div.slds-no-print>one-appnav div.slds-context-bar";
// or
var cssSel = "body>div.desktop div.slds-no-print div.slds-context-bar";

I get an exception...

OpenQA.Selenium.NoSuchElementException: no such element: Unable to locate element:
 {"method":"css selector",
  "selector":"body>div.desktop div.slds-no-print>one-appnav>div.slds-context-bar"}

Despite the fact that I could see that element in the DOM tree previously (as shown in the example output up above).

I can also see all the target elements in the Chrome Inspector when I inspect Salesforce pages.

So, why can I see my target elements in the DOM tree when accessing their 'distant' ancestors, but not when accessing their more 'recent' ancestors? Again, I have no problems accessing all of these target elements using XPaths. So why not when using CSS Selectors?

So, no joy in trying to find a solution to this strange scenario. In fact, I've now come across a similar case in a different Salesforce DOM tree.

Again I can see the entire DOM tree below the higher 'distant' ancestors, but as I target further down the tree, at a certain point only the single element is available with apparently nothing accessible below it.

And again this appears to be an issue only when accessing By.CssSelector . When I use By.XPath everything works as expected - I can access any element in the DOM tree.

One interesting point here - when I compare the two 'troublesome' elements from the two DOM trees - the one in the original scenario, and the latest one I just found...

Original...

<one-appnav data-data-rendering-service-uid="138" data-aura-rendered-by="244:0"></one-appnav>

Latest...

<force-aloha-page data-data-rendering-service-uid="1102" data-aura-rendered-by="6404:0" force-alohapage_alohapage-host=""/>

The common factors of these elements are...

  • non-standard html tag names used by Salesforce
  • identical attributes used inside them: data-data-rendering-service-uid and data-aura-rendered-by

My feeling is that is has to do with the rendering / rendered attributes. I'm not sure what they do, or what their associated dynamic values point to... possibly to a javascript function? Questions which are raised here , without any response from Salesforce.

It looks like I'll simply have to revert to using By.XPath instead. Hopefully this will help someone who finds a similar scenario. Let me know if you find a solution.

EDIT:

I have since found references to later releases (Spring 2020) of Salesforce where they recommend using XPaths over CSS Selectors , which states in particular...

*Convert non-XPath locators to XPath*
 
LWC uses a _polyfill_ to implement shadow DOM rather than a native browser
implementation. This implementation restricts Selenium access by non-XPath
selectors, like By.cssSelector(), but still allows direct access with By.xpath().
The simplest fix is to convert your non-XPath locators to XPath.
For reference I'm using:
- Microsoft.NETCore.App (v3.1.0)
- C# (v8)
- Selenium.Support package (v4.1.0)
- Chrome and Chromedriver (v102.0.5005.61)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM