1

I need some clarification on the usage of Cypress. I'm writing some e2e tests and one of them failed, because the element is not visible.

I found this answer helpful, it solved my problem. Clicking element which is reported to be not visible.

cy.get('[data-cy="dApp Info"]').click({force: true});

But now I'm wondering about Cypress best practice.

For example, let's say I have a component, which I want to click. It's a link a inside a div, inside a div, inside a nav. (I gave the link the data-cy property.) Even though as a user, the component is visible and clickable (see 1st image), the component is reported not to be visible (see 2nd image).

Is it best practice to add a data-cy property to any element I want to click and just use .click({force: true}) or should I add a data-cy property to one of the divs which wrap my actual link and click those (is that even possible?)?

enter image description here

not visible

Edit

DOM Structure

<nav data-cy="sidebar-nav-studio">
 <div>
  <div>
   <div>
    <div>
     <ul data-cy="dApp-sub-section-sidebar-nav-studio">
      <span>
       <a data-cy="Add Templates">
        <div> </div>
        <div>
         <p>
         Add Templates
         </p>
        </div>
      </a>
      <a data-cy="Look & Feel">
       <div> </div>
       <div>
        <p>
         Look & Feel
        </p>
      </div>
     </a>
     <a data-cy="dApp Info">
      <div> </div>
      <div>
       <p>
       dApp Info
       </p>
      </div>
    </a>
    </div>
  </div>
 </div>
</div>
Yves Boutellier
  • 1,286
  • 9
  • 19

3 Answers3

3

Actions

If clicking the link is just a way to take action (i.e get to another page) using {force:true} is pragmatic.

Regressions

On the other hand, if you want to test for regressions in the menu system itself forcing might be the wrong thing to do.

Events bubble from one element to another, so it might not be necessary to click the <a> directly.

Try clicking up the parent element chain until you find the wrapper that's both visible and clickable.

Framework libraries

Using a mainstream library like Material UI, it's not necessary to test functionality that is provided by that library.

You can trust that the library builders have already tested it.

So a test like "Does this menu open?" is probably wasting your time (although configuration of the library isn't).


Selecting MUI Menu without force-clicking

Just tried out the sample Material UI menu given in the docs, and you can click the item without using {force:true}.

I'm guessing the step you are missing is opening the menu so that the items are visible.

cy.get('.MuiButton-root').click()            // open the dropdown
cy.get('[data-cy="dApp Info"]').click()      // clicks without forcing

Note that the Nav to open the menu is not located near the menu items, in fact the items appear to be lazy-loaded (not in DOM until menu is opened).

Fody
  • 23,754
  • 3
  • 20
  • 37
  • what does that mean "test for regressions in the menu system itself" ? – Yves Boutellier Jun 16 '22 at 05:14
  • Can only give a for-instance, but menu items can be hidden until you open the menu. If your menu item remains hidden due to change (regression) in source and you use `{force:true}` on it, you will not pick up the error. – Fody Jun 16 '22 at 06:04
  • unfortunately I cannot accept two answers, even though both are good. – Yves Boutellier Jun 16 '22 at 07:47
  • No worries! I think the example I tested is not the same as your code anyway. It's a pity you did not get two up-votes! – Fody Jun 16 '22 at 07:48
2

I would use these selectors

cy.contains('button', 'DApp').click()
cy.contains('a[data-cy="dApp Info"]', 'dApp Info').click()

I agree that using .click({force:true}) is a code-smell.

TesterDick
  • 3,830
  • 5
  • 18
1

I think adding the data-cy attribute to the a tag would be a good option, so that you get the element as visible and click it. What I understood from the cypress best practices page, the data-cy or data-test or data-testid should be added to the target element, which in your case is the a tag.

I would suggest you to not use click({force: true}) until absolutely required because it forces the action and disables waiting for actionability.

By actionability, cypress means commands that simulate a user interacting with your application. Under the hood, Cypress fires the events a browser would fire thus causing your application's event bindings to fire.

So in case, a real user is not able to see or interact with a button for some reason, then the test should fail, but with force:true, the test will pass because it bypasses the actionability checks and forcefully clicks the button. You can read more about Actionability and Forcing from the docs.

Or in case you don't want to use any tags, one good way would be to use the combination of a selector and inner text value to find the element and click it, something like:

cy.get('[data-cy="sidebar-nav-studio"]').click() //opens the nav
cy.contains('a', 'dApp Info').click()
Alapan Das
  • 17,144
  • 3
  • 29
  • 52