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

Need tab support #299

Open
robdodson opened this Issue Nov 17, 2016 · 20 comments

Comments

@robdodson

robdodson commented Nov 17, 2016

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?

@jennifer-shehane

This comment has been minimized.

Show comment
Hide comment
@jennifer-shehane

jennifer-shehane Nov 17, 2016

Member

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.

Member

jennifer-shehane commented Nov 17, 2016

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.

@robdodson

This comment has been minimized.

Show comment
Hide comment
@robdodson

robdodson Nov 17, 2016

thanks for the response @jennifer-mann

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.

robdodson commented Nov 17, 2016

thanks for the response @jennifer-mann

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.

@brian-mann

This comment has been minimized.

Show comment
Hide comment
@brian-mann

brian-mann Nov 17, 2016

Member

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.

Member

brian-mann commented Nov 17, 2016

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.

@robdodson

This comment has been minimized.

Show comment
Hide comment
@robdodson

robdodson Nov 18, 2016

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 :)

robdodson commented Nov 18, 2016

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 :)

@kamituel

This comment has been minimized.

Show comment
Hide comment
@kamituel

kamituel Jul 20, 2017

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()?

kamituel commented Jul 20, 2017

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()?

@jennifer-shehane

This comment has been minimized.

Show comment
Hide comment
@jennifer-shehane

jennifer-shehane Oct 30, 2017

Member

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

Member

jennifer-shehane commented Oct 30, 2017

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

@protoEvangelion

This comment has been minimized.

Show comment
Hide comment
@protoEvangelion

protoEvangelion Dec 1, 2017

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

protoEvangelion commented Dec 1, 2017

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

@alhill10

This comment has been minimized.

Show comment
Hide comment
@alhill10

alhill10 Dec 1, 2017

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

alhill10 commented Dec 1, 2017

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

@davidszepernick

This comment has been minimized.

Show comment
Hide comment
@davidszepernick

davidszepernick Dec 5, 2017

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

davidszepernick commented Dec 5, 2017

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

@siemiatj

This comment has been minimized.

Show comment
Hide comment
@siemiatj

siemiatj Feb 28, 2018

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

siemiatj commented Feb 28, 2018

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

@mirandashort

This comment has been minimized.

Show comment
Hide comment
@mirandashort

mirandashort Mar 26, 2018

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

mirandashort commented Mar 26, 2018

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

@scottschafer

This comment has been minimized.

Show comment
Hide comment
@scottschafer

scottschafer Apr 9, 2018

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 commented Apr 9, 2018

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
    });
  });
});
@brian-mann

This comment has been minimized.

Show comment
Hide comment
@brian-mann

brian-mann Apr 10, 2018

Member

@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

Member

brian-mann commented Apr 10, 2018

@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

@jennifer-shehane

This comment has been minimized.

Show comment
Hide comment
@jennifer-shehane

jennifer-shehane Apr 10, 2018

Member

@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
  });
});
Member

jennifer-shehane commented Apr 10, 2018

@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
  });
});
@scottschafer

This comment has been minimized.

Show comment
Hide comment
@scottschafer

scottschafer Apr 10, 2018

@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 commented Apr 10, 2018

@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.

@jennifer-shehane

This comment has been minimized.

Show comment
Hide comment
@jennifer-shehane

jennifer-shehane Apr 11, 2018

Member

@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.

Member

jennifer-shehane commented Apr 11, 2018

@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.

@lazarljubenovic

This comment has been minimized.

Show comment
Hide comment
@lazarljubenovic

lazarljubenovic May 25, 2018

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?

lazarljubenovic commented May 25, 2018

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?

@decafdennis

This comment has been minimized.

Show comment
Hide comment
@decafdennis

decafdennis May 25, 2018

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 commented May 25, 2018

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!

@samjulien

This comment has been minimized.

Show comment
Hide comment
@samjulien

samjulien Jun 12, 2018

@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.

samjulien commented Jun 12, 2018

@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.

@Bkucera Bkucera added this to the 4.0.0 milestone Jul 30, 2018

@Bkucera

This comment has been minimized.

Show comment
Hide comment
@Bkucera

Bkucera Jul 31, 2018

Member

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

Member

Bkucera commented Jul 31, 2018

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment