isDisplayed为Protractor中的可见元素返回false [英] isDisplayed returns false for a visible element in Protractor

查看:139
本文介绍了isDisplayed为Protractor中的可见元素返回false的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编辑#4 :突破!!

我开始递归遍历父节点并返回相同的值,如下所示。其中一个父母 - 内部 mat-drawer-container - 也为isDisplayed返回false(所有其他人返回true,这看起来很奇怪)。

I started recursively going through the parent nodes and returning the same values as below. One of the parents--the inner mat-drawer-container--also returned false for isDisplayed (all the others returned true, which seems odd).

看一下这个节点,结果证明它是网站上唯一一个拥有 CSS的标签:内容 即可。删除它会导致有问题的按钮 - 其下的所有其他内容 - 为isDisplayed返回true。哎呀,量角器甚至可以点击按钮,我可以在浏览器中看到预期的结果。

Looking at that node, it turns out that it's the only tag on the site to have the CSS of display: contents. Removing that causes the button in question--and everything else below it--to return true for isDisplayed. Heck, Protractor can even click the button and I can see the expected result in the browser.

现在我想问题仍然存在:这是预期的行为还是错误?它不像显示祖先那样简单:应用内容;我将它直接应用到 rb-container ,Protractor仍然可以找到按钮。

Now I suppose the question remains: is this is expected behavior or a bug? It's not as straightforward as there being an ancestor with display: contents applied; I applied it directly to rb-container and Protractor was still able to find the button.

我第一次在Protractor上进行端到端测试,在尝试测试按钮可见时遇到了问题。尽管按钮元素在DOM中并且可见,但isDisplayed返回false并且我的断言失败。

I'm working on end-to-end testing in Protractor for the first time, and I'm running into an issue when trying to test for a button being visible; despite the button element being in the DOM and visible, isDisplayed returns false and my assertion fails.

这是失败的初始断言:

expect(element(by.css("mat-drawer-content rb-container rb-fab-button[data-qaid='create-button'] > button")).isDisplayed()).toBe(true);

(是的,选择器很乱,但我无法控制HTML。)

(Yes, the selector is a mess, but I don't have control over the HTML.)

我使用了很长的browser.sleep()间隔来基本上暂停浏览器,所以我可以使用开发工具来检查人类可见的元素, CSS让我相信它应该被检测为可见。

I've used a long browser.sleep() interval to essentially pause the browser in place so I could use the dev tools to inspect the humanly-visible element, and the CSS leads me to believe it should be detected as visible.

在搜索答案和/或错误无效后,我将一些信息记录到控制台仍然领先我相信isDisplayed应该返回true:

After searching for answers and/or bugs to no avail, I logged some information to the console which still leads me to believe that isDisplayed should return true:

[ 编辑#2,#3:在所有直接上记录更多信息rb-container的孩子;根据量角器,只有一个节点是可见的。]

[ EDITS #2, #3: Logged some more information on all the direct children of rb-container; only one node is "visible", according to Protractor. ]

  let selector = element.all(by.tagName("mat-drawer-content")).get(0).all(by.css("rb-container > *"));

  selector.count().then(function(selCount) {

    for (let match = 0; match < selCount; match ++) {

      browser.sleep(1000).then(() => {
        let elm = selector.get(match);

        console.log("\n >> " + match + "]");

        elm.getTagName().then(tag => { console.log("tag name:", tag); });
        elm.getCssValue("visibility").then(vis => { console.log("visibility:", vis); });
        elm.getCssValue("display").then(disp => { console.log("display:", disp); });
        elm.getCssValue("opacity").then(opa => { console.log("opacity:", opa); });
        elm.getCssValue("overflow").then(ov => { console.log("overflow:", ov); });
        elm.getAttribute("hidden").then(hid => { console.log("hidden:", hid); });
        elm.getAttribute("class").then(c => { console.log("class:", c)});
        elm.getSize().then(size => { console.log("size:", size); });
        elm.getCssValue("position").then(ov => { console.log("position:", ov); });
        elm.getLocation().then(loc => { console.log("location:", loc); });
        elm.isPresent().then(pres => { console.log("isPresent:", pres); });
        elm.isDisplayed().then(disp => { console.log("isDisplayed:", disp); });
      });

    }

  });

这是我看到的记录:

 >> 0]
tag name: div
visibility: visible
display: block
opacity: 1
overflow: auto
hidden: null
class: title-tab dn db-m mediumGreyColor pl4 pv2 overflow-auto
size: { ceil: {},
  clone: {},
  floor: {},
  height: 62,
  round: {},
  scale: {},
  toString: {},
  width: 898 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 0,
  y: 74.765625 }
isPresent: true
isDisplayed: false

 >> 1]
tag name: div
visibility: visible
display: block
opacity: 1
overflow: auto
hidden: null
class: player-menu container overflow-auto dn db-m pv2 ng-star-inserted
size: { ceil: {},
  clone: {},
  floor: {},
  height: 64,
  round: {},
  scale: {},
  toString: {},
  width: 834 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 32,
  y: 136.765625 }
isPresent: true
isDisplayed: false

 >> 2]
