Wie prüfe ich mit einem Winkelmesser, ob ein Element sichtbar ist?

111

Ich versuche mit einem Winkelmesser zu testen, ob ein Element sichtbar ist. So sieht das Element aus:

<i class="icon-spinner icon-spin ng-hide" ng-show="saving"></i>

In der Chrome-Konsole kann ich mit diesem jQuery-Selektor testen, ob das Element sichtbar ist:

$('[ng-show=saving].icon-spin')
[
<i class=​"icon-spinner icon-spin ng-hide" ng-show=​"saving">​</i>​
]
> $('[ng-show=saving].icon-spin:visible')
[]

Wenn ich jedoch versuche, dasselbe in Winkelmesser zu tun, wird zur Laufzeit der folgende Fehler angezeigt:

InvalidElementStateError: 
invalid element state: Failed to execute 'querySelectorAll' on 'Document': 
'[ng-show=saving].icon-spin:visible' is not a valid selector.

Warum ist das nicht gültig? Wie kann ich mit einem Winkelmesser die Sichtbarkeit überprüfen?

limp_chimp
quelle
Hey @limp_chimp hat dir meine unten stehende Antwort geholfen?
Leo Gallucci
@limp_chimp Denken Sie unter anderem an die Verwendung von AngularJS-Client-DOM-Komponententests. Sie sind viel schneller zu betreiben und einfacher zu entwickeln.
Offirmo

Antworten:

144

Dies sollte es tun:

expect($('[ng-show=saving].icon-spin').isDisplayed()).toBe(true);

Denken Sie daran, dass Winkelmesser $nicht jQuery sind und :visiblenoch nicht Teil der verfügbaren CSS-Selektoren + Pseudo-Selektoren sind

Weitere Informationen unter https://stackoverflow.com/a/13388700/511069

Leo Gallucci
quelle
1
Oh Mann. So cool. Genau das musste ich feststellen können. Vielen Dank, Alter.
racl101
2
In der folgenden Antwort wird auch isDisplayed()das Versprechen der Vollständigkeit verwendet, aber nur erweitert, um es zu lösen. Dieser Schritt ist jedoch optional und nur dazu gedacht, Bedingungen in Ihre Tests aufzunehmen, was eine schlechte Praxis ist. @asenovm Kannst du deinen Kommentar "Das ist einfach falsch" weiter ausarbeiten?
Leo Gallucci
@LeoGallucci, isDisplayed () gibt ElementFinder und keinen Booleschen Wert zurück.
Asenovm
1
Bitte .toBeTruthy();verwenden Sie .toBe(true)stattdessen nicht use . .toBeTruthy();wird mit Dingen wie [], 'false', 42 übereinstimmen. Grundsätzlich ist alles, was 0, "", null, undefined, NaN oder false erwartet, wahr.
Brian
78

Die korrekte Methode zum Überprüfen der Sichtbarkeit eines Elements mit Winkelmesser besteht darin, die isDisplayedMethode aufzurufen . Sie sollten jedoch vorsichtig sein, da isDisplayedkein Boolescher Wert zurückgegeben wird, sondern promisedie ausgewertete Sichtbarkeit bereitgestellt wird. Ich habe viele Codebeispiele gesehen, die diese Methode falsch verwenden und daher ihre tatsächliche Sichtbarkeit nicht bewerten.

Beispiel für die Sichtbarkeit eines Elements:

element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
    if (isVisible) {
        // element is visible
    } else {
        // element is not visible
    }
});

Sie benötigen dies jedoch nicht, wenn Sie nur die Sichtbarkeit des Elements überprüfen (anstatt es zu erhalten), da die Winkelmesser-Patches, die Jasmine erwartet (), immer darauf warten, dass Versprechen gelöst werden. Siehe github.com/angular/jasminewd

Sie können also einfach Folgendes tun:

expect(element(by.className('your-class-name')).isDisplayed()).toBeTruthy();

Da Sie AngularJSdie Sichtbarkeit dieses Elements steuern, können Sie das Klassenattribut auch folgendermaßen überprüfen ng-hide:

