¿Cómo usar el transportador para verificar si un elemento es visible?

111

Estoy tratando de probar si un elemento es visible usando un transportador. Así es como se ve el elemento:

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

Cuando estoy en la consola de Chrome, puedo usar este selector de jQuery para probar si el elemento 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')
[]

Sin embargo, cuando intento hacer lo mismo en el transportador, aparece este error en tiempo de ejecución:

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

¿Por qué esto no es válido? ¿Cómo puedo comprobar la visibilidad con un transportador?

limp_chimp
fuente
Hola @limp_chimp, ¿te ayudó mi respuesta a continuación?
Leo Gallucci
@limp_chimp para cosas como la visibilidad, piense en usar las pruebas unitarias DOM del cliente AngularJS. Son mucho más rápidos de ejecutar y más fáciles de desarrollar.
Offirmo

Respuestas:

144

Esto debería hacerlo:

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

Recuerde que el transportador $no es jQuery y aún:visible no es parte de los selectores CSS disponibles + pseudo-selectores

Más información en https://stackoverflow.com/a/13388700/511069

Leo Gallucci
fuente
1
Oh hombre. Muy guay. Esto es exactamente lo que necesitaba para poder determinar. Muchas gracias amigo.
racl101
2
La respuesta a continuación también usa isDisplayed()pero solo se expande para resolver la promesa de integridad, aunque ese paso es opcional y solo está destinado a incluir condicionales en sus pruebas, lo cual es una mala práctica. @asenovm, ¿puede desarrollar más su comentario de "Esto es simplemente incorrecto"?
Leo Gallucci
@LeoGallucci, isDisplayed () devuelve ElementFinder y no un booleano.
asenovm
1
No utilice .toBeTruthy();use .toBe(true)en su lugar. .toBeTruthy();coincidirá con cosas como [], 'falso', 42. Básicamente, cualquier cosa que espere 0, "", nulo, indefinido, NaN o falso es verdadero.
Brian
78

La forma correcta de verificar la visibilidad de un elemento con Protractor es llamar al isDisplayedmétodo. Sin embargo, debe tener cuidado ya isDisplayedque no devuelve un valor booleano, sino que promiseproporciona la visibilidad evaluada. He visto muchos ejemplos de código que usan este método incorrectamente y, por lo tanto, no evalúan su visibilidad real.

Ejemplo para obtener la visibilidad de un elemento:

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

Sin embargo, no necesita esto si solo está verificando la visibilidad del elemento (en lugar de obtenerlo) porque el transportador parchea Jasmine espera () por lo que siempre espera a que se resuelvan las promesas. Ver github.com/angular/jasminewd

Entonces puedes hacer:

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

Dado que está utilizando AngularJSpara controlar la visibilidad de ese elemento, también puede verificar su atributo de clase de ng-hideesta manera:

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

Tuve un problema similar, ya que solo quería devolver elementos que fueran visibles en un objeto de página. Descubrí que puedo usar css :not. En el caso de este problema, esto debería servirle ...

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

En el contexto de un objeto de página, también puede obtener SOLAMENTE aquellos elementos que son visibles de esta manera. P.ej. dada una página con varios elementos, donde solo algunos son visibles, puede usar:

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

Esto te devolverá todos los i.icons visibles

Salmuera
fuente
1
isDisplayed () debería estar en el alcance esperado como lo explicó @leoGallucci.
Rayado
5

Si hay varios elementos en DOM con el mismo nombre de clase. Pero solo uno de los elementos es visible.

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

En este ejemplo, el filtro toma una colección de elementos y devuelve un único elemento visible usando isDisplayed () .

Un Qadeer Qureshi
fuente
Esta es una respuesta genial; ¡considere el caso donde no existe tal elemento! $ ('. text-input-input') alertaría al usuario elegantemente; esto podría fallar porque filteredElement.length === 0?
The Red Pea
1

Esta respuesta será lo suficientemente robusta como para funcionar con elementos que no están en la página, por lo que fallará con gracia (sin generar una excepción) si el selector no pudo encontrar el elemento.

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()
    })
})
decaimiento activo
fuente
1

Para esperar visibilidad

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

Truco de Xpath para encontrar solo elementos visibles

element(by.xpath('//i[not(contains(@style,"display:none")) and @class="icon-spinner icon-spin ng-hide"]))
Drew Royster
fuente
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
fuente
0

Aquí están los pocos fragmentos de código que se pueden usar para el marco que usa TypeScript, transportador, jazmín

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

// Afirmar un texto

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

// Afirmar un elemento

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

    );

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

// Afirmar un formulario

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
fuente