From fab5eba64fdcbf7f9aa2734377e190070adf1854 Mon Sep 17 00:00:00 2001 From: Dmitry Gozman Date: Tue, 28 Jul 2020 15:52:33 -0700 Subject: [PATCH] fix(oopifs): translate coordinates to viewport (#3201) Renderer-based method DOM.getContentQuads and DOM.getBoxModel return coordinates relative to the local root's viewport, but we need them relative to the root viewport. --- src/chromium/crPage.ts | 27 ++++++++++++++++++++++----- test/chromium/oopif.jest.js | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/chromium/crPage.ts b/src/chromium/crPage.ts index 30d3f03976..a840610b12 100644 --- a/src/chromium/crPage.ts +++ b/src/chromium/crPage.ts @@ -829,7 +829,21 @@ class FrameSession { const y = Math.min(quad[1], quad[3], quad[5], quad[7]); const width = Math.max(quad[0], quad[2], quad[4], quad[6]) - x; const height = Math.max(quad[1], quad[3], quad[5], quad[7]) - y; - return {x, y, width, height}; + const position = await this._framePosition(); + if (!position) + return null; + return { x: x + position.x, y: y + position.y, width, height }; + } + + private async _framePosition(): Promise { + const frame = this._page._frameManager.frame(this._targetId); + if (!frame) + return null; + if (frame === this._page.mainFrame()) + return { x: 0, y: 0 }; + const element = await frame.frameElement(); + const box = await element.boundingBox(); + return box; } async _scrollRectIntoViewIfNeeded(handle: dom.ElementHandle, rect?: types.Rect): Promise<'error:notvisible' | 'error:notconnected' | 'done'> { @@ -851,11 +865,14 @@ class FrameSession { }); if (!result) return null; + const position = await this._framePosition(); + if (!position) + return null; return result.quads.map(quad => [ - { x: quad[0], y: quad[1] }, - { x: quad[2], y: quad[3] }, - { x: quad[4], y: quad[5] }, - { x: quad[6], y: quad[7] } + { x: quad[0] + position.x, y: quad[1] + position.y }, + { x: quad[2] + position.x, y: quad[3] + position.y }, + { x: quad[4] + position.x, y: quad[5] + position.y }, + { x: quad[6] + position.x, y: quad[7] + position.y } ]); } diff --git a/test/chromium/oopif.jest.js b/test/chromium/oopif.jest.js index 18385c2362..0da4bee20e 100644 --- a/test/chromium/oopif.jest.js +++ b/test/chromium/oopif.jest.js @@ -293,6 +293,43 @@ describe.skip(!CHROMIUM)('OOPIF', function() { ]); await browser.close(); }); + it('ElementHandle.boundingBox() should work', async function({sppBrowser, sppPage, server}) { + const browser = sppBrowser; + const page = sppPage; + await page.goto(server.PREFIX + '/dynamic-oopif.html'); + await page.$eval('iframe', iframe => { + iframe.style.width = '500px'; + iframe.style.height = '500px'; + iframe.style.marginLeft = '42px'; + iframe.style.marginTop = '17px'; + }); + + expect(await countOOPIFs(browser)).toBe(1); + const handle1 = await page.frames()[1].$('.box:nth-of-type(13)'); + expect(await handle1.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); + + await page.evaluate(() => goLocal()); + expect(await countOOPIFs(browser)).toBe(0); + const handle2 = await page.frames()[1].$('.box:nth-of-type(13)'); + expect(await handle2.boundingBox()).toEqual({ x: 100 + 42, y: 50 + 17, width: 50, height: 50 }); + }); + it('should click', async function({sppBrowser, sppPage, server}) { + const browser = sppBrowser; + const page = sppPage; + await page.goto(server.PREFIX + '/dynamic-oopif.html'); + await page.$eval('iframe', iframe => { + iframe.style.width = '500px'; + iframe.style.height = '500px'; + iframe.style.marginLeft = '102px'; + iframe.style.marginTop = '117px'; + }); + + expect(await countOOPIFs(browser)).toBe(1); + const handle1 = await page.frames()[1].$('.box:nth-of-type(13)'); + await handle1.evaluate(div => div.addEventListener('click', () => window._clicked = true, false)); + await handle1.click(); + expect(await handle1.evaluate(() => window._clicked)).toBe(true); + }); }); async function countOOPIFs(browser) {