cypress-io/cypress

Need tab support

robdodson opened this issue ยท 89 comments

Description
As mentioned here https://docs.cypress.io/v1.0/docs/type#section-typing-tab-key-does-not-work. For accessibility testing I need to be able to tell the keyboard to press tab. If cy.tab is not currently supported is there some way to work around this?

I'd like to hear more about what you are looking to cover in terms of accessibility testing. Can you give me an example of a use case you are trying to test with the tab key?

Right now there is not a way to press "tab".

Currently we simulate all events in Cypress - although we automatically backfill in the browser's default behavior on all actions, which means that your application does what it does identically to native events.

The problem with tab is that it is extremely complicated and its behavior is not necessarily normalized across all behaviors.

The solution for us is to enable native events within Cypress. We can "opt into" native events whenever we want, the problem is mostly with the UX experience around the debugger protocol. Namely that you cannot have Dev Tools open and issue native events due to the limitation of Chrome's debugger protocol.

There is an open issue in Chromium to add multiplexing support so we've been waiting for that to go live. Until then we will kick the can, or eventually be forced into creating a good UX experience that either automatically closes Dev Tools, or prompts the user that their tests cannot continue until it is closed.

thanks for the response

The tab key is one of the primary ways a keyboard user moves around the page so it's difficult to write a high confidence accessibility test without it. In my case I'm building custom components that comply with the aria authoring practices guide. The first thing I would like to do on every page is press tab to focus the element. I can fake this by calling click() but it's not really the same. A non-sighted user will never use the mouse so calling click() feels a bit like cheating and you could imagine a situation where an element has one behavior when clicked and a different behavior when focused via the tab key.

If you're testing the behavior of an element coming into focus, or you're testing things like styles you can just focus the element directly.

cy.get("input").focus()

What this doesn't test for is what the browser's behavior when clicking "tab". But you can often indirectly test this.

For instance, you could just make sure that the element it's supposed to focus on has tabindex set.

What this doesn't test for is what the browser's behavior when clicking "tab". But you can often indirectly test this.

Yeah that's what I've been doing. Still, I would prefer tab key support if it were there because it'd be less boilerplate to write :)

I have a different use case for .tab() - in our app we have a fairly advanced search input (multiline, hence implemented as a <textarea>). A user is supposed to enter a query written in a custom grammar. It might look like this: some.path.here = something. Tab completion is supported, so when the user enters, say, some.p and pressed a tab key, it might get expanded to some.path..

This is obviously distinct from accessibility use cases (as described above).

Any update on .tab()?

In Chrome 63, there is support for multiplexing and we can now better handle native events. See #311

@jennifer-shehane Is this on the road map to be implemented? Or should we not expect this any time soon?

I'd love to know as well. Just ran into this issue while writing a form validation test.

Me too . I was expecting some way to tab to the next field like .type({tab})

Same as the above. I'm testing an app that mimics desktop application and heavily relies on keyboard usage.

Has anyone found a good workaround for this? It seems as if we're not getting a tab function..

This seems to work:

Cypress.Commands.add('typeTab', (shiftKey, ctrlKey) => {
  cy.focused().then(($el) => {
    cy.wrap($el).trigger('keydown', {
      keyCode: 9,
      which: 9,
      shiftKey: shiftKey,
      ctrlKey: ctrlKey
    });
  });
});

@scottschafer that fires the event, but the browser will not perform the default action such as moving the tab focus to the next focusable element

@scottschafer This should be able to be simplified to this:

Cypress.Commands.add('typeTab', (shiftKey, ctrlKey) => {
  cy.focused().trigger('keydown', {
      keyCode: 9,
      which: 9,
      shiftKey: shiftKey,
      ctrlKey: ctrlKey
  });
});

@brian-mann , ah. In our web app we specifically handle keyboard events and change focus programmatically. It works for us - sorry this won't work for you.

@scottschafer Yes, glad to see you got this work in your use case. It should help anyone else that programmatically works off of the user's specific keydown of the tab key.

Whaaat? Tabbing was literally the first thing I tried testing ๐Ÿ˜„ Wanted to test the login form and the fact that pressing Tab on the password form doesn't focus the Show/hide password button but the Login button...

The problem with tab is that it is extremely complicated and its behavior is not necessarily normalized across all behaviors.

Wouldn't it be possible to allow users to customize the "algorithm" for tabbing? Figuring out where the focus will go is indeed a tricky problem, but for a majority of usecases it should work pretty straightforward. Figure out what is the next focusable element in the DOM after the current document.activeElement. Something like button:not([tabindex=0]),a:not([tabindex=0]),[tabindex=1],[tabindex=2],...)?

There are a few very good libs which also try to figure out which elements are focusable in order to trap focus in a modal or a dropdown. Maybe it's a good starting point to figure out what kind of algorithm they use to intercept focus leaving the modal and taking it back to the first focusable element in it?

