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


111

J'essaie de tester si un élément est visible à l'aide d'un rapporteur. 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, lorsque j'essaie de faire la même chose dans rapporteur, j'obtiens cette erreur au moment de 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 n'est-ce pas valable? Comment puis-je vérifier la visibilité à l'aide du rapporteur?


Hé @limp_chimp, ma réponse ci-dessous vous a-t-elle aidé?
Leo Gallucci

@limp_chimp pour des choses comme la visibilité, pensez à utiliser les tests unitaires DOM du client AngularJS. Ils sont beaucoup plus rapides à exécuter et plus faciles à développer.
Offirmo

Réponses:


144

Cela devrait le faire:

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

Rappelez-vous que le rapporteur $n'est pas jQuery et :visiblene fait pas encore partie des sélecteurs CSS + pseudo-sélecteurs disponibles

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


1
Oh mec. Trop cool. C'est exactement ce dont j'avais besoin pour pouvoir déterminer. Merci beaucoup mec.
racl101

2
La réponse ci-dessous utilise également, isDisplayed()mais se développe simplement pour résoudre la promesse d'exhaustivité, bien que cette étape soit facultative et destinée uniquement à inclure des conditions dans vos tests, ce qui est une mauvaise pratique. @asenovm pouvez-vous développer davantage votre commentaire "C'est tout simplement faux"?
Leo Gallucci

@LeoGallucci, isDisplayed () renvoie ElementFinder et non un booléen.
asenovm

1
Veuillez ne pas .toBeTruthy();utiliser à la .toBe(true)place. .toBeTruthy();correspondra à des choses comme [], 'false', 42. Fondamentalement, tout ce qui attend 0, "", null, undefined, NaN ou false est vrai.
Brian

78

La méthode correcte pour vérifier la visibilité d'un élément avec Protractor est d'appeler la isDisplayedméthode. Vous devez cependant faire attention car isDisplayedne renvoie pas un booléen, mais plutôt un promisefournissant la visibilité évaluée. J'ai vu de nombreux 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'en avez pas besoin si vous ne faites que vérifier la visibilité de l'élément (par opposition à l'obtenir) car le rapporteur corrige Jasmine expect () afin qu'il attend toujours que les promesses soient résolues. Voir github.com/angular/jasminewd

Vous pouvez donc simplement faire:

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

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

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

8

J'ai eu un problème similaire, en ce sens que je ne voulais que des éléments de retour visibles dans un objet de 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 de page, vous pouvez également obtenir UNIQUEMENT les éléments visibles de cette manière. Par exemple. étant donné une page avec plusieurs éléments, dont seuls certains sont visibles, vous pouvez utiliser:

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

Cela vous rendra tous visibles i.icons


1
isDisplayed () devrait être dans la portée attendue comme @leoGallucci l'a expliqué.
Striped

5

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 à l'aide de isDisplayed () .


C'est une excellente réponse; considérez le cas où un tel élément n'existe pas! $ ('. text-input-input') alerterait l'utilisateur avec élégance; cela pourrait échouer parce que filteredElement.length === 0?
The Red Pea

1

Cette réponse sera suffisamment robuste pour fonctionner pour les éléments qui ne sont pas sur la page, échouant donc correctement (ne lançant pas d'exception) si le sélecteur ne parvient pas à 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

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 les éléments visibles

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

Voici les quelques extraits de code qui peuvent être utilisés pour les frameworks qui utilisent Typescript, rapporteur, jasmine

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

// Affirmer un texte

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

// Affirmation d'un élément

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

    );

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

// Affirmation d'un formulaire

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);
                    });     
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.