当我可以参见'时,为什么我可以使用(c#)Selenium by.cssselector()访问某些Salesforce dom元素。他们在他们的遥远'祖先节点

发布于 2025-01-27 20:37:06 字数 5222 浏览 6 评论 0 原文

我正在尝试通过具有闪电组件(LWC)的Salesforce实施来编写E2E UI测试。我正在将硒与C#一起自动进行测试。我已经成功地使用XPATH定位了目标元素,但已读到建议使用CSS选择器(用于自动测试速度和鲁棒性),因此我试图通过调用来自调用我的> > by.xpath() to by.cssselector()

但是,当将CSS选择器与Salesforce一起使用时,我会看到奇怪的行为,而且我发现不可能访问DOM中的某些元素,即使我在访问(远处)祖先时可以“看到”它们。

此代码...

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

为我提供了< body> 节点下的每个元素。一切都很好,我可以看到整个DOM结构 - 包括我要定位的元素。

然后,我可以完善搜索以说...

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

我得到了类似的东西……

<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>

仍然很好 - 我的目标元素仍处于DOM结构中。但是,如果我现在下一个元素,其中任何一个...

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";

我只会恢复单个元素,并且不包含任何孩子...

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

我针对的元素低于此&lt;一个-appnav&gt; 元素。但是,如果我尝试使用类似的东西访问它们,

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";

尽管我可以在DOM树中看到该元素,但我会得到一个例外...

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"}

(如上面输出的示例中所示)。

当我检查Salesforce页面时,我还可以看到Chrome检查员中的所有目标元素。

那么,为什么在访问其“遥远”祖先时,我可以在DOM树中看到我的目标元素,而在访问他们的更多“最近”祖先时却看不到?同样,我在使用XPATH访问所有这些目标元素时没有问题。那么,为什么不使用CSS选择器呢?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

始于初秋 2025-02-03 20:37:06

因此,试图找到这种奇怪情况的解决方案并不高兴。实际上,我现在在其他Salesforce Dom树中遇到了类似的情况。

同样,我可以看到高于“遥远”祖先下方的整个DOM树,但是当我进一步定位在树下时,在某个点,只有单个元素可用,在其下方显然无法访问。

同样,这似乎是仅在访问 by.cssselector 时才是一个问题。当我使用 by.xpath 时,一切都按预期工作 - 我可以访问DOM树中的任何元素。

这里一个有趣的观点 - 当我比较两种DOM树的两个“麻烦”元素时 - 原始场景中的一个,以及我刚刚发现的最新元素...

...

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

最新...最新的...

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

原始 元素是...

  • salesforce使用的非标准html标签名称
  • 中使用的相同属性: data-data-rendering-service-uid data-aura-rendered-by >

我的感觉是与渲染/渲染属性有关。我不确定他们的作用,或者与JavaScript函数可能相关的动态值指向什么?提出的问题在这里 ,,没有任何Salesforce的回应。

看来我只需要恢复到使用 by.xpath 。希望这将有助于发现类似情况的人。让我知道您是否找到解决方案。

编辑:

此后,我发现了Salesforce的后来发行版(2020年春季)的参考,他们建议使用
xpaths csss selectors coselectors 特别是...尤其是...

*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.
为了参考,我正在使用:
- Microsoft.NETCore.App (v3.1.0)
- C# (v8)
- Selenium.Support package (v4.1.0)
- Chrome and Chromedriver (v102.0.5005.61)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文