如何使用量角器测试元素是否具有类?


90

我正在尝试量角器以e2e测试Angular应用程序,但还没有弄清楚如何检测元素是否具有特定的类。

就我而言,测试单击了提交按钮,现在我想知道form [name =“ getoffer”]是否具有类.ngDirty。有什么解决方案?

describe('Contact form', function() {
    beforeEach(function(){
        browser.get('http://localhost:9000');
        element(by.linkText('Contact me')).click();
    });

    it('should fail form validation, all fields pristine', function() {
        element(by.css('.form[name="getoffer"] input[type="submit"]')).click();
        expect(element(by.name('getoffer'))).toHaveClass('ngDirty'); // <-- This line
    });
});

Answers:


110

您必须使用来寻找一个陷阱toMatch(),就像在接受的答案中一样,就是部分匹配。例如,假设您有一个可能包含类correct和的元素incorrect,并且您想测试它是否具有类correct。如果要使用expect(element.getAttribute('class')).toMatch('correct'),即使元素具有incorrect类,也将返回true 。

我的建议:

如果您只想接受完全匹配,则可以为其创建一个辅助方法:

var hasClass = function (element, cls) {
    return element.getAttribute('class').then(function (classes) {
        return classes.split(' ').indexOf(cls) !== -1;
    });
};

您可以这样使用它(利用expect自动在量角器中兑现承诺的事实):

expect(hasClass(element(by.name('getoffer')), 'ngDirty')).toBe(true);

1
这对我expect(hasClass(element(by.name('getoffer')), 'ng-dirty')).toBe(true);
有用

我不清楚类的功能在做什么,特别是当传递给.then函数时,类在哪里或什么类,有人能启发我吗?
ErikAGriffin 2015年

@ErikAGriffin:hasClass函数传递了两个参数-一个html元素和要检查的类的名称。然后,该函数获取元素具有的“类”属性(类)。它拆分类字符串以获取类数组。然后,它检查您要查找的类是否在数组的任何正索引中。我认为这是一种检查存在性的方法。
VSO 2015年

我已将您的四行函数重写为这种性感的ES6衬板:hasClass =(element,className)=> element.getAttribute('class')。then((classes)=> classes.split('').indexOf( className)!== -1);
LaurensMäkel'18

在TypeScript中:异步函数hasClass(elm:ElementFinder,className:string):Promise <boolean> {const classNamesStr:string =等待elm.getAttribute('class'); const classNamesArr:string [] = classNamesStr.split(''); 返回classNamesArr.includes(className); }
tedw

56

如果您将量角器与Jasmine一起使用toMatch,则可以使用match作为正则表达式...

expect(element(by.name('getoffer')).getAttribute('class')).toMatch('ngDirty');

另外,请注意toContain,如果需要,它将与列表项匹配。


1
我不确定这是否是理想的方法,但至少它能按预期工作:)
艾伦·塔特

1
不,我想可能不是。我希望element返回一个带有hasClass方法的对象,您可以将其包装在expect调用中...
ryan.l 2013年

2
toContain可能比toMatch这种情况下更好的选择。
TrueWill

如果要防止部分比赛,请尝试类似/(^|\s)ngDirty($|\s)/
安德鲁·迈尔斯

您可能可以.not.toContain用来检查它是否不具有特定的类,或者.toContain用于检查它是否存在
Jack


4

根据Sergey K的回答,您还可以添加一个自定义匹配器来执行此操作:

(咖啡)

  beforeEach(()->
    this.addMatchers({
      toHaveClass: (expected)->
        @message = ()->
          "Expected #{@actual.locator_.value} to have class '#{expected}'"

        @actual.getAttribute('class').then((classes)->
          classes.split(' ').indexOf(expected) isnt -1
        )
    })
  )

然后,您可以在如下测试中使用它:

expect($('div#ugly')).toHaveClass('beautiful')

如果没有,则会出现以下错误:

 Message:
   Expected div#ugly to have class beautiful
 Stacktrace:
   Error: Expected div#ugly to have class 'beautiful'

3

你有没有尝试过...

var el = element(by.name('getoffer'));
expect(e.getAttribute('class')).toBe('ngDirty')

或以上的变化...


5
问题在于,该表单具有多个附加的类。
艾伦·塔特

2

我做了这个匹配器,我不得不把它包装在一个Promise中并使用2个返回值

this.addMatchers({
    toHaveClass: function(a) {
        return this.actual.getAttribute('class').then(function(cls){
            var patt = new RegExp('(^|\\s)' + a + '(\\s|$)');
            return patt.test(cls);
        });
    }
});

在我的测试中,我现在可以像这样做stuf:

   var myDivs = element.all(by.css('div.myClass'));
   expect(myDivs.count()).toBe(3);

   // test for class
   expect(myDivs.get(0)).not.toHaveClass('active');

当一个元素具有多个类或一个元素根本没有class属性时,这也适用。


1

在这里,一个toHaveClass带有否定.not支持的Jasmine 1.3.x自定义匹配器加上最多5秒的等待时间(或您指定的任何时间)。

在此要点中找到要添加到onPrepare块中的完整自定义匹配器

用法示例:

it('test the class finder custom matcher', function() {
    // These guys should pass OK given your user input
    // element starts with an ng-invalid class:
    expect($('#user_name')).toHaveClass('ng-invalid');
    expect($('#user_name')).not.toHaveClass('ZZZ');
    expect($('#user_name')).toNotHaveClass('ZZZ');
    expect($('#user_name')).not.toNotHaveClass('ng-invalid');
    // These guys should each fail:
    expect($('#user_name')).toHaveClass('ZZZ');
    expect($('#user_name')).not.toHaveClass('ng-invalid');
    expect($('#user_name')).toNotHaveClass('ng-invalid');
    expect($('#user_name')).not.toNotHaveClass('ZZZ');
});

1
function checkHasClass (selector, class_name) {
    // custom function returns true/false depending if selector has class name

    // split classes for selector into a list
    return $(selector).getAttribute('class').then(function(classes){
        var classes = classes.split(' ');
        if (classes.indexOf(class_name) > -1) return true;
        return false;
    });
}

至少我是这样做的,不需要使用Expect函数。如果类在元素内部,则此函数仅返回true,否则返回false。这也使用了promise,因此您可以像这样使用它:

checkHasClass('#your-element', 'your-class').then(function(class_found){
    if (class_found) console.log("Your element has that class");
});

编辑:我只是意识到这基本上是最佳答案


1

实现此目的的一种方法是使用xpath并使用 contains()

例:

var expectElementToHaveClass = function (className) {
    var path = by.xpath("//div[contains(@class,'"+ className +"')]");
    expect(element.all(path).count()).to.eventually.be.eq(1);
};

0

您可以使用CSS解析器通过检查是否存在具有给定类的元素来处理此问题:

expect(element(by.css('.form[name="getoffer"].ngDirty')).isPresent()).toBe(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.