var spinner = element.by.css('i.icon-spin');
expect(spinner.getAttribute('class')).not.toMatch('ng-hide'); // expect element to be visible
Mobiletainment
quelle
8

Ich hatte ein ähnliches Problem, da ich nur Rückgabeelemente wollte, die in einem Seitenobjekt sichtbar waren. Ich habe festgestellt, dass ich das CSS verwenden kann :not. Im Fall dieses Problems sollten Sie dies tun ...

expect($('i.icon-spinner:not(.ng-hide)').isDisplayed()).toBeTruthy();

Im Kontext eines Seitenobjekts können Sie NUR die Elemente erhalten, die auch auf diese Weise sichtbar sind. Z.B. Bei einer Seite mit mehreren Elementen, auf der nur einige sichtbar sind, können Sie Folgendes verwenden:

this.visibileIcons = $$('i.icon:not(.ng-hide)'); 

Dies gibt Ihnen alle sichtbaren i.icons zurück

Sole
quelle
1
isDisplayed () sollte im erwarteten Bereich liegen, wie @leoGallucci es erklärt hat.
Gestreift
5

Wenn das DOM mehrere Elemente mit demselben Klassennamen enthält. Es ist jedoch nur eines der Elemente sichtbar.

element.all(by.css('.text-input-input')).filter(function(ele){
        return ele.isDisplayed();
    }).then(function(filteredElement){
        filteredElement[0].click();
    });

In diesem Beispiel nimmt der Filter eine Sammlung von Elementen und gibt mit isDisplayed () ein einzelnes sichtbares Element zurück .

Ein Qadeer Qureshi
quelle
Dies ist eine großartige Antwort. Betrachten Sie den Fall, in dem es kein solches Element gibt! $ ('. Texteingabe-Eingabe') würde den Benutzer elegant alarmieren; das könnte scheitern weil filteredElement.length === 0?
Die rote Erbse
1

Diese Antwort ist robust genug, um für Elemente zu funktionieren, die sich nicht auf der Seite befinden. Sie schlägt daher ordnungsgemäß fehl (ohne eine Ausnahme auszulösen), wenn der Selektor das Element nicht gefunden hat.

const nameSelector = '[data-automation="name-input"]';
const nameInputIsDisplayed = () => {
    return $$(nameSelector).count()
        .then(count => count !== 0)
}
it('should be displayed', () => {
    nameInputIsDisplayed().then(isDisplayed => {
        expect(isDisplayed).toBeTruthy()
    })
})
activedecay
quelle
1

Auf Sichtbarkeit warten

const EC = protractor.ExpectedConditions;
browser.wait(EC.visibilityOf(element(by.css('.icon-spinner icon-spin ng-hide')))).then(function() {
  //do stuff
})

Xpath-Trick, um nur sichtbare Elemente zu finden

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))
Drew Royster
quelle
1
 element(by.className('your-class-name')).isDisplayed().then(function (isVisible) {
if (isVisible) {
    // element is visible
} else {
    // element is not visible
}
}).catch(function(err){
console.log("Element is not found");
})
Anil kumar
quelle
0

Hier sind die wenigen Codefragmente, die für Frameworks verwendet werden können, die Typescript, Winkelmesser und Jasmin verwenden

browser.wait(until.visibilityOf(OversightAutomationOR.lblContentModal), 3000, "Modal text is present");

// Einen Text bestätigen

OversightAutomationOR.lblContentModal.getText().then(text => {
                    this.assertEquals(text.toString().trim(), AdminPanelData.lblContentModal);
                });

// Ein Element bestätigen

expect(OnboardingFormsOR.masterFormActionCloneBtn.isDisplayed()).to.eventually.equal(true

    );

OnboardingFormsOR.customFormActionViewBtn.isDisplayed().then((isDisplayed) => {
                        expect(isDisplayed).to.equal(true);
                });

// Ein Formular bestätigen

formInfoSection.getText().then((text) => {
                        const vendorInformationCount = text[0].split("\n");
                        let found = false;
                        for (let i = 0; i < vendorInformationCount.length; i++) {
                            if (vendorInformationCount[i] === customLabel) {
                                found = true;
                            };
                        };
                        expect(found).to.equal(true);
                    });     
Khyati Sehgal
quelle