I think the key is to find or come up with an implementation that works for your use case. It's hard to come up with a general solution.

FWIW, here's my implementation roughly based off of some of jQuery UI's logic: https://github.com/getstreamline/menu/blob/master/cypress/support/index.js#L39

One of the gotchas is that the focused() command does not work reliably when the browser is not currently in focus, so I also added a separate active() command that is more consistent: https://github.com/getstreamline/menu/blob/master/cypress/support/index.js#L63

It's naive but works for my use case!

@decafdennis your tabbing stuff works well for me, thanks! The solution @jennifer-shehane posted wasn't working with the "shiftKey" variable for some reason. Tabbed forward but not backward.

kuceb commented

Currently working on this, however it may introduce breaking changes around cy.type(), so I've set the milestone for 4.0.0

@jennifer-shehane so, 24 days ago, you removed this from the 4.0.0 milestone. Does that mean there is no interest in fixing this? Or still blocked by browsers support?

We've repurposed the 4.0 release with other breaking changes that are closer to going out - you can see the roadmap for 4.0 here: #2840

This feature falls more closely under our Native Events issue which is also in progress, but has not been assigned a release number yet. See progress for this issue here: #311

Sorry to pile-on, but thought I would add my use-case here. Like the OP I am trying to add integration tests to assert that our open-source accessible React component ('React Accessible Accordion') complies with the WAI ARIA spec.

You can see the assertions which I needed to make here.

Unfortunately I didn't realise that Cypress was not going to support this functionality (or the 'end'/'home' keys it seems). I'm going to abandon Cypress because I can already get equivalent functionality out of the incumbent testing suite (Jest + Enzyme).

There is an issue with an open PR slated for release in 3.2.0 providing end and home key support here: #2033

kuceb commented

We're still working on tab support (and other keys) as part of Native Events #311 , but in the meantime I've made a plugin that adds a .tab() command (supports .tab({shift: true}) as well). cypress-plugin-tab:

However, the actual tab implementation will not be a separate command, so know if you use this plugin, you'll have to refactor your test code when Native Events lands

๐Ÿšจ Please open/discuss issues with the plugin in the issues of the plugin repo, not here ๐Ÿšจ

I see there has been talk about implementation for the tab key. I sort of need to trigger keypress and keydown events in most of applications I am testing.

I am looking for a work-around for the arrow keys, spacebar and the enter button.

Basically I have set up some custom key events for accessible keyboard navigation through list items but I have no way of triggering the events through keydown or keypress inside of cypress :S.

I'm really liking cypress and want to continue using it, but dont know how to get around this issue as all the applications we make and test for work need to be accessible.

