cypress-plugin-tab icon indicating copy to clipboard operation
cypress-plugin-tab copied to clipboard

If a `keydown` handler changes focus, `cy.tab` will chose the wrong element

Open NicholasBoll opened this issue 3 years ago • 0 comments

We have a focus redirect JS function for managing focus of a non-modal dialog. According to WCAG focus requirements, a non-modal dialog should be in the focus order after a triggering button:

https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-focus-order.html

A Web page implements modeless dialogs via scripting. When the trigger button is activated, a dialog opens. The interactive elements in the dialog are inserted in the focus order immediately after the button. When the dialog is open, the focus order goes from the button to the elements of the dialog, then to the interactive element following the button. When the dialog is closed, the focus order goes from the button to the following element.

Since we "portal" our dialog, we manage focus manually. When we're on the last focusable element in a dialog, a keydown handler will close the dialog and shift focus back to the triggering button. When the keydown event is completed, the browser will perform the default action of advancing focus. This plugin uses the previous el to determine the next focusable element before the keydown event is processed. This means this plugin doesn't account for focus changes inside a keydown which is a valid thing to do.

If instead doc.activeElement was used to determine index, this use-case would work.

But this breaks the documented API where focus() is not necessary to tab.

Example, in the tests:

cy.get('a:first').tab()

This example allows you to skip focusing on the a:first element and tab from it anyway, which is not how users really interact with a page. With this change, the test would have to be changed to:

cy.get('a:first').focus().tab()

@Bkucera What do you think? My proposal is more realistic to how browsers work, but would be a breaking change according to the documented API.

NicholasBoll avatar Jun 03 '21 20:06 NicholasBoll