fix: request/response events with backgroundPages (#15032)

This commit is contained in:
Max Schmitt 2022-06-22 17:23:51 +02:00 committed by GitHub
parent d40761541f
commit fb441faab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 50 additions and 8 deletions

View File

@ -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<any>) {

View File

@ -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.

View File

@ -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(`<span>hello world!</span>`);
});
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('<span>hello world!</span>');
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();