cypress-io / cypress

Fast, easy and reliable testing for anything that runs in a browser.
https://cypress.io
MIT License
46.98k stars 3.18k forks source link

Cypress is confusing cy.clear() with cy.click() #26152

Open thekayshawn opened 1 year ago

thekayshawn commented 1 year ago

Current behavior

I've selected a few input fields and told cypress to clear all of them using the multiple: true flag but cypress fails to clear them while saying cy.click() can only be called on a single element. Your subject contained 34 elements. Pass { multiple: true }.

image

Desired behavior

In this situation, cypress should display the correct error and mention the method that's actually used - the cy.clear() method, instead, it's mentioning cy.click() and asking me to pass the multiple: true flag, which is already there.

Test code to reproduce

It's a simple form with about 32 fields, here's the failing code:

cy.get('input:not([type="file"]), textarea').clear({
  force: true,
  multiple: true,
});

Cypress Version

12.8.1

Node version

16.19.0

Operating System

Elementary OS 7

Debug Logs

No response

Other

No response

lmiller1990 commented 1 year ago

Hi. Thanks for the bug report - I agree, we should improve this error messaging. I wonder if clear uses click under the hood?

If you are interested in making a PR to fix this, let me know and I can point you in the right direction.

thekayshawn commented 1 year ago

It's a pleasure. I wonder if clear uses click because I don't see the connection but there's always a possibility. The real problem here, I think, is that the click/clear wasn't seeing the multiple: true property I passed, I had to use each and then clear them all manually. I'd love to make a PR and fix this, you should point me in the right direction.

lmiller1990 commented 1 year ago

Sure! All the code relating to the cy.{click,visit,clear...} API lives in driver. This is the most complex part of Cypress 😅

It looks like click is defined here. Here's where the multiple elements error is thrown. In this case, you just need to find the right conditional and throw the right error, something like

$errUtils.throwErrByPath('click.multiple_elements', {
   args: { cmd: eventName, num: options.$el.length },
})

As long as you are using $errUtils, Cypress will figure the rest out.

To develop this, I think you would just add a test case in the relevant test. If you need a specific scenario, you would just create it using HTML and put it in driver/cypress/fixtures and visit it, like this.

As for actually coding this, the way I usually develop is grab the repo, yarn to install all the things, then yarn dev at the root. It starts a ton of watchers - hopefully you've got a decent modern machine - then you can choose packages/driver as the project and everything will auto reload/run. Then you just TDD until it works.

Alternatively, if your machine struggles with all those processes, I think you can do:

  1. go into packages/runner
  2. yarn watch
  3. (in other terminal) cd packages/driver && yarn cypress:open

This will only watch the driver and runner files, which should be more lightweight and faster.

Let me know if you need any other pointers!

thekayshawn commented 1 year ago

Thanks! I'll get going and try to reproduce the error. I'll let you know if there's an issue.