Fire native system events from Cypress.
Cypress default events are simulated. That means that all events like
cy.clickor
cy.typeare fired from javascript. That's why these events will be untrusted (
event.isTrustedwill be
false) and they can behave a little different from real native events. But for some cases it can be impossible to use native events, for example to fill a native alert or copy to the clipboard.
Thanks to Chrome Devtools Protocol. Cypress is connecting to CDP for tasks like screenshots, this project is using the same connection to fire system events. It works literally like in puppeteer. And as a result unlocks such features like hovering and native focus management via Tab.
Cypress only. Really. Cypress itself can fire native events. The only limitation for real events – they work only in the chromium-based browser. That means that Firefox is not supported, at least for now.
Here is a simple test that can be written with native events:
it("tests real events", () => { cy.get("input").realClick(); // perform a native real click on the field cy.realType("cypress real event"); // fires native system keypress events and fills the field cy.realPress("Tab"); // native tab click switches the focus cy.focused().realHover(); // hovers over the new focused element cy.contains("some text in the hovered popover"); });
Install npm package:
npm install cypress-real-eventsyarn add cypress-real-events
Register new commands by adding this to your
cypress/support/index.{js,ts}file.
import "cypress-real-events/support";
If you are using typescript, also add the following to
cypress/tsconfig.json
{ "compilerOptions": { "types": ["cypress", "cypress-real-events"] } }
The idea of the commands – they should be as similar as possible to cypress default commands (like
cy.type), but starts with
real–
cy.realType.
Here is an overview of the available real event commands: - cy.realClick - cy.realHover - cy.realPress - cy.realTouch - cy.realType - cy.realSwipe
Fires native system click event.
cy.get("button").realClick(); cy.get("button").realClick(options);
Example:
cy.get("button").realClick({ position: "topLeft" }) // click on the top left corner of button cy.get("body").realClick({ x: 100, y: 1240 }) // click by the x & y coordinates relative to the whole window
Options:
Optionalbutton: \"none\" | \"left\" | \"right\" | \"middle\" | \"back\" | \"forward\"
Optionalpointer: \"mouse\" | \"pen\"
Optionalx coordinate to click x: number
Optionaly coordinate to click y: number
Optionalposition: "topLeft" | "top" | "topRight" | "left" | "center" | "right" | "bottomLeft" | "bottom" | "bottomRight"
Make sure that
xandyhas a bigger priority thanposition.
Fires a real native hover event. Yes, it can test
:hoverpreprocessor.
cy.get("button").hover(); cy.get("button").hover(options);
Options:
Optionalpointer: \"mouse\" | \"pen\"
Optionalposition: "topLeft" | "top" | "topRight" | "left" | "center" | "right" | "bottomLeft" | "bottom" | "bottomRight"
Fires native press event. It can fire one key event or the "shortcut" like Shift+Control+M. Make sure that event is global, it means that it is required to firstly focus any control before firing this event.
cy.realPress("Tab"); // switch the focus for a11y testing cy.realPress(["Alt", "Meta", "P"]) // Alt+(Command or Control)+P
cy.realPress(key); cy.realPress(key, options);
| Name | Type | Default value | Description | | --------- | ---------------------------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------ | |
key| string | string[] | - | key or keys to press. Should be the same as cypress's type command argument. All the keys available here. | |
options| -
Optionalpointer: \"mouse\" | \"pen\" | {} | |
Fires native system touch event.
cy.get("button").realTouch(); cy.get("button").realTouch(options);
cy.get("button").realTouch({ position: "topLeft" }) // touches the top left corner of button cy.get("body").realTouch({ x: 100, y: 1240 }) // touches the x & y coordinates relative to the whole window
Options:
Optionalx: undefined | number
default30
Optionaly: undefined | false | true
defaulttrue
Optionalposition: "topLeft" | "top" | "topRight" | "left" | "center" | "right" | "bottomLeft" | "bottom" | "bottomRight"
Runs a sequence of native press events (via
cy.realPress). This can be used to simulate real typing. Make sure that type event is global. This means that it is not attached to any field.
cy.realType("type any text"); // type any text on the pagecy.get("input").focus(); cy.realType("some text {enter}"); // type into focused field
cy.realType(text); cy.realType(text, options);
| Name | Type | Default value | Description | | --------- | ------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------- | |
text| string | - | text to type. Should be around the same as cypress's type command argument (https://docs.cypress.io/api/commands/type.html#Arguments) | |
options| Options | {} | |
Options:
Optionaldelay: undefined | number
default30
Optionallog: undefined | false | true
defaulttrue
OptionalpressDelay: undefined | number
default10
Runs a native swipe events. It means that touch events will be fired. Actually a sequence of
touchStart->
touchMove->
touchEnd. It can perfectly swipe drawers and other tools like this one.
Make sure to enable mobile viewport :)
cy.get('.element').realSwipe("toLeft"); // swipes from right to left cy.get('.element').realSwipe("toRight"); // inverted
cy.realType(direction); cy.realType(direction, options);
| Name | Type | Default value | Description | | --------- | ------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------- | |
direction|
"toLeft" | "toTop" | "toRight" | "toBottom";| - | text to type. Should be around the same as cypress's type command argument (https://docs.cypress.io/api/commands/type.html#Arguments) | |
options| Options | {} | |
Options:
Optionallength: undefined | number
default10
Optionalx coordinate to touch x: number
Optionaly coordinate to touch y: number
OptionaltouchPosition: "topLeft" | "top" | "topRight" | "left" | "center" | "right" | "bottomLeft" | "bottom" | "bottomRight"
One problem of the real native system events I need to mention – you will not get an error message if the event wasn't produced. Similar to selenium or playwright – if a javascript event was not fired you will not get a comprehensive error message.
So probably this package should not be used as a replacement of the cypress events, at least for the writing tests experience 🐨
The project is licensed under the terms of MIT license