Ik probeer Protractor uit om de Angular-app e2e te testen en heb niet ontdekt hoe ik kan detecteren of een element een specifieke klasse heeft of niet.
In mijn geval klikt de test op de verzendknop en nu wil ik weten of form[name=”getoffer”] klasse .ngDirty heeft. Wat kunnen de oplossingen zijn?
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
});
});
Antwoord 1, autoriteit 100%
Eén probleem waar u op moet letten bij het gebruik van toMatch()
, zoals in het geaccepteerde antwoord, zijn gedeeltelijke overeenkomsten. Laten we bijvoorbeeld zeggen dat je een element hebt met de klassen correct
en incorrect
, en dat je wilt testen of het de klasse correct
heeft. . Als u expect(element.getAttribute('class')).toMatch('correct')
zou gebruiken, wordt true geretourneerd, zelfs als het element de klasse incorrect
heeft .
Mijn suggestie:
Als je alleen exacte overeenkomsten wilt accepteren, kun je er een hulpmethode voor maken:
var hasClass = function (element, cls) {
return element.getAttribute('class').then(function (classes) {
return classes.split(' ').indexOf(cls) !== -1;
});
};
Je kunt het als volgt gebruiken (gebruik makend van het feit dat expect
automatisch beloften oplost in Protractor):
expect(hasClass(element(by.name('getoffer')), 'ngDirty')).toBe(true);
Antwoord 2, autoriteit 50%
Als je Protractor gebruikt met Jasmine, kun je toMatch
gebruiken om te matchen als een reguliere expressie…
expect(element(by.name('getoffer')).getAttribute('class')).toMatch('ngDirty');
Houd er ook rekening mee dat toContain
overeenkomt met lijstitems, als je dat nodig hebt.
Antwoord 3, autoriteit 17%
Het eenvoudigst is:
expect(element.getAttribute('class')).toContain("active");
Antwoord 4, autoriteit 4%
Op basis van het antwoord van Sergey K zou je hiervoor ook een aangepaste matcher kunnen toevoegen:
(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
)
})
)
Dan kun je het in tests als deze gebruiken:
expect($('div#ugly')).toHaveClass('beautiful')
En je krijgt de volgende foutmelding als dat niet het geval is:
Message:
Expected div#ugly to have class beautiful
Stacktrace:
Error: Expected div#ugly to have class 'beautiful'
Antwoord 5, autoriteit 4%
Heb je dit al geprobeerd?
const el = element(by.name('getoffer'));
expect(el.getAttribute('class')).toBe('ngDirty')
of een variatie op het bovenstaande…
Antwoord 6, autoriteit 2%
Ik heb deze matcher gemaakt, ik moest hem in een belofte verpakken en 2 retourzendingen gebruiken
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 mijn test kan ik nu dingen als deze doen:
var myDivs = element.all(by.css('div.myClass'));
expect(myDivs.count()).toBe(3);
// test for class
expect(myDivs.get(0)).not.toHaveClass('active');
dit werkt ook wanneer een element meerdere klassen heeft of wanneer een element helemaal geen class-attribuut heeft.
Antwoord 7, autoriteit 2%
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;
});
}
Dit is hoe ik het tenminste doe, zonder de verwachtingsfunctie te hoeven gebruiken. Deze functie retourneert gewoon waar als de klasse zich binnen het element bevindt en onwaar als dat niet het geval is. Dit gebruikt ook beloften, dus je zou het als volgt gebruiken:
checkHasClass('#your-element', 'your-class').then(function(class_found){
if (class_found) console.log("Your element has that class");
});
Bewerken: ik realiseer me net dat dit in wezen hetzelfde is als het bovenste antwoord
Antwoord 8
Hiereen Jasmine 1.3.x aangepaste toHaveClass
matcher met ontkenning .not
ondersteuning plus wacht tot 5 seconden (of wat je ook opgeeft).
Zoek de volledige aangepaste matcher die aan uw onPrepare-blok moet worden toegevoegd
Voorbeeldgebruik:
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');
});
Antwoord 9
Een manier om dit te bereiken is door xpath te gebruiken en contains()
te gebruiken
Voorbeeld:
var expectElementToHaveClass = function (className) {
var path = by.xpath("//div[contains(@class,'"+ className +"')]");
expect(element.all(path).count()).to.eventually.be.eq(1);
};
Antwoord 10
Je kunt de CSS-parser gebruiken om dit af te handelen door te controleren of een element met de opgegeven klasse bestaat:
expect(element(by.css('.form[name="getoffer"].ngDirty')).isPresent()).toBe(true);
Antwoord 11
In wezen lost u een aantal problemen op:
- hoe je les krijgt. class is een html-attribuut en kan dus worden opgehaald met dit commando (
await
is tegenwoordig de aanbevolen manier)
let class = await element.getAttribute('class')
- Zodra je de waarde van een klasse hebt gekregen, wil je deze laten gelden
// 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