From 6c49bee86bda2c1eb00d9dcc03af0b36694a64b7 Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 15 Feb 2024 22:08:23 +0100 Subject: [PATCH 1/3] feat(commands): allow to fallback to `charCodeAt` if key is not in keyCodeDefinitions --- README.md | 4 ++-- cypress/e2e/press.cy.ts | 13 +++++++++++++ cypress/e2e/type.cy.ts | 10 ++++++++++ src/commands/realPress.ts | 25 +++++++++++++++++++++---- src/commands/realType.ts | 14 ++------------ 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index da7ca1a..50ef5a8 100644 --- a/README.md +++ b/README.md @@ -162,7 +162,7 @@ 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](https://docs.cypress.io/api/commands/type.html#Arguments). All the keys available [here](https://github.com/dmtrKovalenko/cypress-real-events/blob/main/src/keyCodeDefinitions.ts) | +| `key` | `string \| string[]` | - | key or keys to press. Should be the same as cypress's [type command argument](https://docs.cypress.io/api/commands/type.html#Arguments). | | `options` | Options | {} | | Options: @@ -217,7 +217,7 @@ 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. All the keys available [here](https://github.com/dmtrKovalenko/cypress-real-events/blob/main/src/keyCodeDefinitions.ts) | +| `text` | string | - | text to type. Should be around the same as cypress's type command argument | | `options` | Options | {} | | Options: diff --git a/cypress/e2e/press.cy.ts b/cypress/e2e/press.cy.ts index 4fdb40e..5ac98ce 100644 --- a/cypress/e2e/press.cy.ts +++ b/cypress/e2e/press.cy.ts @@ -14,6 +14,19 @@ describe("cy.realPress", { retries: 10 }, () => { cy.get("input").should("have.value", "cypress"); }); + it("Can type non alpha-num into an input", () => { + cy.intercept("http://presstest.com/", (req) => { + const html = document.implementation.createHTMLDocument(); + html.body.innerHTML = ``; + req.reply(html.documentElement.innerHTML); + }); + cy.visit("http://presstest.com/"); + cy.get("input").focus(); + + cy.realPress("😊"); + cy.get("input").should("have.value", "😊"); + }); + it("Can fire native Tab focus switch", () => { cy.visit("./cypress/fixtures/focus-order.html"); cy.window().focus(); diff --git a/cypress/e2e/type.cy.ts b/cypress/e2e/type.cy.ts index c71393a..a2f9085 100644 --- a/cypress/e2e/type.cy.ts +++ b/cypress/e2e/type.cy.ts @@ -38,4 +38,14 @@ describe("cy.realType", () => { cy.realType("{{}test}"); cy.get("input[name=q]").should("have.value", "{test}"); }); + + it("can type text with emoji", () => { + const msg = "cypress-real-events is awesome! ❤️❤️❤️❤️❤️❤️" + cy.realType(msg); + + cy.get("input[name=q]").should( + "have.value", + msg, + ); + }); }); diff --git a/src/commands/realPress.ts b/src/commands/realPress.ts index f877f9f..3cb32f7 100644 --- a/src/commands/realPress.ts +++ b/src/commands/realPress.ts @@ -15,10 +15,27 @@ export interface RealPressOptions { log?: boolean; } -function getKeyDefinition(key: keyof typeof keyCodeDefinitions) { - const keyDefinition = keyCodeDefinitions[key]; +// Emoji Unicode range +const EMOJI_RE = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u; + +function isEmoji(char: string) { + return EMOJI_RE.test(char); +} + +function getKeyDefinition(key: string) { + const keyDefinition = keyCodeDefinitions[key as keyof typeof keyCodeDefinitions]; if (!keyDefinition) { + if (key.length === 1 || isEmoji(key)) { + return { + keyCode: key.charCodeAt(0), + key, + text: key, + code: `Key${key.toUpperCase()}`, + location: 0, + windowsVirtualKeyCode: key.charCodeAt(0), + } + } throw new Error(`Unsupported key '${key}'.`); } @@ -37,11 +54,11 @@ function getKeyDefinition(key: keyof typeof keyCodeDefinitions) { type Key = keyof typeof keyCodeDefinitions; // unfortunately passing a string like Shift+P is not possible cause typescript template literals can not handle such giant union -type KeyOrShortcut = Key | Array; +export type KeyOrShortcut = Key | Array; /** @ignore this, update documentation for this function at index.d.ts */ export async function realPress( - keyOrShortcut: KeyOrShortcut, + keyOrShortcut: string | string[], options: RealPressOptions = {}, ) { let log; diff --git a/src/commands/realType.ts b/src/commands/realType.ts index fca819b..ea40a2b 100644 --- a/src/commands/realType.ts +++ b/src/commands/realType.ts @@ -1,5 +1,4 @@ -import { keyCodeDefinitions } from "../keyCodeDefinitions"; -import { realPress } from "./realPress"; +import { realPress, type KeyOrShortcut } from "./realPress"; export interface RealTypeOptions { /** @@ -19,14 +18,6 @@ export interface RealTypeOptions { log?: boolean; } -const availableChars = Object.keys(keyCodeDefinitions); -function assertChar( - char: string, -): asserts char is keyof typeof keyCodeDefinitions { - if (!availableChars.includes(char)) { - throw new Error(`Unrecognized character "${char}".`); - } -} /** @ignore this, update documentation for this function at index.d.ts */ export async function realType(text: string, options: RealTypeOptions = {}) { @@ -52,8 +43,7 @@ export async function realType(text: string, options: RealTypeOptions = {}) { }, [] as string[]); for (const char of chars) { - assertChar(char); - await realPress(char, { + await realPress(char as KeyOrShortcut, { pressDelay: options.pressDelay ?? 15, log: false, }); From 18a1d0956301bfc2da434bb451a6ca784412260d Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 15 Feb 2024 22:18:30 +0100 Subject: [PATCH 2/3] chore: lint-format --- cypress/e2e/type.cy.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/e2e/type.cy.ts b/cypress/e2e/type.cy.ts index a2f9085..b047c98 100644 --- a/cypress/e2e/type.cy.ts +++ b/cypress/e2e/type.cy.ts @@ -39,8 +39,8 @@ describe("cy.realType", () => { cy.get("input[name=q]").should("have.value", "{test}"); }); - it("can type text with emoji", () => { - const msg = "cypress-real-events is awesome! ❤️❤️❤️❤️❤️❤️" + it("can type text with emoji and cyrillic characters", () => { + const msg = "cypress-real-events is awesome! ❤️❤️❤️❤️❤️❤️ В" cy.realType(msg); cy.get("input[name=q]").should( From 17ee93064b991f2ff70488f11488ae8bd015224b Mon Sep 17 00:00:00 2001 From: julien huang Date: Thu, 15 Feb 2024 22:22:10 +0100 Subject: [PATCH 3/3] chore: prettier format --- cypress/e2e/type.cy.ts | 7 ++----- src/commands/realPress.ts | 8 +++++--- src/commands/realType.ts | 1 - 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/cypress/e2e/type.cy.ts b/cypress/e2e/type.cy.ts index b047c98..346c1bf 100644 --- a/cypress/e2e/type.cy.ts +++ b/cypress/e2e/type.cy.ts @@ -40,12 +40,9 @@ describe("cy.realType", () => { }); it("can type text with emoji and cyrillic characters", () => { - const msg = "cypress-real-events is awesome! ❤️❤️❤️❤️❤️❤️ В" + const msg = "cypress-real-events is awesome! ❤️❤️❤️❤️❤️❤️ В"; cy.realType(msg); - cy.get("input[name=q]").should( - "have.value", - msg, - ); + cy.get("input[name=q]").should("have.value", msg); }); }); diff --git a/src/commands/realPress.ts b/src/commands/realPress.ts index 3cb32f7..6d7ae65 100644 --- a/src/commands/realPress.ts +++ b/src/commands/realPress.ts @@ -16,14 +16,16 @@ export interface RealPressOptions { } // Emoji Unicode range -const EMOJI_RE = /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u; +const EMOJI_RE = + /[\u{1F600}-\u{1F64F}\u{1F300}-\u{1F5FF}\u{1F680}-\u{1F6FF}\u{1F700}-\u{1F77F}\u{1F780}-\u{1F7FF}\u{1F800}-\u{1F8FF}\u{1F900}-\u{1F9FF}\u{1FA00}-\u{1FA6F}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u; function isEmoji(char: string) { return EMOJI_RE.test(char); } function getKeyDefinition(key: string) { - const keyDefinition = keyCodeDefinitions[key as keyof typeof keyCodeDefinitions]; + const keyDefinition = + keyCodeDefinitions[key as keyof typeof keyCodeDefinitions]; if (!keyDefinition) { if (key.length === 1 || isEmoji(key)) { @@ -34,7 +36,7 @@ function getKeyDefinition(key: string) { code: `Key${key.toUpperCase()}`, location: 0, windowsVirtualKeyCode: key.charCodeAt(0), - } + }; } throw new Error(`Unsupported key '${key}'.`); } diff --git a/src/commands/realType.ts b/src/commands/realType.ts index ea40a2b..03edad4 100644 --- a/src/commands/realType.ts +++ b/src/commands/realType.ts @@ -18,7 +18,6 @@ export interface RealTypeOptions { log?: boolean; } - /** @ignore this, update documentation for this function at index.d.ts */ export async function realType(text: string, options: RealTypeOptions = {}) { let log;