(tried the work-around above with updated keycodes but that didn't seem to work)

cypress-plugin-tab

Nice one! I've added it to my project

Tab is a no brainer. Currently testing a javascript dropdown box where user types in a country for example and the list shortens per character typed and tab is the way to proceed with what's selected onto the next field. This is easy to use as a human, tab is a natural progression out of this field. Cypress is lacking by not having tab key support. Hope to see it arrive soon.

Update: Cypress plugin tab - https://github.com/Bkucera/cypress-plugin-tab - works very well! However, this plugin shouldn't have a reason to exist. Cypress needs to add this as core functionality.

I tried the cypress-plugin-tab, I have some differences in order at manual testing.
For example if I have divs in body, which have different tabindices:

<html>
  <head>
  </head>
  <body>
    <div tabindex="10">1</div>
    <div tabindex="5">2</div>
    <div tabindex="3">3</div>
  </body>
</html>

When using the plugin, the first cy.get("body").tab() selects the div with "10" tabindex.
But at manual testing the "3" tabindex won.

Is it a bug of the plugin, or I did something wrong? How can I fix that?

Svish commented

@kvaternio-dev Maybe add that as an issue/question on the https://github.com/Bkucera/cypress-plugin-tab repo?

@kvaternio-dev Maybe add that as an issue/question on the https://github.com/Bkucera/cypress-plugin-tab repo?

I'll, thank you.

For people testing dropdowns or autocomplete where you use tab to go to the first suggestion, notice that usually you can also use the arrows to navigate among suggestions, so no need to use the tab plugin, instead you can do something like:

cy.get("[cy-data='newLabelInput']").type("lab{downarrow}{enter}");

^ But if we've built our own dropdown/autocomplete, the whole point is to test if the tab works properly.

I'm going to throw my support in for this as well.

Screen Shot 2019-12-11 at 7 01 10 AM

This is just the use case thats triggering this comment, but this isnt uncommon throughout web apps or our enterprise ( top 50 in the fortune 500).

We need to test that when a user hits tab, it'll go through each of the top elements, then down to the green level. Currently, its skipping the green layer altogether. We want to be able to automate our accessibility testing, this means checking if a keyboard user can get to various parts of the application. Since tabbing is a large part of that, this seems like a pretty clear value add.

Any update about it?

We are building our own library of components and like to test accessibility.
What about also testing that a user can navigate with the arrow keys in a list of radio buttons and that they can actually select a value using the space key.

I tried using .type('{downarrow}') from the radio button and cy.get('body').trigger('keydown', { key: 'ArrowDown', code: 'ArrowDown', which: 40 }); without any success.

Will the ability to type {enter} or (space) on an in-focus button to "press" it be included in this work please?

For my team, this is similarly important to tabbing for testing keyboard navigation flows through our UI. We're using cypress-plugin-tab successfully for tabbing, but using type('{enter}') on in-focus buttons doesn't press them the way that manual interaction does. We are currently using click() on in-focus buttons as a compromise, but ideally we'd like to automate all UI interactions with the keyboard only, with no mouse interaction at all.

Any update on this?

It is possible to run a native system tab using CDP. Find the ready-to-use command in this package https://github.com/dmtrKovalenko/cypress-real-events.

Fire the native tab press using

cy.realPress("Tab")

+1 for tab support

Another +1 for tab support ๐Ÿ˜„

#311 lists both {tab} {shift+tab} as done, but I cannot find a PR adding the support for it. So was it done or was it not?

@AlexDaniel it seems to be implemented with this package but not yet officially built-in with Cypress because, I'm guessing, there's no Firefox support and the Cypress team is working on other issues.

Can anyone please tell me how to use this method in .ts file..
Cypress.Commands.add('typeTab', (shiftKey, ctrlKey) => {
cy.focused().trigger('keydown', {
keyCode: 9,
which: 9,
shiftKey: shiftKey,
ctrlKey: ctrlKey
});
});

i wanted to test tab and shift+tab functionality? Really appreciate.

declare global {
  namespace Cypress {
    interface Chainable {
      typeTab: (shiftKey: Boolean, ctrlKey: boolean) => void;
    }
  }
}

I'm feeling after almost 5 years of this being an issue, it's not going to get fixed. But I'll put my +1 here. I'll try out that plugin.

Will the ability to type {enter} or (space) on an in-focus button to "press" it be included in this work please?

For my team, this is similarly important to tabbing for testing keyboard navigation flows through our UI. We're using cypress-plugin-tab successfully for tabbing, but using type('{enter}') on in-focus buttons doesn't press them the way that manual interaction does. We are currently using click() on in-focus buttons as a compromise, but ideally we'd like to automate all UI interactions with the keyboard only, with no mouse interaction at all.

@BrambleRamble I had the same issue and made the cypress-keyboard-plugin. That plugin works in conjunction with the cypress-plugin-tab to more accurately simulate space and enter keys on various elements and even detects event handlers that disable default actions (as realistic as possible without native events).

This is a basic key event how this isn't yet supported natively in Cypress? Cmon guys...

+1 for tab support

+1 :)

This does not seem to have been implemented yet.
Do we have a workaround pls.thanks

@theTestingApproach

This does not seem to have been implemented yet. Do we have a workaround pls.thanks

https://github.com/Bkucera/cypress-plugin-tab is a workaround -- but nothing more. It's quite useful, but it does have its limitations and bugs you'll have to workaround (or just not test some particular thing it doesn't work for). We're using it on https://github.com/focus-trap/focus-trap

I do not recommend cypress plug-in tab because it is a mock of browser focus tree which may not work correctly.

There is my plug-in https://github.com/dmtrKovalenko/cypress-real-events which exposes cy.realPress("Tab") and fires native tab event which is equal to puppeteer pressing tab.

Maybe we can disable conversation on this issue for now because I reply with a workaround for the 3d time

I do not recommend cypress plug-in tab because it is a mock of browser focus tree which may not work correctly.

There is my plug-in https://github.com/dmtrKovalenko/cypress-real-events which exposes cy.realPress("Tab") and fires native tab event which is equal to puppeteer pressing tab.

I appreciate the link. Unfortunately, your library relies on Chrome DevTools, and therefore Firefox is not supported. So with your library, we can perhaps "fully" or reliably test with tabs on Chrome, but cannot test at all on FF. With cypress-plugin-tab, while it has its limitations, we're able to test on both Chrome and FF, which is technically better coverage.

Hardly disagree, that is technically less coverage. Because when you are mocking something and exactly know that it didn't work like a real browser API you are kinda lying yourself that this part of my app work. But in fact you can't be sure that it works correctly with or without this test.

But I agree, having firefox browser automation api available will be nice for real events

Why is that? Does it fail under some circumstances?

Here's one example I've encountered, that being that cypress-plugin-tab doesn't understand that a non-tabbable node can still be focusable and can be tabbed away from. You can set focus to the node, but when you try to use cypress.tab() to move away from it, the plugin will throw an error.

