Jak używać kątomierza, aby sprawdzić, czy element jest widoczny?


111

Próbuję sprawdzić, czy element jest widoczny za pomocą kątomierza. Oto jak wygląda element:

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

Będąc w konsoli chrome mogę użyć tego selektora jQuery, aby sprawdzić, czy element jest widoczny:

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

Jednak gdy próbuję zrobić to samo w kątomierzu, pojawia się ten błąd w czasie wykonywania:

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

Dlaczego to nie jest ważne? Jak mogę sprawdzić widoczność za pomocą kątomierza?


Hej @limp_chimp, czy moja poniższa odpowiedź ci pomogła?
— Leo Gallucci

@limp_chimp w przypadku takich rzeczy jak widoczność, pomyśl o użyciu testów jednostkowych DOM klienta AngularJS. Są znacznie szybsze w biegu i łatwiejsze w rozwoju.
— Offirmo

Odpowiedzi:


144

To powinno wystarczyć:

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

Pamiętaj, że kątomierz $nie jest jQuery i :visiblenie jest jeszcze częścią dostępnych selektorów CSS + pseudoselektorów

Więcej informacji na https://stackoverflow.com/a/13388700/511069


1
Ah człowieku. Ale fajnie. To jest dokładnie to, czego potrzebowałem, aby móc to określić. Dziękuję bardzo stary.
— racl101

2
Poniższa odpowiedź również wykorzystuje, isDisplayed()ale tylko rozszerza obietnicę kompletności, chociaż ten krok jest opcjonalny i przeznaczony tylko do włączenia warunków warunkowych do twoich testów, co jest złą praktyką. @asenovm Czy możesz bardziej szczegółowo rozwinąć swój komentarz „To jest po prostu zły”?
— Leo Gallucci,

@LeoGallucci, isDisplayed () zwraca ElementFinder, a nie wartość logiczną.
— asenovm

1
Proszę nie .toBeTruthy();używać .toBe(true)zamiast tego. .toBeTruthy();dopasuje takie elementy jak [], 'false', 42. W zasadzie wszystko, czego oczekuje się od 0, "", null, undefined, NaN lub false jest prawdziwe.
— Brian

78

Prawidłowym sposobem sprawdzenia widoczności elementu za pomocą Protractor jest wywołanie isDisplayedmetody. Należy jednak zachować ostrożność, ponieważ isDisplayednie zwraca wartości logicznej, a raczej promisezapewnia oszacowaną widoczność. Widziałem wiele przykładów kodu, które nieprawidłowo używają tej metody i dlatego nie oceniają jej rzeczywistej widoczności.

Przykład uzyskania widoczności elementu:

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

Jednak nie jest to potrzebne, jeśli po prostu sprawdzasz widoczność elementu (w przeciwieństwie do uzyskiwania go), ponieważ Jasmine patrzy na kątomierz, więc zawsze czeka na rozwiązanie obietnic. Zobacz github.com/angular/jasminewd

Możesz więc po prostu:

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

Ponieważ używasz AngularJSdo kontrolowania widoczności tego elementu, możesz również sprawdzić jego atrybut class w ng-hidenastępujący sposób:

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

8

Miałem podobny problem, ponieważ chciałem zwrócić tylko te elementy, które były widoczne w obiekcie strony. Okazało się, że jestem w stanie korzystać z CSS :not. W przypadku tego problemu powinno to wystarczyć ...

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

W kontekście obiektu strony możesz pobrać TYLKO te elementy, które są w ten sposób widoczne. Na przykład. mając stronę z wieloma elementami, na których widoczne są tylko niektóre, możesz użyć:

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

To zwróci ci wszystkie widoczne i.icons


1
isDisplayed () powinno znajdować się w zakresie oczekiwania, jak wyjaśnił @leoGallucci.
— Striped

5

Jeśli w DOM jest wiele elementów o tej samej nazwie klasy. Ale widoczny jest tylko jeden element.

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

W tym przykładzie filtr pobiera kolekcję elementów i zwraca pojedynczy widoczny element za pomocą metody isDisplayed () .


To świetna odpowiedź; rozważ przypadek, w którym nie ma takiego elementu! $ ('. text-input-input') ostrzeże użytkownika elegancko; to może się nie powieść, ponieważ filteredElement.length === 0?
— The Red Pea

1

Ta odpowiedź będzie wystarczająco solidna, aby działać dla elementów, których nie ma na stronie, a zatem zakończy się niepowodzeniem (bez zgłaszania wyjątku), jeśli selektor nie odnajdzie elementu.

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

1

Czekać na widoczność

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

Xpath trik, aby znaleźć tylko widoczne elementy

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))

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

0

Oto kilka fragmentów kodu, których można użyć we frameworku używającym Typescript, kątomierz, jaśmin

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

// Potwierdzenie tekstu

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

// Potwierdzenie elementu

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

    );

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

// Potwierdzenie formularza

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);
                    });     
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.