From afb9355b1597a210f1c42035ee9a37656325fa59 Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 12 Feb 2019 17:38:48 -0800 Subject: [PATCH] feat(firefox): basic support for Network (#3988) This patch introduces basic Request and Response events for page. It also teaches navigation methods, e.g. `page.goto` to return navigation response. --- experimental/puppeteer-firefox/lib/Events.js | 13 +- .../puppeteer-firefox/lib/FrameManager.js | 16 ++ .../puppeteer-firefox/lib/NetworkManager.js | 174 ++++++++++++++++++ experimental/puppeteer-firefox/lib/Page.js | 60 +++--- experimental/puppeteer-firefox/lib/api.js | 2 + experimental/puppeteer-firefox/package.json | 2 +- test/navigation.spec.js | 31 ++-- test/network.spec.js | 26 +-- test/puppeteer.spec.js | 2 +- 9 files changed, 270 insertions(+), 56 deletions(-) create mode 100644 experimental/puppeteer-firefox/lib/NetworkManager.js diff --git a/experimental/puppeteer-firefox/lib/Events.js b/experimental/puppeteer-firefox/lib/Events.js index 5646db63..b99bbf4f 100644 --- a/experimental/puppeteer-firefox/lib/Events.js +++ b/experimental/puppeteer-firefox/lib/Events.js @@ -10,6 +10,10 @@ const Events = { Load: 'load', PageError: 'pageerror', Popup: 'popup', + Request: 'request', + Response: 'response', + RequestFinished: 'requestfinished', + RequestFailed: 'requestfailed', }, Browser: { TargetCreated: 'targetcreated', @@ -30,8 +34,15 @@ const Events = { Load: Symbol('Events.FrameManager.Load'), DOMContentLoaded: Symbol('Events.FrameManager.DOMContentLoaded'), FrameAttached: Symbol('Events.FrameManager.FrameAttached'), + FrameNavigated: Symbol('Events.FrameManager.FrameNavigated'), FrameDetached: Symbol('Events.FrameManager.FrameDetached'), - } + }, + + NetworkManager: { + Request: Symbol('Events.NetworkManager.Request'), + Response: Symbol('Events.NetworkManager.Response'), + RequestFinished: Symbol('Events.NetworkManager.RequestFinished'), + }, }; module.exports = {Events}; diff --git a/experimental/puppeteer-firefox/lib/FrameManager.js b/experimental/puppeteer-firefox/lib/FrameManager.js index 72016132..02dfdf23 100644 --- a/experimental/puppeteer-firefox/lib/FrameManager.js +++ b/experimental/puppeteer-firefox/lib/FrameManager.js @@ -24,6 +24,8 @@ class FrameManager extends EventEmitter { helper.addEventListener(this._session, 'Page.eventFired', this._onEventFired.bind(this)), helper.addEventListener(this._session, 'Page.frameAttached', this._onFrameAttached.bind(this)), helper.addEventListener(this._session, 'Page.frameDetached', this._onFrameDetached.bind(this)), + helper.addEventListener(this._session, 'Page.navigationCommitted', this._onNavigationCommitted.bind(this)), + helper.addEventListener(this._session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), ]; } @@ -48,6 +50,20 @@ class FrameManager extends EventEmitter { } } + _onNavigationCommitted(params) { + const frame = this._frames.get(params.frameId); + frame._navigated(params.url, params.name, params.navigationId); + frame._DOMContentLoadedFired = false; + frame._loadFired = false; + this.emit(Events.FrameManager.FrameNavigated, frame); + } + + _onSameDocumentNavigation(params) { + const frame = this._frames.get(params.frameId); + frame._url = params.url; + this.emit(Events.FrameManager.FrameNavigated, frame); + } + _onFrameAttached(params) { const frame = new Frame(this._session, this, this._page, params.frameId, this._timeoutSettings); const parentFrame = this._frames.get(params.parentFrameId) || null; diff --git a/experimental/puppeteer-firefox/lib/NetworkManager.js b/experimental/puppeteer-firefox/lib/NetworkManager.js new file mode 100644 index 00000000..7dd93205 --- /dev/null +++ b/experimental/puppeteer-firefox/lib/NetworkManager.js @@ -0,0 +1,174 @@ +const {helper} = require('./helper'); +const util = require('util'); +const EventEmitter = require('events'); +const {Events} = require('./Events'); + +class NetworkManager extends EventEmitter { + constructor(session, frameManager) { + super(); + this._session = session; + + this._requests = new Map(); + this._frameManager = frameManager; + + this._eventListeners = [ + helper.addEventListener(session, 'Page.requestWillBeSent', this._onRequestWillBeSent.bind(this)), + helper.addEventListener(session, 'Page.responseReceived', this._onResponseReceived.bind(this)), + helper.addEventListener(session, 'Page.requestFinished', this._onRequestFinished.bind(this)), + ]; + } + + _onRequestWillBeSent(event) { + const frame = this._frameManager && event.frameId ? this._frameManager.frame(event.frameId) : null; + if (!frame) + return; + let redirectChain = []; + const redirected = event.redirectedFrom ? this._requests.get(event.redirectedFrom) : null; + if (redirected) { + redirectChain = redirected._redirectChain; + redirectChain.push(redirected); + this._requests.delete(redirected._id); + } + const request = new Request(frame, redirectChain, event); + this._requests.set(request._id, request); + this.emit(Events.NetworkManager.Request, request); + } + + _onResponseReceived(event) { + const request = this._requests.get(event.requestId); + if (!request) + return; + const response = new Response(request, event); + request._response = response; + this.emit(Events.NetworkManager.Response, response); + } + + _onRequestFinished(event) { + const request = this._requests.get(event.requestId); + if (!request) + return; + // Keep redirected requests in the map for future reference in redirectChain. + const isRedirected = request.response().status() >= 300 && request.response().status() <= 399; + if (!isRedirected) + this._requests.delete(request._id); + this.emit(Events.NetworkManager.RequestFinished, request); + } + + dispose() { + helper.removeEventListeners(this._eventListeners); + } +} + +/** + * + * document, stylesheet, image, media, font, script, texttrack, xhr, fetch, eventsource, websocket, manifest, other. + */ +const causeToResourceType = { + TYPE_INVALID: 'other', + TYPE_OTHER: 'other', + TYPE_SCRIPT: 'script', + TYPE_IMAGE: 'image', + TYPE_STYLESHEET: 'stylesheet', + TYPE_OBJECT: 'other', + TYPE_DOCUMENT: 'document', + TYPE_SUBDOCUMENT: 'document', + TYPE_REFRESH: 'document', + TYPE_XBL: 'other', + TYPE_PING: 'other', + TYPE_XMLHTTPREQUEST: 'xhr', + TYPE_OBJECT_SUBREQUEST: 'other', + TYPE_DTD: 'other', + TYPE_FONT: 'font', + TYPE_MEDIA: 'media', + TYPE_WEBSOCKET: 'websocket', + TYPE_CSP_REPORT: 'other', + TYPE_XSLT: 'other', + TYPE_BEACON: 'other', + TYPE_FETCH: 'fetch', + TYPE_IMAGESET: 'images', + TYPE_WEB_MANIFEST: 'manifest', +}; + +class Request { + constructor(frame, redirectChain, payload) { + this._frame = frame; + this._id = payload.requestId; + this._redirectChain = redirectChain; + this._url = payload.url; + this._response = null; + this._isNavigationRequest = payload.isNavigationRequest; + this._method = payload.method; + this._resourceType = causeToResourceType[payload.cause] || 'other'; + } + + redirectChain() { + return this._redirectChain.slice(); + } + + resourceType() { + return this._resourceType; + } + + url() { + return this._url; + } + + method() { + return this._method; + } + + isNavigationRequest() { + return this._isNavigationRequest; + } + + frame() { + return this._frame; + } + + response() { + return this._response; + } +} + +class Response { + constructor(request, payload) { + this._request = request; + this._remoteIPAddress = payload.remoteIPAddress; + this._remotePort = payload.remotePort; + this._status = payload.status; + this._statusText = payload.statusText; + } + + status() { + return this._status; + } + + statusText() { + return this._statusText; + } + + ok() { + return this._status >= 200 && this._status <= 299; + } + + remoteAddress() { + return { + ip: this._remoteIPAddress, + port: this._remotePort, + }; + } + + frame() { + return this._request.frame(); + } + + url() { + return this._request.url(); + } + + request() { + return this._request; + } +} + +module.exports = {NetworkManager, Request, Response}; diff --git a/experimental/puppeteer-firefox/lib/Page.js b/experimental/puppeteer-firefox/lib/Page.js index 064928ff..b489e1a1 100644 --- a/experimental/puppeteer-firefox/lib/Page.js +++ b/experimental/puppeteer-firefox/lib/Page.js @@ -9,6 +9,7 @@ const EventEmitter = require('events'); const {createHandle} = require('./JSHandle'); const {Events} = require('./Events'); const {FrameManager} = require('./FrameManager'); +const {NetworkManager} = require('./NetworkManager'); const {TimeoutSettings} = require('./TimeoutSettings'); const writeFileAsync = util.promisify(fs.writeFile); @@ -74,17 +75,21 @@ class Page extends EventEmitter { this._mouse = new Mouse(session, this._keyboard); this._isClosed = false; this._frameManager = new FrameManager(session, this, this._timeoutSettings); + this._networkManager = new NetworkManager(session, this._frameManager); this._eventListeners = [ helper.addEventListener(this._session, 'Page.uncaughtError', this._onUncaughtError.bind(this)), helper.addEventListener(this._session, 'Page.consoleAPICalled', this._onConsole.bind(this)), helper.addEventListener(this._session, 'Page.dialogOpened', this._onDialogOpened.bind(this)), helper.addEventListener(this._session, 'Browser.tabClosed', this._onClosed.bind(this)), - helper.addEventListener(this._session, 'Page.navigationCommitted', this._onNavigationCommitted.bind(this)), - helper.addEventListener(this._session, 'Page.sameDocumentNavigation', this._onSameDocumentNavigation.bind(this)), helper.addEventListener(this._frameManager, Events.FrameManager.Load, () => this.emit(Events.Page.Load)), helper.addEventListener(this._frameManager, Events.FrameManager.DOMContentLoaded, () => this.emit(Events.Page.DOMContentLoaded)), helper.addEventListener(this._frameManager, Events.FrameManager.FrameAttached, frame => this.emit(Events.Page.FrameAttached, frame)), helper.addEventListener(this._frameManager, Events.FrameManager.FrameDetached, frame => this.emit(Events.Page.FrameDetached, frame)), + helper.addEventListener(this._frameManager, Events.FrameManager.FrameNavigated, frame => this.emit(Events.Page.FrameNavigated, frame)), + helper.addEventListener(this._networkManager, Events.NetworkManager.Request, request => this.emit(Events.Page.Request, request)), + helper.addEventListener(this._networkManager, Events.NetworkManager.Response, response => this.emit(Events.Page.Response, response)), + helper.addEventListener(this._networkManager, Events.NetworkManager.RequestFinished, request => this.emit(Events.Page.RequestFinished, request)), + helper.addEventListener(this._networkManager, Events.NetworkManager.RequestFailed, request => this.emit(Events.Page.RequestFailed, request)), ]; this._viewport = null; } @@ -206,20 +211,6 @@ class Page extends EventEmitter { return this._frameManager.mainFrame(); } - _onNavigationCommitted(params) { - const frame = this._frameManager.frame(params.frameId); - frame._navigated(params.url, params.name, params.navigationId); - frame._DOMContentLoadedFired = false; - frame._loadFired = false; - this.emit(Events.Page.FrameNavigated, frame); - } - - _onSameDocumentNavigation(params) { - const frame = this._frameManager.frame(params.frameId); - frame._url = params.url; - this.emit(Events.Page.FrameNavigated, frame); - } - get keyboard(){ return this._keyboard; } @@ -272,10 +263,10 @@ class Page extends EventEmitter { if (!navigationId) { // Same document navigation happened. clearTimeout(timeoutId); - return; + return null; } - const watchDog = new NavigationWatchdog(this._session, frame, navigationId, url, normalizedWaitUntil); + const watchDog = new NavigationWatchdog(this._session, frame, this._networkManager, navigationId, url, normalizedWaitUntil); const error = await Promise.race([ timeoutPromise, watchDog.promise(), @@ -284,6 +275,7 @@ class Page extends EventEmitter { clearTimeout(timeoutId); if (error) throw error; + return watchDog.navigationResponse(); } /** @@ -309,7 +301,7 @@ class Page extends EventEmitter { const timeoutPromise = new Promise(resolve => timeoutCallback = resolve.bind(null, timeoutError)); const timeoutId = timeout ? setTimeout(timeoutCallback, timeout) : null; - const watchDog = new NavigationWatchdog(this._session, frame, navigationId, url, normalizedWaitUntil); + const watchDog = new NavigationWatchdog(this._session, frame, this._networkManager, navigationId, url, normalizedWaitUntil); const error = await Promise.race([ timeoutPromise, watchDog.promise(), @@ -318,6 +310,7 @@ class Page extends EventEmitter { clearTimeout(timeoutId); if (error) throw error; + return watchDog.navigationResponse(); } /** @@ -334,14 +327,14 @@ class Page extends EventEmitter { frameId: frame._frameId, }); if (!navigationId) - return; + return null; const timeoutError = new TimeoutError('Navigation Timeout Exceeded: ' + timeout + 'ms'); let timeoutCallback; const timeoutPromise = new Promise(resolve => timeoutCallback = resolve.bind(null, timeoutError)); const timeoutId = timeout ? setTimeout(timeoutCallback, timeout) : null; - const watchDog = new NavigationWatchdog(this._session, frame, navigationId, navigationURL, normalizedWaitUntil); + const watchDog = new NavigationWatchdog(this._session, frame, this._networkManager, navigationId, navigationURL, normalizedWaitUntil); const error = await Promise.race([ timeoutPromise, watchDog.promise(), @@ -350,6 +343,7 @@ class Page extends EventEmitter { clearTimeout(timeoutId); if (error) throw error; + return watchDog.navigationResponse(); } /** @@ -366,14 +360,14 @@ class Page extends EventEmitter { frameId: frame._frameId, }); if (!navigationId) - return; + return null; const timeoutError = new TimeoutError('Navigation Timeout Exceeded: ' + timeout + 'ms'); let timeoutCallback; const timeoutPromise = new Promise(resolve => timeoutCallback = resolve.bind(null, timeoutError)); const timeoutId = timeout ? setTimeout(timeoutCallback, timeout) : null; - const watchDog = new NavigationWatchdog(this._session, frame, navigationId, navigationURL, normalizedWaitUntil); + const watchDog = new NavigationWatchdog(this._session, frame, this._networkManager, navigationId, navigationURL, normalizedWaitUntil); const error = await Promise.race([ timeoutPromise, watchDog.promise(), @@ -382,6 +376,7 @@ class Page extends EventEmitter { clearTimeout(timeoutId); if (error) throw error; + return watchDog.navigationResponse(); } /** @@ -398,14 +393,14 @@ class Page extends EventEmitter { frameId: frame._frameId, }); if (!navigationId) - return; + return null; const timeoutError = new TimeoutError('Navigation Timeout Exceeded: ' + timeout + 'ms'); let timeoutCallback; const timeoutPromise = new Promise(resolve => timeoutCallback = resolve.bind(null, timeoutError)); const timeoutId = timeout ? setTimeout(timeoutCallback, timeout) : null; - const watchDog = new NavigationWatchdog(this._session, frame, navigationId, navigationURL, normalizedWaitUntil); + const watchDog = new NavigationWatchdog(this._session, frame, this._networkManager, navigationId, navigationURL, normalizedWaitUntil); const error = await Promise.race([ timeoutPromise, watchDog.promise(), @@ -414,6 +409,7 @@ class Page extends EventEmitter { clearTimeout(timeoutId); if (error) throw error; + return watchDog.navigationResponse(); } /** @@ -724,13 +720,14 @@ class NextNavigationWatchdog { * @internal */ class NavigationWatchdog { - constructor(session, navigatedFrame, targetNavigationId, targetURL, firedEvents) { + constructor(session, navigatedFrame, networkManager, targetNavigationId, targetURL, firedEvents) { this._navigatedFrame = navigatedFrame; this._targetNavigationId = targetNavigationId; this._firedEvents = firedEvents; this._targetURL = targetURL; this._promise = new Promise(x => this._resolveCallback = x); + this._navigationRequest = null; const check = this._checkNavigationComplete.bind(this); this._eventListeners = [ @@ -740,10 +737,21 @@ class NavigationWatchdog { helper.addEventListener(session, 'Page.navigationStarted', check), helper.addEventListener(session, 'Page.navigationCommitted', check), helper.addEventListener(session, 'Page.navigationAborted', this._onNavigationAborted.bind(this)), + helper.addEventListener(networkManager, Events.NetworkManager.Request, this._onRequest.bind(this)), ]; check(); } + _onRequest(request) { + if (request.frame() !== this._navigatedFrame || !request.isNavigationRequest()) + return; + this._navigationRequest = request; + } + + navigationResponse() { + return this._navigationRequest ? this._navigationRequest.response() : null; + } + _checkNavigationComplete() { if (this._navigatedFrame._lastCommittedNavigationId === this._targetNavigationId && checkFiredEvents(this._navigatedFrame, this._firedEvents)) { diff --git a/experimental/puppeteer-firefox/lib/api.js b/experimental/puppeteer-firefox/lib/api.js index c29c62da..1f01e99c 100644 --- a/experimental/puppeteer-firefox/lib/api.js +++ b/experimental/puppeteer-firefox/lib/api.js @@ -12,6 +12,8 @@ module.exports = { Mouse: require('./Input').Mouse, Page: require('./Page').Page, Puppeteer: require('./Puppeteer').Puppeteer, + Request: require('./NetworkManager').Request, + Response: require('./NetworkManager').Response, Target: require('./Browser').Target, TimeoutError: require('./Errors').TimeoutError, }; diff --git a/experimental/puppeteer-firefox/package.json b/experimental/puppeteer-firefox/package.json index e18958da..7214ae56 100644 --- a/experimental/puppeteer-firefox/package.json +++ b/experimental/puppeteer-firefox/package.json @@ -9,7 +9,7 @@ "node": ">=8.9.4" }, "puppeteer": { - "firefox_revision": "592ca01fa3d2566a9f494e2df8ca6876c5b5b4bb" + "firefox_revision": "668e06245e539adf0d453b447401b8eb6e9acb44" }, "scripts": { "install": "node install.js", diff --git a/test/navigation.spec.js b/test/navigation.spec.js index e75d2eca..102cae23 100644 --- a/test/navigation.spec.js +++ b/test/navigation.spec.js @@ -33,11 +33,11 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { await page.goto(server.PREFIX + '/redirect/1.html'); expect(page.url()).toBe(server.EMPTY_PAGE); }); - it_fails_ffox('should navigate to about:blank', async({page, server}) => { + it('should navigate to about:blank', async({page, server}) => { const response = await page.goto('about:blank'); expect(response).toBe(null); }); - it_fails_ffox('should return response when page changes its URL after load', async({page, server}) => { + it('should return response when page changes its URL after load', async({page, server}) => { const response = await page.goto(server.PREFIX + '/historyapi.html'); expect(response.status()).toBe(200); }); @@ -66,7 +66,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { expect(response.status()).toBe(200); expect(response.securityDetails()).toBe(null); }); - it_fails_ffox('should work when page calls history API in beforeunload', async({page, server}) => { + it('should work when page calls history API in beforeunload', async({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.evaluate(() => { window.addEventListener('beforeunload', () => history.replaceState(null, 'initial', window.location.href), false); @@ -90,7 +90,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { else expect(error.message).toContain('Invalid url'); }); - it_fails_ffox('should fail when navigating to bad SSL', async({page, httpsServer}) => { + it('should fail when navigating to bad SSL', async({page, httpsServer}) => { // Make sure that network events do not emit 'undefined'. // @see https://crbug.com/750469 page.on('request', request => expect(request).toBeTruthy()); @@ -98,7 +98,10 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { page.on('requestfailed', request => expect(request).toBeTruthy()); let error = null; await page.goto(httpsServer.EMPTY_PAGE).catch(e => error = e); - expect(error.message).toContain('net::ERR_CERT_AUTHORITY_INVALID'); + if (CHROME) + expect(error.message).toContain('net::ERR_CERT_AUTHORITY_INVALID'); + else + expect(error.message).toContain('SSL_ERROR_UNKNOWN'); }); it('should fail when navigating to bad SSL after redirects', async({page, server, httpsServer}) => { server.setRedirect('/redirect/1.html', '/redirect/2.html'); @@ -167,7 +170,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { expect(error).toBe(null); expect(loaded).toBe(true); }); - it_fails_ffox('should work when navigating to valid url', async({page, server}) => { + it('should work when navigating to valid url', async({page, server}) => { const response = await page.goto(server.EMPTY_PAGE); expect(response.ok()).toBe(true); }); @@ -175,12 +178,12 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { const response = await page.goto('data:text/html,hello'); expect(response.ok()).toBe(true); }); - it_fails_ffox('should work when navigating to 404', async({page, server}) => { + it('should work when navigating to 404', async({page, server}) => { const response = await page.goto(server.PREFIX + '/not-found'); expect(response.ok()).toBe(false); expect(response.status()).toBe(404); }); - it_fails_ffox('should return last response in redirect chain', async({page, server}) => { + it('should return last response in redirect chain', async({page, server}) => { server.setRedirect('/redirect/1.html', '/redirect/2.html'); server.setRedirect('/redirect/2.html', '/redirect/3.html'); server.setRedirect('/redirect/3.html', server.EMPTY_PAGE); @@ -293,7 +296,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { expect(requests.length).toBe(1); expect(requests[0].url()).toBe(server.EMPTY_PAGE); }); - it_fails_ffox('should work with self requesting page', async({page, server}) => { + it('should work with self requesting page', async({page, server}) => { const response = await page.goto(server.PREFIX + '/self-request.html'); expect(response.status()).toBe(200); expect(response.url()).toContain('self-request.html'); @@ -323,7 +326,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { }); describe('Page.waitForNavigation', function() { - it_fails_ffox('should work', async({page, server}) => { + it('should work', async({page, server}) => { await page.goto(server.EMPTY_PAGE); const [response] = await Promise.all([ page.waitForNavigation(), @@ -352,7 +355,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { await bothFiredPromise; await navigationPromise; }); - it_fails_ffox('should work with clicking on anchor links', async({page, server}) => { + it('should work with clicking on anchor links', async({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.setContent(`foobar`); const [response] = await Promise.all([ @@ -362,7 +365,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { expect(response).toBe(null); expect(page.url()).toBe(server.EMPTY_PAGE + '#foobar'); }); - it_fails_ffox('should work with history.pushState()', async({page, server}) => { + it('should work with history.pushState()', async({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.setContent(` SPA @@ -377,7 +380,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { expect(response).toBe(null); expect(page.url()).toBe(server.PREFIX + '/wow.html'); }); - it_fails_ffox('should work with history.replaceState()', async({page, server}) => { + it('should work with history.replaceState()', async({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.setContent(` SPA @@ -436,7 +439,7 @@ module.exports.addTests = function({testRunner, expect, Errors, CHROME}) { }); describe('Page.goBack', function() { - it_fails_ffox('should work', async({page, server}) => { + it('should work', async({page, server}) => { await page.goto(server.EMPTY_PAGE); await page.goto(server.PREFIX + '/grid.html'); diff --git a/test/network.spec.js b/test/network.spec.js index e3233f30..4666e1b2 100644 --- a/test/network.spec.js +++ b/test/network.spec.js @@ -20,10 +20,10 @@ const utils = require('./utils'); module.exports.addTests = function({testRunner, expect}) { const {describe, xdescribe, fdescribe, describe_fails_ffox} = testRunner; - const {it, fit, xit} = testRunner; + const {it, fit, xit, it_fails_ffox} = testRunner; const {beforeAll, beforeEach, afterAll, afterEach} = testRunner; - describe_fails_ffox('Network Events', function() { + describe('Network Events', function() { it('Page.Events.Request', async({page, server}) => { const requests = []; page.on('request', request => requests.push(request)); @@ -36,7 +36,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(requests[0].frame() === page.mainFrame()).toBe(true); expect(requests[0].frame().url()).toBe(server.EMPTY_PAGE); }); - it('Page.Events.Request should report post data', async({page, server}) => { + it_fails_ffox('Page.Events.Request should report post data', async({page, server}) => { await page.goto(server.EMPTY_PAGE); server.setRoute('/post', (req, res) => res.end()); let request = null; @@ -45,7 +45,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(request).toBeTruthy(); expect(request.postData()).toBe('{"foo":"bar"}'); }); - it('Page.Events.Response', async({page, server}) => { + it_fails_ffox('Page.Events.Response', async({page, server}) => { const responses = []; page.on('response', response => responses.push(response)); await page.goto(server.EMPTY_PAGE); @@ -71,7 +71,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(response.statusText()).toBe('cool!'); }); - it('Response.fromCache()', async({page, server}) => { + it_fails_ffox('Response.fromCache()', async({page, server}) => { const responses = new Map(); page.on('response', r => responses.set(r.url().split('/').pop(), r)); @@ -85,7 +85,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(responses.get('one-style.css').status()).toBe(200); expect(responses.get('one-style.css').fromCache()).toBe(true); }); - it('Response.fromServiceWorker', async({page, server}) => { + it_fails_ffox('Response.fromServiceWorker', async({page, server}) => { const responses = new Map(); page.on('response', r => responses.set(r.url().split('/').pop(), r)); @@ -101,7 +101,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(responses.get('style.css').fromServiceWorker()).toBe(true); }); - it('Page.Events.Response should provide body', async({page, server}) => { + it_fails_ffox('Page.Events.Response should provide body', async({page, server}) => { let response = null; page.on('response', r => response = r); await page.goto(server.PREFIX + '/simple.json'); @@ -109,7 +109,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(await response.text()).toBe('{"foo": "bar"}\n'); expect(await response.json()).toEqual({foo: 'bar'}); }); - it('Page.Events.Response should throw when requesting body of redirected response', async({page, server}) => { + it_fails_ffox('Page.Events.Response should throw when requesting body of redirected response', async({page, server}) => { server.setRedirect('/foo.html', '/empty.html'); const response = await page.goto(server.PREFIX + '/foo.html'); const redirectChain = response.request().redirectChain(); @@ -120,7 +120,7 @@ module.exports.addTests = function({testRunner, expect}) { await redirected.text().catch(e => error = e); expect(error.message).toContain('Response body is unavailable for redirect responses'); }); - it('Page.Events.Response should not report body unless request is finished', async({page, server}) => { + it_fails_ffox('Page.Events.Response should not report body unless request is finished', async({page, server}) => { await page.goto(server.EMPTY_PAGE); // Setup server to trap request. let serverResponse = null; @@ -151,7 +151,7 @@ module.exports.addTests = function({testRunner, expect}) { await new Promise(x => serverResponse.end('ld!', x)); expect(await responseText).toBe('hello world!'); }); - it('Page.Events.RequestFailed', async({page, server}) => { + it_fails_ffox('Page.Events.RequestFailed', async({page, server}) => { await page.setRequestInterception(true); page.on('request', request => { if (request.url().endsWith('css')) @@ -213,7 +213,7 @@ module.exports.addTests = function({testRunner, expect}) { }); }); - describe_fails_ffox('Request.isNavigationRequest', () => { + describe('Request.isNavigationRequest', () => { it('should work', async({page, server}) => { const requests = new Map(); page.on('request', request => requests.set(request.url().split('/').pop(), request)); @@ -225,7 +225,7 @@ module.exports.addTests = function({testRunner, expect}) { expect(requests.get('script.js').isNavigationRequest()).toBe(false); expect(requests.get('style.css').isNavigationRequest()).toBe(false); }); - it('should work with request interception', async({page, server}) => { + it_fails_ffox('should work with request interception', async({page, server}) => { const requests = new Map(); page.on('request', request => { requests.set(request.url().split('/').pop(), request); @@ -632,7 +632,7 @@ module.exports.addTests = function({testRunner, expect}) { }); }); - describe_fails_ffox('Page.Events.Request', function() { + describe('Page.Events.Request', function() { it('should fire', async({page, server}) => { const requests = []; page.on('request', request => requests.push(request)); diff --git a/test/puppeteer.spec.js b/test/puppeteer.spec.js index 4d3d83d6..6fa08891 100644 --- a/test/puppeteer.spec.js +++ b/test/puppeteer.spec.js @@ -38,7 +38,7 @@ module.exports.addTests = ({testRunner, product, puppeteer, Errors, DeviceDescri executablePath: CHROME ? process.env.CHROME : process.env.FFOX, slowMo, headless, - dumpio: (process.env.DUMPIO || 'false').trim().toLowerCase() === 'true', + dumpio: !!process.env.DUMPIO, }; if (defaultBrowserOptions.executablePath) {