diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef552161b12..bb5ef85d8e9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -103,6 +103,10 @@ npm run unit -- --filter=waitFor ``` HEADLESS=false npm run unit ``` +- To run tests in slow-mode: +``` +HEADLESS=false SLOW_MO=500 npm run unit +``` - To debug a test, "focus" a test first and then run: ``` npm run debug-unit diff --git a/docs/api.md b/docs/api.md index 992a35966ab..abb059d6540 100644 --- a/docs/api.md +++ b/docs/api.md @@ -183,7 +183,9 @@ browser.newPage().then(async page => { - `options` <[Object]> Set of configurable options to set on the browser. Can have the following fields: - `headless` <[boolean]> Whether to run chromium in [headless mode](https://developers.google.com/web/updates/2017/04/headless-chrome). Defaults to `true`. - `executablePath` <[string]> Path to a chromium executable to run instead of bundled chromium. If `executablePath` is a relative path, then it is resolved relative to [current working directory](https://nodejs.org/api/process.html#process_process_cwd). - - `args` <[Array]<[string]>> Additional arguments to pass to the chromium instance. List of chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). + - `slowMo` <[number]> Slows down Puppeteer operations by the specified amount of milliseconds. Useful +so that you can see what is going on. + - `args` <[Array]<[string]>> Additional arguments to pass to the chromium instance. List of chromium flags can be found [here](http://peter.sh/experiments/chromium-command-line-switches/). #### browser.close() diff --git a/lib/Browser.js b/lib/Browser.js index 7546589c398..8c7a9d8372f 100644 --- a/lib/Browser.js +++ b/lib/Browser.js @@ -74,6 +74,7 @@ class Browser { } if (Array.isArray(options.args)) this._chromeArguments.push(...options.args); + this._connectionDelay = options.slowMo || 0; this._terminated = false; this._chromeProcess = null; this._launchPromise = null; @@ -90,7 +91,7 @@ class Browser { await this._ensureChromeIsRunning(); if (!this._chromeProcess || this._terminated) throw new Error('ERROR: this chrome instance is not alive any more!'); - let client = await Connection.create(this._remoteDebuggingPort); + let client = await Connection.create(this._remoteDebuggingPort, this._connectionDelay); let page = await Page.create(client, this._screenshotTaskQueue); return page; } diff --git a/lib/Connection.js b/lib/Connection.js index 3dda171f323..a38c32099f8 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -25,14 +25,16 @@ class Connection extends EventEmitter { * @param {number} port * @param {string} targetId * @param {!WebSocket} ws + * @param {number=} delay */ - constructor(port, targetId, ws) { + constructor(port, targetId, ws, delay) { super(); this._port = port; this._targetId = targetId; this._lastId = 0; /** @type {!Map}*/ this._callbacks = new Map(); + this._delay = delay || 0; this._ws = ws; this._ws.on('message', this._onMessage.bind(this)); @@ -64,7 +66,9 @@ class Connection extends EventEmitter { /** * @param {string} message */ - _onMessage(message) { + async _onMessage(message) { + if (this._delay) + await new Promise(f => setTimeout(f, this._delay)); debug('◀ RECV ' + message); let object = JSON.parse(message); if (object.id && this._callbacks.has(object.id)) { @@ -96,15 +100,16 @@ class Connection extends EventEmitter { /** * @param {number} port + * @param {number=} delay * @return {!Promise} */ - static async create(port) { + static async create(port, delay) { let newTab = await runJsonCommand(port, 'new'); let url = newTab.webSocketDebuggerUrl; return new Promise((resolve, reject) => { let ws = new WebSocket(url, { perMessageDeflate: false }); - ws.on('open', () => resolve(new Connection(port, newTab.id, ws))); + ws.on('open', () => resolve(new Connection(port, newTab.id, ws, delay))); ws.on('error', reject); }); } diff --git a/test/test.js b/test/test.js index 6565800c162..435da3d616e 100644 --- a/test/test.js +++ b/test/test.js @@ -37,7 +37,9 @@ const iPhone = require('../DeviceDescriptors')['iPhone 6']; const iPhoneLandscape = require('../DeviceDescriptors')['iPhone 6 landscape']; const headless = (process.env.HEADLESS || 'true').trim().toLowerCase() === 'true'; -if (process.env.DEBUG_TEST) +const slowMo = parseInt((process.env.SLOW_MO || '0').trim(), 10); + +if (process.env.DEBUG_TEST || slowMo) jasmine.DEFAULT_TIMEOUT_INTERVAL = 1000 * 1000 * 1000; else jasmine.DEFAULT_TIMEOUT_INTERVAL = 10 * 1000; @@ -57,7 +59,7 @@ describe('Puppeteer', function() { let page; beforeAll(SX(async function() { - browser = new Browser({headless, args: ['--no-sandbox']}); + browser = new Browser({headless, slowMo, args: ['--no-sandbox']}); const assetsPath = path.join(__dirname, 'assets'); server = await SimpleServer.create(assetsPath, PORT); httpsServer = await SimpleServer.createHTTPS(assetsPath, HTTPS_PORT);