如何使用Protractor测试元素是否具有类?

时间:2013-11-28 14:01:33

标签: angularjs protractor

我正在尝试使用Protractor来测试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
    });
});

11 个答案:

答案 0 :(得分:98)

你必须注意使用toMatch(),因为在接受的答案中,是部分匹配。例如,假设您有一个可能包含类correctincorrect的元素,并且您想测试它是否具有类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自动解决Protractor中的承诺这一事实):

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

答案 1 :(得分:53)

如果您使用带有Jasmine的量角器,您可以使用toMatch作为正则表达式进行匹配...

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

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

答案 2 :(得分:16)

最简单的是:

expect(element.getAttribute('class')).toContain("active");

答案 3 :(得分:4)

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

(CoffeeScript的)

  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'

答案 4 :(得分:3)

你试过......

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

或以上的变体......

答案 5 :(得分:2)

我制作了这个匹配器,我必须将它包装在一个承诺中并使用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);
        });
    }
});

在我的测试中我现在可以这样做了:

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

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

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

答案 6 :(得分:1)

Here一个Jasmine 1.3.x自定义toHaveClass匹配器,支持否定.not加上等待最多5秒(或您指定的任何内容)。

Find the full custom matcher to be added on your onPrepare block in this gist

样本用法:

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');
});

答案 7 :(得分: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。这也使用promises,所以你可以使用它:

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

编辑:我刚刚意识到这与最佳答案基本相同

答案 8 :(得分: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);
};

答案 9 :(得分:1)

本质上,您正在解决一些问题:

  1. 如何上课。 class 是一个 html 属性,因此可以通过此命令检索(await 是目前推荐的方式)
let class = await element.getAttribute('class')
  1. 获得类的值后,您想对其进行断言
// for exact value
expect(class).toBe("active");

// for partial match
expect(class).toContain("active");
// or
expect(class.includes("active")).toBe(true);

// BUT, keep in mind
expect('male').toContain('male');
expect('female').toContain('male');
// BOTH pass

答案 10 :(得分:0)

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

expect(element(by.css('.form[name="getoffer"].ngDirty')).isPresent()).toBe(true);