mirror of
https://github.com/microsoft/playwright.git
synced 2024-12-14 05:37:20 +03:00
chore: improve handling with missing xserver (#12724)
This commit is contained in:
parent
daff643516
commit
dd32956ccc
@ -31,6 +31,9 @@ import { helper } from './helper';
|
|||||||
import { RecentLogsCollector } from '../utils/debugLogger';
|
import { RecentLogsCollector } from '../utils/debugLogger';
|
||||||
import { CallMetadata, SdkObject } from './instrumentation';
|
import { CallMetadata, SdkObject } from './instrumentation';
|
||||||
|
|
||||||
|
export const kNoXServerRunningError = 'Looks like you launched a headed browser without having a XServer running.\n' +
|
||||||
|
'Set either \'headless: false\' or use \'xvfb-run <your-playwright-app>\' before running Playwright.\n\n<3 Playwright Team';
|
||||||
|
|
||||||
export abstract class BrowserType extends SdkObject {
|
export abstract class BrowserType extends SdkObject {
|
||||||
private _name: BrowserName;
|
private _name: BrowserName;
|
||||||
readonly _playwrightOptions: PlaywrightOptions;
|
readonly _playwrightOptions: PlaywrightOptions;
|
||||||
@ -76,7 +79,7 @@ export abstract class BrowserType extends SdkObject {
|
|||||||
|
|
||||||
async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
|
async _innerLaunchWithRetries(progress: Progress, options: types.LaunchOptions, persistent: types.BrowserContextOptions | undefined, protocolLogger: types.ProtocolLogger, userDataDir?: string): Promise<Browser> {
|
||||||
try {
|
try {
|
||||||
return this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir);
|
return await this._innerLaunch(progress, options, persistent, protocolLogger, userDataDir);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
// @see https://github.com/microsoft/playwright/issues/5214
|
// @see https://github.com/microsoft/playwright/issues/5214
|
||||||
const errorMessage = typeof error === 'object' && typeof error.message === 'string' ? error.message : '';
|
const errorMessage = typeof error === 'object' && typeof error.message === 'string' ? error.message : '';
|
||||||
|
@ -22,12 +22,12 @@ import { CRBrowser } from './crBrowser';
|
|||||||
import { Env, gracefullyCloseSet } from '../../utils/processLauncher';
|
import { Env, gracefullyCloseSet } from '../../utils/processLauncher';
|
||||||
import { kBrowserCloseMessageId } from './crConnection';
|
import { kBrowserCloseMessageId } from './crConnection';
|
||||||
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||||
import { BrowserType } from '../browserType';
|
import { BrowserType, kNoXServerRunningError } from '../browserType';
|
||||||
import { ConnectionTransport, ProtocolRequest, WebSocketTransport } from '../transport';
|
import { ConnectionTransport, ProtocolRequest, WebSocketTransport } from '../transport';
|
||||||
import { CRDevTools } from './crDevTools';
|
import { CRDevTools } from './crDevTools';
|
||||||
import { Browser, BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
import { Browser, BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
import { debugMode, fetchData, getUserAgent, headersArrayToObject, HTTPRequestParams, removeFolders, streamToString } from '../../utils/utils';
|
import { debugMode, fetchData, getUserAgent, headersArrayToObject, HTTPRequestParams, removeFolders, streamToString, wrapInASCIIBox } from '../../utils/utils';
|
||||||
import { RecentLogsCollector } from '../../utils/debugLogger';
|
import { RecentLogsCollector } from '../../utils/debugLogger';
|
||||||
import { Progress, ProgressController } from '../progress';
|
import { Progress, ProgressController } from '../progress';
|
||||||
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
import { TimeoutSettings } from '../../utils/timeoutSettings';
|
||||||
@ -126,6 +126,8 @@ export class Chromium extends BrowserType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rewriteStartupError(error: Error): Error {
|
_rewriteStartupError(error: Error): Error {
|
||||||
|
if (error.message.includes('Missing X server'))
|
||||||
|
return rewriteErrorMessage(error, '\n' + wrapInASCIIBox(kNoXServerRunningError, 1));
|
||||||
// These error messages are taken from Chromium source code as of July, 2020:
|
// These error messages are taken from Chromium source code as of July, 2020:
|
||||||
// https://github.com/chromium/chromium/blob/70565f67e79f79e17663ad1337dc6e63ee207ce9/content/browser/zygote_host/zygote_host_impl_linux.cc
|
// https://github.com/chromium/chromium/blob/70565f67e79f79e17663ad1337dc6e63ee207ce9/content/browser/zygote_host/zygote_host_impl_linux.cc
|
||||||
if (!error.message.includes('crbug.com/357670') && !error.message.includes('No usable sandbox!') && !error.message.includes('crbug.com/638180'))
|
if (!error.message.includes('crbug.com/357670') && !error.message.includes('No usable sandbox!') && !error.message.includes('crbug.com/638180'))
|
||||||
|
@ -20,11 +20,13 @@ import fs from 'fs';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { FFBrowser } from './ffBrowser';
|
import { FFBrowser } from './ffBrowser';
|
||||||
import { kBrowserCloseMessageId } from './ffConnection';
|
import { kBrowserCloseMessageId } from './ffConnection';
|
||||||
import { BrowserType } from '../browserType';
|
import { BrowserType, kNoXServerRunningError } from '../browserType';
|
||||||
import { Env } from '../../utils/processLauncher';
|
import { Env } from '../../utils/processLauncher';
|
||||||
import { ConnectionTransport } from '../transport';
|
import { ConnectionTransport } from '../transport';
|
||||||
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
|
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||||
|
import { wrapInASCIIBox } from '../../utils/utils';
|
||||||
|
|
||||||
export class Firefox extends BrowserType {
|
export class Firefox extends BrowserType {
|
||||||
constructor(playwrightOptions: PlaywrightOptions) {
|
constructor(playwrightOptions: PlaywrightOptions) {
|
||||||
@ -36,6 +38,8 @@ export class Firefox extends BrowserType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rewriteStartupError(error: Error): Error {
|
_rewriteStartupError(error: Error): Error {
|
||||||
|
if (error.message.includes('no DISPLAY environment variable specified'))
|
||||||
|
return rewriteErrorMessage(error, '\n' + wrapInASCIIBox(kNoXServerRunningError, 1));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,12 @@ import { WKBrowser } from '../webkit/wkBrowser';
|
|||||||
import { Env } from '../../utils/processLauncher';
|
import { Env } from '../../utils/processLauncher';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { kBrowserCloseMessageId } from './wkConnection';
|
import { kBrowserCloseMessageId } from './wkConnection';
|
||||||
import { BrowserType } from '../browserType';
|
import { BrowserType, kNoXServerRunningError } from '../browserType';
|
||||||
import { ConnectionTransport } from '../transport';
|
import { ConnectionTransport } from '../transport';
|
||||||
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
import { BrowserOptions, PlaywrightOptions } from '../browser';
|
||||||
import * as types from '../types';
|
import * as types from '../types';
|
||||||
|
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||||
|
import { wrapInASCIIBox } from '../../utils/utils';
|
||||||
|
|
||||||
export class WebKit extends BrowserType {
|
export class WebKit extends BrowserType {
|
||||||
constructor(playwrightOptions: PlaywrightOptions) {
|
constructor(playwrightOptions: PlaywrightOptions) {
|
||||||
@ -38,6 +40,8 @@ export class WebKit extends BrowserType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_rewriteStartupError(error: Error): Error {
|
_rewriteStartupError(error: Error): Error {
|
||||||
|
if (error.message.includes('cannot open display'))
|
||||||
|
return rewriteErrorMessage(error, '\n' + wrapInASCIIBox(kNoXServerRunningError, 1));
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,3 +40,17 @@ it('should kill browser process on timeout after close', async ({ browserType, m
|
|||||||
await browser.close();
|
await browser.close();
|
||||||
expect(stalled).toBeTruthy();
|
expect(stalled).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should throw a friendly error if its headed and there is no xserver on linux running', async ({ browserType, platform }) => {
|
||||||
|
it.skip(platform !== 'linux');
|
||||||
|
const error: Error = await browserType.launch({
|
||||||
|
headless: false,
|
||||||
|
env: {
|
||||||
|
...process.env,
|
||||||
|
DISPLAY: undefined,
|
||||||
|
},
|
||||||
|
}).catch(e => e);
|
||||||
|
expect(error).toBeInstanceOf(Error);
|
||||||
|
expect(error.message).toMatch(/Looks like you launched a headed browser without having a XServer running./);
|
||||||
|
expect(error.message).toMatch(/xvfb-run/);
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user