Skip to content

Commit eaffbbe

Browse files
committed
improve scroll function
1 parent 3623c98 commit eaffbbe

File tree

5 files changed

+104
-15
lines changed

5 files changed

+104
-15
lines changed

__mocks__/got.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ const requestMock: any = vi.fn().mockImplementation((uri, params) => {
241241
result = params.json.args[0][ELEMENT_KEY] === genericElementId
242242
? { [ELEMENT_KEY]: 'some-next-elem' }
243243
: {}
244+
} else if (params.json.script.includes('scrollX')) {
245+
result = [0, 0]
244246
} else if (params.json.script.includes('function isFocused')) {
245247
result = true
246248
} else {

e2e/wdio/headless/test.e2e.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,26 @@ describe('main suite 1', () => {
100100
it('should be able to handle successive scrollIntoView', async () => {
101101
await browser.url('http://guinea-pig.webdriver.io')
102102
await browser.setWindowSize(500, 500)
103-
const searchInput = await $('.searchinput')
103+
let searchInput = await $('.searchinput')
104104

105+
await browser.newWindow('http://guinea-pig.webdriver.io')
106+
await browser.setWindowSize(500, 500)
107+
const handles = await browser.getWindowHandles()
105108
const scrollAndCheck = async (params?: ScrollIntoViewOptions | boolean) => {
109+
110+
await browser.switchToWindow(handles[0])
111+
await browser.pause(500)
112+
searchInput = await $('.searchinput')
106113
await searchInput.scrollIntoView(params)
107114
await browser.pause(500)
108115
const [wdioX, wdioY] = await browser.execute(() => [
109116
window.scrollX, window.scrollY
110117
])
111118

119+
await browser.switchToWindow(handles[1])
120+
await browser.pause(500)
121+
searchInput = await $('.searchinput')
122+
112123
await browser.execute((elem, _params) => elem.scrollIntoView(_params), searchInput, params)
113124
await browser.pause(500)
114125
const [windowX, windowY] = await browser.execute(() => [
@@ -123,6 +134,7 @@ describe('main suite 1', () => {
123134
await scrollAndCheck({ block: 'nearest', inline: 'nearest' })
124135
await scrollAndCheck()
125136
await scrollAndCheck({ block: 'center', inline: 'center' })
137+
await scrollAndCheck({ block: 'start', inline: 'start' })
126138
await scrollAndCheck({ block: 'end', inline: 'end' })
127139
await scrollAndCheck(true)
128140
await scrollAndCheck({ block: 'nearest', inline: 'nearest' })

packages/webdriverio/src/commands/element/scrollIntoView.ts

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,19 @@ export async function scrollIntoView (
6161
*/
6262
const elemRect = await browser.getElementRect(this.elementId)
6363
const viewport = await browser.getWindowSize()
64+
let [windowX, windowY] = await browser.execute(() => [
65+
window.scrollX, window.scrollY
66+
])
67+
68+
const origin = windowX === 0 && windowY === 0 ? this : undefined
69+
70+
windowX = elemRect.x <= viewport.width ? elemRect.x - 10 : viewport.width / 2
71+
windowY = elemRect.y <= viewport.height ? elemRect.y - 10 : viewport.height / 2
72+
6473
const deltaByOption = {
6574
start: { y: elemRect.y, x: elemRect.x },
6675
center: { y: elemRect.y - Math.round((viewport.height - elemRect.height) / 2), x: elemRect.x - Math.round((viewport.width - elemRect.width) / 2) },
67-
end: { y: elemRect.y - (viewport.height - elemRect.height), x: elemRect.x - (viewport.width - elemRect.width) }
76+
end: { y: elemRect.y - (viewport.height - elemRect.height - 20), x: elemRect.x - (viewport.width - elemRect.width) }
6877
}
6978
let [deltaX, deltaY] = [deltaByOption.start.x, deltaByOption.start.y]
7079
if (options && typeof options !== 'boolean') {
@@ -83,12 +92,23 @@ export async function scrollIntoView (
8392
}
8493
}
8594

86-
deltaX = Math.round(deltaX)
87-
deltaY = Math.round(deltaY)
95+
if (origin) {
96+
deltaX = Math.round(deltaX - elemRect.x)
97+
deltaY = Math.round(deltaY - (elemRect.y - viewport.height))
98+
99+
windowX = 0
100+
windowY = 0
101+
} else {
102+
deltaX = Math.round(deltaX - windowX)
103+
deltaY = Math.round(deltaY - windowY)
104+
105+
windowX = Math.round(windowX)
106+
windowY = Math.round(windowY)
107+
}
88108

89109
try {
90110
return await browser.action('wheel')
91-
.scroll({ duration: 200, deltaX, deltaY, origin: this })
111+
.scroll({ duration: 200, x: windowX, y: windowY, deltaX, deltaY, origin })
92112
.perform()
93113
} catch (err: any) {
94114
log.warn(

packages/webdriverio/tests/commands/element/__snapshots__/scrollIntoView.test.ts.snap

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,67 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`scrollIntoView test > desktop > scrolls by default the element after a previous scr 1`] = `
4+
{
5+
"actions": [
6+
{
7+
"actions": [
8+
{
9+
"deltaX": 0,
10+
"deltaY": 800,
11+
"duration": 200,
12+
"origin": {
13+
"element-6066-11e4-a52e-4f735466cecf": {
14+
"scrollIntoView": [MockFunction spy],
15+
},
16+
},
17+
"type": "scroll",
18+
"x": 0,
19+
"y": 0,
20+
},
21+
],
22+
"id": "action7",
23+
"parameters": {},
24+
"type": "wheel",
25+
},
26+
],
27+
}
28+
`;
29+
30+
exports[`scrollIntoView test > desktop > scrolls by default the element after a previous scroll 1`] = `
31+
{
32+
"actions": [
33+
{
34+
"actions": [
35+
{
36+
"deltaX": 0,
37+
"deltaY": 800,
38+
"duration": 200,
39+
"origin": {
40+
"element-6066-11e4-a52e-4f735466cecf": {
41+
"scrollIntoView": [MockFunction spy],
42+
},
43+
},
44+
"type": "scroll",
45+
"x": 0,
46+
"y": 0,
47+
},
48+
],
49+
"id": "action7",
50+
"parameters": {},
51+
"type": "wheel",
52+
},
53+
],
54+
}
55+
`;
56+
357
exports[`scrollIntoView test > desktop > scrolls by default the element to the top 1`] = `
458
{
559
"actions": [
660
{
761
"actions": [
862
{
9-
"deltaX": 15,
10-
"deltaY": 20,
63+
"deltaX": 0,
64+
"deltaY": 800,
1165
"duration": 200,
1266
"origin": {
1367
"element-6066-11e4-a52e-4f735466cecf": "some-elem-123",
@@ -31,8 +85,8 @@ exports[`scrollIntoView test > desktop > scrolls element using scroll into view
3185
{
3286
"actions": [
3387
{
34-
"deltaX": -260,
35-
"deltaY": -365,
88+
"deltaX": -275,
89+
"deltaY": 415,
3690
"duration": 200,
3791
"origin": {
3892
"element-6066-11e4-a52e-4f735466cecf": "some-elem-123",
@@ -56,8 +110,8 @@ exports[`scrollIntoView test > desktop > scrolls element when using boolean scro
56110
{
57111
"actions": [
58112
{
59-
"deltaX": 15,
60-
"deltaY": 20,
113+
"deltaX": 0,
114+
"deltaY": 800,
61115
"duration": 200,
62116
"origin": {
63117
"element-6066-11e4-a52e-4f735466cecf": "some-elem-123",
@@ -81,8 +135,8 @@ exports[`scrollIntoView test > desktop > scrolls element when using boolean scro
81135
{
82136
"actions": [
83137
{
84-
"deltaX": 15,
85-
"deltaY": 20,
138+
"deltaX": 0,
139+
"deltaY": 800,
86140
"duration": 200,
87141
"origin": {
88142
"element-6066-11e4-a52e-4f735466cecf": "some-elem-123",

packages/webdriverio/tests/commands/element/scrollIntoView.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,10 @@ describe('scrollIntoView test', () => {
7272
({ x: 15.34, y: 20.23, height: 30.2344, width: 50.543 }))
7373
await elem.scrollIntoView({ block: 'center', inline: 'center' })
7474
const optionsCenter = vi.mocked(got).mock.calls.slice(-2, -1)[0][1] as any
75-
expect(optionsCenter.json.actions[0].actions[0].deltaX).toBe(-260)
76-
expect(optionsCenter.json.actions[0].actions[0].deltaY).toBe(-365)
75+
expect(optionsCenter.json.actions[0].actions[0].deltaX).toBe(-275)
76+
expect(optionsCenter.json.actions[0].actions[0].deltaY).toBe(415)
7777
})
78+
7879
})
7980

8081
describe('mobile', () => {

0 commit comments

Comments
 (0)