web-dev-qa-db-fra.com

Comment tester si un élément a une classe utilisant Protractor?

J'essaie Protractor to e2e à tester l'application Angular et je n'ai pas trouvé comment détecter si un élément a une classe spécifique ou non.

Dans mon cas, le test clique sur le bouton d'envoi et je souhaite maintenant savoir si le formulaire [name = "getoffer"] a la classe .ngDirty. Quelles peuvent être les solutions?

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

Il faut chercher avec toMatch(), comme dans la réponse acceptée, des correspondances partielles. Par exemple, supposons que vous ayez un élément qui pourrait avoir les classes correct et incorrect et que vous voulez vérifier qu'il a la classe correct. Si vous utilisiez expect(element.getAttribute('class')).toMatch('correct'), cela renverra true même si l'élément a la classe incorrect.

Ma suggestion:

Si vous voulez n'accepter que les correspondances exactes, vous pouvez créer une méthode d'assistance pour cela:

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

Vous pouvez l'utiliser comme ceci (en tirant parti du fait que expect résout automatiquement les promesses dans Protractor):

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

Si vous utilisez Protractor avec Jasmine, vous pouvez utiliser toMatch pour faire correspondre une expression régulière ...

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

Notez également que toContain correspondra aux éléments de la liste, si vous en avez besoin.

52
ryan.l

Le plus simple est:

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

Sur la base de la réponse de Sergey K, vous pouvez également ajouter un élément de correspondance personnalisé pour ce faire:

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

Ensuite, vous pouvez l'utiliser dans des tests comme celui-ci:

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

Et vous obtiendrez l'erreur suivante si ce n'est pas le cas:

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

As-tu essayé...

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

ou une variation de ce qui précède ...

3
James Dykes

J'ai fabriqué cet accessoire, je devais l'envelopper dans une promesse et utiliser 2 déclarations

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

dans mon test je peux maintenant faire stuf comme ceci:

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

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

cela fonctionne aussi lorsqu'un élément a plusieurs classes ou lorsqu'un élément n'a aucun attribut de classe.

2
Michiel

Une façon d'y parvenir serait d'utiliser xpath et d'utiliser contains()

Exemple: 

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

C'est comme ça que je le fais au moins, sans avoir besoin d'utiliser la fonction expect. Cette fonction retourne simplement true si la classe est à l'intérieur de l'élément et false sinon. Ceci utilise aussi des promesses pour que vous l'utilisiez comme:

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

Edit: Je viens de me rendre compte que c'est essentiellement la même chose que la réponse du haut

1
Sir Neuman

Ici un matcher toHaveClass personnalisé de Jasmine 1.3.x avec le support de négation .not et attendez jusqu'à 5 secondes (ou tout ce que vous spécifiez).

Trouvez le matcher personnalisé complet à ajouter sur votre bloc onPrepare dans ce Gist

Exemple d'utilisation:

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

Vous pouvez utiliser l'analyseur CSS pour gérer cela en vérifiant si un élément avec la classe donnée existe:

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