I think that after much beating, I have an answer.
I think the main reason is that mdc-select-item has display:flex , which allows it to go beyond the boundaries of its parents (strictly speaking, this is like misusing display flex if I remember the tutorial correctly, however .. .).
Cypress does a lot of parenting when determining visibility, see visibility.coffee ,
#
But when using .should('be.visible') we are stuck with the parent properties, not passing the child visibility check, even if we can actually see the child.
We need an alternative test.
Workaround
The jquery.js reference, this is one definition for the visibility of the element itself (ignoring the parent properties).
jQuery.expr.pseudos.visible = function( elem ) { return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length ); }
therefore, we can use this as a basis for an alternative.
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 }); }); })
Footnote - Using "then" (or "each")
You typically use the statement in Cypress through chains of commands that basically wrap the elements being checked and handle things like repeating and waiting for DOM changes.
However, in this case, we have a contradiction between the standard statement of visibility .should('be.visible') and the structure used to create the page, so we use then(fn) ( ref ) to access the expanded DOM. Then we can apply our own version of the visibility test using the Jasmine syntax.
Turns out you can also use the function with .should(fn) , this works too
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 }); });
Using should instead of then does not make a difference in the visibility test, but note that the should version can repeat the function several times, so it cannot be used with the click test (for example).
From the documents
What is the difference between .then () and .should () /. AND()?
Using .then () just allows you to use the resulting item in a callback function and should be used when you need to manipulate some values ββor perform some actions.
When using the callback function with .should () or .and (), on the other hand, there is special logic to re-run the callback function until statements are added to it. You should be careful with side effects in the .should () or .and () callback function, which should not be executed multiple times.
You can also solve this problem by expanding the basic statements, but the documentation on this is not extensive, so it can potentially work more.