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
});
});
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);
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.
Le plus simple est:
expect(element.getAttribute('class')).toContain("active");
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'
As-tu essayé...
var el = element(by.name('getoffer'));
expect(e.getAttribute('class')).toBe('ngDirty')
ou une variation de ce qui précède ...
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.
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);
};
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
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
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');
});
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);