import logger from '@wdio/logger'
import { getBrowserObject } from '@wdio/utils'
import type { MoveToOptions } from '../../types.js'
const log = logger('webdriver')
*
* Move the mouse by an offset of the specified element. If no element is specified,
* the move is relative to the current mouse cursor. If an element is provided but
* no offset, the mouse will be moved to the center of the element. If the element
* is not visible, it will be scrolled into view.
*
* @param {MoveToOptions=} options moveTo command options
* @param {Number=} options.xOffset X offset to move to, relative to the center of the element. If not specified, the mouse will move to the center of the element.
* @param {Number=} options.yOffset Y offset to move to, relative to the center of the element. If not specified, the mouse will move to the center of the element.
*
* @see https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidmoveto
* @type protocol
*/
export async function moveTo (
this: WebdriverIO.Element,
{ xOffset, yOffset }: MoveToOptions = {},
) {
* W3C way of handle the mouse move actions
*/
const browser = getBrowserObject(this)
if (xOffset || yOffset) {
const { width, height } = await browser.getElementRect(this.elementId)
if ((xOffset && xOffset < (-Math.floor(width / 2))) || (xOffset && xOffset > Math.floor(width / 2))) {
log.warn('xOffset would cause a out of bounds error as it goes outside of element')
}
if ((yOffset && yOffset < (-Math.floor(height / 2))) || (yOffset && yOffset > Math.floor(height / 2))) {
log.warn('yOffset would cause a out of bounds error as it goes outside of element')
}
}
const moveToNested = async () => {
await browser.action('pointer', { parameters: { pointerType: 'mouse' } })
.move({ origin: this, x: xOffset || 0, y: yOffset || 0 })
.perform()
}
try {
await moveToNested()
} catch {
* Workaround, because sometimes browser.action().move() flaky and isn't able to scroll pointer to into view
* Moreover the action with 'nearest' behavior by default where element is aligned at the bottom of its ancestor.
* and could be overlapped. Scroll to center should definitely work even if element was covered with sticky header/footer
*/
await this.scrollIntoView({ block: 'center', inline: 'center' })
await moveToNested()
}
}