I am really thinking that keyboard and mouse events does not trigger well with cypress.
For ex i cannot use mouseover for hovering a text it never works .
same mousedown never works
I tried cy.get('input').type('{shift}{alt}Q') from example here it does not work as well.
sometimes i have to use cy,invoke('show') which is not a good practice as it is checking the DOM but not the interface.

dcb99 commented

+1 for tab key, it's a basic part of accessible navigation.

agreed - essential for accessible navigation testing

+1 it's an essential feature of accessibility tests.

+1

This issue has been open for quite some years and a lot of people follow it (and thus get emails for new comments).

Please refrain from posting comments that merely say โ€œ+1โ€ and clutter the issue. These make it more difficult for people to find other comments that discuss what is needed to move this forward or other packages that people can use as a workaround.

Instead of posting โ€œ+1โ€ please hit the ๐Ÿ‘ on the opening post.

+1

+1

ffs please use the +1 button, this one:
Screenshot_20220726_203620

instead of adding "+1" comments, which will notify everyone subscribed to this issue!

Just unsubscribe from the thread. It's not fixed in 6 years. The chance for a better project/stack popping up is higher than cypress getting its shit together :)

This needs to be prioritised in some manner. Leaving disabled people behind as we all forge ahead only testing mouse interactions is probably a violation of policy for many if not law.

The chance for a better project/stack popping up is higher than cypress getting its shit together :)

https://github.com/microsoft/playwright is already here and supports any keys ๐Ÿ‘

What is the threshold for getting this in? Literally has more thumbs up than people watching this repo ๐Ÿ˜‚

This likely isn't getting implemented. Some decisions made at a fundamental level put it in the "too hard" basket.

Thus as mentioned above, the real solution is everyone switching to new tooling which doesn't suffer the same design flaw.

Sad that it is taking years to get recognition that USERS use the tab key to navigate web pages. Sad.
Why not just make the plugin code native to Cypress since that is what you are telling people to use. That would make one less package to manage for us consumers.

Just use cypress-real-events, works great.

This would be a great feature and I don't know why it's not already supported for tabbing between elements. It is required a great deal in most web based workflows.

Just use cypress-real-events, works great.

just FYI for those who are testing in firefox. cypress-real-events is not supported in firefox

How many more thumb ups do we need?

@walleyyang could very well be that the way Cypress works does not allow an easy implementation of this. How many more times people need to tell you to use Playwright instead? ๐Ÿ˜†

Just use cypress-real-events, works great.

No. It does not work great.

Is there any update on this feature request?

Will Cypress's new paid accessibility product cover tab navigation of forms and other interactable elements? https://www.cypress.io/blog/2024/02/16/introducing-cypress-accessibility

Wow, is this still going on? May I suggest everyone do the correct thing... cough Playwright cough

Will Cypress's new paid accessibility product cover tab navigation of forms and other interactable elements? https://www.cypress.io/blog/2024/02/16/introducing-cypress-accessibility

From my read that just checks tags and things exist. Some kind of basic checklist, surely not worth paying for.

While Cypress itself will continue being incapable of actually testing the types of interactions needed to confirm accessibility.

Well the website for the underlying service certainly has the "Use enough contrast as to be painful to look at" part down ;D

https://dequeuniversity.com/checklists/web/

I'm gonna add another vote "pro" multiple tabs feature.

I got a case where all pages open in new tabs by clicking on respective buttons.

The buttons don't have "target" attr or anything like that which would allow me to manipulate the DOM.

And changing the whole system behavior based on one guy's request (who's just a QA and not an end-user) is absurd and nobody will do that, as the organization is huge. Nobody is gonna change the tool as it's already deeply rooted into the system architecture.

I hope it will be added someday.

@alexzavg This issue is in relation to Cypress not having support for simulating a press of the TAB key.

It sounds like your comment may be for something related to multiple browser tabs?

I stumbled over this feature today and can't believe, that Cypress does not support the {tab} key since 2016 and still do not support it natively. ๐Ÿ˜ฎ

+1 for adding {tab} to this list: https://docs.cypress.io/api/commands/type#Arguments

@alexzavg This issue is in relation to Cypress not having support for simulating a press of the TAB key.

It sounds like your comment may be for something related to multiple browser tabs?

oh, yeah, sorry about that, I was referring to the multiple tabs feature which is also something of importance. I guess I've misunderstood the thread title.

+1 for adding {tab} to this list: https://docs.cypress.io/api/commands/type#Arguments. Is there any timeline?

+1 for adding {tab} to this list: https://docs.cypress.io/api/commands/type#Arguments. Is there any timeline?

It's not that list.

It's that you can't test pressing tab to navigate between fields. Thus can't test accessibility.

It will never be implemented. We're all just hanging out here for the laughs.

The laughs is the only way to play right!