Skip to content

Commit

Permalink
Make dragAndDrop respect scroll position (webdriverio#4302)
Browse files Browse the repository at this point in the history
* webdriverio: make drag n drop respect scroll position

* webdriverio: fix moveTo
  • Loading branch information
mgrybyk authored and christian-bromann committed Aug 5, 2019
1 parent f4b7511 commit 279c1ec
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 29 deletions.
11 changes: 6 additions & 5 deletions packages/webdriverio/src/commands/element/dragAndDrop.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*
*/

import { getElementRect } from '../../utils'
import { getElementRect, getScrollPosition } from '../../utils'

const ACTION_BUTTON = 0

Expand All @@ -29,12 +29,13 @@ export default async function dragAndDrop (target, duration = 100) {
/**
* get coordinates to drag and drop
*/
const { scrollX, scrollY } = await getScrollPosition(this)
const sourceRect = await getElementRect(this)
const targetRect = await getElementRect(target)
const sourceX = parseInt(sourceRect.x + (sourceRect.width / 2), 10)
const sourceY = parseInt(sourceRect.y + (sourceRect.height / 2), 10)
const targetX = parseInt(targetRect.x + (targetRect.width / 2), 10) - sourceX
const targetY = parseInt(targetRect.y + (targetRect.height / 2), 10) - sourceY
const sourceX = parseInt(sourceRect.x - scrollX + (sourceRect.width / 2), 10)
const sourceY = parseInt(sourceRect.y - scrollY + (sourceRect.height / 2), 10)
const targetX = parseInt(targetRect.x - scrollX + (targetRect.width / 2), 10) - sourceX
const targetY = parseInt(targetRect.y - scrollY + (targetRect.height / 2), 10) - sourceY

/**
* W3C way of handle the drag and drop action
Expand Down
7 changes: 4 additions & 3 deletions packages/webdriverio/src/commands/element/moveTo.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
* @type protocol
*/

import { getElementRect } from '../../utils'
import { getElementRect, getScrollPosition } from '../../utils'

export default async function moveTo (xoffset, yoffset) {
if (!this.isW3C) {
Expand All @@ -23,8 +23,9 @@ export default async function moveTo (xoffset, yoffset) {
* get rect of element
*/
const { x, y, width, height } = await getElementRect(this)
const newXoffset = parseInt(x + (typeof xoffset === 'number' ? xoffset : (width / 2)), 10)
const newYoffset = parseInt(y + (typeof yoffset === 'number' ? yoffset : (height / 2)), 10)
const { scrollX, scrollY } = await getScrollPosition(this)
const newXoffset = parseInt(x + (typeof xoffset === 'number' ? xoffset : (width / 2)), 10) - scrollX
const newYoffset = parseInt(y + (typeof yoffset === 'number' ? yoffset : (height / 2)), 10) - scrollY

/**
* W3C way of handle the mouse move actions
Expand Down
8 changes: 8 additions & 0 deletions packages/webdriverio/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,3 +352,11 @@ export function validateUrl (url, origError) {
return validateUrl(`http://${url}`, e)
}
}

/**
* get window's scrollX and scrollY
* @param {object} scope
*/
export function getScrollPosition (scope) {
return getBrowserObject(scope).execute('return { scrollX: this.scrollX, scrollY: this.scrollY };')
}
21 changes: 11 additions & 10 deletions packages/webdriverio/tests/commands/element/dragAndDrop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,24 +40,25 @@ describe('dragAndDrop', () => {

const elem = await browser.$('#foo')
const subElem = await elem.$('#subfoo')
request.setMockResponse([{ scrollX: 0, scrollY: 20 }])
await elem.dragAndDrop(subElem)

// move to
expect(request.mock.calls[3][0].uri.path).toContain('/element/some-elem-123/rect')
expect(request.mock.calls[4][0].uri.path).toContain('/element/some-sub-elem-321/rect')
expect(request.mock.calls[5][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[5][0].body.actions).toHaveLength(1)
expect(request.mock.calls[5][0].body.actions[0].type).toBe('pointer')
expect(request.mock.calls[5][0].body.actions[0].actions).toHaveLength(5)
expect(request.mock.calls[5][0].body.actions[0].actions).toEqual([
{ type: 'pointerMove', duration: 0, x: 40, y: 35 },
expect(request.mock.calls[4][0].uri.path).toContain('/element/some-elem-123/rect')
expect(request.mock.calls[5][0].uri.path).toContain('/element/some-sub-elem-321/rect')
expect(request.mock.calls[6][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[6][0].body.actions).toHaveLength(1)
expect(request.mock.calls[6][0].body.actions[0].type).toBe('pointer')
expect(request.mock.calls[6][0].body.actions[0].actions).toHaveLength(5)
expect(request.mock.calls[6][0].body.actions[0].actions).toEqual([
{ type: 'pointerMove', duration: 0, x: 40, y: 15 },
{ type: 'pointerDown', button: 0 },
{ type: 'pause', duration: 10 },
{ type: 'pointerMove', duration: 100, origin: 'pointer', x: 135, y: 225 },
{ type: 'pointerUp', button: 0 }
])
expect(request.mock.calls[6][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[6][0].method).toContain('DELETE')
expect(request.mock.calls[7][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[7][0].method).toContain('DELETE')
})

it('should do a dragAndDrop (no w3c)', async () => {
Expand Down
23 changes: 12 additions & 11 deletions packages/webdriverio/tests/commands/element/moveTo.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ describe('moveTo', () => {
})

const elem = await browser.$('#elem')
request.setMockResponse([undefined, { scrollX: 0, scrollY: 20 }])
await elem.moveTo()

expect(request.mock.calls[3][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[3][0].body.actions).toHaveLength(1)
expect(request.mock.calls[3][0].body.actions[0].type).toBe('pointer')
expect(request.mock.calls[3][0].body.actions[0].actions).toHaveLength(1)
expect(request.mock.calls[3][0].body.actions[0].actions[0])
.toEqual({ type: 'pointerMove', duration: 0, x: 40, y: 35 })
expect(request.mock.calls[4][0].uri.path).toContain('/foobar-123/actions')
expect(request.mock.calls[4][0].body.actions).toHaveLength(1)
expect(request.mock.calls[4][0].body.actions[0].type).toBe('pointer')
expect(request.mock.calls[4][0].body.actions[0].actions).toHaveLength(1)
expect(request.mock.calls[4][0].body.actions[0].actions[0])
.toEqual({ type: 'pointerMove', duration: 0, x: 40, y: 15 })
})

it('should do a moveTo with params', async () => {
Expand All @@ -30,9 +31,10 @@ describe('moveTo', () => {
})

const elem = await browser.$('#elem')
request.setMockResponse([undefined, { scrollX: 19, scrollY: 0 }])
await elem.moveTo(5, 10)
expect(request.mock.calls[3][0].body.actions[0].actions[0])
.toEqual({ type: 'pointerMove', duration: 0, x: 20, y: 30 })
expect(request.mock.calls[4][0].body.actions[0].actions[0])
.toEqual({ type: 'pointerMove', duration: 0, x: 1, y: 30 })
})

it('should do a moveTo with params if getElementRect returned empty object', async () => {
Expand All @@ -44,9 +46,9 @@ describe('moveTo', () => {
})

const elem = await browser.$('#elem')
request.setMockResponse([{}, { x: 5, y: 10, height: 33, width: 44 }])
request.setMockResponse([{}, { x: 5, y: 10, height: 33, width: 44 }, { scrollX: 0, scrollY: 0 }])
await elem.moveTo(5, 10)
expect(request.mock.calls[4][0].body.actions[0].actions[0])
expect(request.mock.calls[5][0].body.actions[0].actions[0])
.toEqual({ type: 'pointerMove', duration: 0, x: 10, y: 20 })
})

Expand All @@ -72,7 +74,6 @@ describe('moveTo', () => {
})

const elem = await browser.$('#elem')

await elem.moveTo()
expect(request.mock.calls[2][0].uri.path).toContain('/foobar-123/moveto')
expect(request.mock.calls[2][0].body).toEqual({ element: 'some-elem-123' })
Expand Down

0 comments on commit 279c1ec

Please sign in to comment.