From 56368aa07a190e03371d6573c147b41e2738b0d3 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Wed, 18 Jul 2018 18:51:18 -0700 Subject: [PATCH] fix(page): page.click should work with disabled javascript (#2907) Unfortunately, disabling javascript in page prevents any microtasks to be executed even from puppeteer-originating javascript. As a result, the IntersectionObserver hack we use to conditionally scroll into view doesn't work. To workaround this, we start always scrolling before clicking if page's javascript is disabled. Fixes #2898 --- lib/ElementHandle.js | 9 +++++++-- lib/Page.js | 4 ++++ test/input.spec.js | 9 +++++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/ElementHandle.js b/lib/ElementHandle.js index ab9de81a32e..e79fab8573b 100644 --- a/lib/ElementHandle.js +++ b/lib/ElementHandle.js @@ -55,11 +55,16 @@ class ElementHandle extends JSHandle { } async _scrollIntoViewIfNeeded() { - const error = await this.executionContext().evaluate(async element => { + const error = await this.executionContext().evaluate(async(element, pageJavascriptEnabled) => { 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', behavior: 'instant'}); + return false; + } const visibleRatio = await new Promise(resolve => { const observer = new IntersectionObserver(entries => { resolve(entries[0].intersectionRatio); @@ -70,7 +75,7 @@ class ElementHandle extends JSHandle { if (visibleRatio !== 1.0) element.scrollIntoView({block: 'center', inline: 'center', behavior: 'instant'}); return false; - }, this); + }, this, this._page._javascriptEnabled); if (error) throw new Error(error); } diff --git a/lib/Page.js b/lib/Page.js index 4eee98b4f2a..80380077a31 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -88,6 +88,7 @@ class Page extends EventEmitter { this._ignoreHTTPSErrors = ignoreHTTPSErrors; this._coverage = new Coverage(client); this._defaultNavigationTimeout = 30000; + this._javascriptEnabled = true; this._screenshotTaskQueue = screenshotTaskQueue; @@ -714,6 +715,9 @@ class Page extends EventEmitter { * @param {boolean} enabled */ async setJavaScriptEnabled(enabled) { + if (this._javascriptEnabled === enabled) + return; + this._javascriptEnabled = enabled; await this._client.send('Emulation.setScriptExecutionDisabled', { value: !enabled }); } diff --git a/test/input.spec.js b/test/input.spec.js index 306153a31a2..a50c6b7624c 100644 --- a/test/input.spec.js +++ b/test/input.spec.js @@ -28,6 +28,15 @@ module.exports.addTests = function({testRunner, expect, DeviceDescriptors}) { await page.click('button'); expect(await page.evaluate(() => result)).toBe('Clicked'); }); + it('should click with disabled javascript', async({page, server}) => { + await page.setJavaScriptEnabled(false); + await page.goto(server.PREFIX + '/wrappedlink.html'); + await Promise.all([ + page.click('a'), + page.waitForNavigation() + ]); + expect(page.url()).toBe(server.PREFIX + '/wrappedlink.html#clicked'); + }); it('should click offscreen buttons', async({page, server}) => { await page.goto(server.PREFIX + '/offscreenbuttons.html');