From f38c8bb17b2c84d5346e6aba6296c80e07bbbbf7 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 24 Oct 2017 10:05:15 -0700 Subject: [PATCH] feat(Page.goto): support multiple events in waitUntil option (#1147) This patch adds support to multiple events that could be passed inside navigation methods: - Page.goto - Page.waitForNavigation - Page.goForward - Page.goBack - Page.reload Fixes #805 --- docs/api.md | 10 +++++----- lib/NavigatorWatcher.js | 16 +++++++++++----- test/test.js | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 10 deletions(-) diff --git a/docs/api.md b/docs/api.md index 63fa85c1..8bdbe320 100644 --- a/docs/api.md +++ b/docs/api.md @@ -761,7 +761,7 @@ If there's no element matching `selector`, the method throws an error. #### page.goBack(options) - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. - - `waitUntil` <[string]> When to consider a navigation finished, defaults to `load`. Can be either: + - `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events Can be either: - `load` - consider navigation to be finished when the `load` event is fired. - `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired. - `networkidle0` - consider navigation to be finished when there are no more then 0 network connections for at least `500` ms. @@ -774,7 +774,7 @@ Navigate to the previous page in history. #### page.goForward(options) - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. - - `waitUntil` <[string]> When to consider navigation succeeded, defaults to `load`. Can be either: + - `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events Can be either: - `load` - consider navigation to be finished when the `load` event is fired. - `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired. - `networkidle0` - consider navigation to be finished when there are no more then 0 network connections for at least `500` ms. @@ -788,7 +788,7 @@ Navigate to the next page in history. - `url` <[string]> URL to navigate page to. The url should include scheme, e.g. `https://`. - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. - - `waitUntil` <[string]> When to consider navigation succeeded, defaults to `load`. Can be either: + - `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events Can be either: - `load` - consider navigation to be finished when the `load` event is fired. - `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired. - `networkidle0` - consider navigation to be finished when there are no more then 0 network connections for at least `500` ms. @@ -903,7 +903,7 @@ Shortcut for [page.mainFrame().executionContext().queryObjects(prototypeHandle)] #### page.reload(options) - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. - - `waitUntil` <[string]> When to consider navigation succeeded, defaults to `load`. Can be either: + - `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events Can be either: - `load` - consider navigation to be finished when the `load` event is fired. - `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired. - `networkidle0` - consider navigation to be finished when there are no more then 0 network connections for at least `500` ms. @@ -1107,7 +1107,7 @@ Shortcut for [page.mainFrame().waitForFunction(pageFunction[, options[, ...args] #### page.waitForNavigation(options) - `options` <[Object]> Navigation parameters which might have the following properties: - `timeout` <[number]> Maximum navigation time in milliseconds, defaults to 30 seconds, pass `0` to disable timeout. - - `waitUntil` <[string]> When to consider navigation succeeded, defaults to `load`. Can be either: + - `waitUntil` <[string]|[Array]<[string]>> When to consider navigation succeeded, defaults to `load`. Given an array of event strings, navigation is considered to be successful after all events have been fired. Events Can be either: - `load` - consider navigation to be finished when the `load` event is fired. - `domcontentloaded` - consider navigation to be finished when the `DOMContentLoaded` event is fired. - `networkidle0` - consider navigation to be finished when there are no more then 0 network connections for at least `500` ms. diff --git a/lib/NavigatorWatcher.js b/lib/NavigatorWatcher.js index f48dfb9b..f76e0086 100644 --- a/lib/NavigatorWatcher.js +++ b/lib/NavigatorWatcher.js @@ -30,11 +30,17 @@ class NavigatorWatcher { this._client = client; this._frameId = frameId; this._ignoreHTTPSErrors = ignoreHTTPSErrors; - this._timeout = typeof options['timeout'] === 'number' ? options['timeout'] : 30000; - const waitUntil = typeof options['waitUntil'] === 'string' ? options['waitUntil'] : 'load'; - const isAllowedWaitUntil = waitUntil === 'networkidle0' || waitUntil === 'networkidle2' || waitUntil === 'load' || waitUntil === 'domcontentloaded'; - console.assert(isAllowedWaitUntil, 'Unknown value for options.waitUntil: ' + waitUntil); - this._pendingEvents = new Set([waitUntil]); + this._timeout = typeof options.timeout === 'number' ? options.timeout : 30000; + let waitUntil = ['load']; + if (Array.isArray(options.waitUntil)) + waitUntil = options.waitUntil.slice(); + else if (typeof options.waitUntil === 'string') + waitUntil = [options.waitUntil]; + for (const value of waitUntil) { + const isAllowedValue = value === 'networkidle0' || value === 'networkidle2' || value === 'load' || value === 'domcontentloaded'; + console.assert(isAllowedValue, 'Unknown value for options.waitUntil: ' + value); + } + this._pendingEvents = new Set(waitUntil); } /** diff --git a/test/test.js b/test/test.js index b92951c7..767b51ea 100644 --- a/test/test.js +++ b/test/test.js @@ -1098,6 +1098,25 @@ describe('Page', function() { expect(response.ok).toBe(true); expect(response.url).toContain('grid.html'); })); + it('should work with both domcontentloaded and load', SX(async function() { + let response = null; + server.setRoute('/one-style.css', (req, res) => response = res); + page.goto(PREFIX + '/one-style.html'); + const domContentLoadedPromise = page.waitForNavigation({ + waitUntil: 'domcontentloaded' + }); + + let bothFired = false; + const bothFiredPromise = page.waitForNavigation({ + waitUntil: ['load', 'domcontentloaded'] + }).then(() => bothFired = true); + + await server.waitForRequest('/one-style.css'); + await domContentLoadedPromise; + expect(bothFired).toBe(false); + response.end(); + await bothFiredPromise; + })); }); describe('Page.goBack', function() {