tag name: rb-fab-button
visibility: visible
display: block
opacity: 1
overflow: visible
hidden: null
class: add-fab-button absolute dn db-m ng-star-inserted
size: { ceil: {},
  clone: {},
  floor: {},
  height: 56,
  round: {},
  scale: {},
  toString: {},
  width: 56 }
position: absolute
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 762,
  y: 154.765625 }
isPresent: true
isDisplayed: false

 >> 3]
tag name: div
visibility: visible
display: block
opacity: 1
overflow: visible
hidden: null
class: mr4-l w-100-m
size: { ceil: {},
  clone: {},
  floor: {},
  height: 0,
  round: {},
  scale: {},
  toString: {},
  width: 834 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 32,
  y: 200.765625 }
isPresent: true
isDisplayed: false

 >> 4]
tag name: rb-table-wrapper
visibility: visible
display: block
opacity: 1
overflow: visible
hidden: null
class: dn db-m
size: { ceil: {},
  clone: {},
  floor: {},
  height: 672,
  round: {},
  scale: {},
  toString: {},
  width: 834 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 32,
  y: 200.765625 }
isPresent: true
isDisplayed: true

 >> 5]
tag name: div
visibility: visible
display: block
opacity: 1
overflow: visible
hidden: null
class: container
size: { ceil: {},
  clone: {},
  floor: {},
  height: 0,
  round: {},
  scale: {},
  toString: {},
  width: 834 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 32,
  y: 872.5625 }
isPresent: true
isDisplayed: false

 >> 6]
tag name: rb-table-wrapper
visibility: visible
display: none
opacity: 1
overflow: visible
hidden: null
class: db dn-m
size: { ceil: {},
  clone: {},
  floor: {},
  height: 0,
  round: {},
  scale: {},
  toString: {},
  width: 0 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 0,
  y: 0 }
isPresent: true
isDisplayed: false

 >> 7]
tag name: div
visibility: visible
display: none
opacity: 1
overflow: auto
hidden: null
class: player-menu container overflow-auto db dn-m ng-star-inserted
size: { ceil: {},
  clone: {},
  floor: {},
  height: 0,
  round: {},
  scale: {},
  toString: {},
  width: 0 }
position: static
location: { ceil: {},
  clone: {},
  floor: {},
  round: {},
  scale: {},
  toString: {},
  translate: {},
  x: 0,
  y: 0 }
isPresent: true
isDisplayed: false

未设置隐藏属性,显示值不是无,可见性设置为可见,非零尺寸,我希望isDisplayed返回true。

With no hidden attribute set, a display value that isn't "none", visibility set to "visible", and non-zero size dimensions, I would expect isDisplayed to return true.

看一下节点4很有意思,isDisplayed的唯一子元素返回true,并将它与节点2进行比较,rb-fab-button元素我是试图访问。我能看到的唯一值得注意的差异是rb-fab-button绝对定位;但是,其他静态定位元素也会为isDisplayed返回false。

