Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve clicking with modifier(s) #486

Closed
chrisbreiding opened this issue Apr 19, 2017 · 11 comments · Fixed by #8114
Closed

Improve clicking with modifier(s) #486

chrisbreiding opened this issue Apr 19, 2017 · 11 comments · Fixed by #8114
Labels
pkg/driver This is due to an issue in the packages/driver directory topic: cy.click 🖱 type: enhancement Requested enhancement of existing feature

Comments

@chrisbreiding
Copy link
Contributor

chrisbreiding commented Apr 19, 2017

The current experience issuing a ctrl-click , cmd-click, etc could use some improvement.

First, add a section to the cy.click doc concerning modifiers, with an example or two.

Second, consider updating the cy.click command to accept modifiers directly instead of needing cy.type command first.

Currently you need this to ctrl-click:

cy.get('body').type('{ctrl}', { release: false })
cy.get('#some-el').click()

Something like this would be a lot better:

cy.get('#some-el').click({ ctrlKey: true })
@jennifer-shehane jennifer-shehane added pkg/driver This is due to an issue in the packages/driver directory type: enhancement Requested enhancement of existing feature labels Apr 25, 2017
@tascioglu
Copy link

Hi Chris.. is it also possible to do this when there isn't any textfield?

@chrisbreiding
Copy link
Contributor Author

The first example above works for a non-textfield.

@fr0
Copy link

fr0 commented Feb 4, 2019

The workaround didn't work for me. The cy.get('body').type('{ctrl}', { release: false }) never fired the keydown event on window, which is what my app is looking for.

@chrisbreiding
Copy link
Contributor Author

@fr0, cy.get('body').type('{ctrl}', { release: false }) won't fire a keydown event. It sets the ctrl so the next action, such as a click, has ctrlKey set. If you'd like to type ctrl+character, you can do that like so:

// type ctrl+a on body
cy.get('body').type('{ctrl}a')

@fr0
Copy link

fr0 commented Feb 4, 2019

Yes, I figured out that trigger is what I need given my app's coding.

As a side note, when I'm writing tests, I don't really want to have to think about these sorts of things. It would be nice if there were an API that was simply "press/release these keys exactly as if the user had done it", much like sendKeys in Selenium. Under the hood, it would make sure the keydown/keyup happened, make sure the ctrlKey modifier (etc.) was set, and all of the other bits that have to happen.

@chrisbreiding
Copy link
Contributor Author

cy.type does exactly that. cy.get('body').type('{ctrl}a') will handle keydown/keyup. I think it expresses the user's actions pretty well as is, but we're always looking for ways to make the API more intuitive, so I'd love to hear any suggestions for improvement.

Can you describe in more detail what your test is doing that requires cy.trigger? It's possible it can be accomplished with cy.type. Or it might point out a use-case we haven't considered and that we can improve the experience for.

@fr0
Copy link

fr0 commented Feb 4, 2019

cy.type does exactly that. cy.get('body').type('{ctrl}a') will handle keydown/keyup.

That's not what I've experienced. Try these two tests, which (IMO) should both pass. However, only the second one does.

    it('handles keydown (via type)', () => {
      let shiftPressed = false;
      cy.window().then(win => {
        win.addEventListener('keydown', ev => {
          if (ev.key === 'shift') {
            shiftPressed = true;
          }
        });
      });
      cy.get('body').type('{shift}', {release: false}).then(() => {
        expect(shiftPressed).to.be.true;
      });
    });

    it('handles keydown (via trigger)', () => {
      let shiftPressed = false;
      cy.window().then(win => {
        win.addEventListener('keydown', ev => {
          if (ev.key === 'shift') {
            shiftPressed = true;
          }
        });
      });
      cy.get('body').trigger('keydown', {key: 'shift'}).then(() => {
        expect(shiftPressed).to.be.true;
      });
    });

@chrisbreiding
Copy link
Contributor Author

I see. Thanks for the information. This looks like a bug in how cy.type handles modifiers. I created a separate issue to track this.

@jennifer-shehane jennifer-shehane added the stage: ready for work The issue is reproducible and in scope label Feb 5, 2019
@gnapse
Copy link

gnapse commented Jan 24, 2020

I created this custom command, in case is helpful for others, or to know if there are any caveats here, if I'm shooting myself in the foot or anything like it (just devised it and seems to work well, but who knows, especially the hack to be able to use it inside .within):

Cypress.Commands.add(
    "clickWithModifier",
    { prevSubject: "element" },
    (subject, modifier) => {
        // Make sure we can get the body even if inside a .within block
        cy.document().then($doc => {
            // Type the modifier into <body /> without releasing it
            const body = $doc.querySelector("body")
            cy.wrap(body).type(modifier, { release: false })
        })

        // Click the element while the modifier key is pressed
        cy.wrap(subject).click()

        cy.document().then($doc => {
            // Release the modifier key, again against <body />
            cy.wrap($doc.querySelector("body")).type(modifier)
        })
    }
)

Use it like this:

cy.findByText("Hello world").clickWithModifier("{shift}")

@cypress-bot
Copy link
Contributor

cypress-bot bot commented Aug 10, 2020

The code for this is done in cypress-io/cypress#8114, but has yet to be released.
We'll update this issue and reference the changelog when it's released.

@cypress-bot cypress-bot bot added stage: pending release and removed stage: needs review The PR code is done & tested, needs review labels Aug 10, 2020
@cypress-bot
Copy link
Contributor

cypress-bot bot commented Aug 20, 2020

Released in 5.0.0.

This comment thread has been locked. If you are still experiencing this issue after upgrading to
Cypress v5.0.0, please open a new issue.

@cypress-bot cypress-bot bot locked as resolved and limited conversation to collaborators Aug 20, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
pkg/driver This is due to an issue in the packages/driver directory topic: cy.click 🖱 type: enhancement Requested enhancement of existing feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants