import {fireEvent} from '@testing-library/dom'; function isElement(obj) { if (typeof obj !== 'object') { return false } let prototypeStr, prototype do { prototype = Object.getPrototypeOf(obj) // to work in iframe prototypeStr = Object.prototype.toString.call(prototype) // '[object Document]' is used to detect document if ( prototypeStr === '[object Element]' || prototypeStr === '[object Document]' ) { return true } obj = prototype // null is the terminal of object } while (prototype !== null) return false } function getElementClientCenter(element) { const {left, top, width, height} = element.getBoundingClientRect() return { x: left + width / 2, y: top + height / 2, } } const getCoords = charlie => isElement(charlie) ? getElementClientCenter(charlie) : charlie const sleep = ms => new Promise(resolve => { setTimeout(resolve, ms); }); export default async function drag( element, {to: inTo, delta, steps = 20, duration = 500}, ) { const from = getElementClientCenter(element) const to = delta ? { x: from.x + delta.x, y: from.y + delta.y, } : getCoords(inTo) const step = { x: (to.x - from.x) / steps, y: (to.y - from.y) / steps, } const current = { clientX: from.x, clientY: from.y, } fireEvent.mouseEnter(element, current) fireEvent.mouseOver(element, current) fireEvent.mouseMove(element, current) fireEvent.mouseDown(element, current) for (let i = 0; i < steps; i++) { current.clientX += step.x current.clientY += step.y await sleep(duration / steps) fireEvent.mouseMove(element, current) } fireEvent.mouseUp(element, current) }