wake-up-neo.com

Wie teste ich, ob ein Element eine Klasse mit Protractor hat?

Ich probiere Protractor für e2e test Angular App aus und habe nicht herausgefunden, wie man erkennt, ob ein Element eine bestimmte Klasse hat oder nicht.

In meinem Fall klickt der Test auf "Submit" und jetzt möchte ich wissen, ob form [name = "getoffer"] die Klasse .ngDirty hat. Was können die Lösungen sein?

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
    });
});
79
Allan Tatter

Ein Problem, auf das Sie bei der Verwendung von toMatch() achten müssen, wie in der akzeptierten Antwort, ist teilweise Übereinstimmung. Angenommen, Sie haben ein Element mit den Klassen correct und incorrect, und Sie möchten testen, dass es die Klasse correct hat. Wenn Sie expect(element.getAttribute('class')).toMatch('correct') verwenden würden, wird true zurückgegeben, auch wenn das Element die incorrect-Klasse hat.

Mein Vorschlag:

Wenn Sie nur exakte Übereinstimmungen akzeptieren möchten, können Sie dazu eine Hilfsmethode erstellen:

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

Sie können es so verwenden (die Tatsache ausnutzen, dass expect Versprechungen in Protractor automatisch löst):

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

Wenn Sie Protractor mit Jasmine verwenden, können Sie toMatch als regulären Ausdruck verwenden ...

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

Beachten Sie auch, dass toContain mit Listenelementen übereinstimmt, falls Sie dies benötigen.

52
ryan.l

Am einfachsten ist:

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

Basierend auf der Antwort von Sergey K können Sie dazu auch einen benutzerdefinierten Matcher hinzufügen:

(Kaffeeskript)

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

Dann können Sie es in Tests wie folgt verwenden:

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

Wenn dies nicht der Fall ist, wird folgende Fehlermeldung angezeigt:

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

Hast du es versucht...

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

oder eine Variation der oben genannten ...

3
James Dykes

Ich habe diesen Matcher gemacht, ich musste ihn in ein Versprechen einpacken und 2 Retouren verwenden

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

in meinem test kann ich jetzt stuf so machen:

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

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

dies funktioniert auch, wenn ein Element mehrere Klassen hat oder wenn ein Element überhaupt kein Klassenattribut hat.

2
Michiel

Eine Möglichkeit, dies zu erreichen, wäre xpath und contains() zu verwenden.

Beispiel: 

var expectElementToHaveClass = function (className) {
    var path = by.xpath("//div[contains(@class,'"+ className +"')]");
    expect(element.all(path).count()).to.eventually.be.eq(1);
};
1
Chanthu
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;
    });
}

So mache ich es zumindest, ohne die Expect-Funktion verwenden zu müssen. Diese Funktion gibt einfach true zurück, wenn sich die Klasse innerhalb des Elements befindet, und false, wenn nicht. Dies verwendet auch Versprechen, so dass Sie es wie folgt verwenden würden:

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

Edit: Ich habe gerade gemerkt, dass dies im Wesentlichen der Top-Antwort entspricht

1
Sir Neuman

Hier ein Jasmine 1.3.x-benutzerdefinierter toHaveClass-Matcher mit Negation .not-Unterstützung plus Wartezeit bis zu 5 Sekunden (oder was auch immer Sie angeben).

Finden Sie den vollständigen benutzerdefinierten Matcher, der in Ihrem onPrepare-Block in dieser Gist hinzugefügt werden soll

Verwendungsbeispiel:

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
Leo Gallucci

Mit dem CSS-Parser können Sie dies umgehen, indem Sie prüfen, ob ein Element mit der angegebenen Klasse vorhanden ist:

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