chore: add reuse context to internal test suite (#9359)

This commit is contained in:
Max Schmitt 2021-10-07 23:01:08 +02:00 committed by GitHub
parent 3781faeaaa
commit b10140d9c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 15 deletions

View file

@ -35,7 +35,7 @@ type WorkerAndFileFixtures = PlaywrightWorkerArgs & PlaywrightWorkerOptions & {
_reuseBrowserContext: ReuseBrowserContextStorage, _reuseBrowserContext: ReuseBrowserContextStorage,
}; };
class ReuseBrowserContextStorage { export class ReuseBrowserContextStorage {
private _browserContext?: BrowserContext; private _browserContext?: BrowserContext;
private _uniqueOrigins = new Set<string>(); private _uniqueOrigins = new Set<string>();
private _options?: BrowserContextOptions; private _options?: BrowserContextOptions;
@ -54,18 +54,25 @@ class ReuseBrowserContextStorage {
private async _createNewContext(browser: Browser): Promise<BrowserContext> { private async _createNewContext(browser: Browser): Promise<BrowserContext> {
this._browserContext = await browser.newContext(); this._browserContext = await browser.newContext();
this._options = (this._browserContext as any)._options; this._options = (this._browserContext as any)._options;
this._browserContext.on('page', page => page.on('framenavigated', frame => { this._browserContext.on('page', page => {
if (this._pauseNavigationEventCollection) page.on('framenavigated', frame => {
return; if (this._pauseNavigationEventCollection)
this._uniqueOrigins.add(new URL(frame.url()).origin); return;
})); const origin = new URL(frame.url()).origin;
if (origin !== 'null') // 'chrome-error://chromewebdata/'
this._uniqueOrigins.add(origin);
});
page.on('crash', () => {
this._browserContext?.close().then(() => {});
this._browserContext = undefined;
});
});
return this._browserContext; return this._browserContext;
} }
async _refurbishExistingContext(newContextOptions: BrowserContextOptions): Promise<BrowserContext> { async _refurbishExistingContext(newContextOptions: BrowserContextOptions): Promise<BrowserContext> {
assert(this._browserContext); assert(this._browserContext);
const pages = this._browserContext.pages(); const page = this._browserContext.pages().length > 0 ? this._browserContext.pages()[0] : await this._browserContext.newPage();
const page = pages[0];
this._pauseNavigationEventCollection = true; this._pauseNavigationEventCollection = true;
try { try {
const initialOrigin = new URL(page.url()).origin; const initialOrigin = new URL(page.url()).origin;
@ -78,8 +85,8 @@ class ReuseBrowserContextStorage {
await page.evaluate(() => window.sessionStorage.clear()); await page.evaluate(() => window.sessionStorage.clear());
} }
await page.unroute('**/*'); await page.unroute('**/*');
await Promise.all(pages.slice(1).map(page => page.close()));
await page.goto('about:blank'); await page.goto('about:blank');
await Promise.all(this._browserContext.pages().slice(1).map(page => page.close()));
await this._browserContext.clearCookies(); await this._browserContext.clearCookies();
await this._applyNewContextOptions(page, newContextOptions); await this._applyNewContextOptions(page, newContextOptions);
} finally { } finally {
@ -90,14 +97,16 @@ class ReuseBrowserContextStorage {
private async _applyNewContextOptions(page: Page, newOptions: BrowserContextOptions) { private async _applyNewContextOptions(page: Page, newOptions: BrowserContextOptions) {
assert(this._options); assert(this._options);
const currentViewport = page.viewportSize();
const newViewport = newOptions.viewport === undefined ? { width: 1280, height: 720 } : newOptions.viewport;
if ( if (
( (
this._options.viewport?.width !== newOptions.viewport?.width || currentViewport?.width !== newViewport?.width ||
this._options.viewport?.height !== newOptions.viewport?.height currentViewport?.height !== newViewport?.height
) && ) &&
(newOptions.viewport?.height && newOptions.viewport?.width) (newViewport?.height && newViewport?.width)
) )
await page.setViewportSize({ width: newOptions.viewport?.width, height: newOptions.viewport?.height }); await page.setViewportSize(newViewport);
this._options = newOptions; this._options = newOptions;
} }

View file

@ -17,6 +17,7 @@
import type { Fixtures } from './test-runner'; import type { Fixtures } from './test-runner';
import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from '../../index'; import type { Browser, BrowserContext, BrowserContextOptions, BrowserType, LaunchOptions, Page } from '../../index';
import { removeFolders } from '../../lib/utils/utils'; import { removeFolders } from '../../lib/utils/utils';
import { ReuseBrowserContextStorage } from '../../lib/test/index';
import * as path from 'path'; import * as path from 'path';
import * as fs from 'fs'; import * as fs from 'fs';
import * as os from 'os'; import * as os from 'os';
@ -34,6 +35,7 @@ export type PlaywrightWorkerFixtures = {
browserOptions: LaunchOptions; browserOptions: LaunchOptions;
browser: Browser; browser: Browser;
browserVersion: string; browserVersion: string;
_reuseBrowserContext: ReuseBrowserContextStorage,
}; };
type PlaywrightTestOptions = { type PlaywrightTestOptions = {
hasTouch: BrowserContextOptions['hasTouch']; hasTouch: BrowserContextOptions['hasTouch'];
@ -80,6 +82,8 @@ export const playwrightFixtures: Fixtures<PlaywrightTestOptions & PlaywrightTest
await run(browser.version()); await run(browser.version());
}, { scope: 'worker' } ], }, { scope: 'worker' } ],
_reuseBrowserContext: [new ReuseBrowserContextStorage(), { scope: 'worker' }],
createUserDataDir: async ({}, run) => { createUserDataDir: async ({}, run) => {
const dirs: string[] = []; const dirs: string[] = [];
// We do not put user data dir in testOutputPath, // We do not put user data dir in testOutputPath,
@ -180,11 +184,20 @@ export const playwrightFixtures: Fixtures<PlaywrightTestOptions & PlaywrightTest
})); }));
}, },
context: async ({ contextFactory }, run) => { context: async ({ contextFactory, browser, _reuseBrowserContext, contextOptions }, run) => {
if (_reuseBrowserContext.isEnabled()) {
const context = await _reuseBrowserContext.obtainContext(browser, contextOptions);
await run(context);
return;
}
await run(await contextFactory()); await run(await contextFactory());
}, },
page: async ({ context }, run) => { page: async ({ context, _reuseBrowserContext }, run) => {
if (_reuseBrowserContext.isEnabled()) {
await run(await _reuseBrowserContext.obtainPage());
return;
}
await run(await context.newPage()); await run(await context.newPage());
}, },
}; };