如何使用量角器检查元素是否可见?


111

我正在尝试使用量角器测试元素是否可见。元素的外观如下:

<i class="icon-spinner icon-spin ng-hide" ng-show="saving"></i>

在chrome控制台中时,我可以使用此jQuery选择器测试该元素是否可见:

$('[ng-show=saving].icon-spin')
[
<i class=​"icon-spinner icon-spin ng-hide" ng-show=​"saving">​</i>​
]
> $('[ng-show=saving].icon-spin:visible')
[]

但是,当我尝试在量角器中执行相同操作时,在运行时出现此错误:

InvalidElementStateError: 
invalid element state: Failed to execute 'querySelectorAll' on 'Document': 
'[ng-show=saving].icon-spin:visible' is not a valid selector.

为什么这无效?如何使用量角器检查可见性?


嘿@limp_chimp我的以下回答对您有帮助吗?
Leo Gallucci 2014年

对于可见性之类的@limp_chimp,请考虑使用AngularJS客户端DOM单元测试。它们运行起来更快,更容易开发。
Offirmo 2014年

Answers:


144

应该这样做:

expect($('[ng-show=saving].icon-spin').isDisplayed()).toBe(true);

记住量角器的$不是jQuery和:visible的一部分提供CSS选择器+伪选择

有关更多信息,访问https://stackoverflow.com/a/13388700/511069


1
真是的 非常酷。这正是我需要确定的。非常感谢老兄。
racl101

2
下面的答案也可以使用,isDisplayed()但可以扩展为解决完整性问题,尽管该步骤是可选的,并且仅意味着在测试中包含条件,这是一种不好的做法。@asenovm您能否进一步阐述您的“这是完全错误的”评论?
Leo Gallucci

@LeoGallucci,isDisplayed()返回ElementFinder而不是布尔值。
asenovm '16

1
请不要使用.toBeTruthy();use .toBe(true)来代替。.toBeTruthy();将匹配[],'false',42之类的东西。基本上任何期望为0,“”,null,undefined,NaN或false都是真实的。
布莱恩

78

使用量角器检查元素可见性的正确方法是调用该isDisplayed方法。但是您应该小心,因为isDisplayed它不会返回布尔值,而是会promise提供评估后的可见性。我见过很多错误使用此方法的代码示例,因此不评估其实际可见性。

获取元素可见性的示例:

element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
    if (isVisible) {
        // element is visible
    } else {
        // element is not visible
    }
});

但是,如果只检查元素的可见性(而不是获取它),则不需要此方法,因为量角器修补了Jasmine Expect(),因此它总是等待promise得以解决。见github.com/angular/jasminewd

因此,您可以执行以下操作:

expect(element(by.className('your-class-name')).isDisplayed()).toBeTruthy();

由于您AngularJS用来控制该元素的可见性,因此您还可以ng-hide像这样检查其class属性:

var spinner = element.by.css('i.icon-spin');
expect(spinner.getAttribute('class')).not.toMatch('ng-hide'); // expect element to be visible

8

我有一个类似的问题,因为我只想要在页面对象中可见的return元素。我发现我可以使用CSS了:not。如果是这个问题,您应该这样做...

expect($('i.icon-spinner:not(.ng-hide)').isDisplayed()).toBeTruthy();

在页面对象的上下文中,您也只能获取以这种方式可见的那些元素。例如。给定一个包含多个项目的页面,其中只有一些可见,您可以使用:

this.visibileIcons = $$('i.icon:not(.ng-hide)'); 

这将返回所有可见的i.icons


1
isDisplayed()应该在@leoGallucci解释的预期范围内。
2015年

5

DOM中是否有多个具有相同类名的元素。但是只有一个元素可见。

element.all(by.css('.text-input-input')).filter(function(ele){
        return ele.isDisplayed();
    }).then(function(filteredElement){
        filteredElement[0].click();
    });

在此示例中,filter接受元素的集合,并使用isDisplayed()返回单个可见元素。


这是一个很好的答案。考虑没有这种元素的情况!$('。text-input-input')会优雅地警告用户;这可能会失败,因为filteredElement.length === 0
红豌豆

1

这个答案将足够健壮,可以处理不在页面上的元素,因此,如果选择器未能找到该元素,则该错误将优雅地出现(不会引发异常)。

const nameSelector = '[data-automation="name-input"]';
const nameInputIsDisplayed = () => {
    return $$(nameSelector).count()
        .then(count => count !== 0)
}
it('should be displayed', () => {
    nameInputIsDisplayed().then(isDisplayed => {
        expect(isDisplayed).toBeTruthy()
    })
})

1

等待可见性

const EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(element(by.css('.icon-spinner icon-spin ng-hide')))).then(function() {
  //do stuff
})

Xpath技巧只查找可见元素

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))

1
 element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
if (isVisible) {
    // element is visible
} else {
    // element is not visible
}
}).catch(function(err){
console.log("Element is not found");
})

0

这是一些可用于使用Typescript,protractor,jasmine的框架的代码段

browser.wait(until.visibilityOf(OversightAutomationOR.lblContentModal), 3000, "Modal text is present");

//声明文本

OversightAutomationOR.lblContentModal.getText().then(text => {
                    this.assertEquals(text.toString().trim(), AdminPanelData.lblContentModal);
                });

//声明一个元素

expect(OnboardingFormsOR.masterFormActionCloneBtn.isDisplayed()).to.eventually.equal(true

    );

OnboardingFormsOR.customFormActionViewBtn.isDisplayed().then((isDisplayed) => {
                        expect(isDisplayed).to.equal(true);
                });

//声明一个表单

formInfoSection.getText().then((text) => {
                        const vendorInformationCount = text[0].split("\n");
                        let found = false;
                        for (let i = 0; i < vendorInformationCount.length; i++) {
                            if (vendorInformationCount[i] === customLabel) {
                                found = true;
                            };
                        };
                        expect(found).to.equal(true);
                    });     
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.