Saltar al contenido

Elemento de acceso cuyo padre está oculto – cypress.io

Este equipo de especialistas luego de días de trabajo y de recopilar de datos, obtuvieron los datos necesarios, queremos que resulte útil para ti para tu trabajo.

Solución:

Después de mucho rechinar los dientes, creo que tengo una respuesta.

Creo que la causa fundamental es que mdc-select-item tiene display:flex, lo que le permite exceder los límites de sus padres (estrictamente hablando, esto se siente como una aplicación incorrecta de display flex, si recuerdo el tutorial correctamente, sin embargo …).

Cypress realiza muchas comprobaciones de los padres al determinar la visibilidad, consulte visibilidad.coffee,

## WARNING:
## developer beware. visibility is a sink hole
## that leads to sheer madness. you should
## avoid this file before its too late.
...
when $parent = parentHasDisplayNone($el.parent())
  parentNode = $elements.stringify($parent, "short")

  "This element '#node' is not visible because its parent '#parentNode' has CSS property: 'display: none'"
...
when $parent = parentHasNoOffsetWidthOrHeightAndOverflowHidden($el.parent())
  parentNode  = $elements.stringify($parent, "short")
  width       = elOffsetWidth($parent)
  height      = elOffsetHeight($parent)

  "This element '#node' is not visible because its parent '#parentNode' has CSS property: 'overflow: hidden' and an effective width and height of: '#width x #height' pixels."

Pero, al usar .should('be.visible'), estamos atascados con las propiedades de los padres que fallan en la verificación de visibilidad del niño, aunque en realidad podemos ver al niño.
Necesitamos una prueba alternativa.

La solución alternativa

Ref jquery.js, esta es una definición para la visibilidad del elemento en sí (ignorando las propiedades principales).

jQuery.expr.pseudos.visible = function( elem ) 

por lo que podríamos usar eso como base para una alternativa.

describe('Testing select options', function() {

  // Change this function if other criteria are required.
  const isVisible = (elem) => !!( 
    elem.offsetWidth || 
    elem.offsetHeight || 
    elem.getClientRects().length 
  )

  it('checks select option is visible', function() 

    const doc = cy.visit('http://localhost:4200')
    cy.get("mdc-select").contains("installation type").click()

    //cy.get('mdc-select-item').contains("ITEM1").should('be.visible') //this will fail
    cy.get('mdc-select-item').contains("ITEM1").then (item1 => 
      expect(isVisible(item1[0])).to.be.true
    );
  );

  it('checks select option is not visible', function() 

    const doc = cy.visit('http://localhost:4200')
    cy.get("mdc-select").contains("installation type").click()

    cy.document().then(function(document) 

      const item1 = document.querySelectorAll('mdc-select-item')[0]
      item1.style.display = 'none'

      cy.get('mdc-select-item').contains("ITEM1").then (item => 
        expect(isVisible(item[0])).to.be.false
      )
    )
  );

  it('checks select option is clickable', function() 

    const doc = cy.visit('http://localhost:4200')
    cy.get("mdc-select").contains("installation type").click()
    
    //cy.get('mdc-select-item').contains("ITEM1").click()    // this will fail
    cy.get('mdc-select-item').contains("ITEM1").then (item1 => 
    
      cy.get('mdc-select-item').contains("ITEM2").then (item2 => 
        expect(isVisible(item2[0])).to.be.true  //visible when list is first dropped
      );
          
      item1.click();
      cy.wait(500)
          
      cy.get('mdc-select-item').contains("ITEM2").then (item2 => 
        expect(isVisible(item2[0])).to.be.false  // not visible after item1 selected
      );
    );
    
  )

Nota a pie de página: uso de ‘entonces’ (o ‘cada uno’)

La forma en que normalmente usa la aserción en cypress es a través de cadenas de comandos, que básicamente envuelve los elementos que se están probando y maneja cosas como reintentar y esperar cambios DOM.

Sin embargo, en este caso tenemos una contradicción entre la afirmación de visibilidad estándar .should('be.visible') y el marco utilizado para crear la página, por lo que usamos then(fn) (ref) para obtener acceso al DOM sin envolver. Luego podemos aplicar nuestra propia versión de la prueba de visibilidad usando la sintaxis stand jasmine.

Resulta que también puedes usar una función con .should(fn), esto también funciona

it('checks select option is visible - 2', function() 
  const doc = cy.visit('http://localhost:4200')
  cy.get("mdc-select").contains("installation type").click()

  cy.get('mdc-select-item').contains("ITEM1").should(item1 => 
    expect(isVisible(item1[0])).to.be.true
  );
);

Utilizando should en lugar de then no hace ninguna diferencia en la prueba de visibilidad, pero tenga en cuenta la should La versión puede reintentar la función varias veces, por lo que no se puede usar con click prueba (por ejemplo).

De los documentos,

¿Cuál es la diferencia entre .then () y .should () /. Y ()?

El uso de .then () simplemente le permite usar el sujeto cedido en una función de devolución de llamada y debe usarse cuando necesite manipular algunos valores o realizar algunas acciones.

Cuando se usa una función de devolución de llamada con .should () o .and (), por otro lado, existe una lógica especial para volver a ejecutar la función de devolución de llamada hasta que no se produzcan aserciones dentro de ella. Debe tener cuidado con los efectos secundarios en una función de devolución de llamada .should () o .and () que no le gustaría que se realizaran varias veces.

También puede resolver el problema extendiendo las afirmaciones de chai, pero la documentación para esto no es extensa, por lo que potencialmente es más trabajo.

Encontré este tema pero no pude ejecutar su ejemplo. Así que probé un poco y mi solución final es esta. tal vez alguien más también necesite esto. Tenga en cuenta que utilizo mecanografiado.

Primero: defina un comando personalizado

Cypress.Commands.add("isVisible",  prevSubject: true, (p1: string) => 
      cy.get(p1).should((jq: JQuery) => );
);

Tenga en cuenta el TODO. En mi caso, estaba apuntando a un botón que tiene dos cuadros de borde. El primero con alto y ancho 0. Entonces debo seleccionar el segundo. Ajústelo a sus necesidades.

Segundo: Úselo

cy.wrap("#some_id_or_other_locator").isVisible();

Por conveniencia y reutilización tuve que mezclar la respuesta de Richard Matsen y Josef Biehler.

Definir el comando

// Access element whose parent is hidden
Cypress.Commands.add('isVisible', 
  prevSubject: true
, (subject) => 
    elem.getClientRects().length
  )
  expect(isVisible(subject[0])).to.be.true
)

Ahora puede encadenarlo desde contiene

describe('Testing select options', function() 
  it('checks select option is visible', function() 

    const doc = cy.visit('http://localhost:4200')
    cy.get("mdc-select").contains("installation type").click()

    //cy.get('mdc-select-item').contains("ITEM1").should('be.visible') // this will fail
    cy.get('mdc-select-item').contains("ITEM1").isVisible()
  );
);

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *