From b99961249730bf26e597de281396e948454e42a1 Mon Sep 17 00:00:00 2001 From: Dmitriy Kovalenko Date: Sat, 19 Dec 2020 15:22:10 +0200 Subject: [PATCH] Make a realDnd concept --- cypress/integration/realdnd.spec.ts | 10 ++++ src/commands/realDnd.ts | 78 +++++++++++++++++++++++++++++ src/index.d.ts | 12 +++++ src/support.ts | 15 ++++++ 4 files changed, 115 insertions(+) create mode 100644 cypress/integration/realdnd.spec.ts create mode 100644 src/commands/realDnd.ts diff --git a/cypress/integration/realdnd.spec.ts b/cypress/integration/realdnd.spec.ts new file mode 100644 index 0000000..c56fd3a --- /dev/null +++ b/cypress/integration/realdnd.spec.ts @@ -0,0 +1,10 @@ +describe("cy.realDnd", () => { + beforeEach(() => { + cy.visit("https://csb-q3r9e-l9d9gloe1.vercel.app/") + }) + + + it("can drag and drop", () => { + cy.get("div[draggable=true]").realDnd(':nth-child(43) > [style="position: relative; width: 100%; height: 100%;"] > div') + }) +}) \ No newline at end of file diff --git a/src/commands/realDnd.ts b/src/commands/realDnd.ts new file mode 100644 index 0000000..7a11713 --- /dev/null +++ b/src/commands/realDnd.ts @@ -0,0 +1,78 @@ +import { fireCdpCommand } from "../fireCdpCommand"; +import { + getCypressElementCoordinates, + Position, +} from "../getCypressElementCoordinates"; + +export interface RealDndOptions { + /** Pointer type for realClick, if "pen" touch simulated */ + pointer?: "mouse" | "pen"; + /** + * Position of the click event relative to the element + * @example cy.realClick({ position: "topLeft" }) + */ + position?: Position; +} + +function isJQuery(obj: unknown): obj is JQuery { + return Boolean(obj.jquery); +} + +/** @ignore this, update documentation for this function at index.d.ts */ +export async function realDnd( + subject: JQuery, + destination: JQuery | { x: number; y: number }, + options: RealDndOptions = {} +) { + if (!destination) { + throw new Error( + "destination is required when using cy.realDnd(destination)" + ); + } + + const startCoords = getCypressElementCoordinates(subject, options.position); + const endCoords = isJQuery(destination) + ? getCypressElementCoordinates(destination, options.position) + : destination; + + const log = Cypress.log({ + $el: subject, + name: "realClick", + consoleProps: () => ({ + Dragged: subject.get(0), + From: startCoords, + End: endCoords, + }), + }); + + log.snapshot("before"); + await fireCdpCommand("Input.dispatchMouseEvent", { + type: "mousePressed", + ...startCoords, + clickCount: 1, + buttons: 1, + pointerType: options.pointer ?? "mouse", + button: "left", + }); + + console.log(endCoords) + await fireCdpCommand("Input.dispatchMouseEvent", { + ...endCoords, + type: "mouseMoved", + button: "left", + pointerType: options.pointer ?? "mouse", + }); + + await fireCdpCommand("Input.dispatchMouseEvent", { + type: "mouseReleased", + ...endCoords, + clickCount: 1, + buttons: 1, + pointerType: options.pointer ?? "mouse", + button: "left", + }); + + log.snapshot("after").end(); + + return subject; +} diff --git a/src/index.d.ts b/src/index.d.ts index 1c8f179..089893a 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -48,5 +48,17 @@ declare namespace Cypress { * @param text text to type. Should be the same as cypress's default type command argument (https://docs.cypress.io/api/commands/type.html#Arguments) */ realType: typeof import("./commands/realType").realType; + /** + * Runs native drag and drop event. + * @see https://github.com/dmtrKovalenko/cypress-real-events#cyrealtype + * @example + * cy.get(".card").realDnd(".someOtherPane") + * cy.get(".card").realDnd({ x: 1000, y: 251 }) + * @param destination where to drop the element + * @param options dnd options + */ + realDnd: NormalizeCypressCommand< + typeof import("./commands/realDnd").realDnd + >; } } diff --git a/src/support.ts b/src/support.ts index 54de5c9..5392b3f 100644 --- a/src/support.ts +++ b/src/support.ts @@ -1,4 +1,5 @@ import { realClick } from "./commands/realClick"; +import { realDnd } from "./commands/realDnd"; import { realHover } from "./commands/realHover"; import { realPress } from "./commands/realPress"; import { realType } from "./commands/realType"; @@ -7,3 +8,17 @@ Cypress.Commands.add("realClick", { prevSubject: true }, realClick); Cypress.Commands.add("realHover", { prevSubject: true }, realHover); Cypress.Commands.add("realPress", realPress); Cypress.Commands.add("realType", realType); +Cypress.Commands.add("realDndRaw", realDnd); +Cypress.Commands.add( + "realDnd", + { prevSubject: true }, + (subject, destination, opts) => { + if (typeof destination === "string") { + cy.get(destination).then((el) => { + cy.realDndRaw(subject, el, opts); + }); + } else { + cy.realDndRaw(subject, destination, opts); + } + } +);