diff --git a/lib/Navigator.js b/lib/Navigator.js index cbfff512..e30bffeb 100644 --- a/lib/Navigator.js +++ b/lib/Navigator.js @@ -44,18 +44,15 @@ class Navigator { let loadEventFired = new Promise(fulfill => this._client.once('Page.loadEventFired', fulfill)).then(() => null); let watchdog = new Promise(fulfill => this._maximumTimer = setTimeout(fulfill, this._maxTime)).then(() => new Error('Navigation Timeout Exceeded: ' + this._maxTime + 'ms exceeded')); - // Await for the command to throw exception in case of illegal arguments. try { + // Await for the command to throw exception in case of illegal arguments. await this._client.send('Page.navigate', {url: this._url, referrer: this._referrer}); - } catch (e) { + const error = await Promise.race([certificateError, watchdog, this._waitUntil === 'load' ? loadEventFired : networkIdle]); + if (error) + throw error; + } finally { this._cleanup(); - throw e; } - - const error = await Promise.race([certificateError, watchdog, this._waitUntil === 'load' ? loadEventFired : networkIdle]); - this._cleanup(); - if (error) - throw error; } /** diff --git a/lib/Page.js b/lib/Page.js index 078168e8..b338068e 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -35,13 +35,11 @@ class Page extends EventEmitter { client.send('Runtime.enable', {}), client.send('Security.enable', {}), ]); - let screenDPIExpression = helper.evaluationString(() => window.devicePixelRatio); - let {result:{value: screenDPI}} = await client.send('Runtime.evaluate', { expression: screenDPIExpression, returnByValue: true }); let userAgentExpression = helper.evaluationString(() => window.navigator.userAgent); let {result:{value: userAgent}} = await client.send('Runtime.evaluate', { expression: userAgentExpression, returnByValue: true }); let frameManager = await FrameManager.create(client); let networkManager = new NetworkManager(client, userAgent); - let page = new Page(client, frameManager, networkManager, screenDPI); + let page = new Page(client, frameManager, networkManager); // Initialize default page size. await page.setViewportSize({width: 400, height: 300}); return page; @@ -51,14 +49,12 @@ class Page extends EventEmitter { * @param {!Connection} client * @param {!FrameManager} frameManager * @param {!NetworkManager} networkManager - * @param {number} screenDPI */ - constructor(client, frameManager, networkManager, screenDPI) { + constructor(client, frameManager, networkManager) { super(); this._client = client; this._frameManager = frameManager; this._networkManager = networkManager; - this._screenDPI = screenDPI; /** @type {!Map} */ this._inPageCallbacks = new Map(); @@ -260,20 +256,17 @@ class Page extends EventEmitter { * @return {!Promise} */ async navigate(url, options) { + const referrer = this._networkManager.httpHeaders()['referer']; /** @type {!Map} */ const responses = new Map(); const onResponse = response => responses.set(response.url, response); - const navigator = new Navigator(this._client, url, this._networkManager.httpHeaders().referer, options); - + const navigator = new Navigator(this._client, url, referrer, options); + this._networkManager.on(NetworkManager.Events.Response, onResponse); try { - this._networkManager.on(NetworkManager.Events.Response, onResponse); await navigator.navigate(); - } catch (e) { + } finally { this._networkManager.removeListener(NetworkManager.Events.Response, onResponse); - throw e; } - - this._networkManager.removeListener(NetworkManager.Events.Response, onResponse); const response = responses.get(this.mainFrame().url()); console.assert(response); return response; @@ -283,25 +276,9 @@ class Page extends EventEmitter { * @param {!{width: number, height: number}} size * @return {!Promise} */ - async setViewportSize(size) { + setViewportSize(size) { this._viewportSize = size; - let width = size.width; - let height = size.height; - let zoom = this._screenDPI; - return Promise.all([ - this._client.send('Emulation.setDeviceMetricsOverride', { - width, - height, - deviceScaleFactor: 1, - scale: 1 / zoom, - mobile: false, - fitWindow: false - }), - this._client.send('Emulation.setVisibleSize', { - width: Math.floor(width / zoom), - height: Math.floor(height / zoom), - }) - ]); + return this._resetDeviceEmulation(); } /** @@ -311,6 +288,17 @@ class Page extends EventEmitter { return this._viewportSize; } + _resetDeviceEmulation() { + const width = this._viewportSize.width; + const height = this._viewportSize.height; + const deviceScaleFactor = 1; + const mobile = false; + const screenOrientation = { angle: 0, type: 'portraitPrimary' }; + return Promise.all([ + this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }), + ]); + } + /** * @param {function()} pageFunction * @param {!Array<*>} args @@ -371,48 +359,31 @@ class Page extends EventEmitter { } /** - * @param {string} screenshotType + * @param {string} format * @param {!Object=} options * @return {!Promise} */ - async _screenshotTask(screenshotType, options) { - if (options.clip) { - await Promise.all([ - this._client.send('Emulation.setVisibleSize', { - width: Math.ceil(options.clip.width / this._screenDPI), - height: Math.ceil(options.clip.height / this._screenDPI), - }), - this._client.send('Emulation.forceViewport', { - x: options.clip.x / this._screenDPI, - y: options.clip.y / this._screenDPI, - scale: 1, - }) - ]); - } else if (options.fullPage) { - let response = await this._client.send('Page.getLayoutMetrics'); - await Promise.all([ - this._client.send('Emulation.setVisibleSize', { - width: Math.ceil(response.contentSize.width / this._screenDPI), - height: Math.ceil(response.contentSize.height / this._screenDPI), - }), - this._client.send('Emulation.forceViewport', { - x: 0, - y: 0, - scale: 1, - }) - ]); - } - let result = await this._client.send('Page.captureScreenshot', { - fromSurface: true, - format: screenshotType, - quality: options.quality - }); - if (options.clip || options.fullPage) { - await Promise.all([ - this.setViewportSize(this.viewportSize()), - this._client.send('Emulation.resetViewport') - ]); + async _screenshotTask(format, options) { + if (options.fullPage) { + let metrics = await this._client.send('Page.getLayoutMetrics'); + const width = Math.ceil(metrics.contentSize.width); + const height = Math.ceil(metrics.contentSize.height); + await this._client.send('Emulation.resetPageScaleFactor'); + const mobile = false; + const deviceScaleFactor = 1; + const landscape = false; + const screenOrientation = landscape ? { angle: 90, type: 'landscapePrimary' } : { angle: 0, type: 'portraitPrimary' }; + await this._client.send('Emulation.setDeviceMetricsOverride', { mobile, width, height, deviceScaleFactor, screenOrientation }); } + + let clip = options.clip ? Object.assign({}, options['clip']) : undefined; + if (clip) + clip.scale = 1; + let result = await this._client.send('Page.captureScreenshot', { format, quality: options.quality, clip }); + + if (options.fullPage) + await this.setViewportSize(this.viewportSize()); + let buffer = new Buffer(result.data, 'base64'); if (options.path) fs.writeFileSync(options.path, buffer); @@ -523,8 +494,8 @@ class Page extends EventEmitter { }, selector); if (!center) throw new Error('No node found for selector: ' + selector); - let x = Math.round(center.x / this._screenDPI); - let y = Math.round(center.y / this._screenDPI); + let x = Math.round(center.x); + let y = Math.round(center.y); this._client.send('Input.dispatchMouseEvent', { type: 'mouseMoved', x, y diff --git a/package.json b/package.json index 87263fdd..3646f88a 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "ws": "^3.0.0" }, "puppeteer": { - "chromium_revision": "485143" + "chromium_revision": "486981" }, "devDependencies": { "commonmark": "^0.27.0", diff --git a/test/test.js b/test/test.js index ecb7e41f..9b4b5b58 100644 --- a/test/test.js +++ b/test/test.js @@ -221,7 +221,7 @@ describe('Puppeteer', function() { await page.waitFor('*'); fail('Failed waitFor did not throw.'); } catch (e) { - expect(e.message).toBe('Evaluation failed: document.querySelector is not a function'); + expect(e.message).toContain('Evaluation failed: document.querySelector is not a function'); } })); });