Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion docs/webapi/moveCursorTo.mustache
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
Moves cursor to element matched by locator.
Extra shift can be set with offsetX and offsetY options.

An optional `context` (as a second parameter) can be specified to narrow the search to an element within a parent.
When the second argument is a non-number (string or locator object), it is treated as context.

```js
I.moveCursorTo('.tooltip');
I.moveCursorTo('#submit', 5,5);
I.moveCursorTo('#submit', '.container');
```

@param {CodeceptJS.LocatorOrString} locator located by CSS|XPath|strict locator.
@param {number} [offsetX=0] (optional, `0` by default) X-axis offset.
@param {number|CodeceptJS.LocatorOrString} [offsetX=0] (optional, `0` by default) X-axis offset or context locator.
@param {number} [offsetY=0] (optional, `0` by default) Y-axis offset.
@returns {void} automatically synchronized promise through #recorder
19 changes: 17 additions & 2 deletions lib/helper/Playwright.js
Original file line number Diff line number Diff line change
Expand Up @@ -1495,8 +1495,23 @@ class Playwright extends Helper {
*
*/
async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
const el = await this._locateElement(locator)
assertElementExists(el, locator)
let context = null
if (typeof offsetX !== 'number') {
context = offsetX
offsetX = 0
}

let el
if (context) {
const contextEls = await this._locate(context)
assertElementExists(contextEls, context, 'Context element')
el = await findElements.call(this, contextEls[0], locator)
assertElementExists(el, locator)
el = el[0]
} else {
el = await this._locateElement(locator)
assertElementExists(el, locator)
}

// Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
const { x, y } = await clickablePoint(el)
Expand Down
23 changes: 20 additions & 3 deletions lib/helper/Puppeteer.js
Original file line number Diff line number Diff line change
Expand Up @@ -821,9 +821,26 @@ class Puppeteer extends Helper {
* {{ react }}
*/
async moveCursorTo(locator, offsetX = 0, offsetY = 0) {
const el = await this._locateElement(locator)
if (!el) {
throw new ElementNotFound(locator, 'Element to move cursor to')
let context = null
if (typeof offsetX !== 'number') {
context = offsetX
offsetX = 0
}

let el
if (context) {
const contextEls = await findElements.call(this, this.page, context)
assertElementExists(contextEls, context, 'Context element')
const els = await findElements.call(this, contextEls[0], locator)
if (!els || els.length === 0) {
throw new ElementNotFound(locator, 'Element to move cursor to')
}
el = els[0]
} else {
el = await this._locateElement(locator)
if (!el) {
throw new ElementNotFound(locator, 'Element to move cursor to')
}
}

// Use manual mouse.move instead of .hover() so the offset can be added to the coordinates
Expand Down
18 changes: 16 additions & 2 deletions lib/helper/WebDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -1976,8 +1976,22 @@ class WebDriver extends Helper {
* {{> moveCursorTo }}
*/
async moveCursorTo(locator, xOffset, yOffset) {
const res = await this._locate(withStrictLocator(locator), true)
assertElementExists(res, locator)
let context = null
if (typeof xOffset !== 'number' && xOffset !== undefined) {
context = xOffset
xOffset = undefined
}

let res
if (context) {
const contextRes = await this._locate(withStrictLocator(context), true)
assertElementExists(contextRes, context, 'Context element')
res = await contextRes[0].$$(withStrictLocator(locator))
assertElementExists(res, locator)
} else {
res = await this._locate(withStrictLocator(locator), true)
assertElementExists(res, locator)
}
const elem = usingFirstElement(res)
try {
await elem.moveTo({ xOffset, yOffset })
Expand Down
5 changes: 5 additions & 0 deletions test/helper/Playwright_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ describe('Playwright', function () {
I.amOnPage('/form/hover')
.then(() => I.moveCursorTo('#hover', 100, 100))
.then(() => I.dontSee('Hovered', '#show')))

it('should trigger hover event within a context', () =>
I.amOnPage('/form/hover')
.then(() => I.moveCursorTo('#hover', 'body'))
.then(() => I.see('Hovered', '#show')))
})

describe('#switchToNextTab, #switchToPreviousTab, #openNewTab, #closeCurrentTab, #closeOtherTabs, #grabNumberOfOpenTabs, #waitForNumberOfTabs', () => {
Expand Down
5 changes: 5 additions & 0 deletions test/helper/Puppeteer_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ describe('Puppeteer', function () {
I.amOnPage('/form/hover')
.then(() => I.moveCursorTo('#hover', 100, 100))
.then(() => I.dontSee('Hovered', '#show')))

it('should trigger hover event within a context', () =>
I.amOnPage('/form/hover')
.then(() => I.moveCursorTo('#hover', 'body'))
.then(() => I.see('Hovered', '#show')))
})

describe('#switchToNextTab, #switchToPreviousTab, #openNewTab, #closeCurrentTab, #closeOtherTabs, #grabNumberOfOpenTabs, #waitForNumberOfTabs', () => {
Expand Down
6 changes: 6 additions & 0 deletions test/helper/WebDriver_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,12 @@ describe('WebDriver', function () {
await wd.moveCursorTo('#hover', 100, 100)
await wd.dontSee('Hovered', '#show')
})

it('should trigger hover event within a context', async () => {
await wd.amOnPage('/form/hover')
await wd.moveCursorTo('#hover', 'body')
await wd.see('Hovered', '#show')
})
})

describe('#switchToNextTab, #switchToPreviousTab, #openNewTab, #closeCurrentTab, #closeOtherTabs, #grabNumberOfOpenTabs, #waitForNumberOfTabs', () => {
Expand Down