diff --git a/src/common/ElementHandle.ts b/src/common/ElementHandle.ts index d40406000ae46..6e56b7d1ff4ba 100644 --- a/src/common/ElementHandle.ts +++ b/src/common/ElementHandle.ts @@ -240,50 +240,52 @@ export class ElementHandle< async #scrollIntoViewIfNeeded(this: ElementHandle): Promise { const error = await this.evaluate( - async (element, pageJavascriptEnabled): Promise => { + async (element): Promise => { if (!element.isConnected) { return 'Node is detached from document'; } if (element.nodeType !== Node.ELEMENT_NODE) { return 'Node is not of type HTMLElement'; } - // force-scroll if page's javascript is disabled. - if (!pageJavascriptEnabled) { - element.scrollIntoView({ - block: 'center', - inline: 'center', - // @ts-expect-error Chrome still supports behavior: instant but - // it's not in the spec so TS shouts We don't want to make this - // breaking change in Puppeteer yet so we'll ignore the line. - behavior: 'instant', - }); - return false; - } - const visibleRatio = await new Promise(resolve => { - const observer = new IntersectionObserver(entries => { - resolve(entries[0]!.intersectionRatio); - observer.disconnect(); - }); - observer.observe(element); - }); - if (visibleRatio !== 1.0) { - element.scrollIntoView({ - block: 'center', - inline: 'center', - // @ts-expect-error Chrome still supports behavior: instant but - // it's not in the spec so TS shouts We don't want to make this - // breaking change in Puppeteer yet so we'll ignore the line. - behavior: 'instant', - }); - } - return false; - }, - this.#page.isJavaScriptEnabled() + return; + } ); if (error) { throw new Error(error); } + + try { + await this._client.send('DOM.scrollIntoViewIfNeeded', { + objectId: this._remoteObject.objectId, + }); + } catch (_err) { + // Fallback to Element.scrollIntoView if DOM.scrollIntoViewIfNeeded is not supported + await this.evaluate( + async (element, pageJavascriptEnabled): Promise => { + const visibleRatio = async () => { + return await new Promise(resolve => { + const observer = new IntersectionObserver(entries => { + resolve(entries[0]!.intersectionRatio); + observer.disconnect(); + }); + observer.observe(element); + }); + }; + if (!pageJavascriptEnabled || (await visibleRatio()) !== 1.0) { + element.scrollIntoView({ + block: 'center', + inline: 'center', + // @ts-expect-error Chrome still supports behavior: instant but + // it's not in the spec so TS shouts We don't want to make this + // breaking change in Puppeteer yet so we'll ignore the line. + behavior: 'instant', + }); + } + }, + this.#page.isJavaScriptEnabled() + ); + } } async #getOOPIFOffsets( diff --git a/test/assets/offscreenbuttons.html b/test/assets/offscreenbuttons.html index e487caf4d35ef..878f118e1ed16 100644 --- a/test/assets/offscreenbuttons.html +++ b/test/assets/offscreenbuttons.html @@ -6,18 +6,19 @@ height: 20px; } - #btn0 { right: 0px; top: 0; } - #btn1 { right: -10px; top: 25px; } - #btn2 { right: -20px; top: 50px; } - #btn3 { right: -30px; top: 75px; } - #btn4 { right: -40px; top: 100px; } - #btn5 { right: -50px; top: 125px; } + #btn0 { right: -120px; top: 0; } + #btn1 { right: -110px; top: 25px; } + #btn2 { right: -100px; top: 50px; } + #btn3 { right: -90px; top: 75px; } + #btn4 { right: -80px; top: 100px; } + #btn5 { right: -70px; top: 125px; } #btn6 { right: -60px; top: 150px; } - #btn7 { right: -70px; top: 175px; } - #btn8 { right: -80px; top: 200px; } - #btn9 { right: -90px; top: 225px; } - #btn10 { right: -100px; top: 250px; } - #btn11 { right: -99.999px; top: 275px; } + #btn7 { right: -50px; top: 175px; } + #btn8 { right: -40px; top: 200px; } + #btn9 { right: -30px; top: 225px; } + #btn10 { right: -20px; top: 250px; } + #btn11 { right: -10px; top: 275px; } + #btn12 { right: 0; top: 300px; } @@ -31,6 +32,7 @@ +