diff --git a/package.json b/package.json index 4c712aba76..79570ee1bb 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "main": "index.js", "playwright": { "chromium_revision": "733125", - "firefox_revision": "1016", + "firefox_revision": "1017", "webkit_revision": "1106" }, "scripts": { diff --git a/src/firefox/ffNetworkManager.ts b/src/firefox/ffNetworkManager.ts index 68969eecd8..d16eb456de 100644 --- a/src/firefox/ffNetworkManager.ts +++ b/src/firefox/ffNetworkManager.ts @@ -155,7 +155,7 @@ class InterceptableRequest implements network.RequestDelegate { for (const {name, value} of payload.headers) headers[name.toLowerCase()] = value; - this.request = new network.Request(payload.suspended ? this : null, frame, redirectChain, payload.navigationId, + this.request = new network.Request(payload.isIntercepted ? this : null, frame, redirectChain, payload.navigationId, payload.url, causeToResourceType[payload.cause] || 'other', payload.method, payload.postData, headers); } @@ -163,23 +163,53 @@ class InterceptableRequest implements network.RequestDelegate { const { headers, } = overrides; - await this._session.send('Network.resumeSuspendedRequest', { + await this._session.send('Network.resumeInterceptedRequest', { requestId: this._id, - headers: headers ? Object.entries(headers).filter(([, value]) => !Object.is(value, undefined)).map(([name, value]) => ({name, value})) : undefined, + headers: headers ? headersArray(headers) : undefined, }).catch(error => { debugError(error); }); } async fulfill(response: { status: number; headers: network.Headers; contentType: string; body: (string | platform.BufferType); }) { - throw new Error('Fulfill is not supported in Firefox'); + const responseBody = response.body && helper.isString(response.body) ? platform.Buffer.from(response.body) : (response.body || null); + + const responseHeaders: { [s: string]: string; } = {}; + if (response.headers) { + for (const header of Object.keys(response.headers)) + responseHeaders[header.toLowerCase()] = response.headers[header]; + } + if (response.contentType) + responseHeaders['content-type'] = response.contentType; + if (responseBody && !('content-length' in responseHeaders)) + responseHeaders['content-length'] = String(platform.Buffer.byteLength(responseBody)); + + await this._session.send('Network.fulfillInterceptedRequest', { + requestId: this._id, + status: response.status || 200, + statusText: network.STATUS_TEXTS[String(response.status || 200)] || '', + headers: headersArray(responseHeaders), + base64body: responseBody ? responseBody.toString('base64') : undefined, + }).catch(error => { + debugError(error); + }); } - async abort() { - await this._session.send('Network.abortSuspendedRequest', { + async abort(errorCode: string) { + await this._session.send('Network.abortInterceptedRequest', { requestId: this._id, + errorCode, }).catch(error => { debugError(error); }); } } + +function headersArray(headers: network.Headers): Protocol.Network.HTTPHeader[] { + const result: Protocol.Network.HTTPHeader[] = []; + for (const name in headers) { + if (!Object.is(headers[name], undefined)) + result.push({name, value: headers[name] + ''}); + } + return result; +} diff --git a/src/firefox/ffPage.ts b/src/firefox/ffPage.ts index 32c836bf79..8e9650d03c 100644 --- a/src/firefox/ffPage.ts +++ b/src/firefox/ffPage.ts @@ -294,8 +294,8 @@ export class FFPage implements PageDelegate { throw new Error('Offline mode not implemented in Firefox'); } - async authenticate(credentials: types.Credentials): Promise { - throw new Error('Offline mode not implemented in Firefox'); + async authenticate(credentials: types.Credentials | null): Promise { + await this._session.send('Network.setAuthCredentials', credentials || { username: null, password: null }); } async reload(): Promise { diff --git a/test/golden-firefox/mock-binary-response.png b/test/golden-firefox/mock-binary-response.png new file mode 100644 index 0000000000..be9f4a4468 Binary files /dev/null and b/test/golden-firefox/mock-binary-response.png differ diff --git a/test/interception.spec.js b/test/interception.spec.js index a347113151..1cb70b3455 100644 --- a/test/interception.spec.js +++ b/test/interception.spec.js @@ -178,7 +178,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p if (WEBKIT) expect(failedRequest.failure().errorText).toBe('Request intercepted'); else if (FFOX) - expect(failedRequest.failure().errorText).toBe('NS_ERROR_FAILURE'); + expect(failedRequest.failure().errorText).toBe('NS_ERROR_OFFLINE'); else expect(failedRequest.failure().errorText).toBe('net::ERR_INTERNET_DISCONNECTED'); }); @@ -438,7 +438,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); }); - describe.skip(FFOX)('interception.fulfill', function() { + describe('interception.fulfill', function() { it('should work', async({page, server}) => { await page.setRequestInterception(true); page.on('request', request => { @@ -506,7 +506,7 @@ module.exports.describe = function({testRunner, expect, defaultBrowserOptions, p }); }); - describe.skip(FFOX)('Interception.authenticate', function() { + describe('Page.authenticate', function() { it('should work', async({page, server}) => { server.setAuth('/empty.html', 'user', 'pass'); let response = await page.goto(server.EMPTY_PAGE);