Comment utiliser protractor pour vérifier si un élément est visible?

J'essaie de tester si un élément est visible à l'aide de protractor. Voici à quoi ressemble l'élément:

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

Dans la console chrome, je peux utiliser ce sélecteur jQuery pour tester si l'élément est visible:

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

Cependant, quand j'essaie de faire la même chose dans protractor, j'obtiens cette erreur à l'exécution:

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

Pourquoi cela n'est-il pas valide? Comment puis-je vérifier la visibilité à l'aide de protractor?

98
demandé sur limp_chimp 2014-04-04 02:36:16

6 réponses

, Cela devrait le faire:

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

Rappelez-vous que le Rapporteur $ n'est pas jQuery et que :visible n'est pas encore une partie de sélecteurs CSS disponibles + pseudo-sélecteurs

Plus d'infos sur https://stackoverflow.com/a/13388700/511069

131
répondu Leo Gallucci 2017-05-23 12:18:23

Le bon moyen de contrôler la visibilité d'un élément avec le Rapporteur est d'appeler le isDisplayed la méthode. Vous devriez faire attention cependant puisque isDisplayed ne renvoie pas un booléen, mais plutôt un promise fournir la visibilité évaluée. J'ai vu beaucoup d'exemples de code qui utilisent cette méthode à tort et n'évaluent donc pas sa visibilité réelle.

Exemple pour obtenir la visibilité d'un élément:

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

Cependant, vous n'avez pas besoin de cela si vous vérifient simplement la visibilité de l'élément (par opposition à l'obtenir) parce que protractor patches Jasmine expect() donc il attend toujours que les promesses soient résolues. Voir github.com/angular/jasminewd

Donc vous pouvez simplement faire:

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

Puisque vous utilisez AngularJS pour contrôler la visibilité de cet élément, vous pouvez également vérifier son attribut de classe pour ng-hide comme ceci:

var spinner = element.by.css('i.icon-spin');
expect(spinner.getAttribute('class')).not.toMatch('ng-hide'); // expect element to be visible
72
répondu Mobiletainment 2014-09-22 10:34:15

J'ai eu un problème similaire, en ce sens que je ne voulais que renvoyer des éléments visibles dans un objet page. J'ai trouvé que je suis capable d'utiliser le css :not. Dans le cas de ce problème, cela devrait vous faire...

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

Dans le contexte d'un objet page, vous ne pouvez obtenir que les éléments qui sont visibles de cette manière. Par exemple. étant donné une page avec plusieurs éléments, où seuls certains sont visibles, vous pouvez utiliser:

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

Cela vous renvoie tous visibles i.icons

6
répondu Brine 2018-09-12 14:12:45

S'il y a plusieurs éléments dans DOM avec le même nom de classe. Mais un seul élément est visible.

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

Dans cet exemple, le filtre prend une collection d'éléments et renvoie un seul élément visible en utilisant isDisplayed () .

5
répondu A Qadeer Qureshi 2016-03-24 12:39:00

Cette réponse sera suffisamment robuste pour fonctionner pour les éléments qui ne sont pas sur la page, donc échouant gracieusement (ne pas lancer d'exception) si le sélecteur n'a pas réussi à trouver l'élément.

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
répondu activedecay 2017-02-17 00:12:42

Pour attendre la visibilité

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

Astuce Xpath pour ne trouver que des éléments visibles

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))
1
répondu Drew Royster 2018-03-01 21:08:41