mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-05 19:04:43 +03:00
chore: explicit server mode control (#23215)
This commit is contained in:
parent
b814e8a5f1
commit
6cce93b697
@ -49,7 +49,7 @@ export class AndroidServerLauncherImpl {
|
||||
const path = options.wsPath ? (options.wsPath.startsWith('/') ? options.wsPath : `/${options.wsPath}`) : `/${createGuid()}`;
|
||||
|
||||
// 2. Start the server
|
||||
const server = new PlaywrightServer({ path, maxConnections: 1, preLaunchedAndroidDevice: device });
|
||||
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: 1, preLaunchedAndroidDevice: device });
|
||||
const wsEndpoint = await server.listen(options.port);
|
||||
|
||||
// 3. Return the BrowserServer interface
|
||||
|
@ -57,7 +57,7 @@ export class BrowserServerLauncherImpl implements BrowserServerLauncher {
|
||||
const path = options.wsPath ? (options.wsPath.startsWith('/') ? options.wsPath : `/${options.wsPath}`) : `/${createGuid()}`;
|
||||
|
||||
// 2. Start the server
|
||||
const server = new PlaywrightServer({ path, maxConnections: Infinity, preLaunchedBrowser: browser, preLaunchedSocksProxy: socksProxy });
|
||||
const server = new PlaywrightServer({ mode: 'launchServer', path, maxConnections: Infinity, preLaunchedBrowser: browser, preLaunchedSocksProxy: socksProxy });
|
||||
const wsEndpoint = await server.listen(options.port);
|
||||
|
||||
// 3. Return the BrowserServer interface
|
||||
|
@ -54,6 +54,7 @@ export function runDriver() {
|
||||
export type RunServerOptions = {
|
||||
port?: number,
|
||||
path?: string,
|
||||
extension?: boolean,
|
||||
maxConnections?: number,
|
||||
browserProxyMode?: 'client' | 'tether',
|
||||
ownedByTetherClient?: boolean,
|
||||
@ -64,8 +65,9 @@ export async function runServer(options: RunServerOptions) {
|
||||
port,
|
||||
path = '/',
|
||||
maxConnections = Infinity,
|
||||
extension,
|
||||
} = options;
|
||||
const server = new PlaywrightServer({ path, maxConnections });
|
||||
const server = new PlaywrightServer({ mode: extension ? 'extension' : 'default', path, maxConnections });
|
||||
const wsEndpoint = await server.listen(port);
|
||||
process.on('exit', () => server.close().catch(console.error));
|
||||
console.log('Listening on ' + wsEndpoint); // eslint-disable-line no-console
|
||||
|
@ -246,11 +246,13 @@ program
|
||||
.option('--port <port>', 'Server port')
|
||||
.option('--path <path>', 'Endpoint Path', '/')
|
||||
.option('--max-clients <maxClients>', 'Maximum clients')
|
||||
.option('--mode <mode>', 'Server mode, either "default" or "extension"')
|
||||
.action(function(options) {
|
||||
runServer({
|
||||
port: options.port ? +options.port : undefined,
|
||||
path: options.path,
|
||||
maxConnections: options.maxClients ? +options.maxClients : Infinity,
|
||||
extension: options.mode === 'extension' || !!process.env.PW_EXTENSION_MODE,
|
||||
}).catch(logErrorAndExit);
|
||||
});
|
||||
|
||||
|
@ -28,7 +28,7 @@ import { startProfiling, stopProfiling } from '../utils';
|
||||
import { monotonicTime } from '../utils';
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
|
||||
export type ClientType = 'controller' | 'playwright' | 'launch-browser' | 'reuse-browser' | 'pre-launched-browser-or-android';
|
||||
export type ClientType = 'controller' | 'launch-browser' | 'reuse-browser' | 'pre-launched-browser-or-android';
|
||||
|
||||
type Options = {
|
||||
socksProxyPattern: string | undefined,
|
||||
@ -102,24 +102,10 @@ export class PlaywrightConnection {
|
||||
return this._preLaunched.browser ? await this._initPreLaunchedBrowserMode(scope) : await this._initPreLaunchedAndroidMode(scope);
|
||||
if (clientType === 'launch-browser')
|
||||
return await this._initLaunchBrowserMode(scope);
|
||||
if (clientType === 'playwright')
|
||||
return await this._initPlaywrightConnectMode(scope);
|
||||
throw new Error('Unsupported client type: ' + clientType);
|
||||
});
|
||||
}
|
||||
|
||||
private async _initPlaywrightConnectMode(scope: RootDispatcher) {
|
||||
debugLogger.log('server', `[${this._id}] engaged playwright.connect mode`);
|
||||
const playwright = createPlaywright('javascript');
|
||||
// Close all launched browsers on disconnect.
|
||||
this._cleanups.push(async () => {
|
||||
await Promise.all(playwright.allBrowsers().map(browser => browser.close()));
|
||||
});
|
||||
|
||||
const ownedSocksProxy = await this._createOwnedSocksProxy(playwright);
|
||||
return new PlaywrightDispatcher(scope, playwright, ownedSocksProxy);
|
||||
}
|
||||
|
||||
private async _initLaunchBrowserMode(scope: RootDispatcher) {
|
||||
debugLogger.log('server', `[${this._id}] engaged launch mode for "${this._options.browserName}"`);
|
||||
const playwright = createPlaywright('javascript');
|
||||
|
@ -34,6 +34,7 @@ const kConnectionSymbol = Symbol('kConnection');
|
||||
type ServerOptions = {
|
||||
path: string;
|
||||
maxConnections: number;
|
||||
mode: 'default' | 'launchServer' | 'extension';
|
||||
preLaunchedBrowser?: Browser;
|
||||
preLaunchedAndroidDevice?: AndroidDevice;
|
||||
preLaunchedSocksProxy?: SocksProxy;
|
||||
@ -97,38 +98,35 @@ export class PlaywrightServer {
|
||||
const proxyValue = url.searchParams.get('proxy') || (Array.isArray(proxyHeader) ? proxyHeader[0] : proxyHeader);
|
||||
|
||||
const launchOptionsHeader = request.headers['x-playwright-launch-options'] || '';
|
||||
const launchOptionsHeaderValue = Array.isArray(launchOptionsHeader) ? launchOptionsHeader[0] : launchOptionsHeader;
|
||||
const launchOptionsParam = url.searchParams.get('launch-options');
|
||||
let launchOptions: LaunchOptions = {};
|
||||
try {
|
||||
launchOptions = JSON.parse(Array.isArray(launchOptionsHeader) ? launchOptionsHeader[0] : launchOptionsHeader);
|
||||
launchOptions = JSON.parse(launchOptionsParam || launchOptionsHeaderValue);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
const id = String(++lastConnectionId);
|
||||
debugLogger.log('server', `[${id}] serving connection: ${request.url}`);
|
||||
const isDebugControllerClient = !!request.headers['x-playwright-debug-controller'];
|
||||
const shouldReuseBrowser = !!request.headers['x-playwright-reuse-context'];
|
||||
|
||||
// If we started in the legacy reuse-browser mode, create this._preLaunchedPlaywright.
|
||||
// If we get a debug-controller request, create this._preLaunchedPlaywright.
|
||||
if (isDebugControllerClient || shouldReuseBrowser) {
|
||||
// Instantiate playwright for the extension modes.
|
||||
const isExtension = this._options.mode === 'extension';
|
||||
if (isExtension) {
|
||||
if (!this._preLaunchedPlaywright)
|
||||
this._preLaunchedPlaywright = createPlaywright('javascript');
|
||||
}
|
||||
|
||||
let clientType: ClientType = 'playwright';
|
||||
let clientType: ClientType = 'launch-browser';
|
||||
let semaphore: Semaphore = browserSemaphore;
|
||||
if (isDebugControllerClient) {
|
||||
if (isExtension && url.searchParams.has('debug-controller')) {
|
||||
clientType = 'controller';
|
||||
semaphore = controllerSemaphore;
|
||||
} else if (shouldReuseBrowser) {
|
||||
} else if (isExtension) {
|
||||
clientType = 'reuse-browser';
|
||||
semaphore = reuseBrowserSemaphore;
|
||||
} else if (this._options.preLaunchedBrowser || this._options.preLaunchedAndroidDevice) {
|
||||
} else if (this._options.mode === 'launchServer') {
|
||||
clientType = 'pre-launched-browser-or-android';
|
||||
semaphore = browserSemaphore;
|
||||
} else if (browserName) {
|
||||
clientType = 'launch-browser';
|
||||
semaphore = browserSemaphore;
|
||||
}
|
||||
|
||||
const connection = new PlaywrightConnection(
|
||||
|
@ -409,7 +409,7 @@ ${colors.dim('Waiting for file changes. Press')} ${colors.bold('enter')} ${color
|
||||
async function toggleShowBrowser(config: FullConfigInternal, originalWorkers: number) {
|
||||
if (!showBrowserServer) {
|
||||
config.config.workers = 1;
|
||||
showBrowserServer = new PlaywrightServer({ path: '/' + createGuid(), maxConnections: 1 });
|
||||
showBrowserServer = new PlaywrightServer({ mode: 'extension', path: '/' + createGuid(), maxConnections: 1 });
|
||||
const wsEndpoint = await showBrowserServer.listen();
|
||||
process.env.PW_TEST_REUSE_CONTEXT = '1';
|
||||
process.env.PW_TEST_CONNECT_WS_ENDPOINT = wsEndpoint;
|
||||
|
@ -132,7 +132,7 @@ const test = baseTest.extend<BrowserTestTestFixtures, BrowserTestWorkerFixtures>
|
||||
server = remoteServer;
|
||||
} else {
|
||||
const runServer = new RunServer();
|
||||
await runServer._start(childProcess);
|
||||
await runServer.start(childProcess);
|
||||
server = runServer;
|
||||
}
|
||||
return server;
|
||||
|
@ -115,9 +115,7 @@ export class Backend extends EventEmitter {
|
||||
}
|
||||
|
||||
async connect(wsEndpoint: string) {
|
||||
this._transport = await WebSocketTransport.connect(wsEndpoint, {
|
||||
'x-playwright-debug-controller': 'true'
|
||||
});
|
||||
this._transport = await WebSocketTransport.connect(wsEndpoint + '?debug-controller');
|
||||
this._transport.onmessage = (message: any) => {
|
||||
if (!message.id) {
|
||||
this.emit(message.method, message.params);
|
||||
|
@ -27,9 +27,12 @@ export class RunServer implements PlaywrightServer {
|
||||
private _process: TestChildProcess;
|
||||
_wsEndpoint: string;
|
||||
|
||||
async _start(childProcess: CommonFixtures['childProcess']) {
|
||||
async start(childProcess: CommonFixtures['childProcess'], mode?: 'extension' | 'default') {
|
||||
const command = ['node', path.join(__dirname, '..', '..', 'packages', 'playwright-core', 'lib', 'cli', 'cli.js'), 'run-server'];
|
||||
if (mode === 'extension')
|
||||
command.push('--mode=extension');
|
||||
this._process = childProcess({
|
||||
command: ['node', path.join(__dirname, '..', '..', 'packages', 'playwright-core', 'lib', 'cli', 'cli.js'), 'run-server'],
|
||||
command,
|
||||
env: {
|
||||
...process.env,
|
||||
PWTEST_UNDER_TEST: '1',
|
||||
|
@ -31,7 +31,7 @@ type Fixtures = {
|
||||
const test = baseTest.extend<Fixtures>({
|
||||
wsEndpoint: async ({ }, use) => {
|
||||
process.env.PW_DEBUG_CONTROLLER_HEADLESS = '1';
|
||||
const server = new PlaywrightServer({ path: '/' + createGuid(), maxConnections: Number.MAX_VALUE, enableSocksProxy: false });
|
||||
const server = new PlaywrightServer({ mode: 'extension', path: '/' + createGuid(), maxConnections: Number.MAX_VALUE, enableSocksProxy: false });
|
||||
const wsEndpoint = await server.listen();
|
||||
await use(wsEndpoint);
|
||||
await server.close();
|
||||
|
@ -23,7 +23,7 @@ const test = baseTest.extend<{ runServer: () => Promise<PlaywrightServer> }>({
|
||||
let server: PlaywrightServer | undefined;
|
||||
await use(async () => {
|
||||
const runServer = new RunServer();
|
||||
await runServer._start(childProcess);
|
||||
await runServer.start(childProcess, 'extension');
|
||||
server = runServer;
|
||||
return server;
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user