From fb441faab11a83603733a5f362ea8e709fc0a835 Mon Sep 17 00:00:00 2001 From: Max Schmitt Date: Wed, 22 Jun 2022 17:23:51 +0200 Subject: [PATCH] fix: request/response events with backgroundPages (#15032) --- .../src/server/chromium/crPage.ts | 8 +--- packages/playwright-core/src/server/page.ts | 4 +- tests/library/chromium/launcher.spec.ts | 46 +++++++++++++++++++ 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/packages/playwright-core/src/server/chromium/crPage.ts b/packages/playwright-core/src/server/chromium/crPage.ts index 4bd9f44827..90f09e38d5 100644 --- a/packages/playwright-core/src/server/chromium/crPage.ts +++ b/packages/playwright-core/src/server/chromium/crPage.ts @@ -45,6 +45,7 @@ import { exceptionToError, releaseObject, toConsoleMessageLocation } from './crP import { platformToFontFamilies } from './defaultFontFamilies'; import type { Protocol } from './protocol'; import { VideoRecorder } from './videoRecorder'; +import { BrowserContext } from '../browserContext'; const UTILITY_WORLD_NAME = '__playwright_utility_world__'; @@ -122,12 +123,7 @@ export class CRPage implements PageDelegate { } private _reportAsNew(error?: Error) { - if (this._isBackgroundPage) { - if (!error) - this._browserContext.emit(CRBrowserContext.CREvents.BackgroundPage, this._page); - } else { - this._page.reportAsNew(error); - } + this._page.reportAsNew(error, this._isBackgroundPage ? CRBrowserContext.CREvents.BackgroundPage : BrowserContext.Events.Page); } private async _forAllFrameSessions(cb: (frame: FrameSession) => Promise) { diff --git a/packages/playwright-core/src/server/page.ts b/packages/playwright-core/src/server/page.ts index 67c5b47953..a9e15b61af 100644 --- a/packages/playwright-core/src/server/page.ts +++ b/packages/playwright-core/src/server/page.ts @@ -207,7 +207,7 @@ export class Page extends SdkObject { this._opener = openerPage; } - reportAsNew(error?: Error) { + reportAsNew(error: Error | undefined = undefined, contextEvent: string = BrowserContext.Events.Page) { if (error) { // Initialization error could have happened because of // context/browser closure. Just ignore the page. @@ -216,7 +216,7 @@ export class Page extends SdkObject { this._setIsError(error); } this._initialized = true; - this.emitOnContext(BrowserContext.Events.Page, this); + this.emitOnContext(contextEvent, this); // I may happen that page initialization finishes after Close event has already been sent, // in that case we fire another Close event to ensure that each reported Page will have // corresponding Close event after it is reported on the context. diff --git a/tests/library/chromium/launcher.spec.ts b/tests/library/chromium/launcher.spec.ts index 89ca8a3eb6..9bcf51b092 100644 --- a/tests/library/chromium/launcher.spec.ts +++ b/tests/library/chromium/launcher.spec.ts @@ -99,6 +99,52 @@ it('should return background pages when recording video', async ({ browserType, await context.close(); }); +it('should support request/response events when using backgroundPage()', async ({ browserType, createUserDataDir, asset, server }) => { + server.setRoute('/empty.html', (req, res) => { + res.writeHead(200, { 'Content-Type': 'text/html', 'x-response-foobar': 'BarFoo' }); + res.end(`hello world!`); + }); + const userDataDir = await createUserDataDir(); + const extensionPath = asset('simple-extension'); + const extensionOptions = { + headless: false, + args: [ + `--disable-extensions-except=${extensionPath}`, + `--load-extension=${extensionPath}`, + ], + }; + const context = await browserType.launchPersistentContext(userDataDir, extensionOptions); + const backgroundPages = context.backgroundPages(); + const backgroundPage = backgroundPages.length + ? backgroundPages[0] + : await context.waitForEvent('backgroundpage'); + const [, request, response, contextRequest, contextResponse] = await Promise.all([ + backgroundPage.evaluate(url => fetch(url, { + method: 'POST', + body: 'foobar', + headers: { 'X-FOOBAR': 'KEKBAR' } + }), server.EMPTY_PAGE), + backgroundPage.waitForEvent('request'), + backgroundPage.waitForEvent('response'), + context.waitForEvent('request'), + context.waitForEvent('response'), + ]); + expect(request).toBe(contextRequest); + expect(response).toBe(contextResponse); + expect(request.url()).toBe(server.EMPTY_PAGE); + expect(request.method()).toBe('POST'); + expect(await request.allHeaders()).toEqual(expect.objectContaining({ 'x-foobar': 'KEKBAR' })); + expect(request.postData()).toBe('foobar'); + + expect(response.status()).toBe(200); + expect(response.url()).toBe(server.EMPTY_PAGE); + expect(response.request()).toBe(request); + expect(await response.text()).toBe('hello world!'); + expect(await response.allHeaders()).toEqual(expect.objectContaining({ 'x-response-foobar': 'BarFoo' })); + + await context.close(); +}); + it('should not create pages automatically', async ({ browserType }) => { const browser = await browserType.launch(); const browserSession = await browser.newBrowserCDPSession();