It's interesting to look at node 4, the only child element for which isDisplayed returns true, and compare it with node 2, the rb-fab-button element I'm trying to access. The only noticeable difference I can see is that rb-fab-button is positioned absolutely; however, the other statically-positioned elements also return false for isDisplayed.

我错过了什么吗?我决定检查css可见性,但我的下一个测试是单击该按钮,如果元素不可见则会出错。

Am I missing something? I'd settle for checking for css visibility, but my next test is to click that button, which errors if the element is not visible.

[ 编辑#1:添加了一些HTML:]

[ EDIT #1: Added some HTML: ]

<mat-drawer-container _ngcontent-c0="" class="root-container w-100 mat-drawer-container mat-drawer-container-explicit-backdrop" hasbackdrop="true" ng-reflect-has-backdrop="true">
    <div class="mat-drawer-backdrop ng-star-inserted"></div>
    <div tabindex="-1" class="cdk-visually-hidden cdk-focus-trap-anchor"></div>
    <mat-drawer _ngcontent-c0="" class="mobile-drawer dn-m w-80 mat-drawer ng-tns-c2-0 ng-trigger ng-trigger-transform mat-drawer-over ng-star-inserted" tabindex="-1" ng-reflect-mode="over" style="box-shadow: none; visibility: hidden;">
      <!-- [... mobile nav ...] -->
    </mat-drawer>
    <div tabindex="-1" class="cdk-visually-hidden cdk-focus-trap-anchor"></div>
    <mat-drawer-content _ngcontent-c0="" class="mat-drawer-content">
        <rb-navbar _ngcontent-c0="" _nghost-c7="" class="ng-star-inserted">
          <!-- [... nav bar ...] -->
        </rb-navbar>
        <div _ngcontent-c0="" class="main-body">
            <div _ngcontent-c0="" class="container h-100">
                <router-outlet _ngcontent-c0=""></router-outlet>
                <rb-system-setup _nghost-c18="" class="ng-star-inserted">
                    <router-outlet _ngcontent-c18=""></router-outlet>
                    <rb-site-tab class="ng-star-inserted">
                        <mat-drawer-container autosize="" class="mat-drawer-container" ng-reflect-autosize="">
                            <div class="mat-drawer-backdrop ng-star-inserted"></div>
                            <div tabindex="-1" class="cdk-visually-hidden cdk-focus-trap-anchor"></div>
                            <mat-drawer class="mat-drawer ng-tns-c2-8 ng-trigger ng-trigger-transform mat-drawer-end mat-drawer-over ng-star-inserted" disableclose="true" mode="over" position="end" tabindex="-1" ng-reflect-position="end" ng-reflect-mode="over" ng-reflect-disable-close="true" style="box-shadow: none; visibility: hidden;">
                                <rb-create-site _nghost-c20="" ng-reflect-side-panel="[object Object]" ng-reflect-side-panel-container="[object Object]" ng-reflect-ng-grid="[object Object]" ng-reflect-is-editing="false" ng-reflect-timezones="[object Object],[object Object">
                                    <rb-side-panel _ngcontent-c20="" _nghost-c24="" ng-reflect-title="Add Site" ng-reflect-close-button-label="Cancel" ng-reflect-submit-button-label="CREATE_SITE.SUBMIT" ng-reflect-show-submit-button="true" ng-reflect-modal-submitting="true" ng-reflect-side-panel-container="[object Object]">
                                      <!-- [... side panel ...] -->
                                    </rb-side-panel>
                                </rb-create-site>
                            </mat-drawer>
                            <div tabindex="-1" class="cdk-visually-hidden cdk-focus-trap-anchor"></div>
                            <mat-drawer-content cdkscrollable="" class="mat-drawer-content ng-star-inserted">
                                <div class="ph4-m h-100">
                                    <rb-card _nghost-c21="">
                                        <div _ngcontent-c21="" class="card rb-min-width-1 h-100">
                                            <div _ngcontent-c21="" class="relative h-100">
                                                <rb-container _nghost-c22="" ng-reflect-row-data="[object Object]" ng-reflect-show-player="true" ng-reflect-show-search-bar="true" ng-reflect-include-edit="true" ng-reflect-include-delete="true" ng-reflect-include-stop="false" ng-reflect-include-sync="false" ng-reflect-include-checkbox="true" ng-reflect-include-fab-button="true" ng-reflect-route-type="systemSetup" ng-reflect-header="Sites" ng-reflect-mobile-table="site" ng-reflect-show-site-selector="false" ng-reflect-mobile-navigation="true">
                                                    <div _ngcontent-c22="" class="title-tab dn db-m mediumGreyColor pl4 pv2 overflow-auto">
                                                        <h1 _ngcontent-c22="" class="header-text pa2 fl ng-star-inserted">Sites</h1></div>
                                                    <div _ngcontent-c22="" class="player-menu container overflow-auto dn db-m pv2 ng-star-inserted">
                                                      <!-- [... player menu ...] -->
                                                    </div>
                                                    <rb-fab-button _ngcontent-c22="" class="add-fab-button absolute dn db-m ng-star-inserted" data-qaid="create-button" _nghost-c28="">
                                                        <button _ngcontent-c28="" class="w-10 z-1 mat-fab mat-accent" mat-fab="" type="button" ng-reflect-disabled="false"><span class="mat-button-wrapper"><mat-icon _ngcontent-c28="" aria-label="add" class="mat-icon material-icons ng-star-inserted" role="img" aria-hidden="true">add</mat-icon></span>
                                                            <div class="mat-button-ripple mat-ripple mat-button-ripple-round" matripple="" ng-reflect-centered="false" ng-reflect-disabled="false" ng-reflect-trigger="[object HTMLButtonElement]"></div>
                                                            <div class="mat-button-focus-overlay"></div>
                                                        </button>
                                                    </rb-fab-button>
                                                    <div _ngcontent-c22="" class="mr4-l w-100-m"></div>
                                                    <rb-table-wrapper _ngcontent-c22="" class="dn db-m" ng-reflect-row-data="[object Object]" ng-reflect-enable-sorting="true" ng-reflect-include-checkbox="true" ng-reflect-is-clickable="false" ng-reflect-row-selection="multiple" ng-reflect-dom-layout="" ng-reflect-columns="[object Object],[object Object" ng-reflect-un-select-all_="[object Object]" ng-reflect-mobile-table="site" ng-reflect-mobile-navigation="true" ng-reflect-row-drag="false" ng-reflect-row-drag-field-name="">
                                                        <ag-grid-angular class="ag-theme-material" ng-reflect-grid-options="[object Object]" ng-reflect-row-data="[object Object]" ng-reflect-column-defs="[object Object],[object Object" ng-reflect-default-col-def="[object Object]" ng-reflect-row-selection="multiple" ng-reflect-suppress-row-click-selection="true" ng-reflect-enable-sorting="true" ng-reflect-enable-filter="true" ng-reflect-suppress-no-rows-overlay="true" ng-reflect-dom-layout="" ng-reflect-row-drag-managed="false">
                                                          <!-- [... data grid ...] -->
                                                        </ag-grid-angular>
                                                        <div class="backgroundColor w-100 fixed bottom-0 left-0 dn db-m ng-star-inserted">
                                                            <div class="item-selection fr w-20">0/ 1 Selected</div>
                                                        </div>
                                                    </rb-table-wrapper>
                                                    <div _ngcontent-c22="" class="player-menu container overflow-auto db dn-m ng-star-inserted"></div>
                                                </rb-container>
                                            </div>
                                        </div>
                                    </rb-card>
                                </div>
                            </mat-drawer-content>
                        </mat-drawer-container>
                    </rb-site-tab>
                </rb-system-setup>
            </div>
            <div _ngcontent-c0="" class="snacks fixed mw6 rb-min-width-2">
                <rb-global-snack-bar _ngcontent-c0="" _nghost-c8="" class="ng-tns-c8-3">
                    <div _ngcontent-c8="" class="snackBar">
                        <ul _ngcontent-c8="" class="ma0 pa0 list"></ul>
                    </div>
                </rb-global-snack-bar>
            </div>
        </div>
    </mat-drawer-content>
</mat-drawer-container>

推荐答案

我开始递归遍历父节点并返回相同的值,如下所示。其中一个父母 - 内部 mat-drawer-container - 也为isDisplayed返回false(所有其他人返回true,这看起来很奇怪)。

I started recursively going through the parent nodes and returning the same values as below. One of the parents--the inner mat-drawer-container--also returned false for isDisplayed (all the others returned true, which seems odd).

看一下这个节点,结果证明它是网站上唯一一个拥有 CSS的标签:内容 即可。删除它会导致有问题的按钮 - 其下的所有其他内容 - 为isDisplayed返回true。哎呀,量角器甚至可以点击按钮,我可以在浏览器中看到预期的结果。

Looking at that node, it turns out that it's the only tag on the site to have the CSS of display: contents. Removing that causes the button in question--and everything else below it--to return true for isDisplayed. Heck, Protractor can even click the button and I can see the expected result in the browser.

现在我想问题仍然存在:这是预期的行为还是错误?它不像显示祖先那样简单:应用内容;我将它直接应用到 rb-container ,Protractor仍然可以找到按钮。

Now I suppose the question remains: is this is expected behavior or a bug? It's not as straightforward as there being an ancestor with display: contents applied; I applied it directly to rb-container and Protractor was still able to find the button.

我打开了量角器GitHub上的一个问题,所以他们可以进一步了解它。

I opened an issue on the protractor GitHub so they could look further into it.

[更新:我已经在GitHub上更新了这个问题,但我想我也会在这里分享:]

[UPDATE: I've updated the issue on GitHub, but thought I'd share here as well:]

经过一番挖掘,我发现它是两种样式声明的组合: display:contents with 溢出:隐藏

After some digging, I've found that it's a combination of two style declarations: display: contents with overflow: hidden.

从表面上看,你不应该真正使用这些,因为你试图隐藏一个不存在的容器元素的溢出;但是,我觉得如果所述元素的孩子被浏览器显示出来 - 在这种情况下,它是 - 它可能应该被量角器检测为可见。

On the surface, it sounds like common sense that you shouldn't really use those together, since you're trying to hide the overflow of a container element that isn't really there; however, I feel if a child of said element is being rendered visibly by the browser--and in this case, it is--it probably should be detected as visible by protractor.

HTML / CSS:

The HTML/CSS:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>isDisplayed() issue</title>
    <style>

    .not-displayed .display-contents {
        overflow: hidden;
        display: contents; 
    }

    </style>
</head>
<body>

<div class="not-displayed">
    <div class="display-contents">
        <div class="wrong">isDisplayed() returns false</div>
    </div>
</div>

<div class="displayed">
    <div class="display-contents">
        <div class="right">isDisplayed() returns true</div>
    </div>
</div>

</body>
</html>

规格文件:

import { browser, by, element } from 'protractor';

describe('Testing the Protractor Bug', () => {

    it('should display debugging info', () => {

        browser.waitForAngularEnabled(false);
        browser.get('_[file location]_');

        element(by.css('.wrong')).isDisplayed().then(disp => { console.log('"wrong" isDisplayed:', disp); });
        element(by.css('.right')).isDisplayed().then(disp => { console.log('"right" isDisplayed:', disp); });

    });
});

该输出:

[17:04:50] I/launcher - Running 1 instances of WebDriver
[17:04:50] I/direct - Using ChromeDriver directly...

DevTools listening on ws://127.0.0.1:59412/devtools/browser/3f76f1a9-25f5-4497-8ae3-6933d01d0c7e
Jasmine started
"wrong" isDisplayed: false
"right" isDisplayed: true

  Testing the Protractor Bug
    √ should display debugging info

Executed 1 of 1 spec SUCCESS in 0.202 sec.
[17:04:53] I/launcher - 0 instance(s) of WebDriver still running
[17:04:53] I/launcher - chrome #01 passed

这篇关于isDisplayed为Protractor中的可见元素返回false的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