Как проверить, имеет ли элемент класс с помощью Protractor?

Я пытаюсь использовать Protractor для тестирования e2e Angular и не понял, как определить, имеет ли элемент определенный класс или нет.

В моем случае тест нажимает кнопку отправки, и теперь я хочу знать, имеет ли форма [ 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
    });
});

Ответ 1

Один из них, который вы должны искать с помощью toMatch(), как и в принятом ответе, - это частичные совпадения. Например, предположим, что у вас есть элемент, который может иметь классы correct и incorrect, и вы хотите проверить, что он имеет класс correct. Если бы вы использовали expect(element.getAttribute('class')).toMatch('correct'), это вернет true, даже если элемент имеет класс incorrect.

Мое предложение:

Если вы хотите принимать только точные соответствия, вы можете создать для него вспомогательный метод:

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

Вы можете использовать его так (воспользовавшись тем, что expect автоматически разрешает promises в Protractor):

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

Ответ 2

Если вы используете Protractor с Jasmine, вы можете использовать toMatch для соответствия регулярному выражению...

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

Также обратите внимание, что toContain будет соответствовать элементам списка, если вам это нужно.

Ответ 3

Проще всего:

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

Ответ 4

Вы пробовали...

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

или вариант выше...

Ответ 5

Основываясь на ответе Сергея К, вы также можете добавить пользовательский матчи для этого:

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

Ответ 6

Я сделал этот помощник, мне пришлось обернуть его обещанием и использовать 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');

это также работает, когда элемент имеет несколько классов или когда элемент вообще не имеет атрибута класса.

Ответ 7

Здесь настраиваемый toHaveClass шаблон Jasmine 1.3.x с поддержкой отрицания .not плюс ожидание до 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');
});

Ответ 8

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

Вот как я это делаю, по крайней мере, без необходимости использовать функцию ожидания. Эта функция просто возвращает значение true, если класс находится внутри элемента, а false - нет. Это также использует promises, чтобы вы использовали его как:

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

Изменить: я просто понял, что это по сути то же самое, что и главный ответ

Ответ 9

Один из способов добиться этого - использовать xpath и использовать contains()

Пример:

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