cherry-pick(#13413): chore: use utils via index export (5)
This commit is contained in:
parent
f803a929e4
commit
18c8862b97
|
|
@ -24,9 +24,16 @@
|
|||
"./lib/outofprocess": "./lib/outofprocess.js",
|
||||
"./lib/utils": "./lib/utils/index.js",
|
||||
"./lib/utils/comparators": "./lib/utils/comparators.js",
|
||||
"./lib/utils/eventsHelper": "./lib/utils/eventsHelper.js",
|
||||
"./lib/utils/fileUtils": "./lib/utils/fileUtils.js",
|
||||
"./lib/utils/httpServer": "./lib/utils/httpServer.js",
|
||||
"./lib/utils/hostPlatform": "./lib/utils/hostPlatform.js",
|
||||
"./lib/utils/manualPromise": "./lib/utils/manualPromise.js",
|
||||
"./lib/utils/multimap": "./lib/utils/multimap.js",
|
||||
"./lib/utils/processLauncher": "./lib/utils/processLauncher.js",
|
||||
"./lib/utils/spawnAsync": "./lib/utils/spawnAsync.js",
|
||||
"./lib/utils/stackTrace": "./lib/utils/stackTrace.js",
|
||||
"./lib/utils/timeoutRunner": "./lib/utils/timeoutRunner.js",
|
||||
"./lib/remote/playwrightServer": "./lib/remote/playwrightServer.js",
|
||||
"./lib/remote/playwrightClient": "./lib/remote/playwrightClient.js",
|
||||
"./lib/server": "./lib/server/index.js"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ import type { BrowserType } from '../client/browserType';
|
|||
import type { BrowserContextOptions, LaunchOptions } from '../client/types';
|
||||
import { spawn } from 'child_process';
|
||||
import { getPlaywrightVersion } from '../common/userAgent';
|
||||
import { spawnAsync, wrapInASCIIBox } from '../utils';
|
||||
import { wrapInASCIIBox } from '../utils';
|
||||
import { spawnAsync } from '../utils/spawnAsync';
|
||||
import { launchGridAgent } from '../grid/gridAgent';
|
||||
import type { GridFactory } from '../grid/gridServer';
|
||||
import { GridServer } from '../grid/gridServer';
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import type * as channels from '../protocol/channels';
|
||||
import * as fs from 'fs';
|
||||
import { Stream } from './stream';
|
||||
import { mkdirIfNeeded } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import type { Readable } from 'stream';
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,8 @@ import { Events } from './events';
|
|||
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||
import { Waiter } from './waiter';
|
||||
import type { URLMatch, Headers, WaitForEventOptions, BrowserContextOptions, StorageState, LaunchOptions } from './types';
|
||||
import { headersObjectToArray, mkdirIfNeeded } from '../utils';
|
||||
import { headersObjectToArray } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { isSafeCloseError } from '../common/errors';
|
||||
import type * as api from '../../types/types';
|
||||
import type * as structs from '../../types/structs';
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import { envObjectToArray } from './clientHelper';
|
|||
import { assert, headersObjectToArray, monotonicTime } from '../utils';
|
||||
import type * as api from '../../types/types';
|
||||
import { kBrowserClosedError } from '../common/errors';
|
||||
import { raceAgainstTimeout } from '../utils';
|
||||
import { raceAgainstTimeout } from '../utils/timeoutRunner';
|
||||
import type { Playwright } from './playwright';
|
||||
|
||||
export interface BrowserServerLauncher {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import { createScheme, ValidationError } from '../protocol/validator';
|
|||
import { debugLogger } from '../common/debugLogger';
|
||||
import type { ParsedStackTrace } from '../utils/stackTrace';
|
||||
import { captureRawStack, captureStackTrace } from '../utils/stackTrace';
|
||||
import { isUnderTest, zones } from '../utils';
|
||||
import { isUnderTest } from '../utils';
|
||||
import { zones } from '../utils/zones';
|
||||
import type { ClientInstrumentation } from './clientInstrumentation';
|
||||
import type { Connection } from './connection';
|
||||
import type { Logger } from './types';
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ import type { SelectOption, FilePayload, Rect, SelectOptionOptions } from './typ
|
|||
import fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import path from 'path';
|
||||
import { assert, isString, mkdirIfNeeded } from '../utils';
|
||||
import { assert, isString } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import type * as api from '../../types/types';
|
||||
import type * as structs from '../../types/structs';
|
||||
import type { BrowserContext } from './browserContext';
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import type * as api from '../../types/types';
|
|||
import type { HeadersArray } from '../common/types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import { kBrowserOrContextClosedError } from '../common/errors';
|
||||
import { assert, headersObjectToArray, isFilePayload, isString, mkdirIfNeeded, objectToArray } from '../utils';
|
||||
import { assert, headersObjectToArray, isFilePayload, isString, objectToArray } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { ChannelOwner } from './channelOwner';
|
||||
import * as network from './network';
|
||||
import { RawHeaders } from './network';
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ import type { Headers, RemoteAddr, SecurityDetails, WaitForEventOptions } from '
|
|||
import fs from 'fs';
|
||||
import * as mime from 'mime';
|
||||
import { isString, headersObjectToArray } from '../utils';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { Events } from './events';
|
||||
import type { Page } from './page';
|
||||
import { Waiter } from './waiter';
|
||||
import type * as api from '../../types/types';
|
||||
import type { HeadersArray, URLMatch } from '../common/types';
|
||||
import { urlMatches } from './clientHelper';
|
||||
import { MultiMap } from '../utils';
|
||||
import { MultiMap } from '../utils/multimap';
|
||||
import { APIResponse } from './fetch';
|
||||
|
||||
export type NetworkCookie = {
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ import fs from 'fs';
|
|||
import path from 'path';
|
||||
import type { Size, URLMatch, Headers, LifecycleEvent, WaitForEventOptions, SelectOption, SelectOptionOptions, FilePayload, WaitForFunctionOptions } from './types';
|
||||
import { evaluationScript, urlMatches } from './clientHelper';
|
||||
import { isString, isRegExp, isObject, mkdirIfNeeded, headersObjectToArray } from '../utils';
|
||||
import { isString, isRegExp, isObject, headersObjectToArray } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import { isSafeCloseError } from '../common/errors';
|
||||
import { Video } from './video';
|
||||
import { Artifact } from './artifact';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { IpcTransport } from './protocol/transport';
|
|||
import type { Playwright } from './client/playwright';
|
||||
import * as childProcess from 'child_process';
|
||||
import * as path from 'path';
|
||||
import { ManualPromise } from './utils';
|
||||
import { ManualPromise } from './utils/manualPromise';
|
||||
|
||||
export async function start(env: any = {}): Promise<{ playwright: Playwright, stop: () => Promise<void> }> {
|
||||
const client = new PlaywrightClient(env);
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import os from 'os';
|
|||
import path from 'path';
|
||||
import type * as stream from 'stream';
|
||||
import * as ws from 'ws';
|
||||
import { createGuid, makeWaitForNextTask, removeFolders } from '../../utils';
|
||||
import { createGuid, makeWaitForNextTask } from '../../utils';
|
||||
import { removeFolders } from '../../utils/fileUtils';
|
||||
import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
||||
import type { BrowserContext } from '../browserContext';
|
||||
import { validateBrowserContextOptions } from '../browserContext';
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
import fs from 'fs';
|
||||
import { assert } from '../utils';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { SdkObject } from './instrumentation';
|
||||
|
||||
type SaveCallback = (localPath: string, error?: string) => Promise<void>;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@
|
|||
|
||||
import * as os from 'os';
|
||||
import { TimeoutSettings } from '../common/timeoutSettings';
|
||||
import { debugMode, mkdirIfNeeded, createGuid } from '../utils';
|
||||
import { debugMode, createGuid } from '../utils';
|
||||
import { mkdirIfNeeded } from '../utils/fileUtils';
|
||||
import type { Browser, BrowserOptions } from './browser';
|
||||
import type { Download } from './download';
|
||||
import type * as frames from './frames';
|
||||
|
|
|
|||
|
|
@ -31,7 +31,8 @@ import type { Progress } from './progress';
|
|||
import { ProgressController } from './progress';
|
||||
import type * as types from './types';
|
||||
import { DEFAULT_TIMEOUT, TimeoutSettings } from '../common/timeoutSettings';
|
||||
import { debugMode, existsAsync } from '../utils';
|
||||
import { debugMode } from '../utils';
|
||||
import { existsAsync } from '../utils/fileUtils';
|
||||
import { helper } from './helper';
|
||||
import { RecentLogsCollector } from '../common/debugLogger';
|
||||
import type { CallMetadata } from './instrumentation';
|
||||
|
|
|
|||
|
|
@ -33,7 +33,8 @@ import type * as types from '../types';
|
|||
import type { HTTPRequestParams } from '../../common/netUtils';
|
||||
import { fetchData } from '../../common/netUtils';
|
||||
import { getUserAgent } from '../../common/userAgent';
|
||||
import { debugMode, headersArrayToObject, removeFolders, streamToString, wrapInASCIIBox } from '../../utils';
|
||||
import { debugMode, headersArrayToObject, streamToString, wrapInASCIIBox } from '../../utils';
|
||||
import { removeFolders } from '../../utils/fileUtils';
|
||||
import { RecentLogsCollector } from '../../common/debugLogger';
|
||||
import type { Progress } from '../progress';
|
||||
import { ProgressController } from '../progress';
|
||||
|
|
@ -43,7 +44,7 @@ import type { CallMetadata } from '../instrumentation';
|
|||
import http from 'http';
|
||||
import https from 'https';
|
||||
import { registry } from '../registry';
|
||||
import { ManualPromise } from '../../utils';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
|
||||
const ARTIFACTS_FOLDER = path.join(os.tmpdir(), 'playwright-artifacts-');
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
*/
|
||||
|
||||
import type { CRSession } from './crConnection';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { Protocol } from './protocol';
|
||||
import type * as types from '../types';
|
||||
import { assert } from '../../utils';
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
import type { CRSession } from './crConnection';
|
||||
import type { Page } from '../page';
|
||||
import { helper } from '../helper';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { Protocol } from './protocol';
|
||||
import * as network from '../network';
|
||||
import type * as frames from '../frames';
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
*/
|
||||
|
||||
import path from 'path';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import { registry } from '../registry';
|
||||
import { rewriteErrorMessage } from '../../utils/stackTrace';
|
||||
import { assert, createGuid, headersArrayToObject } from '../../utils';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import type { CRSession } from './crConnection';
|
|||
import type { Protocol } from './protocol';
|
||||
import fs from 'fs';
|
||||
import type * as types from '../types';
|
||||
import { mkdirIfNeeded } from '../../utils';
|
||||
import { mkdirIfNeeded } from '../../utils/fileUtils';
|
||||
import { splitErrorMessage } from '../../utils/stackTrace';
|
||||
|
||||
export function getExceptionMessage(exceptionDetails: Protocol.Runtime.ExceptionDetails): string {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import type { DispatcherScope } from './dispatcher';
|
|||
import { Dispatcher } from './dispatcher';
|
||||
import { StreamDispatcher } from './streamDispatcher';
|
||||
import fs from 'fs';
|
||||
import { mkdirIfNeeded } from '../../utils';
|
||||
import { mkdirIfNeeded } from '../../utils/fileUtils';
|
||||
import type { Artifact } from '../artifact';
|
||||
|
||||
export class ArtifactDispatcher extends Dispatcher<Artifact, channels.ArtifactChannel> implements channels.ArtifactChannel {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import path from 'path';
|
|||
import yauzl from 'yauzl';
|
||||
import yazl from 'yazl';
|
||||
import type * as channels from '../../protocol/channels';
|
||||
import { ManualPromise } from '../../utils';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
import { assert, createGuid } from '../../utils';
|
||||
import type { DispatcherScope } from './dispatcher';
|
||||
import { Dispatcher } from './dispatcher';
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ import type { BrowserWindow } from 'electron';
|
|||
import type { Progress } from '../progress';
|
||||
import { ProgressController } from '../progress';
|
||||
import { helper } from '../helper';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { BrowserOptions, BrowserProcess, PlaywrightOptions } from '../browser';
|
||||
import type * as childProcess from 'child_process';
|
||||
import * as readline from 'readline';
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { FFSession } from './ffConnection';
|
||||
import type { Page } from '../page';
|
||||
import * as network from '../network';
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@
|
|||
import * as dialog from '../dialog';
|
||||
import * as dom from '../dom';
|
||||
import type * as frames from '../frames';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import { assert } from '../../utils';
|
||||
import type { PageBinding, PageDelegate } from '../page';
|
||||
import { Page, Worker } from '../page';
|
||||
|
|
@ -34,7 +34,7 @@ import type { Protocol } from './protocol';
|
|||
import type { Progress } from '../progress';
|
||||
import { splitErrorMessage } from '../../utils/stackTrace';
|
||||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { ManualPromise } from '../../utils';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
|
||||
export const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import type * as channels from '../protocol/channels';
|
|||
import type { ConsoleMessage } from './console';
|
||||
import * as dom from './dom';
|
||||
import { helper } from './helper';
|
||||
import type { RegisteredListener } from '../utils';
|
||||
import { eventsHelper } from '../utils';
|
||||
import type { RegisteredListener } from '../utils/eventsHelper';
|
||||
import { eventsHelper } from '../utils/eventsHelper';
|
||||
import * as js from './javascript';
|
||||
import * as network from './network';
|
||||
import type { Dialog } from './dialog';
|
||||
|
|
@ -30,7 +30,7 @@ import { BrowserContext } from './browserContext';
|
|||
import type { Progress } from './progress';
|
||||
import { ProgressController } from './progress';
|
||||
import { assert, constructURLBasedOnBaseURL, makeWaitForNextTask } from '../utils';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
import type { CallMetadata } from './instrumentation';
|
||||
import { serverSideCallMetadata, SdkObject } from './instrumentation';
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import type { EventEmitter } from 'events';
|
|||
import type * as types from './types';
|
||||
import type { Progress } from './progress';
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
import type { RegisteredListener } from '../utils';
|
||||
import { eventsHelper } from '../utils';
|
||||
import type { RegisteredListener } from '../utils/eventsHelper';
|
||||
import { eventsHelper } from '../utils/eventsHelper';
|
||||
|
||||
class Helper {
|
||||
static completeUserURL(urlString: string): string {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as utilityScriptSource from '../generated/utilityScriptSource';
|
|||
import { serializeAsCallArgument } from './common/utilityScriptSerializers';
|
||||
import { type UtilityScript } from './injected/utilityScript';
|
||||
import { SdkObject } from './instrumentation';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
|
||||
export type ObjectId = string;
|
||||
export type RemoteObject = {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import type * as frames from './frames';
|
|||
import type * as types from './types';
|
||||
import type * as channels from '../protocol/channels';
|
||||
import { assert } from '../utils';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { SdkObject } from './instrumentation';
|
||||
import type { NameValue } from '../common/types';
|
||||
import { APIRequestContext } from './fetch';
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import { FileChooser } from './fileChooser';
|
|||
import type { Progress } from './progress';
|
||||
import { ProgressController } from './progress';
|
||||
import { assert, isError } from '../utils';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import { debugLogger } from '../common/debugLogger';
|
||||
import type { ImageComparatorOptions } from '../utils/comparators';
|
||||
import { getComparator } from '../utils/comparators';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import { assert, monotonicTime } from '../utils';
|
|||
import type { LogName } from '../common/debugLogger';
|
||||
import type { CallMetadata, Instrumentation, SdkObject } from './instrumentation';
|
||||
import type { ElementHandle } from './dom';
|
||||
import { ManualPromise } from '../utils';
|
||||
import { ManualPromise } from '../utils/manualPromise';
|
||||
import type { LogEntry } from './injected/injectedScript';
|
||||
|
||||
export interface Progress {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import fs from 'fs';
|
|||
import os from 'os';
|
||||
import path from 'path';
|
||||
import { getUserAgent } from '../../common/userAgent';
|
||||
import { existsAsync } from '../../utils';
|
||||
import { existsAsync } from '../../utils/fileUtils';
|
||||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { download } from './download';
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@ import path from 'path';
|
|||
import * as os from 'os';
|
||||
import childProcess from 'child_process';
|
||||
import * as utils from '../../utils';
|
||||
import { spawnAsync } from '../../utils/spawnAsync';
|
||||
import { hostPlatform } from '../../utils/hostPlatform';
|
||||
import { buildPlaywrightCLICommand } from '.';
|
||||
import { deps } from './nativeDeps';
|
||||
import { getUbuntuVersion } from '../../utils/ubuntuVersion';
|
||||
|
|
@ -66,7 +68,7 @@ export async function installDependenciesWindows(targets: Set<DependencyGroup>,
|
|||
console.log(`${command} ${quoteProcessArgs(args).join(' ')}`); // eslint-disable-line no-console
|
||||
return;
|
||||
}
|
||||
const { code } = await utils.spawnAsync(command, args, { cwd: BIN_DIRECTORY, stdio: 'inherit' });
|
||||
const { code } = await spawnAsync(command, args, { cwd: BIN_DIRECTORY, stdio: 'inherit' });
|
||||
if (code !== 0)
|
||||
throw new Error('Failed to install windows dependencies!');
|
||||
}
|
||||
|
|
@ -77,7 +79,7 @@ export async function installDependenciesLinux(targets: Set<DependencyGroup>, dr
|
|||
throw new Error(`Unsupported Linux distribution, only Ubuntu is supported!`);
|
||||
const libraries: string[] = [];
|
||||
for (const target of targets) {
|
||||
const info = deps[utils.hostPlatform];
|
||||
const info = deps[hostPlatform];
|
||||
if (!info) {
|
||||
console.warn('Cannot install dependencies for this linux distribution!'); // eslint-disable-line no-console
|
||||
return;
|
||||
|
|
@ -92,7 +94,7 @@ export async function installDependenciesLinux(targets: Set<DependencyGroup>, dr
|
|||
commands.push(['apt-get', 'install', '-y', '--no-install-recommends',
|
||||
...uniqueLibraries,
|
||||
].join(' '));
|
||||
const { command, args, elevatedPermissions } = await utils.transformCommandsForRoot(commands);
|
||||
const { command, args, elevatedPermissions } = await transformCommandsForRoot(commands);
|
||||
if (dryRun) {
|
||||
console.log(`${command} ${quoteProcessArgs(args).join(' ')}`); // eslint-disable-line no-console
|
||||
return;
|
||||
|
|
@ -189,7 +191,7 @@ export async function validateDependenciesLinux(sdkLanguage: string, linuxLddDir
|
|||
const missingPackages = new Set();
|
||||
|
||||
const libraryToPackageNameMapping = {
|
||||
...(deps[utils.hostPlatform]?.lib2package || {}),
|
||||
...(deps[hostPlatform]?.lib2package || {}),
|
||||
...MANUAL_LIBRARY_TO_PACKAGE_NAME_UBUNTU,
|
||||
};
|
||||
// Translate missing dependencies to package names to install with apt.
|
||||
|
|
@ -287,7 +289,7 @@ async function executablesOrSharedLibraries(directoryPath: string): Promise<stri
|
|||
async function missingFileDependenciesWindows(filePath: string): Promise<Array<string>> {
|
||||
const executable = path.join(__dirname, '..', '..', '..', 'bin', 'PrintDeps.exe');
|
||||
const dirname = path.dirname(filePath);
|
||||
const { stdout, code } = await utils.spawnAsync(executable, [filePath], {
|
||||
const { stdout, code } = await spawnAsync(executable, [filePath], {
|
||||
cwd: dirname,
|
||||
env: {
|
||||
...process.env,
|
||||
|
|
@ -305,7 +307,7 @@ async function missingFileDependencies(filePath: string, extraLDPaths: string[])
|
|||
let LD_LIBRARY_PATH = extraLDPaths.join(':');
|
||||
if (process.env.LD_LIBRARY_PATH)
|
||||
LD_LIBRARY_PATH = `${process.env.LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}`;
|
||||
const { stdout, code } = await utils.spawnAsync('ldd', [filePath], {
|
||||
const { stdout, code } = await spawnAsync('ldd', [filePath], {
|
||||
cwd: dirname,
|
||||
env: {
|
||||
...process.env,
|
||||
|
|
@ -324,7 +326,7 @@ async function missingDLOPENLibraries(libraries: string[]): Promise<string[]> {
|
|||
// NOTE: Using full-qualified path to `ldconfig` since `/sbin` is not part of the
|
||||
// default PATH in CRON.
|
||||
// @see https://github.com/microsoft/playwright/issues/3397
|
||||
const { stdout, code, error } = await utils.spawnAsync('/sbin/ldconfig', ['-p'], {});
|
||||
const { stdout, code, error } = await spawnAsync('/sbin/ldconfig', ['-p'], {});
|
||||
if (code !== 0 || error)
|
||||
return [];
|
||||
const isLibraryAvailable = (library: string) => stdout.toLowerCase().includes(library.toLowerCase());
|
||||
|
|
@ -346,3 +348,13 @@ function quoteProcessArgs(args: string[]): string[] {
|
|||
return arg;
|
||||
});
|
||||
}
|
||||
|
||||
export async function transformCommandsForRoot(commands: string[]): Promise<{ command: string, args: string[], elevatedPermissions: boolean}> {
|
||||
const isRoot = process.getuid() === 0;
|
||||
if (isRoot)
|
||||
return { command: 'sh', args: ['-c', `${commands.join('&& ')}`], elevatedPermissions: false };
|
||||
const sudoExists = await spawnAsync('which', ['sudo']);
|
||||
if (sudoExists.code === 0)
|
||||
return { command: 'sudo', args: ['--', 'sh', '-c', `${commands.join('&& ')}`], elevatedPermissions: true };
|
||||
return { command: 'su', args: ['root', '-c', `${commands.join('&& ')}`], elevatedPermissions: true };
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,12 @@ import lockfile from 'proper-lockfile';
|
|||
import { getUbuntuVersion } from '../../utils/ubuntuVersion';
|
||||
import { fetchData } from '../../common/netUtils';
|
||||
import { getClientLanguage } from '../../common/userAgent';
|
||||
import { getFromENV, getAsBooleanFromENV, calculateSha1, removeFolders, existsAsync, hostPlatform, canAccessFile, spawnAsync, wrapInASCIIBox, transformCommandsForRoot } from '../../utils';
|
||||
import { getFromENV, getAsBooleanFromENV, calculateSha1, wrapInASCIIBox } from '../../utils';
|
||||
import { removeFolders, existsAsync, canAccessFile } from '../../utils/fileUtils';
|
||||
import { hostPlatform } from '../../utils/hostPlatform';
|
||||
import { spawnAsync } from '../../utils/spawnAsync';
|
||||
import type { DependencyGroup } from './dependencies';
|
||||
import { transformCommandsForRoot } from './dependencies';
|
||||
import { installDependenciesLinux, installDependenciesWindows, validateDependenciesLinux, validateDependenciesWindows } from './dependencies';
|
||||
import { downloadBrowserWithProgressBar, logPolitely } from './browserFetcher';
|
||||
export { writeDockerVersion } from './dependencies';
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import type { ParsedSelector } from './common/selectorParser';
|
|||
import type * as types from './types';
|
||||
import type { Progress } from './progress';
|
||||
import { assert } from '../utils';
|
||||
import { MultiMap } from '../utils';
|
||||
import { MultiMap } from '../utils/multimap';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
|
|
|||
|
|
@ -22,10 +22,10 @@ import * as network from '../../network';
|
|||
import { Page } from '../../page';
|
||||
import type * as har from './har';
|
||||
import { calculateSha1, monotonicTime } from '../../../utils';
|
||||
import type { RegisteredListener } from '../../../utils';
|
||||
import { eventsHelper } from '../../../utils';
|
||||
import type { RegisteredListener } from '../../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../../utils/eventsHelper';
|
||||
import * as mime from 'mime';
|
||||
import { ManualPromise } from '../../../utils';
|
||||
import { ManualPromise } from '../../../utils/manualPromise';
|
||||
|
||||
const FALLBACK_HTTP_VERSION = 'HTTP/1.1';
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ import { createGuid, monotonicTime } from '../../utils';
|
|||
import { metadataToCallLog } from './recorder/recorderUtils';
|
||||
import { Debugger } from './debugger';
|
||||
import { EventEmitter } from 'events';
|
||||
import { raceAgainstTimeout } from '../../utils';
|
||||
import { raceAgainstTimeout } from '../../utils/timeoutRunner';
|
||||
|
||||
type BindingSource = { frame: Frame, page: Page };
|
||||
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
import { BrowserContext } from '../../browserContext';
|
||||
import { Page } from '../../page';
|
||||
import type { RegisteredListener } from '../../../utils';
|
||||
import { eventsHelper } from '../../../utils';
|
||||
import type { RegisteredListener } from '../../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../../utils/eventsHelper';
|
||||
import { debugLogger } from '../../../common/debugLogger';
|
||||
import type { Frame } from '../../frames';
|
||||
import type { SnapshotData } from './snapshotterInjected';
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ import yazl from 'yazl';
|
|||
import type { NameValue } from '../../../common/types';
|
||||
import type { TracingTracingStopChunkParams } from '../../../protocol/channels';
|
||||
import { commandsWithTracingSnapshots } from '../../../protocol/channels';
|
||||
import { ManualPromise } from '../../../utils';
|
||||
import type { RegisteredListener } from '../../../utils';
|
||||
import { eventsHelper } from '../../../utils';
|
||||
import { assert, calculateSha1, createGuid, mkdirIfNeeded, monotonicTime, removeFolders } from '../../../utils';
|
||||
import { ManualPromise } from '../../../utils/manualPromise';
|
||||
import type { RegisteredListener } from '../../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../../utils/eventsHelper';
|
||||
import { assert, calculateSha1, createGuid, monotonicTime } from '../../../utils';
|
||||
import { mkdirIfNeeded, removeFolders } from '../../../utils/fileUtils';
|
||||
import { Artifact } from '../../artifact';
|
||||
import { BrowserContext } from '../../browserContext';
|
||||
import { ElementHandle } from '../../dom';
|
||||
|
|
|
|||
|
|
@ -18,8 +18,9 @@
|
|||
import type { BrowserOptions } from '../browser';
|
||||
import { Browser } from '../browser';
|
||||
import { assertBrowserContextIsNotOwned, BrowserContext, verifyGeolocation } from '../browserContext';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { assert, eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { assert } from '../../utils';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import * as network from '../network';
|
||||
import type { Page, PageBinding, PageDelegate } from '../page';
|
||||
import type { ConnectionTransport } from '../transport';
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import type * as types from '../types';
|
|||
import type { Protocol } from './protocol';
|
||||
import type { WKSession } from './wkConnection';
|
||||
import { assert, headersObjectToArray, headersArrayToObject } from '../../utils';
|
||||
import { ManualPromise } from '../../utils';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
|
||||
const errorReasons: { [reason: string]: Protocol.Network.ResourceErrorType } = {
|
||||
'aborted': 'Cancellation',
|
||||
|
|
|
|||
|
|
@ -19,13 +19,14 @@ import * as jpeg from 'jpeg-js';
|
|||
import path from 'path';
|
||||
import * as png from 'pngjs';
|
||||
import { splitErrorMessage } from '../../utils/stackTrace';
|
||||
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray, hostPlatform } from '../../utils';
|
||||
import { assert, createGuid, debugAssert, headersArrayToObject, headersObjectToArray } from '../../utils';
|
||||
import { hostPlatform } from '../../utils/hostPlatform';
|
||||
import type * as accessibility from '../accessibility';
|
||||
import * as dialog from '../dialog';
|
||||
import * as dom from '../dom';
|
||||
import type * as frames from '../frames';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import { helper } from '../helper';
|
||||
import type { JSHandle } from '../javascript';
|
||||
import * as network from '../network';
|
||||
|
|
@ -43,7 +44,7 @@ import { WKInterceptableRequest, WKRouteImpl } from './wkInterceptableRequest';
|
|||
import { WKProvisionalPage } from './wkProvisionalPage';
|
||||
import { WKWorkers } from './wkWorkers';
|
||||
import { debugLogger } from '../../common/debugLogger';
|
||||
import { ManualPromise } from '../../utils';
|
||||
import { ManualPromise } from '../../utils/manualPromise';
|
||||
|
||||
const UTILITY_WORLD_NAME = '__playwright_utility_world__';
|
||||
const BINDING_CALL_MESSAGE = '__playwright_binding_call__';
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@
|
|||
|
||||
import type { WKSession } from './wkConnection';
|
||||
import type { WKPage } from './wkPage';
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { Protocol } from './protocol';
|
||||
import { assert } from '../../utils';
|
||||
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { RegisteredListener } from '../../utils';
|
||||
import { eventsHelper } from '../../utils';
|
||||
import type { RegisteredListener } from '../../utils/eventsHelper';
|
||||
import { eventsHelper } from '../../utils/eventsHelper';
|
||||
import type { Page } from '../page';
|
||||
import { Worker } from '../page';
|
||||
import type { Protocol } from './protocol';
|
||||
|
|
|
|||
48
packages/playwright-core/src/utils/fileUtils.ts
Normal file
48
packages/playwright-core/src/utils/fileUtils.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import removeFolder from 'rimraf';
|
||||
|
||||
export const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
|
||||
export async function mkdirIfNeeded(filePath: string) {
|
||||
// This will harmlessly throw on windows if the dirname is the root directory.
|
||||
await fs.promises.mkdir(path.dirname(filePath), { recursive: true }).catch(() => {});
|
||||
}
|
||||
|
||||
export async function removeFolders(dirs: string[]): Promise<Array<Error|null|undefined>> {
|
||||
return await Promise.all(dirs.map((dir: string) => {
|
||||
return new Promise<Error|null|undefined>(fulfill => {
|
||||
removeFolder(dir, { maxBusyTries: 10 }, error => {
|
||||
fulfill(error ?? undefined);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
export function canAccessFile(file: string) {
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
try {
|
||||
fs.accessSync(file);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
66
packages/playwright-core/src/utils/hostPlatform.ts
Normal file
66
packages/playwright-core/src/utils/hostPlatform.ts
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import os from 'os';
|
||||
import { getUbuntuVersionSync } from './ubuntuVersion';
|
||||
|
||||
export type HostPlatform = 'win64' |
|
||||
'mac10.13' |
|
||||
'mac10.14' |
|
||||
'mac10.15' |
|
||||
'mac11' | 'mac11-arm64' |
|
||||
'mac12' | 'mac12-arm64' |
|
||||
'ubuntu18.04' | 'ubuntu18.04-arm64' |
|
||||
'ubuntu20.04' | 'ubuntu20.04-arm64' |
|
||||
'generic-linux' | 'generic-linux-arm64' |
|
||||
'<unknown>';
|
||||
|
||||
export const hostPlatform = ((): HostPlatform => {
|
||||
const platform = os.platform();
|
||||
if (platform === 'darwin') {
|
||||
const ver = os.release().split('.').map((a: string) => parseInt(a, 10));
|
||||
let macVersion = '';
|
||||
if (ver[0] < 18) {
|
||||
// Everything before 10.14 is considered 10.13.
|
||||
macVersion = 'mac10.13';
|
||||
} else if (ver[0] === 18) {
|
||||
macVersion = 'mac10.14';
|
||||
} else if (ver[0] === 19) {
|
||||
macVersion = 'mac10.15';
|
||||
} else {
|
||||
// ver[0] >= 20
|
||||
const LAST_STABLE_MAC_MAJOR_VERSION = 12;
|
||||
// Best-effort support for MacOS beta versions.
|
||||
macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MAC_MAJOR_VERSION);
|
||||
// BigSur is the first version that might run on Apple Silicon.
|
||||
if (os.cpus().some(cpu => cpu.model.includes('Apple')))
|
||||
macVersion += '-arm64';
|
||||
}
|
||||
return macVersion as HostPlatform;
|
||||
}
|
||||
if (platform === 'linux') {
|
||||
const archSuffix = os.arch() === 'arm64' ? '-arm64' : '';
|
||||
const ubuntuVersion = getUbuntuVersionSync();
|
||||
if (!ubuntuVersion)
|
||||
return ('generic-linux' + archSuffix) as HostPlatform;
|
||||
if (parseInt(ubuntuVersion, 10) <= 19)
|
||||
return ('ubuntu18.04' + archSuffix) as HostPlatform;
|
||||
return ('ubuntu20.04' + archSuffix) as HostPlatform;
|
||||
}
|
||||
if (platform === 'win32')
|
||||
return 'win64';
|
||||
return '<unknown>';
|
||||
})();
|
||||
|
|
@ -14,41 +14,14 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SpawnOptions } from 'child_process';
|
||||
import { spawn } from 'child_process';
|
||||
import * as crypto from 'crypto';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
import removeFolder from 'rimraf';
|
||||
import type stream from 'stream';
|
||||
import * as URL from 'url';
|
||||
import type { NameValue } from '../protocol/channels';
|
||||
import { getUbuntuVersionSync } from './ubuntuVersion';
|
||||
|
||||
export { eventsHelper } from './eventsHelper';
|
||||
export type { RegisteredListener } from './eventsHelper';
|
||||
export { ManualPromise } from './manualPromise';
|
||||
export { MultiMap } from './multimap';
|
||||
export { raceAgainstTimeout, TimeoutRunner, TimeoutRunnerError } from './timeoutRunner';
|
||||
export { zones } from './zones';
|
||||
|
||||
export const existsAsync = (path: string): Promise<boolean> => new Promise(resolve => fs.stat(path, err => resolve(!err)));
|
||||
|
||||
export function spawnAsync(cmd: string, args: string[], options: SpawnOptions = {}): Promise<{stdout: string, stderr: string, code: number | null, error?: Error}> {
|
||||
const process = spawn(cmd, args, Object.assign({ windowsHide: true }, options));
|
||||
|
||||
return new Promise(resolve => {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
if (process.stdout)
|
||||
process.stdout.on('data', data => stdout += data);
|
||||
if (process.stderr)
|
||||
process.stderr.on('data', data => stderr += data);
|
||||
process.on('close', code => resolve({ stdout, stderr, code }));
|
||||
process.on('error', error => resolve({ stdout, stderr, code: 0, error }));
|
||||
});
|
||||
}
|
||||
type NameValue = {
|
||||
name: string,
|
||||
value: string,
|
||||
};
|
||||
|
||||
// See https://joel.tools/microtasks/
|
||||
export function makeWaitForNextTask() {
|
||||
|
|
@ -149,11 +122,6 @@ export function getAsBooleanFromENV(name: string): boolean {
|
|||
return !!value && value !== 'false' && value !== '0';
|
||||
}
|
||||
|
||||
export async function mkdirIfNeeded(filePath: string) {
|
||||
// This will harmlessly throw on windows if the dirname is the root directory.
|
||||
await fs.promises.mkdir(path.dirname(filePath), { recursive: true }).catch(() => {});
|
||||
}
|
||||
|
||||
type HeadersArray = { name: string, value: string }[];
|
||||
type HeadersObject = { [key: string]: string };
|
||||
|
||||
|
|
@ -214,28 +182,6 @@ export function createGuid(): string {
|
|||
return crypto.randomBytes(16).toString('hex');
|
||||
}
|
||||
|
||||
export async function removeFolders(dirs: string[]): Promise<Array<Error|null|undefined>> {
|
||||
return await Promise.all(dirs.map((dir: string) => {
|
||||
return new Promise<Error|null|undefined>(fulfill => {
|
||||
removeFolder(dir, { maxBusyTries: 10 }, error => {
|
||||
fulfill(error ?? undefined);
|
||||
});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
export function canAccessFile(file: string) {
|
||||
if (!file)
|
||||
return false;
|
||||
|
||||
try {
|
||||
fs.accessSync(file);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function constructURLBasedOnBaseURL(baseURL: string | undefined, givenURL: string): string {
|
||||
try {
|
||||
return (new URL.URL(givenURL, baseURL)).toString();
|
||||
|
|
@ -244,54 +190,6 @@ export function constructURLBasedOnBaseURL(baseURL: string | undefined, givenURL
|
|||
}
|
||||
}
|
||||
|
||||
export type HostPlatform = 'win64' |
|
||||
'mac10.13' |
|
||||
'mac10.14' |
|
||||
'mac10.15' |
|
||||
'mac11' | 'mac11-arm64' |
|
||||
'mac12' | 'mac12-arm64' |
|
||||
'ubuntu18.04' | 'ubuntu18.04-arm64' |
|
||||
'ubuntu20.04' | 'ubuntu20.04-arm64' |
|
||||
'generic-linux' | 'generic-linux-arm64' |
|
||||
'<unknown>';
|
||||
|
||||
export const hostPlatform = ((): HostPlatform => {
|
||||
const platform = os.platform();
|
||||
if (platform === 'darwin') {
|
||||
const ver = os.release().split('.').map((a: string) => parseInt(a, 10));
|
||||
let macVersion = '';
|
||||
if (ver[0] < 18) {
|
||||
// Everything before 10.14 is considered 10.13.
|
||||
macVersion = 'mac10.13';
|
||||
} else if (ver[0] === 18) {
|
||||
macVersion = 'mac10.14';
|
||||
} else if (ver[0] === 19) {
|
||||
macVersion = 'mac10.15';
|
||||
} else {
|
||||
// ver[0] >= 20
|
||||
const LAST_STABLE_MAC_MAJOR_VERSION = 12;
|
||||
// Best-effort support for MacOS beta versions.
|
||||
macVersion = 'mac' + Math.min(ver[0] - 9, LAST_STABLE_MAC_MAJOR_VERSION);
|
||||
// BigSur is the first version that might run on Apple Silicon.
|
||||
if (os.cpus().some(cpu => cpu.model.includes('Apple')))
|
||||
macVersion += '-arm64';
|
||||
}
|
||||
return macVersion as HostPlatform;
|
||||
}
|
||||
if (platform === 'linux') {
|
||||
const archSuffix = os.arch() === 'arm64' ? '-arm64' : '';
|
||||
const ubuntuVersion = getUbuntuVersionSync();
|
||||
if (!ubuntuVersion)
|
||||
return ('generic-linux' + archSuffix) as HostPlatform;
|
||||
if (parseInt(ubuntuVersion, 10) <= 19)
|
||||
return ('ubuntu18.04' + archSuffix) as HostPlatform;
|
||||
return ('ubuntu20.04' + archSuffix) as HostPlatform;
|
||||
}
|
||||
if (platform === 'win32')
|
||||
return 'win64';
|
||||
return '<unknown>';
|
||||
})();
|
||||
|
||||
export function wrapInASCIIBox(text: string, padding = 0): string {
|
||||
const lines = text.split('\n');
|
||||
const maxLength = Math.max(...lines.map(line => line.length));
|
||||
|
|
@ -314,56 +212,3 @@ export function streamToString(stream: stream.Readable): Promise<string> {
|
|||
stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
|
||||
});
|
||||
}
|
||||
|
||||
export async function transformCommandsForRoot(commands: string[]): Promise<{ command: string, args: string[], elevatedPermissions: boolean}> {
|
||||
const isRoot = process.getuid() === 0;
|
||||
if (isRoot)
|
||||
return { command: 'sh', args: ['-c', `${commands.join('&& ')}`], elevatedPermissions: false };
|
||||
const sudoExists = await spawnAsync('which', ['sudo']);
|
||||
if (sudoExists.code === 0)
|
||||
return { command: 'sudo', args: ['--', 'sh', '-c', `${commands.join('&& ')}`], elevatedPermissions: true };
|
||||
return { command: 'su', args: ['root', '-c', `${commands.join('&& ')}`], elevatedPermissions: true };
|
||||
}
|
||||
|
||||
export class SigIntWatcher {
|
||||
private _hadSignal: boolean = false;
|
||||
private _sigintPromise: Promise<void>;
|
||||
private _sigintHandler: () => void;
|
||||
constructor() {
|
||||
let sigintCallback: () => void;
|
||||
this._sigintPromise = new Promise<void>(f => sigintCallback = f);
|
||||
this._sigintHandler = () => {
|
||||
// We remove the handler so that second Ctrl+C immediately kills the runner
|
||||
// via the default sigint handler. This is handy in the case where our shutdown
|
||||
// takes a lot of time or is buggy.
|
||||
//
|
||||
// When running through NPM we might get multiple SIGINT signals
|
||||
// for a single Ctrl+C - this is an NPM bug present since at least NPM v6.
|
||||
// https://github.com/npm/cli/issues/1591
|
||||
// https://github.com/npm/cli/issues/2124
|
||||
//
|
||||
// Therefore, removing the handler too soon will just kill the process
|
||||
// with default handler without printing the results.
|
||||
// We work around this by giving NPM 1000ms to send us duplicate signals.
|
||||
// The side effect is that slow shutdown or bug in our runner will force
|
||||
// the user to hit Ctrl+C again after at least a second.
|
||||
setTimeout(() => process.off('SIGINT', this._sigintHandler), 1000);
|
||||
this._hadSignal = true;
|
||||
sigintCallback();
|
||||
};
|
||||
process.on('SIGINT', this._sigintHandler);
|
||||
}
|
||||
|
||||
promise(): Promise<void> {
|
||||
return this._sigintPromise;
|
||||
}
|
||||
|
||||
hadSignal(): boolean {
|
||||
return this._hadSignal;
|
||||
}
|
||||
|
||||
disarm() {
|
||||
process.off('SIGINT', this._sigintHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,8 @@
|
|||
import * as childProcess from 'child_process';
|
||||
import * as readline from 'readline';
|
||||
import { eventsHelper } from './eventsHelper';
|
||||
import { isUnderTest, removeFolders } from './';
|
||||
import { isUnderTest } from './';
|
||||
import { removeFolders } from './fileUtils';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
export type Env = {[key: string]: string | number | boolean | undefined};
|
||||
|
|
|
|||
33
packages/playwright-core/src/utils/spawnAsync.ts
Normal file
33
packages/playwright-core/src/utils/spawnAsync.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import type { SpawnOptions } from 'child_process';
|
||||
import { spawn } from 'child_process';
|
||||
|
||||
export function spawnAsync(cmd: string, args: string[], options: SpawnOptions = {}): Promise<{stdout: string, stderr: string, code: number | null, error?: Error}> {
|
||||
const process = spawn(cmd, args, Object.assign({ windowsHide: true }, options));
|
||||
|
||||
return new Promise(resolve => {
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
if (process.stdout)
|
||||
process.stdout.on('data', data => stdout += data);
|
||||
if (process.stderr)
|
||||
process.stderr.on('data', data => stderr += data);
|
||||
process.on('close', code => resolve({ stdout, stderr, code }));
|
||||
process.on('error', error => resolve({ stdout, stderr, code: 0, error }));
|
||||
});
|
||||
}
|
||||
|
|
@ -13,7 +13,8 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { createGuid, spawnAsync } from 'playwright-core/lib/utils';
|
||||
import { createGuid } from 'playwright-core/lib/utils';
|
||||
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
||||
|
||||
const GIT_OPERATIONS_TIMEOUT_MS = 1500;
|
||||
const kContentTypePlainText = 'text/plain';
|
||||
|
|
|
|||
|
|
@ -29,7 +29,8 @@ import type { FilePatternFilter } from './util';
|
|||
import { showHTMLReport } from './reporters/html';
|
||||
import { GridServer } from 'playwright-core/lib/grid/gridServer';
|
||||
import dockerFactory from 'playwright-core/lib/grid/dockerGridFactory';
|
||||
import { createGuid, hostPlatform } from 'playwright-core/lib/utils';
|
||||
import { createGuid } from 'playwright-core/lib/utils';
|
||||
import { hostPlatform } from 'playwright-core/lib/utils/hostPlatform';
|
||||
import { fileIsModule } from './loader';
|
||||
|
||||
const defaultTimeout = 30000;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import type { RunPayload, TestBeginPayload, TestEndPayload, DonePayload, TestOut
|
|||
import type { TestResult, Reporter, TestStep, TestError } from '../types/testReporter';
|
||||
import type { Suite, TestCase } from './test';
|
||||
import type { Loader } from './loader';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils/manualPromise';
|
||||
|
||||
export type TestGroup = {
|
||||
workerHash: string;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
import expectLibrary from 'expect';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils/timeoutRunner';
|
||||
import path from 'path';
|
||||
import {
|
||||
INVERTED_COLOR,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
import { formatLocation, debugTest } from './util';
|
||||
import * as crypto from 'crypto';
|
||||
import type { FixturesWithLocation, Location, WorkerInfo } from './types';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils/manualPromise';
|
||||
import type { TestInfoImpl } from './testInfo';
|
||||
import type { FixtureDescription, TimeoutManager } from './timeoutManager';
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ import * as path from 'path';
|
|||
import type { LaunchOptions, BrowserContextOptions, Page, BrowserContext, Video, APIRequestContext, Tracing } from 'playwright-core';
|
||||
import type { TestType, PlaywrightTestArgs, PlaywrightTestOptions, PlaywrightWorkerArgs, PlaywrightWorkerOptions, TestInfo } from '../types/test';
|
||||
import { rootTestType } from './testType';
|
||||
import { createGuid, removeFolders, debugMode } from 'playwright-core/lib/utils';
|
||||
import { createGuid, debugMode } from 'playwright-core/lib/utils';
|
||||
import { removeFolders } from 'playwright-core/lib/utils/fileUtils';
|
||||
import { GridClient } from 'playwright-core/lib/grid/gridClient';
|
||||
export { expect } from './expect';
|
||||
export const _baseTest: TestType<{}, {}> = rootTestType.test;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ import type { TransformCallback } from 'stream';
|
|||
import { Transform } from 'stream';
|
||||
import type { FullConfig, Suite, Reporter } from '../../types/testReporter';
|
||||
import { HttpServer } from 'playwright-core/lib/utils/httpServer';
|
||||
import { assert, calculateSha1, removeFolders } from 'playwright-core/lib/utils';
|
||||
import { assert, calculateSha1 } from 'playwright-core/lib/utils';
|
||||
import { removeFolders } from 'playwright-core/lib/utils/fileUtils';
|
||||
import type { JsonAttachment, JsonReport, JsonSuite, JsonTestCase, JsonTestResult, JsonTestStep } from './raw';
|
||||
import RawReporter from './raw';
|
||||
import yazl from 'yazl';
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import { assert, calculateSha1 } from 'playwright-core/lib/utils';
|
|||
import { sanitizeForFilePath } from '../util';
|
||||
import { formatResultFailure } from './base';
|
||||
import { toPosixPath, serializePatterns } from './json';
|
||||
import { MultiMap } from 'playwright-core/lib/utils';
|
||||
import { MultiMap } from 'playwright-core/lib/utils/multimap';
|
||||
import { codeFrameColumns } from '@babel/code-frame';
|
||||
import type { FullConfigInternal } from '../types';
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ import { Minimatch } from 'minimatch';
|
|||
import type { Config } from './types';
|
||||
import type { FullConfigInternal } from './types';
|
||||
import { WebServer } from './webServer';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils';
|
||||
import { SigIntWatcher } from 'playwright-core/lib/utils';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils/timeoutRunner';
|
||||
import { SigIntWatcher } from './sigIntWatcher';
|
||||
|
||||
const removeFolderAsync = promisify(rimraf);
|
||||
const readDirAsync = promisify(fs.readdir);
|
||||
|
|
|
|||
57
packages/playwright-test/src/sigIntWatcher.ts
Normal file
57
packages/playwright-test/src/sigIntWatcher.ts
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* Copyright (c) Microsoft Corporation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export class SigIntWatcher {
|
||||
private _hadSignal: boolean = false;
|
||||
private _sigintPromise: Promise<void>;
|
||||
private _sigintHandler: () => void;
|
||||
constructor() {
|
||||
let sigintCallback: () => void;
|
||||
this._sigintPromise = new Promise<void>(f => sigintCallback = f);
|
||||
this._sigintHandler = () => {
|
||||
// We remove the handler so that second Ctrl+C immediately kills the runner
|
||||
// via the default sigint handler. This is handy in the case where our shutdown
|
||||
// takes a lot of time or is buggy.
|
||||
//
|
||||
// When running through NPM we might get multiple SIGINT signals
|
||||
// for a single Ctrl+C - this is an NPM bug present since at least NPM v6.
|
||||
// https://github.com/npm/cli/issues/1591
|
||||
// https://github.com/npm/cli/issues/2124
|
||||
//
|
||||
// Therefore, removing the handler too soon will just kill the process
|
||||
// with default handler without printing the results.
|
||||
// We work around this by giving NPM 1000ms to send us duplicate signals.
|
||||
// The side effect is that slow shutdown or bug in our runner will force
|
||||
// the user to hit Ctrl+C again after at least a second.
|
||||
setTimeout(() => process.off('SIGINT', this._sigintHandler), 1000);
|
||||
this._hadSignal = true;
|
||||
sigintCallback();
|
||||
};
|
||||
process.on('SIGINT', this._sigintHandler);
|
||||
}
|
||||
|
||||
promise(): Promise<void> {
|
||||
return this._sigintPromise;
|
||||
}
|
||||
|
||||
hadSignal(): boolean {
|
||||
return this._hadSignal;
|
||||
}
|
||||
|
||||
disarm() {
|
||||
process.off('SIGINT', this._sigintHandler);
|
||||
}
|
||||
}
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
import colors from 'colors/safe';
|
||||
import { TimeoutRunner, TimeoutRunnerError } from 'playwright-core/lib/utils';
|
||||
import { TimeoutRunner, TimeoutRunnerError } from 'playwright-core/lib/utils/timeoutRunner';
|
||||
import type { TestError } from '../types/test';
|
||||
import type { Location } from './types';
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import http from 'http';
|
|||
import https from 'https';
|
||||
import net from 'net';
|
||||
import debug from 'debug';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils';
|
||||
import { raceAgainstTimeout } from 'playwright-core/lib/utils/timeoutRunner';
|
||||
import type { WebServerConfig } from './types';
|
||||
import { launchProcess } from 'playwright-core/lib/utils/processLauncher';
|
||||
import type { Reporter } from '../types/testReporter';
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import type { Suite, TestCase } from './test';
|
|||
import type { Annotation, TestError, TestStepInternal } from './types';
|
||||
import type { ProjectImpl } from './project';
|
||||
import { FixtureRunner } from './fixtures';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils';
|
||||
import { ManualPromise } from 'playwright-core/lib/utils/manualPromise';
|
||||
import { TestInfoImpl } from './testInfo';
|
||||
import type { TimeSlot } from './timeoutManager';
|
||||
import { TimeoutManager } from './timeoutManager';
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ import * as os from 'os';
|
|||
import type { PageTestFixtures, PageWorkerFixtures } from '../page/pageTestApi';
|
||||
import * as path from 'path';
|
||||
import type { BrowserContext, BrowserContextOptions, BrowserType, Page } from 'playwright-core';
|
||||
import { removeFolders } from '../../packages/playwright-core/lib/utils';
|
||||
import { removeFolders } from '../../packages/playwright-core/lib/utils/fileUtils';
|
||||
import { baseTest } from './baseTest';
|
||||
import type { RemoteServerOptions } from './remoteServer';
|
||||
import { RemoteServer } from './remoteServer';
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import fs from 'fs';
|
|||
import { test as baseTest, expect, createImage } from './playwright-test-fixtures';
|
||||
import type { HttpServer } from '../../packages/playwright-core/lib/utils/httpServer';
|
||||
import { startHtmlReportServer } from '../../packages/playwright-test/lib/reporters/html';
|
||||
import { spawnAsync } from 'playwright-core/lib/utils';
|
||||
import { spawnAsync } from 'playwright-core/lib/utils/spawnAsync';
|
||||
|
||||
const test = baseTest.extend<{ showReport: () => Promise<void> }>({
|
||||
showReport: async ({ page }, use, testInfo) => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue