diff --git a/docs/api/commands/focus.mdx b/docs/api/commands/focus.mdx index 36024d875a..bf1f67c959 100644 --- a/docs/api/commands/focus.mdx +++ b/docs/api/commands/focus.mdx @@ -159,4 +159,5 @@ the following: - [`.blur()`](/api/commands/blur) - [`.click()`](/api/commands/click) - [`cy.focused()`](/api/commands/focused) +- [`cy.press()`](/api/commands/press) - [`.type()`](/api/commands/type) diff --git a/docs/api/commands/press.mdx b/docs/api/commands/press.mdx new file mode 100644 index 0000000000..f0bef379fe --- /dev/null +++ b/docs/api/commands/press.mdx @@ -0,0 +1,134 @@ +--- +title: 'cy.press() | Cypress Documentation' +description: Trigger native key events in your application to simulate keyboard interactions. +sidebar_label: press +slug: /api/commands/press +componentSpecific: false +--- + + + +# press + +Trigger native key events in your application to simulate keyboard interactions. + +A `keydown`, `press`, and `keyup` event will be dispatched directly to the browser window. + +Unlike `cy.type()`, which is best for typing character keys, `cy.press()` will dispatch real keyboard events rather than simulated ones. This command is especially useful when testing focus management and keyboard navigation patterns which are critical for [accessibility testing](/app/guides/accessibility-testing) and great keyboard UX. + +Currently, the only key supported is `Tab`. + +:::caution + +Supported Browsers: +This command is supported in chromium browsers and Firefox versions >= v135. WebKit +is not supported. This command will fail if executed in a browser that does not support +it. + +::: + +## Syntax + +```javascript +cy.press(key) +cy.press(key, options) +``` + +## Signature + +```typescript +interface PressCommand { + ( + key: KeyPressSupportedKeys, + options?: Partial & Partial + ): void +} +``` + +## Usage + + **Correct Usage** + +```javascript +cy.get('input.first').focus() +cy.press(Cypress.Keyboard.Keys.TAB) +cy.get('input.second').should('have.focus') +``` + + **Incorrect Usage** + +```javascript +cy.get('input.first').focus() +cy.press(Cypress.Keyboard.Keys.TAB) + // Errors because press yields null + .should('have.focus') +``` + +### Arguments + + **key _(String)_** + +The key to press. The supported values are available on [`Cypress.Keyboard.Keys`](/api/cypress-api/keyboard-api), and may change from time to time. It's recomended that you reference these values from `Cypress.Keyboard.Keys` rather than passing in a string. + +### Supported Keys + +| Reference | Value | +| --------------------------- | ------- | +| `Cypress.Keyboard.Keys.TAB` | `"Tab"` | + + **options _(Object)_** + +Pass in an options object to change the default behavior of `.press()`. + +| Option | Default | Description | +| --------- | ----------------------------------------------------------------- | ----------------------------------------------------------------------------------- | +| `log` | `true` | Displays the command in the [Command log](/app/core-concepts/open-mode#Command-Log) | +| `timeout` | [`defaultCommandTimeout`](/app/references/configuration#Timeouts) | Time to wait for `cy.press()` to resolve before timing out | + + + +- `cy.press()` yields `null`. + +## Examples + +### Test focus order of tab + +```js +it('moves focus to the next form element when pressing Tab', () => { + cy.visit('/my-login') + cy.get('input.email').type('username') + cy.press(Cypress.Keyboard.Keys.TAB) + cy.get('input.password').should('have.focus') +}) +``` + +### Test autocomplete of search input with tab + +```js +it('autocompletes search input when pressing Tab', () => { + cy.get('[data-cy="search"]').type('cy') + cy.press(Cypress.Keyboard.Keys.TAB) + cy.get('[data-cy="search"]').should('have.value', 'cypress') +}) +``` + +## Notes + +### Transient activation + +By dispatching native keyboard events to the browser, this command will cause the browser to enter [Transient activation](https://developer.mozilla.org/en-US/docs/Glossary/Transient_activation) state. + +If your application prevents the default behavior of the `beforeunload` event, this may cause issues when navigating away from the current page. + +## History + +| Version | Changes | +| ----------------------------------- | ---------------------------- | +| [14.3.0](/app/references/changelog) | Added the `.press()` command | + +## See also + +- [`Cypress.Keyboard`](/api/cypress-api/keyboard-api) +- [`.focus()`](/api/commands/focus) +- [`.focused()`](/api/commands/focused) +- [`.type()`](/api/commands/type) diff --git a/docs/api/commands/type.mdx b/docs/api/commands/type.mdx index 075919fa71..97f7030c87 100644 --- a/docs/api/commands/type.mdx +++ b/docs/api/commands/type.mdx @@ -664,5 +664,6 @@ following: - [`.clear()`](/api/commands/clear) - [`.click()`](/api/commands/click) - [`.focus()`](/api/commands/focus) +- [`cy.press()`](/api/commands/press) - [`.submit()`](/api/commands/submit) - [`Cypress.Keyboard`](/api/cypress-api/keyboard-api) diff --git a/docs/api/cypress-api/keyboard-api.mdx b/docs/api/cypress-api/keyboard-api.mdx index 8a8823e0c4..e01f3ab19f 100644 --- a/docs/api/cypress-api/keyboard-api.mdx +++ b/docs/api/cypress-api/keyboard-api.mdx @@ -9,16 +9,29 @@ sidebar_position: 150 # Cypress.Keyboard -The Keyboard API allows you set the default values for how the +The Keyboard API allows you to access available `Keys` for use with [`cy.press()`](/api/commands/press) or to set the default values for how the [.type()](/api/commands/type) command is executed. ## Syntax ```javascript +Cypress.Keyboard.Keys(key) Cypress.Keyboard.defaults(options) ``` -### Arguments +### Keys Arguments + + **key _(String)_** + +The key available for `cy.press()`. + +The following keys are supported: + +| Reference | Value | +| --------------------------- | ------- | +| `Cypress.Keyboard.Keys.TAB` | `"Tab"` | + +### defaults Arguments **options _(Object)_** @@ -30,6 +43,13 @@ An object containing the following: ## Examples +### Press tab key + +```javascript +cy.press(Cypress.Keyboard.Keys.TAB) +cy.get('input.second').should('have.focus') +``` + ### Slow down typing by increasing the keystroke delay ```javascript @@ -59,22 +79,31 @@ The keystroke delay can also be set via which can be useful when setting it for a single test or a subset of tests. ```javascript -it('removes keystroke delay for all typing in this test', { keystrokeDelay: 0 }, () => { - cy.get('input').eq(0).type('fast typing') - cy.get('input').eq(1).type('more fast typing') -}) - -describe('removes keystroke delay in all tests in this suite', { keystrokeDelay: 0 }, () => { - it('types fast in the first input', () => { +it( + 'removes keystroke delay for all typing in this test', + { keystrokeDelay: 0 }, + () => { cy.get('input').eq(0).type('fast typing') - }) - - it('types fast in the second input', () => { cy.get('input').eq(1).type('more fast typing') - }) -})) + } +) + +describe( + 'removes keystroke delay in all tests in this suite', + { keystrokeDelay: 0 }, + () => { + it('types fast in the first input', () => { + cy.get('input').eq(0).type('fast typing') + }) + + it('types fast in the second input', () => { + cy.get('input').eq(1).type('more fast typing') + }) + } +) ``` ## See also +- [`cy.press()`](/api/commands/press) - [`.type()`](/api/commands/type) diff --git a/docs/api/table-of-contents.mdx b/docs/api/table-of-contents.mdx index 693ea90714..01c2a7f43f 100644 --- a/docs/api/table-of-contents.mdx +++ b/docs/api/table-of-contents.mdx @@ -139,6 +139,7 @@ Cypress has a variety of additional commands to help write tests. | [`.mount()`](/api/commands/mount) | Mount a component for Cypress Component Testing. | | [`.origin()`](/api/commands/origin) | Visit multiple domains of different origin in a single test. | | [`.pause()`](/api/commands/pause) | Pause test execution, allowing interaction with the application under test before resuming. | +| [`.press()`](/api/commands/press) | Trigger native key events in your application to simulate real user keyboard interactions. | | [`.readFile()`](/api/commands/readfile) | Read a file from disk. | | [`.reload()`](/api/commands/reload) | Reload the page. | | [`.request()`](/api/commands/request) | Make an HTTP request. | diff --git a/docs/app/guides/accessibility-testing.mdx b/docs/app/guides/accessibility-testing.mdx index 827095944e..62d4e594cf 100644 --- a/docs/app/guides/accessibility-testing.mdx +++ b/docs/app/guides/accessibility-testing.mdx @@ -169,6 +169,13 @@ This means that, without some assertions about either the `button` element itsel Developers who are unfamiliar with accessibility may assume that if a Testing Library `ByRole` locator can be made to pass before and after a code change, there has been no functional or accessibility-related change in the underlying element. As we've seen, this is not actually the case, because of the extra behavior browsers only implement for native HTML elements. For more about this difference and why semantic HTML elements are preferred, see the [first rule of Accessible Rich Internet Applications (ARIA)](https://www.w3.org/TR/using-aria/#rule1). +### Keyboard navigation + +To test intra-page navigation with the keyboard, you can use the [`cy.press()`](/api/commands/press) to dispatch native tab events. + +Note that the application under test does not have focus by default. You must focus an element in your application before it will receive +this event. + ## Where to test accessibility So what should you do in your test automation to help confirm the UI is accessible? First of all, for known critical areas like forms or checkout flows, ensure that the accessibility behavior is tested explicitly in at least one place. The means verifying that form fields and buttons have the correct labels and use the expected HTML elements, and other aspects of the DOM that communicate necessary information.