Best JavaScript code snippet using playwright-internal
index.js
Source:index.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.Registry = void 0;6exports.buildPlaywrightCLICommand = buildPlaywrightCLICommand;7exports.findChromiumChannel = findChromiumChannel;8exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;9exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;10exports.registryDirectory = exports.registry = void 0;11Object.defineProperty(exports, "writeDockerVersion", {12 enumerable: true,13 get: function () {14 return _dependencies.writeDockerVersion;15 }16});17var os = _interopRequireWildcard(require("os"));18var _path = _interopRequireDefault(require("path"));19var util = _interopRequireWildcard(require("util"));20var fs = _interopRequireWildcard(require("fs"));21var _properLockfile = _interopRequireDefault(require("proper-lockfile"));22var _ubuntuVersion = require("../../utils/ubuntuVersion");23var _netUtils = require("../../common/netUtils");24var _userAgent = require("../../common/userAgent");25var _utils = require("../../utils");26var _fileUtils = require("../../utils/fileUtils");27var _hostPlatform = require("../../utils/hostPlatform");28var _spawnAsync = require("../../utils/spawnAsync");29var _dependencies = require("./dependencies");30var _browserFetcher = require("./browserFetcher");31function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }32function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }33function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }34/**35 * Copyright 2017 Google Inc. All rights reserved.36 * Modifications copyright (c) Microsoft Corporation.37 *38 * Licensed under the Apache License, Version 2.0 (the "License");39 * you may not use this file except in compliance with the License.40 * You may obtain a copy of the License at41 *42 * http://www.apache.org/licenses/LICENSE-2.043 *44 * Unless required by applicable law or agreed to in writing, software45 * distributed under the License is distributed on an "AS IS" BASIS,46 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.47 * See the License for the specific language governing permissions and48 * limitations under the License.49 */50const PACKAGE_PATH = _path.default.join(__dirname, '..', '..', '..');51const BIN_PATH = _path.default.join(__dirname, '..', '..', '..', 'bin');52const EXECUTABLE_PATHS = {53 'chromium': {54 'linux': ['chrome-linux', 'chrome'],55 'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],56 'win': ['chrome-win', 'chrome.exe']57 },58 'firefox': {59 'linux': ['firefox', 'firefox'],60 'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],61 'win': ['firefox', 'firefox.exe']62 },63 'webkit': {64 'linux': ['pw_run.sh'],65 'mac': ['pw_run.sh'],66 'win': ['Playwright.exe']67 },68 'ffmpeg': {69 'linux': ['ffmpeg-linux'],70 'mac': ['ffmpeg-mac'],71 'win': ['ffmpeg-win64.exe']72 }73};74const DOWNLOAD_PATHS = {75 'chromium': {76 '<unknown>': undefined,77 'generic-linux': 'builds/chromium/%s/chromium-linux.zip',78 'generic-linux-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',79 'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',80 'ubuntu20.04': 'builds/chromium/%s/chromium-linux.zip',81 'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',82 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',83 'mac10.13': 'builds/chromium/%s/chromium-mac.zip',84 'mac10.14': 'builds/chromium/%s/chromium-mac.zip',85 'mac10.15': 'builds/chromium/%s/chromium-mac.zip',86 'mac11': 'builds/chromium/%s/chromium-mac.zip',87 'mac11-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',88 'mac12': 'builds/chromium/%s/chromium-mac.zip',89 'mac12-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',90 'win64': 'builds/chromium/%s/chromium-win64.zip'91 },92 'chromium-with-symbols': {93 '<unknown>': undefined,94 'generic-linux': 'builds/chromium/%s/chromium-with-symbols-linux.zip',95 'generic-linux-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',96 'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',97 'ubuntu20.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',98 'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',99 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',100 'mac10.13': 'builds/chromium/%s/chromium-with-symbols-mac.zip',101 'mac10.14': 'builds/chromium/%s/chromium-with-symbols-mac.zip',102 'mac10.15': 'builds/chromium/%s/chromium-with-symbols-mac.zip',103 'mac11': 'builds/chromium/%s/chromium-with-symbols-mac.zip',104 'mac11-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',105 'mac12': 'builds/chromium/%s/chromium-with-symbols-mac.zip',106 'mac12-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',107 'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip'108 },109 'firefox': {110 '<unknown>': undefined,111 'generic-linux': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',112 'generic-linux-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',113 'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',114 'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',115 'ubuntu18.04-arm64': undefined,116 'ubuntu20.04-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',117 'mac10.13': 'builds/firefox/%s/firefox-mac-11.zip',118 'mac10.14': 'builds/firefox/%s/firefox-mac-11.zip',119 'mac10.15': 'builds/firefox/%s/firefox-mac-11.zip',120 'mac11': 'builds/firefox/%s/firefox-mac-11.zip',121 'mac11-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',122 'mac12': 'builds/firefox/%s/firefox-mac-11.zip',123 'mac12-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',124 'win64': 'builds/firefox/%s/firefox-win64.zip'125 },126 'firefox-beta': {127 '<unknown>': undefined,128 'generic-linux': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',129 'generic-linux-arm64': undefined,130 'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',131 'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',132 'ubuntu18.04-arm64': undefined,133 'ubuntu20.04-arm64': undefined,134 'mac10.13': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',135 'mac10.14': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',136 'mac10.15': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',137 'mac11': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',138 'mac11-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',139 'mac12': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',140 'mac12-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',141 'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip'142 },143 'webkit': {144 '<unknown>': undefined,145 'generic-linux': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',146 'generic-linux-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',147 'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',148 'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',149 'ubuntu18.04-arm64': undefined,150 'ubuntu20.04-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',151 'mac10.13': undefined,152 'mac10.14': 'builds/deprecated-webkit-mac-10.14/%s/deprecated-webkit-mac-10.14.zip',153 'mac10.15': 'builds/webkit/%s/webkit-mac-10.15.zip',154 'mac11': 'builds/webkit/%s/webkit-mac-11.zip',155 'mac11-arm64': 'builds/webkit/%s/webkit-mac-11-arm64.zip',156 'mac12': 'builds/webkit/%s/webkit-mac-12.zip',157 'mac12-arm64': 'builds/webkit/%s/webkit-mac-12-arm64.zip',158 'win64': 'builds/webkit/%s/webkit-win64.zip'159 },160 'ffmpeg': {161 '<unknown>': undefined,162 'generic-linux': 'builds/ffmpeg/%s/ffmpeg-linux.zip',163 'generic-linux-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',164 'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',165 'ubuntu20.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',166 'ubuntu18.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',167 'ubuntu20.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',168 'mac10.13': 'builds/ffmpeg/%s/ffmpeg-mac.zip',169 'mac10.14': 'builds/ffmpeg/%s/ffmpeg-mac.zip',170 'mac10.15': 'builds/ffmpeg/%s/ffmpeg-mac.zip',171 'mac11': 'builds/ffmpeg/%s/ffmpeg-mac.zip',172 'mac11-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',173 'mac12': 'builds/ffmpeg/%s/ffmpeg-mac.zip',174 'mac12-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',175 'win64': 'builds/ffmpeg/%s/ffmpeg-win64.zip'176 }177};178const registryDirectory = (() => {179 let result;180 const envDefined = (0, _utils.getFromENV)('PLAYWRIGHT_BROWSERS_PATH');181 if (envDefined === '0') {182 result = _path.default.join(__dirname, '..', '..', '..', '.local-browsers');183 } else if (envDefined) {184 result = envDefined;185 } else {186 let cacheDirectory;187 if (process.platform === 'linux') cacheDirectory = process.env.XDG_CACHE_HOME || _path.default.join(os.homedir(), '.cache');else if (process.platform === 'darwin') cacheDirectory = _path.default.join(os.homedir(), 'Library', 'Caches');else if (process.platform === 'win32') cacheDirectory = process.env.LOCALAPPDATA || _path.default.join(os.homedir(), 'AppData', 'Local');else throw new Error('Unsupported platform: ' + process.platform);188 result = _path.default.join(cacheDirectory, 'ms-playwright');189 }190 if (!_path.default.isAbsolute(result)) {191 // It is important to resolve to the absolute path:192 // - for unzipping to work correctly;193 // - so that registry directory matches between installation and execution.194 // INIT_CWD points to the root of `npm/yarn install` and is probably what195 // the user meant when typing the relative path.196 result = _path.default.resolve((0, _utils.getFromENV)('INIT_CWD') || process.cwd(), result);197 }198 return result;199})();200exports.registryDirectory = registryDirectory;201function isBrowserDirectory(browserDirectory) {202 const baseName = _path.default.basename(browserDirectory);203 for (const browserName of allDownloadable) {204 if (baseName.startsWith(browserName + '-')) return true;205 }206 return false;207}208function readDescriptors(browsersJSON) {209 return browsersJSON['browsers'].map(obj => {210 const name = obj.name;211 const revisionOverride = (obj.revisionOverrides || {})[_hostPlatform.hostPlatform];212 const revision = revisionOverride || obj.revision;213 const browserDirectoryPrefix = revisionOverride ? `${name}_${_hostPlatform.hostPlatform}_special` : `${name}`;214 const descriptor = {215 name,216 revision,217 installByDefault: !!obj.installByDefault,218 // Method `isBrowserDirectory` determines directory to be browser iff219 // it starts with some browser name followed by '-'. Some browser names220 // are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.221 // To avoid older registries erroneously removing 'webkit-technology-preview', we have to222 // ensure that browser folders to never include dashes inside.223 dir: _path.default.join(registryDirectory, browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision)224 };225 return descriptor;226 });227}228const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-with-symbols'];229class Registry {230 constructor(browsersJSON) {231 this._executables = void 0;232 const descriptors = readDescriptors(browsersJSON);233 const findExecutablePath = (dir, name) => {234 let tokens = undefined;235 if (_hostPlatform.hostPlatform.startsWith('ubuntu') || _hostPlatform.hostPlatform.startsWith('generic-linux')) tokens = EXECUTABLE_PATHS[name]['linux'];else if (_hostPlatform.hostPlatform.startsWith('mac')) tokens = EXECUTABLE_PATHS[name]['mac'];else if (_hostPlatform.hostPlatform.startsWith('win')) tokens = EXECUTABLE_PATHS[name]['win'];236 return tokens ? _path.default.join(dir, ...tokens) : undefined;237 };238 const executablePathOrDie = (name, e, installByDefault, sdkLanguage) => {239 if (!e) throw new Error(`${name} is not supported on ${_hostPlatform.hostPlatform}`);240 const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install${installByDefault ? '' : ' ' + name}`);241 if (!(0, _fileUtils.canAccessFile)(e)) {242 const prettyMessage = [`Looks like Playwright Test or Playwright was just installed or updated.`, `Please run the following command to download new browser${installByDefault ? 's' : ''}:`, ``, ` ${installCommand}`, ``, `<3 Playwright Team`].join('\n');243 throw new Error(`Executable doesn't exist at ${e}\n${(0, _utils.wrapInASCIIBox)(prettyMessage, 1)}`);244 }245 return e;246 };247 this._executables = [];248 const chromium = descriptors.find(d => d.name === 'chromium');249 const chromiumExecutable = findExecutablePath(chromium.dir, 'chromium');250 this._executables.push({251 type: 'browser',252 name: 'chromium',253 browserName: 'chromium',254 directory: chromium.dir,255 executablePath: () => chromiumExecutable,256 executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),257 installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',258 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),259 _install: () => this._downloadExecutable(chromium, chromiumExecutable, DOWNLOAD_PATHS['chromium'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),260 _dependencyGroup: 'chromium',261 _isHermeticInstallation: true262 });263 const chromiumWithSymbols = descriptors.find(d => d.name === 'chromium-with-symbols');264 const chromiumWithSymbolsExecutable = findExecutablePath(chromiumWithSymbols.dir, 'chromium');265 this._executables.push({266 type: 'tool',267 name: 'chromium-with-symbols',268 browserName: 'chromium',269 directory: chromiumWithSymbols.dir,270 executablePath: () => chromiumWithSymbolsExecutable,271 executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-with-symbols', chromiumWithSymbolsExecutable, chromiumWithSymbols.installByDefault, sdkLanguage),272 installType: chromiumWithSymbols.installByDefault ? 'download-by-default' : 'download-on-demand',273 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumWithSymbols.dir, ['chrome-linux'], [], ['chrome-win']),274 _install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable, DOWNLOAD_PATHS['chromium-with-symbols'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),275 _dependencyGroup: 'chromium',276 _isHermeticInstallation: true277 });278 this._executables.push(this._createChromiumChannel('chrome', {279 'linux': '/opt/google/chrome/chrome',280 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',281 'win32': `\\Google\\Chrome\\Application\\chrome.exe`282 }, () => this._installChromiumChannel('chrome', {283 'linux': 'reinstall_chrome_stable_linux.sh',284 'darwin': 'reinstall_chrome_stable_mac.sh',285 'win32': 'reinstall_chrome_stable_win.ps1'286 })));287 this._executables.push(this._createChromiumChannel('chrome-beta', {288 'linux': '/opt/google/chrome-beta/chrome',289 'darwin': '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',290 'win32': `\\Google\\Chrome Beta\\Application\\chrome.exe`291 }, () => this._installChromiumChannel('chrome-beta', {292 'linux': 'reinstall_chrome_beta_linux.sh',293 'darwin': 'reinstall_chrome_beta_mac.sh',294 'win32': 'reinstall_chrome_beta_win.ps1'295 })));296 this._executables.push(this._createChromiumChannel('chrome-dev', {297 'linux': '/opt/google/chrome-unstable/chrome',298 'darwin': '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev',299 'win32': `\\Google\\Chrome Dev\\Application\\chrome.exe`300 }));301 this._executables.push(this._createChromiumChannel('chrome-canary', {302 'linux': '',303 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',304 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`305 }));306 this._executables.push(this._createChromiumChannel('msedge', {307 'linux': '/opt/microsoft/msedge/msedge',308 'darwin': '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',309 'win32': `\\Microsoft\\Edge\\Application\\msedge.exe`310 }, () => this._installMSEdgeChannel('msedge', {311 'linux': 'reinstall_msedge_stable_linux.sh',312 'darwin': 'reinstall_msedge_stable_mac.sh',313 'win32': 'reinstall_msedge_stable_win.ps1'314 })));315 this._executables.push(this._createChromiumChannel('msedge-beta', {316 'linux': '/opt/microsoft/msedge-beta/msedge',317 'darwin': '/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',318 'win32': `\\Microsoft\\Edge Beta\\Application\\msedge.exe`319 }, () => this._installMSEdgeChannel('msedge-beta', {320 'darwin': 'reinstall_msedge_beta_mac.sh',321 'linux': 'reinstall_msedge_beta_linux.sh',322 'win32': 'reinstall_msedge_beta_win.ps1'323 })));324 this._executables.push(this._createChromiumChannel('msedge-dev', {325 'linux': '/opt/microsoft/msedge-dev/msedge',326 'darwin': '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',327 'win32': `\\Microsoft\\Edge Dev\\Application\\msedge.exe`328 }, () => this._installMSEdgeChannel('msedge-dev', {329 'darwin': 'reinstall_msedge_dev_mac.sh',330 'linux': 'reinstall_msedge_dev_linux.sh',331 'win32': 'reinstall_msedge_dev_win.ps1'332 })));333 this._executables.push(this._createChromiumChannel('msedge-canary', {334 'linux': '',335 'darwin': '/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',336 'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`337 }));338 const firefox = descriptors.find(d => d.name === 'firefox');339 const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox');340 this._executables.push({341 type: 'browser',342 name: 'firefox',343 browserName: 'firefox',344 directory: firefox.dir,345 executablePath: () => firefoxExecutable,346 executablePathOrDie: sdkLanguage => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),347 installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',348 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),349 _install: () => this._downloadExecutable(firefox, firefoxExecutable, DOWNLOAD_PATHS['firefox'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),350 _dependencyGroup: 'firefox',351 _isHermeticInstallation: true352 });353 const firefoxBeta = descriptors.find(d => d.name === 'firefox-beta');354 const firefoxBetaExecutable = findExecutablePath(firefoxBeta.dir, 'firefox');355 this._executables.push({356 type: 'tool',357 name: 'firefox-beta',358 browserName: 'firefox',359 directory: firefoxBeta.dir,360 executablePath: () => firefoxBetaExecutable,361 executablePathOrDie: sdkLanguage => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),362 installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',363 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),364 _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable, DOWNLOAD_PATHS['firefox-beta'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),365 _dependencyGroup: 'firefox',366 _isHermeticInstallation: true367 });368 const webkit = descriptors.find(d => d.name === 'webkit');369 const webkitExecutable = findExecutablePath(webkit.dir, 'webkit');370 const webkitLinuxLddDirectories = [_path.default.join('minibrowser-gtk'), _path.default.join('minibrowser-gtk', 'bin'), _path.default.join('minibrowser-gtk', 'lib'), _path.default.join('minibrowser-gtk', 'sys', 'lib'), _path.default.join('minibrowser-wpe'), _path.default.join('minibrowser-wpe', 'bin'), _path.default.join('minibrowser-wpe', 'lib'), _path.default.join('minibrowser-wpe', 'sys', 'lib')];371 this._executables.push({372 type: 'browser',373 name: 'webkit',374 browserName: 'webkit',375 directory: webkit.dir,376 executablePath: () => webkitExecutable,377 executablePathOrDie: sdkLanguage => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),378 installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',379 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),380 _install: () => this._downloadExecutable(webkit, webkitExecutable, DOWNLOAD_PATHS['webkit'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST'),381 _dependencyGroup: 'webkit',382 _isHermeticInstallation: true383 });384 const ffmpeg = descriptors.find(d => d.name === 'ffmpeg');385 const ffmpegExecutable = findExecutablePath(ffmpeg.dir, 'ffmpeg');386 this._executables.push({387 type: 'tool',388 name: 'ffmpeg',389 browserName: undefined,390 directory: ffmpeg.dir,391 executablePath: () => ffmpegExecutable,392 executablePathOrDie: sdkLanguage => executablePathOrDie('ffmpeg', ffmpegExecutable, ffmpeg.installByDefault, sdkLanguage),393 installType: ffmpeg.installByDefault ? 'download-by-default' : 'download-on-demand',394 validateHostRequirements: () => Promise.resolve(),395 _install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable, DOWNLOAD_PATHS['ffmpeg'][_hostPlatform.hostPlatform], 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST'),396 _dependencyGroup: 'tools',397 _isHermeticInstallation: true398 });399 }400 _createChromiumChannel(name, lookAt, install) {401 const executablePath = (sdkLanguage, shouldThrow) => {402 const suffix = lookAt[process.platform];403 if (!suffix) {404 if (shouldThrow) throw new Error(`Chromium distribution '${name}' is not supported on ${process.platform}`);405 return undefined;406 }407 const prefixes = process.platform === 'win32' ? [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']].filter(Boolean) : [''];408 for (const prefix of prefixes) {409 const executablePath = _path.default.join(prefix, suffix);410 if ((0, _fileUtils.canAccessFile)(executablePath)) return executablePath;411 }412 if (!shouldThrow) return undefined;413 const location = prefixes.length ? ` at ${_path.default.join(prefixes[0], suffix)}` : ``; // TODO: language-specific error message414 const installation = install ? `\nRun "${buildPlaywrightCLICommand(sdkLanguage, 'install ' + name)}"` : '';415 throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);416 };417 return {418 type: 'channel',419 name,420 browserName: 'chromium',421 directory: undefined,422 executablePath: sdkLanguage => executablePath(sdkLanguage, false),423 executablePathOrDie: sdkLanguage => executablePath(sdkLanguage, true),424 installType: install ? 'install-script' : 'none',425 validateHostRequirements: () => Promise.resolve(),426 _isHermeticInstallation: false,427 _install: install428 };429 }430 executables() {431 return this._executables;432 }433 findExecutable(name) {434 return this._executables.find(b => b.name === name);435 }436 defaultExecutables() {437 return this._executables.filter(e => e.installType === 'download-by-default');438 }439 _addRequirementsAndDedupe(executables) {440 const set = new Set();441 for (const executable of executables) {442 set.add(executable);443 if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));444 }445 return Array.from(set);446 }447 async _validateHostRequirements(sdkLanguage, browserName, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {448 if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS')) {449 process.stdout.write('Skipping host requirements validation logic because `PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS` env variable is set.\n');450 return;451 }452 const ubuntuVersion = await (0, _ubuntuVersion.getUbuntuVersion)();453 if (browserName === 'firefox' && ubuntuVersion === '16.04') throw new Error(`Cannot launch Firefox on Ubuntu 16.04! Minimum required Ubuntu version for Firefox browser is 18.04`);454 if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);455 if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));456 }457 async installDeps(executablesToInstallDeps, dryRun) {458 const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);459 const targets = new Set();460 for (const executable of executables) {461 if (executable._dependencyGroup) targets.add(executable._dependencyGroup);462 }463 targets.add('tools');464 if (os.platform() === 'win32') return await (0, _dependencies.installDependenciesWindows)(targets, dryRun);465 if (os.platform() === 'linux') return await (0, _dependencies.installDependenciesLinux)(targets, dryRun);466 }467 async install(executablesToInstall, forceReinstall) {468 const executables = this._addRequirementsAndDedupe(executablesToInstall);469 await fs.promises.mkdir(registryDirectory, {470 recursive: true471 });472 const lockfilePath = _path.default.join(registryDirectory, '__dirlock');473 const linksDir = _path.default.join(registryDirectory, '.links');474 let releaseLock;475 try {476 releaseLock = await _properLockfile.default.lock(registryDirectory, {477 retries: {478 // Retry 20 times during 10 minutes with479 // exponential back-off.480 // See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions481 retries: 20,482 factor: 1.27579483 },484 onCompromised: err => {485 throw new Error(`${err.message} Path: ${lockfilePath}`);486 },487 lockfilePath488 }); // Create a link first, so that cache validation does not remove our own browsers.489 await fs.promises.mkdir(linksDir, {490 recursive: true491 });492 await fs.promises.writeFile(_path.default.join(linksDir, (0, _utils.calculateSha1)(PACKAGE_PATH)), PACKAGE_PATH); // Remove stale browsers.493 await this._validateInstallationCache(linksDir); // Install browsers for this package.494 for (const executable of executables) {495 if (!executable._install) throw new Error(`ERROR: Playwright does not support installing ${executable.name}`);496 const {497 langName498 } = (0, _userAgent.getClientLanguage)();499 if (!(0, _utils.getAsBooleanFromENV)('CI') && !executable._isHermeticInstallation && !forceReinstall && executable.executablePath(langName)) {500 const command = buildPlaywrightCLICommand(langName, 'install --force ' + executable.name);501 throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`ATTENTION: "${executable.name}" is already installed on the system!`, ``, `"${executable.name}" installation is not hermetic; installing newer version`, `requires *removal* of a current installation first.`, ``, `To *uninstall* current version and re-install latest "${executable.name}":`, ``, `- Close all running instances of "${executable.name}", if any`, `- Use "--force" to install browser:`, ``, ` ${command}`, ``, `<3 Playwright Team`].join('\n'), 1));502 }503 await executable._install();504 }505 } catch (e) {506 if (e.code === 'ELOCKED') {507 const rmCommand = process.platform === 'win32' ? 'rm -R' : 'rm -rf';508 throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`An active lockfile is found at:`, ``, ` ${lockfilePath}`, ``, `Either:`, `- wait a few minutes if other Playwright is installing browsers in parallel`, `- remove lock manually with:`, ``, ` ${rmCommand} ${lockfilePath}`, ``, `<3 Playwright Team`].join('\n'), 1));509 } else {510 throw e;511 }512 } finally {513 if (releaseLock) await releaseLock();514 }515 }516 async _downloadExecutable(descriptor, executablePath, downloadPathTemplate, downloadHostEnv) {517 if (!downloadPathTemplate || !executablePath) throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${_hostPlatform.hostPlatform}`);518 if (_hostPlatform.hostPlatform === 'generic-linux' || _hostPlatform.hostPlatform === 'generic-linux-arm64') (0, _browserFetcher.logPolitely)('BEWARE: your OS is not officially supported by Playwright; downloading Ubuntu build as a fallback.');519 const downloadHost = downloadHostEnv && (0, _utils.getFromENV)(downloadHostEnv) || (0, _utils.getFromENV)('PLAYWRIGHT_DOWNLOAD_HOST') || 'https://playwright.azureedge.net';520 const downloadPath = util.format(downloadPathTemplate, descriptor.revision);521 const downloadURL = `${downloadHost}/${downloadPath}`;522 const title = `${descriptor.name} v${descriptor.revision}`;523 const downloadFileName = `playwright-download-${descriptor.name}-${_hostPlatform.hostPlatform}-${descriptor.revision}.zip`;524 await (0, _browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURL, downloadFileName).catch(e => {525 throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);526 });527 await fs.promises.writeFile(markerFilePath(descriptor.dir), '');528 }529 async _installMSEdgeChannel(channel, scripts) {530 const scriptArgs = [];531 if (process.platform !== 'linux') {532 const products = JSON.parse(await (0, _netUtils.fetchData)({533 url: 'https://edgeupdates.microsoft.com/api/products'534 }));535 const productName = {536 'msedge': 'Stable',537 'msedge-beta': 'Beta',538 'msedge-dev': 'Dev'539 }[channel];540 const product = products.find(product => product.Product === productName);541 const searchConfig = {542 darwin: {543 platform: 'MacOS',544 arch: 'universal',545 artifact: 'pkg'546 },547 win32: {548 platform: 'Windows',549 arch: 'x64',550 artifact: 'msi'551 }552 }[process.platform];553 const release = searchConfig ? product.Releases.find(release => release.Platform === searchConfig.platform && release.Architecture === searchConfig.arch) : null;554 const artifact = release ? release.Artifacts.find(artifact => artifact.ArtifactName === searchConfig.artifact) : null;555 if (artifact) scriptArgs.push(artifact.Location556 /* url */557 );else throw new Error(`Cannot install ${channel} on ${process.platform}`);558 }559 await this._installChromiumChannel(channel, scripts, scriptArgs);560 }561 async _installChromiumChannel(channel, scripts, scriptArgs = []) {562 const scriptName = scripts[process.platform];563 if (!scriptName) throw new Error(`Cannot install ${channel} on ${process.platform}`);564 const cwd = BIN_PATH;565 const isPowerShell = scriptName.endsWith('.ps1');566 if (isPowerShell) {567 const args = ['-ExecutionPolicy', 'Bypass', '-File', _path.default.join(BIN_PATH, scriptName), ...scriptArgs];568 const {569 code570 } = await (0, _spawnAsync.spawnAsync)('powershell.exe', args, {571 cwd,572 stdio: 'inherit'573 });574 if (code !== 0) throw new Error(`Failed to install ${channel}`);575 } else {576 const {577 command,578 args,579 elevatedPermissions580 } = await (0, _dependencies.transformCommandsForRoot)([`bash "${_path.default.join(BIN_PATH, scriptName)}" ${scriptArgs.join('')}`]);581 if (elevatedPermissions) console.log('Switching to root user to install dependencies...'); // eslint-disable-line no-console582 const {583 code584 } = await (0, _spawnAsync.spawnAsync)(command, args, {585 cwd,586 stdio: 'inherit'587 });588 if (code !== 0) throw new Error(`Failed to install ${channel}`);589 }590 }591 async _validateInstallationCache(linksDir) {592 // 1. Collect used downloads and package descriptors.593 const usedBrowserPaths = new Set();594 for (const fileName of await fs.promises.readdir(linksDir)) {595 const linkPath = _path.default.join(linksDir, fileName);596 let linkTarget = '';597 try {598 linkTarget = (await fs.promises.readFile(linkPath)).toString();599 const browsersJSON = require(_path.default.join(linkTarget, 'browsers.json'));600 const descriptors = readDescriptors(browsersJSON);601 for (const browserName of allDownloadable) {602 // We retain browsers if they are found in the descriptor.603 // Note, however, that there are older versions out in the wild that rely on604 // the "download" field in the browser descriptor and use its value605 // to retain and download browsers.606 // As of v1.10, we decided to abandon "download" field.607 const descriptor = descriptors.find(d => d.name === browserName);608 if (!descriptor) continue;609 const usedBrowserPath = descriptor.dir;610 const browserRevision = parseInt(descriptor.revision, 10); // Old browser installations don't have marker file.611 const shouldHaveMarkerFile = browserName === 'chromium' && browserRevision >= 786218 || browserName === 'firefox' && browserRevision >= 1128 || browserName === 'webkit' && browserRevision >= 1307 || // All new applications have a marker file right away.612 browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit';613 if (!shouldHaveMarkerFile || (await (0, _fileUtils.existsAsync)(markerFilePath(usedBrowserPath)))) usedBrowserPaths.add(usedBrowserPath);614 }615 } catch (e) {616 await fs.promises.unlink(linkPath).catch(e => {});617 }618 } // 2. Delete all unused browsers.619 if (!(0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_GC')) {620 let downloadedBrowsers = (await fs.promises.readdir(registryDirectory)).map(file => _path.default.join(registryDirectory, file));621 downloadedBrowsers = downloadedBrowsers.filter(file => isBrowserDirectory(file));622 const directories = new Set(downloadedBrowsers);623 for (const browserDirectory of usedBrowserPaths) directories.delete(browserDirectory);624 for (const directory of directories) (0, _browserFetcher.logPolitely)('Removing unused browser at ' + directory);625 await (0, _fileUtils.removeFolders)([...directories]);626 }627 }628}629exports.Registry = Registry;630function markerFilePath(browserDirectory) {631 return _path.default.join(browserDirectory, 'INSTALLATION_COMPLETE');632}633function buildPlaywrightCLICommand(sdkLanguage, parameters) {634 switch (sdkLanguage) {635 case 'python':636 return `playwright ${parameters}`;637 case 'java':638 return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`;639 case 'csharp':640 return `pwsh bin\\Debug\\netX\\playwright.ps1 ${parameters}`;641 default:642 return `npx playwright ${parameters}`;643 }644}645async function installDefaultBrowsersForNpmInstall() {646 const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);647 return installBrowsersForNpmInstall(defaultBrowserNames);648}649async function installBrowsersForNpmInstall(browsers) {650 // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1651 if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {652 (0, _browserFetcher.logPolitely)('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');653 return false;654 }655 const executables = [];656 for (const browserName of browsers) {657 const executable = registry.findExecutable(browserName);658 if (!executable || executable.installType === 'none') throw new Error(`Cannot install ${browserName}`);659 executables.push(executable);660 }661 await registry.install(executables, false662 /* forceReinstall */663 );664}665function findChromiumChannel(sdkLanguage) {666 // Fall back to the stable channels of popular vendors to work out of the box.667 // Null means no installation and no channels found.668 let channel = null;669 for (const name of ['chromium', 'chrome', 'msedge']) {670 try {671 registry.findExecutable(name).executablePathOrDie(sdkLanguage);672 channel = name === 'chromium' ? undefined : name;673 break;674 } catch (e) {}675 }676 if (channel === null) {677 const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install chromium`);678 const prettyMessage = [`No chromium-based browser found on the system.`, `Please run the following command to download one:`, ``, ` ${installCommand}`, ``, `<3 Playwright Team`].join('\n');679 throw new Error('\n' + (0, _utils.wrapInASCIIBox)(prettyMessage, 1));680 }681 return channel;682}683const registry = new Registry(require('../../../browsers.json'));...
registry.js
Source:registry.js
1"use strict";2Object.defineProperty(exports, "__esModule", {3 value: true4});5exports.Registry = void 0;6exports.buildPlaywrightCLICommand = buildPlaywrightCLICommand;7exports.findChromiumChannel = findChromiumChannel;8exports.installBrowsersForNpmInstall = installBrowsersForNpmInstall;9exports.installDefaultBrowsersForNpmInstall = installDefaultBrowsersForNpmInstall;10exports.registryDirectory = exports.registry = void 0;11var os = _interopRequireWildcard(require("os"));12var _path = _interopRequireDefault(require("path"));13var util = _interopRequireWildcard(require("util"));14var fs = _interopRequireWildcard(require("fs"));15var _properLockfile = _interopRequireDefault(require("proper-lockfile"));16var _ubuntuVersion = require("./ubuntuVersion");17var _utils = require("./utils");18var _dependencies = require("./dependencies");19var _browserFetcher = require("./browserFetcher");20function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }21function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }22function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }23/**24 * Copyright 2017 Google Inc. All rights reserved.25 * Modifications copyright (c) Microsoft Corporation.26 *27 * Licensed under the Apache License, Version 2.0 (the "License");28 * you may not use this file except in compliance with the License.29 * You may obtain a copy of the License at30 *31 * http://www.apache.org/licenses/LICENSE-2.032 *33 * Unless required by applicable law or agreed to in writing, software34 * distributed under the License is distributed on an "AS IS" BASIS,35 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.36 * See the License for the specific language governing permissions and37 * limitations under the License.38 */39const PACKAGE_PATH = _path.default.join(__dirname, '..', '..');40const BIN_PATH = _path.default.join(__dirname, '..', '..', 'bin');41const EXECUTABLE_PATHS = {42 'chromium': {43 'linux': ['chrome-linux', 'chrome'],44 'mac': ['chrome-mac', 'Chromium.app', 'Contents', 'MacOS', 'Chromium'],45 'win': ['chrome-win', 'chrome.exe']46 },47 'firefox': {48 'linux': ['firefox', 'firefox'],49 'mac': ['firefox', 'Nightly.app', 'Contents', 'MacOS', 'firefox'],50 'win': ['firefox', 'firefox.exe']51 },52 'webkit': {53 'linux': ['pw_run.sh'],54 'mac': ['pw_run.sh'],55 'win': ['Playwright.exe']56 },57 'ffmpeg': {58 'linux': ['ffmpeg-linux'],59 'mac': ['ffmpeg-mac'],60 'win': ['ffmpeg-win64.exe']61 }62};63const DOWNLOAD_PATHS = {64 'chromium': {65 'ubuntu18.04': 'builds/chromium/%s/chromium-linux.zip',66 'ubuntu20.04': 'builds/chromium/%s/chromium-linux.zip',67 'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',68 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-linux-arm64.zip',69 'mac10.13': 'builds/chromium/%s/chromium-mac.zip',70 'mac10.14': 'builds/chromium/%s/chromium-mac.zip',71 'mac10.15': 'builds/chromium/%s/chromium-mac.zip',72 'mac11': 'builds/chromium/%s/chromium-mac.zip',73 'mac11-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',74 'mac12': 'builds/chromium/%s/chromium-mac.zip',75 'mac12-arm64': 'builds/chromium/%s/chromium-mac-arm64.zip',76 'win64': 'builds/chromium/%s/chromium-win64.zip'77 },78 'chromium-with-symbols': {79 'ubuntu18.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',80 'ubuntu20.04': 'builds/chromium/%s/chromium-with-symbols-linux.zip',81 'ubuntu18.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',82 'ubuntu20.04-arm64': 'builds/chromium/%s/chromium-with-symbols-linux-arm64.zip',83 'mac10.13': 'builds/chromium/%s/chromium-with-symbols-mac.zip',84 'mac10.14': 'builds/chromium/%s/chromium-with-symbols-mac.zip',85 'mac10.15': 'builds/chromium/%s/chromium-with-symbols-mac.zip',86 'mac11': 'builds/chromium/%s/chromium-with-symbols-mac.zip',87 'mac11-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',88 'mac12': 'builds/chromium/%s/chromium-with-symbols-mac.zip',89 'mac12-arm64': 'builds/chromium/%s/chromium-with-symbols-mac-arm64.zip',90 'win64': 'builds/chromium/%s/chromium-with-symbols-win64.zip'91 },92 'firefox': {93 'ubuntu18.04': 'builds/firefox/%s/firefox-ubuntu-18.04.zip',94 'ubuntu20.04': 'builds/firefox/%s/firefox-ubuntu-20.04.zip',95 'ubuntu18.04-arm64': undefined,96 'ubuntu20.04-arm64': 'builds/firefox/%s/firefox-ubuntu-20.04-arm64.zip',97 'mac10.13': 'builds/firefox/%s/firefox-mac-11.zip',98 'mac10.14': 'builds/firefox/%s/firefox-mac-11.zip',99 'mac10.15': 'builds/firefox/%s/firefox-mac-11.zip',100 'mac11': 'builds/firefox/%s/firefox-mac-11.zip',101 'mac11-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',102 'mac12': 'builds/firefox/%s/firefox-mac-11.zip',103 'mac12-arm64': 'builds/firefox/%s/firefox-mac-11-arm64.zip',104 'win64': 'builds/firefox/%s/firefox-win64.zip'105 },106 'firefox-beta': {107 'ubuntu18.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-18.04.zip',108 'ubuntu20.04': 'builds/firefox-beta/%s/firefox-beta-ubuntu-20.04.zip',109 'ubuntu18.04-arm64': undefined,110 'ubuntu20.04-arm64': undefined,111 'mac10.13': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',112 'mac10.14': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',113 'mac10.15': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',114 'mac11': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',115 'mac11-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',116 'mac12': 'builds/firefox-beta/%s/firefox-beta-mac-11.zip',117 'mac12-arm64': 'builds/firefox-beta/%s/firefox-beta-mac-11-arm64.zip',118 'win64': 'builds/firefox-beta/%s/firefox-beta-win64.zip'119 },120 'webkit': {121 'ubuntu18.04': 'builds/webkit/%s/webkit-ubuntu-18.04.zip',122 'ubuntu20.04': 'builds/webkit/%s/webkit-ubuntu-20.04.zip',123 'ubuntu18.04-arm64': undefined,124 'ubuntu20.04-arm64': 'builds/webkit/%s/webkit-ubuntu-20.04-arm64.zip',125 'mac10.13': undefined,126 'mac10.14': 'builds/deprecated-webkit-mac-10.14/%s/deprecated-webkit-mac-10.14.zip',127 'mac10.15': 'builds/webkit/%s/webkit-mac-10.15.zip',128 'mac11': 'builds/webkit/%s/webkit-mac-10.15.zip',129 'mac11-arm64': 'builds/webkit/%s/webkit-mac-11-arm64.zip',130 'mac12': 'builds/webkit/%s/webkit-mac-12.zip',131 'mac12-arm64': 'builds/webkit/%s/webkit-mac-12-arm64.zip',132 'win64': 'builds/webkit/%s/webkit-win64.zip'133 },134 'ffmpeg': {135 'ubuntu18.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',136 'ubuntu20.04': 'builds/ffmpeg/%s/ffmpeg-linux.zip',137 'ubuntu18.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',138 'ubuntu20.04-arm64': 'builds/ffmpeg/%s/ffmpeg-linux-arm64.zip',139 'mac10.13': 'builds/ffmpeg/%s/ffmpeg-mac.zip',140 'mac10.14': 'builds/ffmpeg/%s/ffmpeg-mac.zip',141 'mac10.15': 'builds/ffmpeg/%s/ffmpeg-mac.zip',142 'mac11': 'builds/ffmpeg/%s/ffmpeg-mac.zip',143 'mac11-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',144 'mac12': 'builds/ffmpeg/%s/ffmpeg-mac.zip',145 'mac12-arm64': 'builds/ffmpeg/%s/ffmpeg-mac-arm64.zip',146 'win64': 'builds/ffmpeg/%s/ffmpeg-win64.zip'147 }148};149const registryDirectory = (() => {150 let result;151 const envDefined = (0, _utils.getFromENV)('PLAYWRIGHT_BROWSERS_PATH');152 if (envDefined === '0') {153 result = _path.default.join(__dirname, '..', '..', '.local-browsers');154 } else if (envDefined) {155 result = envDefined;156 } else {157 let cacheDirectory;158 if (process.platform === 'linux') cacheDirectory = process.env.XDG_CACHE_HOME || _path.default.join(os.homedir(), '.cache');else if (process.platform === 'darwin') cacheDirectory = _path.default.join(os.homedir(), 'Library', 'Caches');else if (process.platform === 'win32') cacheDirectory = process.env.LOCALAPPDATA || _path.default.join(os.homedir(), 'AppData', 'Local');else throw new Error('Unsupported platform: ' + process.platform);159 result = _path.default.join(cacheDirectory, 'ms-playwright');160 }161 if (!_path.default.isAbsolute(result)) {162 // It is important to resolve to the absolute path:163 // - for unzipping to work correctly;164 // - so that registry directory matches between installation and execution.165 // INIT_CWD points to the root of `npm/yarn install` and is probably what166 // the user meant when typing the relative path.167 result = _path.default.resolve((0, _utils.getFromENV)('INIT_CWD') || process.cwd(), result);168 }169 return result;170})();171exports.registryDirectory = registryDirectory;172function isBrowserDirectory(browserDirectory) {173 const baseName = _path.default.basename(browserDirectory);174 for (const browserName of allDownloadable) {175 if (baseName.startsWith(browserName + '-')) return true;176 }177 return false;178}179function readDescriptors(browsersJSON) {180 return browsersJSON['browsers'].map(obj => {181 const name = obj.name;182 const revisionOverride = (obj.revisionOverrides || {})[_utils.hostPlatform];183 const revision = revisionOverride || obj.revision;184 const browserDirectoryPrefix = revisionOverride ? `${name}_${_utils.hostPlatform}_special` : `${name}`;185 const descriptor = {186 name,187 revision,188 installByDefault: !!obj.installByDefault,189 // Method `isBrowserDirectory` determines directory to be browser iff190 // it starts with some browser name followed by '-'. Some browser names191 // are prefixes of others, e.g. 'webkit' is a prefix of `webkit-technology-preview`.192 // To avoid older registries erroneously removing 'webkit-technology-preview', we have to193 // ensure that browser folders to never include dashes inside.194 dir: _path.default.join(registryDirectory, browserDirectoryPrefix.replace(/-/g, '_') + '-' + revision)195 };196 return descriptor;197 });198}199const allDownloadable = ['chromium', 'firefox', 'webkit', 'ffmpeg', 'firefox-beta', 'chromium-with-symbols'];200class Registry {201 constructor(browsersJSON) {202 this._executables = void 0;203 const descriptors = readDescriptors(browsersJSON);204 const findExecutablePath = (dir, name) => {205 let tokens = undefined;206 if (_utils.hostPlatform.startsWith('ubuntu')) tokens = EXECUTABLE_PATHS[name]['linux'];else if (_utils.hostPlatform.startsWith('mac')) tokens = EXECUTABLE_PATHS[name]['mac'];else if (_utils.hostPlatform.startsWith('win')) tokens = EXECUTABLE_PATHS[name]['win'];207 return tokens ? _path.default.join(dir, ...tokens) : undefined;208 };209 const executablePathOrDie = (name, e, installByDefault, sdkLanguage) => {210 if (!e) throw new Error(`${name} is not supported on ${_utils.hostPlatform}`);211 const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install${installByDefault ? '' : ' ' + name}`);212 if (!(0, _utils.canAccessFile)(e)) {213 const prettyMessage = [`Looks like Playwright Test or Playwright was just installed or updated.`, `Please run the following command to download new browser${installByDefault ? 's' : ''}:`, ``, ` ${installCommand}`, ``, `<3 Playwright Team`].join('\n');214 throw new Error(`Executable doesn't exist at ${e}\n${(0, _utils.wrapInASCIIBox)(prettyMessage, 1)}`);215 }216 return e;217 };218 this._executables = [];219 const chromium = descriptors.find(d => d.name === 'chromium');220 const chromiumExecutable = findExecutablePath(chromium.dir, 'chromium');221 this._executables.push({222 type: 'browser',223 name: 'chromium',224 browserName: 'chromium',225 directory: chromium.dir,226 executablePath: () => chromiumExecutable,227 executablePathOrDie: sdkLanguage => executablePathOrDie('chromium', chromiumExecutable, chromium.installByDefault, sdkLanguage),228 installType: chromium.installByDefault ? 'download-by-default' : 'download-on-demand',229 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromium.dir, ['chrome-linux'], [], ['chrome-win']),230 _install: () => this._downloadExecutable(chromium, chromiumExecutable, DOWNLOAD_PATHS['chromium'][_utils.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),231 _dependencyGroup: 'chromium'232 });233 const chromiumWithSymbols = descriptors.find(d => d.name === 'chromium-with-symbols');234 const chromiumWithSymbolsExecutable = findExecutablePath(chromiumWithSymbols.dir, 'chromium');235 this._executables.push({236 type: 'tool',237 name: 'chromium-with-symbols',238 browserName: 'chromium',239 directory: chromiumWithSymbols.dir,240 executablePath: () => chromiumWithSymbolsExecutable,241 executablePathOrDie: sdkLanguage => executablePathOrDie('chromium-with-symbols', chromiumWithSymbolsExecutable, chromiumWithSymbols.installByDefault, sdkLanguage),242 installType: chromiumWithSymbols.installByDefault ? 'download-by-default' : 'download-on-demand',243 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'chromium', chromiumWithSymbols.dir, ['chrome-linux'], [], ['chrome-win']),244 _install: () => this._downloadExecutable(chromiumWithSymbols, chromiumWithSymbolsExecutable, DOWNLOAD_PATHS['chromium-with-symbols'][_utils.hostPlatform], 'PLAYWRIGHT_CHROMIUM_DOWNLOAD_HOST'),245 _dependencyGroup: 'chromium'246 });247 this._executables.push(this._createChromiumChannel('chrome', {248 'linux': '/opt/google/chrome/chrome',249 'darwin': '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',250 'win32': `\\Google\\Chrome\\Application\\chrome.exe`251 }, () => this._installChromiumChannel('chrome', {252 'linux': 'reinstall_chrome_stable_linux.sh',253 'darwin': 'reinstall_chrome_stable_mac.sh',254 'win32': 'reinstall_chrome_stable_win.ps1'255 })));256 this._executables.push(this._createChromiumChannel('chrome-beta', {257 'linux': '/opt/google/chrome-beta/chrome',258 'darwin': '/Applications/Google Chrome Beta.app/Contents/MacOS/Google Chrome Beta',259 'win32': `\\Google\\Chrome Beta\\Application\\chrome.exe`260 }, () => this._installChromiumChannel('chrome-beta', {261 'linux': 'reinstall_chrome_beta_linux.sh',262 'darwin': 'reinstall_chrome_beta_mac.sh',263 'win32': 'reinstall_chrome_beta_win.ps1'264 })));265 this._executables.push(this._createChromiumChannel('chrome-dev', {266 'linux': '/opt/google/chrome-unstable/chrome',267 'darwin': '/Applications/Google Chrome Dev.app/Contents/MacOS/Google Chrome Dev',268 'win32': `\\Google\\Chrome Dev\\Application\\chrome.exe`269 }));270 this._executables.push(this._createChromiumChannel('chrome-canary', {271 'linux': '',272 'darwin': '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',273 'win32': `\\Google\\Chrome SxS\\Application\\chrome.exe`274 }));275 this._executables.push(this._createChromiumChannel('msedge', {276 'linux': '/opt/microsoft/msedge/msedge',277 'darwin': '/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge',278 'win32': `\\Microsoft\\Edge\\Application\\msedge.exe`279 }, () => this._installMSEdgeChannel('msedge', {280 'linux': 'reinstall_msedge_stable_linux.sh',281 'darwin': 'reinstall_msedge_stable_mac.sh',282 'win32': 'reinstall_msedge_stable_win.ps1'283 })));284 this._executables.push(this._createChromiumChannel('msedge-beta', {285 'linux': '/opt/microsoft/msedge-beta/msedge',286 'darwin': '/Applications/Microsoft Edge Beta.app/Contents/MacOS/Microsoft Edge Beta',287 'win32': `\\Microsoft\\Edge Beta\\Application\\msedge.exe`288 }, () => this._installMSEdgeChannel('msedge-beta', {289 'darwin': 'reinstall_msedge_beta_mac.sh',290 'linux': 'reinstall_msedge_beta_linux.sh',291 'win32': 'reinstall_msedge_beta_win.ps1'292 })));293 this._executables.push(this._createChromiumChannel('msedge-dev', {294 'linux': '/opt/microsoft/msedge-dev/msedge',295 'darwin': '/Applications/Microsoft Edge Dev.app/Contents/MacOS/Microsoft Edge Dev',296 'win32': `\\Microsoft\\Edge Dev\\Application\\msedge.exe`297 }, () => this._installMSEdgeChannel('msedge-dev', {298 'darwin': 'reinstall_msedge_dev_mac.sh',299 'linux': 'reinstall_msedge_dev_linux.sh',300 'win32': 'reinstall_msedge_dev_win.ps1'301 })));302 this._executables.push(this._createChromiumChannel('msedge-canary', {303 'linux': '',304 'darwin': '/Applications/Microsoft Edge Canary.app/Contents/MacOS/Microsoft Edge Canary',305 'win32': `\\Microsoft\\Edge SxS\\Application\\msedge.exe`306 }));307 const firefox = descriptors.find(d => d.name === 'firefox');308 const firefoxExecutable = findExecutablePath(firefox.dir, 'firefox');309 this._executables.push({310 type: 'browser',311 name: 'firefox',312 browserName: 'firefox',313 directory: firefox.dir,314 executablePath: () => firefoxExecutable,315 executablePathOrDie: sdkLanguage => executablePathOrDie('firefox', firefoxExecutable, firefox.installByDefault, sdkLanguage),316 installType: firefox.installByDefault ? 'download-by-default' : 'download-on-demand',317 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefox.dir, ['firefox'], [], ['firefox']),318 _install: () => this._downloadExecutable(firefox, firefoxExecutable, DOWNLOAD_PATHS['firefox'][_utils.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),319 _dependencyGroup: 'firefox'320 });321 const firefoxBeta = descriptors.find(d => d.name === 'firefox-beta');322 const firefoxBetaExecutable = findExecutablePath(firefoxBeta.dir, 'firefox');323 this._executables.push({324 type: 'tool',325 name: 'firefox-beta',326 browserName: 'firefox',327 directory: firefoxBeta.dir,328 executablePath: () => firefoxBetaExecutable,329 executablePathOrDie: sdkLanguage => executablePathOrDie('firefox-beta', firefoxBetaExecutable, firefoxBeta.installByDefault, sdkLanguage),330 installType: firefoxBeta.installByDefault ? 'download-by-default' : 'download-on-demand',331 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'firefox', firefoxBeta.dir, ['firefox'], [], ['firefox']),332 _install: () => this._downloadExecutable(firefoxBeta, firefoxBetaExecutable, DOWNLOAD_PATHS['firefox-beta'][_utils.hostPlatform], 'PLAYWRIGHT_FIREFOX_DOWNLOAD_HOST'),333 _dependencyGroup: 'firefox'334 });335 const webkit = descriptors.find(d => d.name === 'webkit');336 const webkitExecutable = findExecutablePath(webkit.dir, 'webkit');337 const webkitLinuxLddDirectories = [_path.default.join('minibrowser-gtk'), _path.default.join('minibrowser-gtk', 'bin'), _path.default.join('minibrowser-gtk', 'lib'), _path.default.join('minibrowser-wpe'), _path.default.join('minibrowser-wpe', 'bin'), _path.default.join('minibrowser-wpe', 'lib')];338 this._executables.push({339 type: 'browser',340 name: 'webkit',341 browserName: 'webkit',342 directory: webkit.dir,343 executablePath: () => webkitExecutable,344 executablePathOrDie: sdkLanguage => executablePathOrDie('webkit', webkitExecutable, webkit.installByDefault, sdkLanguage),345 installType: webkit.installByDefault ? 'download-by-default' : 'download-on-demand',346 validateHostRequirements: sdkLanguage => this._validateHostRequirements(sdkLanguage, 'webkit', webkit.dir, webkitLinuxLddDirectories, ['libGLESv2.so.2', 'libx264.so'], ['']),347 _install: () => this._downloadExecutable(webkit, webkitExecutable, DOWNLOAD_PATHS['webkit'][_utils.hostPlatform], 'PLAYWRIGHT_WEBKIT_DOWNLOAD_HOST'),348 _dependencyGroup: 'webkit'349 });350 const ffmpeg = descriptors.find(d => d.name === 'ffmpeg');351 const ffmpegExecutable = findExecutablePath(ffmpeg.dir, 'ffmpeg');352 this._executables.push({353 type: 'tool',354 name: 'ffmpeg',355 browserName: undefined,356 directory: ffmpeg.dir,357 executablePath: () => ffmpegExecutable,358 executablePathOrDie: sdkLanguage => executablePathOrDie('ffmpeg', ffmpegExecutable, ffmpeg.installByDefault, sdkLanguage),359 installType: ffmpeg.installByDefault ? 'download-by-default' : 'download-on-demand',360 validateHostRequirements: () => Promise.resolve(),361 _install: () => this._downloadExecutable(ffmpeg, ffmpegExecutable, DOWNLOAD_PATHS['ffmpeg'][_utils.hostPlatform], 'PLAYWRIGHT_FFMPEG_DOWNLOAD_HOST'),362 _dependencyGroup: 'tools'363 });364 }365 _createChromiumChannel(name, lookAt, install) {366 const executablePath = (sdkLanguage, shouldThrow) => {367 const suffix = lookAt[process.platform];368 if (!suffix) {369 if (shouldThrow) throw new Error(`Chromium distribution '${name}' is not supported on ${process.platform}`);370 return undefined;371 }372 const prefixes = process.platform === 'win32' ? [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']].filter(Boolean) : [''];373 for (const prefix of prefixes) {374 const executablePath = _path.default.join(prefix, suffix);375 if ((0, _utils.canAccessFile)(executablePath)) return executablePath;376 }377 if (!shouldThrow) return undefined;378 const location = prefixes.length ? ` at ${_path.default.join(prefixes[0], suffix)}` : ``; // TODO: language-specific error message379 const installation = install ? `\nRun "${buildPlaywrightCLICommand(sdkLanguage, 'install ' + name)}"` : '';380 throw new Error(`Chromium distribution '${name}' is not found${location}${installation}`);381 };382 return {383 type: 'channel',384 name,385 browserName: 'chromium',386 directory: undefined,387 executablePath: sdkLanguage => executablePath(sdkLanguage, false),388 executablePathOrDie: sdkLanguage => executablePath(sdkLanguage, true),389 installType: install ? 'install-script' : 'none',390 validateHostRequirements: () => Promise.resolve(),391 _install: install392 };393 }394 executables() {395 return this._executables;396 }397 findExecutable(name) {398 return this._executables.find(b => b.name === name);399 }400 defaultExecutables() {401 return this._executables.filter(e => e.installType === 'download-by-default');402 }403 _addRequirementsAndDedupe(executables) {404 const set = new Set();405 for (const executable of executables) {406 set.add(executable);407 if (executable.browserName === 'chromium') set.add(this.findExecutable('ffmpeg'));408 }409 return Array.from(set);410 }411 async _validateHostRequirements(sdkLanguage, browserName, browserDirectory, linuxLddDirectories, dlOpenLibraries, windowsExeAndDllDirectories) {412 if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS')) {413 process.stdout.write('Skipping host requirements validation logic because `PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS` env variable is set.\n');414 return;415 }416 const ubuntuVersion = await (0, _ubuntuVersion.getUbuntuVersion)();417 if (browserName === 'firefox' && ubuntuVersion === '16.04') throw new Error(`Cannot launch Firefox on Ubuntu 16.04! Minimum required Ubuntu version for Firefox browser is 18.04`);418 if (os.platform() === 'linux') return await (0, _dependencies.validateDependenciesLinux)(sdkLanguage, linuxLddDirectories.map(d => _path.default.join(browserDirectory, d)), dlOpenLibraries);419 if (os.platform() === 'win32' && os.arch() === 'x64') return await (0, _dependencies.validateDependenciesWindows)(windowsExeAndDllDirectories.map(d => _path.default.join(browserDirectory, d)));420 }421 async installDeps(executablesToInstallDeps, dryRun) {422 const executables = this._addRequirementsAndDedupe(executablesToInstallDeps);423 const targets = new Set();424 for (const executable of executables) {425 if (executable._dependencyGroup) targets.add(executable._dependencyGroup);426 }427 targets.add('tools');428 if (os.platform() === 'win32') return await (0, _dependencies.installDependenciesWindows)(targets, dryRun);429 if (os.platform() === 'linux') return await (0, _dependencies.installDependenciesLinux)(targets, dryRun);430 }431 async install(executablesToInstall) {432 const executables = this._addRequirementsAndDedupe(executablesToInstall);433 await fs.promises.mkdir(registryDirectory, {434 recursive: true435 });436 const lockfilePath = _path.default.join(registryDirectory, '__dirlock');437 const linksDir = _path.default.join(registryDirectory, '.links');438 let releaseLock;439 try {440 releaseLock = await _properLockfile.default.lock(registryDirectory, {441 retries: {442 // Retry 20 times during 10 minutes with443 // exponential back-off.444 // See documentation at: https://www.npmjs.com/package/retry#retrytimeoutsoptions445 retries: 20,446 factor: 1.27579447 },448 onCompromised: err => {449 throw new Error(`${err.message} Path: ${lockfilePath}`);450 },451 lockfilePath452 }); // Create a link first, so that cache validation does not remove our own browsers.453 await fs.promises.mkdir(linksDir, {454 recursive: true455 });456 await fs.promises.writeFile(_path.default.join(linksDir, (0, _utils.calculateSha1)(PACKAGE_PATH)), PACKAGE_PATH); // Remove stale browsers.457 await this._validateInstallationCache(linksDir); // Install browsers for this package.458 for (const executable of executables) {459 if (executable._install) await executable._install();else throw new Error(`ERROR: Playwright does not support installing ${executable.name}`);460 }461 } catch (e) {462 if (e.code === 'ELOCKED') {463 const rmCommand = process.platform === 'win32' ? 'rm -R' : 'rm -rf';464 throw new Error('\n' + (0, _utils.wrapInASCIIBox)([`An active lockfile is found at:`, ``, ` ${lockfilePath}`, ``, `Either:`, `- wait a few minutes if other Playwright is installing browsers in parallel`, `- remove lock manually with:`, ``, ` ${rmCommand} ${lockfilePath}`, ``, `<3 Playwright Team`].join('\n'), 1));465 } else {466 throw e;467 }468 } finally {469 if (releaseLock) await releaseLock();470 }471 }472 async _downloadExecutable(descriptor, executablePath, downloadPathTemplate, downloadHostEnv) {473 if (!downloadPathTemplate || !executablePath) throw new Error(`ERROR: Playwright does not support ${descriptor.name} on ${_utils.hostPlatform}`);474 const downloadHost = downloadHostEnv && (0, _utils.getFromENV)(downloadHostEnv) || (0, _utils.getFromENV)('PLAYWRIGHT_DOWNLOAD_HOST') || 'https://playwright.azureedge.net';475 const downloadPath = util.format(downloadPathTemplate, descriptor.revision);476 const downloadURL = `${downloadHost}/${downloadPath}`;477 const title = `${descriptor.name} v${descriptor.revision}`;478 const downloadFileName = `playwright-download-${descriptor.name}-${_utils.hostPlatform}-${descriptor.revision}.zip`;479 await (0, _browserFetcher.downloadBrowserWithProgressBar)(title, descriptor.dir, executablePath, downloadURL, downloadFileName).catch(e => {480 throw new Error(`Failed to download ${title}, caused by\n${e.stack}`);481 });482 await fs.promises.writeFile(markerFilePath(descriptor.dir), '');483 }484 async _installMSEdgeChannel(channel, scripts) {485 const scriptArgs = [];486 if (process.platform !== 'linux') {487 const products = JSON.parse(await (0, _utils.fetchData)({488 url: 'https://edgeupdates.microsoft.com/api/products'489 }));490 const productName = {491 'msedge': 'Stable',492 'msedge-beta': 'Beta',493 'msedge-dev': 'Dev'494 }[channel];495 const product = products.find(product => product.Product === productName);496 const searchConfig = {497 darwin: {498 platform: 'MacOS',499 arch: 'universal',500 artifact: 'pkg'501 },502 win32: {503 platform: 'Windows',504 arch: 'x64',505 artifact: 'msi'506 }507 }[process.platform];508 const release = searchConfig ? product.Releases.find(release => release.Platform === searchConfig.platform && release.Architecture === searchConfig.arch) : null;509 const artifact = release ? release.Artifacts.find(artifact => artifact.ArtifactName === searchConfig.artifact) : null;510 if (artifact) scriptArgs.push(artifact.Location511 /* url */512 );else throw new Error(`Cannot install ${channel} on ${process.platform}`);513 }514 await this._installChromiumChannel(channel, scripts, scriptArgs);515 }516 async _installChromiumChannel(channel, scripts, scriptArgs = []) {517 const scriptName = scripts[process.platform];518 if (!scriptName) throw new Error(`Cannot install ${channel} on ${process.platform}`);519 const cwd = BIN_PATH;520 const isPowerShell = scriptName.endsWith('.ps1');521 if (isPowerShell) {522 const args = ['-ExecutionPolicy', 'Bypass', '-File', _path.default.join(BIN_PATH, scriptName), ...scriptArgs];523 const {524 code525 } = await (0, _utils.spawnAsync)('powershell.exe', args, {526 cwd,527 stdio: 'inherit'528 });529 if (code !== 0) throw new Error(`Failed to install ${channel}`);530 } else {531 const {532 command,533 args,534 elevatedPermissions535 } = await (0, _utils.transformCommandsForRoot)([`bash ${_path.default.join(BIN_PATH, scriptName)} ${scriptArgs.join('')}`]);536 if (elevatedPermissions) console.log('Switching to root user to install dependencies...'); // eslint-disable-line no-console537 const {538 code539 } = await (0, _utils.spawnAsync)(command, args, {540 cwd,541 stdio: 'inherit'542 });543 if (code !== 0) throw new Error(`Failed to install ${channel}`);544 }545 }546 async _validateInstallationCache(linksDir) {547 // 1. Collect used downloads and package descriptors.548 const usedBrowserPaths = new Set();549 for (const fileName of await fs.promises.readdir(linksDir)) {550 const linkPath = _path.default.join(linksDir, fileName);551 let linkTarget = '';552 try {553 linkTarget = (await fs.promises.readFile(linkPath)).toString();554 const browsersJSON = require(_path.default.join(linkTarget, 'browsers.json'));555 const descriptors = readDescriptors(browsersJSON);556 for (const browserName of allDownloadable) {557 // We retain browsers if they are found in the descriptor.558 // Note, however, that there are older versions out in the wild that rely on559 // the "download" field in the browser descriptor and use its value560 // to retain and download browsers.561 // As of v1.10, we decided to abandon "download" field.562 const descriptor = descriptors.find(d => d.name === browserName);563 if (!descriptor) continue;564 const usedBrowserPath = descriptor.dir;565 const browserRevision = parseInt(descriptor.revision, 10); // Old browser installations don't have marker file.566 const shouldHaveMarkerFile = browserName === 'chromium' && browserRevision >= 786218 || browserName === 'firefox' && browserRevision >= 1128 || browserName === 'webkit' && browserRevision >= 1307 || // All new applications have a marker file right away.567 browserName !== 'firefox' && browserName !== 'chromium' && browserName !== 'webkit';568 if (!shouldHaveMarkerFile || (await (0, _utils.existsAsync)(markerFilePath(usedBrowserPath)))) usedBrowserPaths.add(usedBrowserPath);569 }570 } catch (e) {571 await fs.promises.unlink(linkPath).catch(e => {});572 }573 } // 2. Delete all unused browsers.574 if (!(0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_GC')) {575 let downloadedBrowsers = (await fs.promises.readdir(registryDirectory)).map(file => _path.default.join(registryDirectory, file));576 downloadedBrowsers = downloadedBrowsers.filter(file => isBrowserDirectory(file));577 const directories = new Set(downloadedBrowsers);578 for (const browserDirectory of usedBrowserPaths) directories.delete(browserDirectory);579 for (const directory of directories) (0, _browserFetcher.logPolitely)('Removing unused browser at ' + directory);580 await (0, _utils.removeFolders)([...directories]);581 }582 }583}584exports.Registry = Registry;585function markerFilePath(browserDirectory) {586 return _path.default.join(browserDirectory, 'INSTALLATION_COMPLETE');587}588function buildPlaywrightCLICommand(sdkLanguage, parameters) {589 switch (sdkLanguage) {590 case 'python':591 return `playwright ${parameters}`;592 case 'java':593 return `mvn exec:java -e -Dexec.mainClass=com.microsoft.playwright.CLI -Dexec.args="${parameters}"`;594 case 'csharp':595 return `playwright ${parameters}`;596 default:597 return `npx playwright ${parameters}`;598 }599}600async function installDefaultBrowsersForNpmInstall() {601 const defaultBrowserNames = registry.defaultExecutables().map(e => e.name);602 return installBrowsersForNpmInstall(defaultBrowserNames);603}604async function installBrowsersForNpmInstall(browsers) {605 // PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD should have a value of 0 or 1606 if ((0, _utils.getAsBooleanFromENV)('PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD')) {607 (0, _browserFetcher.logPolitely)('Skipping browsers download because `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` env variable is set');608 return false;609 }610 const executables = [];611 for (const browserName of browsers) {612 const executable = registry.findExecutable(browserName);613 if (!executable || executable.installType === 'none') throw new Error(`Cannot install ${browserName}`);614 executables.push(executable);615 }616 await registry.install(executables);617}618function findChromiumChannel(sdkLanguage) {619 // Fall back to the stable channels of popular vendors to work out of the box.620 // Null means no installation and no channels found.621 let channel = null;622 for (const name of ['chromium', 'chrome', 'msedge']) {623 try {624 registry.findExecutable(name).executablePathOrDie(sdkLanguage);625 channel = name === 'chromium' ? undefined : name;626 break;627 } catch (e) {}628 }629 if (channel === null) {630 const installCommand = buildPlaywrightCLICommand(sdkLanguage, `install chromium`);631 const prettyMessage = [`No chromium-based browser found on the system.`, `Please run the following command to download one:`, ``, ` ${installCommand}`, ``, `<3 Playwright Team`].join('\n');632 throw new Error('\n' + (0, _utils.wrapInASCIIBox)(prettyMessage, 1));633 }634 return channel;635}636const registry = new Registry(require('../../browsers.json'));...
utils.js
Source:utils.js
...517 stream.on('error', reject);518 stream.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));519 });520}521async function transformCommandsForRoot(commands) {522 const isRoot = process.getuid() === 0;523 if (isRoot) return {524 command: 'sh',525 args: ['-c', `${commands.join('&& ')}`],526 elevatedPermissions: false527 };528 const sudoExists = await spawnAsync('which', ['sudo']);529 if (sudoExists.code === 0) return {530 command: 'sudo',531 args: ['--', 'sh', '-c', `${commands.join('&& ')}`],532 elevatedPermissions: true533 };534 return {535 command: 'su',...
dependencies.js
Source:dependencies.js
...97 const {98 command,99 args,100 elevatedPermissions101 } = await transformCommandsForRoot(commands);102 if (dryRun) {103 console.log(`${command} ${quoteProcessArgs(args).join(' ')}`); // eslint-disable-line no-console104 return;105 }106 if (elevatedPermissions) console.log('Switching to root user to install dependencies...'); // eslint-disable-line no-console107 const child = _child_process.default.spawn(command, args, {108 stdio: 'inherit'109 });110 await new Promise((resolve, reject) => {111 child.on('exit', code => code === 0 ? resolve() : reject(new Error(`Installation process exited with code: ${code}`)));112 child.on('error', reject);113 });114}115async function validateDependenciesWindows(windowsExeAndDllDirectories) {116 const directoryPaths = windowsExeAndDllDirectories;117 const lddPaths = [];118 for (const directoryPath of directoryPaths) lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));119 const allMissingDeps = await Promise.all(lddPaths.map(lddPath => missingFileDependenciesWindows(lddPath)));120 const missingDeps = new Set();121 for (const deps of allMissingDeps) {122 for (const dep of deps) missingDeps.add(dep);123 }124 if (!missingDeps.size) return;125 let isCrtMissing = false;126 let isMediaFoundationMissing = false;127 for (const dep of missingDeps) {128 if (dep.startsWith('api-ms-win-crt') || dep === 'vcruntime140.dll' || dep === 'vcruntime140_1.dll' || dep === 'msvcp140.dll') isCrtMissing = true;else if (dep === 'mf.dll' || dep === 'mfplat.dll' || dep === 'msmpeg2vdec.dll' || dep === 'evr.dll' || dep === 'avrt.dll') isMediaFoundationMissing = true;129 }130 const details = [];131 if (isCrtMissing) {132 details.push(`Some of the Universal C Runtime files cannot be found on the system. You can fix`, `that by installing Microsoft Visual C++ Redistributable for Visual Studio from:`, `https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads`, ``);133 }134 if (isMediaFoundationMissing) {135 details.push(`Some of the Media Foundation files cannot be found on the system. If you are`, `on Windows Server try fixing this by running the following command in PowerShell`, `as Administrator:`, ``, ` Install-WindowsFeature Server-Media-Foundation`, ``, `For Windows N editions visit:`, `https://support.microsoft.com/en-us/help/3145500/media-feature-pack-list-for-windows-n-editions`, ``);136 }137 details.push(`Full list of missing libraries:`, ` ${[...missingDeps].join('\n ')}`, ``);138 const message = `Host system is missing dependencies!\n\n${details.join('\n')}`;139 if (isSupportedWindowsVersion()) {140 throw new Error(message);141 } else {142 // eslint-disable-next-line no-console143 console.warn(`WARNING: running on unsupported windows version!`); // eslint-disable-next-line no-console144 console.warn(message);145 }146}147async function validateDependenciesLinux(sdkLanguage, linuxLddDirectories, dlOpenLibraries) {148 var _deps$hostPlatform;149 const directoryPaths = linuxLddDirectories;150 const lddPaths = [];151 for (const directoryPath of directoryPaths) lddPaths.push(...(await executablesOrSharedLibraries(directoryPath)));152 const missingDepsPerFile = await Promise.all(lddPaths.map(lddPath => missingFileDependencies(lddPath, directoryPaths)));153 const missingDeps = new Set();154 for (const deps of missingDepsPerFile) {155 for (const dep of deps) missingDeps.add(dep);156 }157 for (const dep of await missingDLOPENLibraries(dlOpenLibraries)) missingDeps.add(dep);158 if (!missingDeps.size) return;159 const allMissingDeps = new Set(missingDeps); // Check Ubuntu version.160 const missingPackages = new Set();161 const libraryToPackageNameMapping = { ...(((_deps$hostPlatform = _nativeDeps.deps[_hostPlatform.hostPlatform]) === null || _deps$hostPlatform === void 0 ? void 0 : _deps$hostPlatform.lib2package) || {}),162 ...MANUAL_LIBRARY_TO_PACKAGE_NAME_UBUNTU163 }; // Translate missing dependencies to package names to install with apt.164 for (const missingDep of missingDeps) {165 const packageName = libraryToPackageNameMapping[missingDep];166 if (packageName) {167 missingPackages.add(packageName);168 missingDeps.delete(missingDep);169 }170 }171 const maybeSudo = process.getuid() !== 0 && os.platform() !== 'win32' ? 'sudo ' : '';172 const dockerInfo = await readDockerVersion();173 const errorLines = [`Host system is missing dependencies to run browsers.`]; // Ignore patch versions when comparing docker container version and Playwright version:174 // we **NEVER** roll browsers in patch releases, so native dependencies do not change.175 if (dockerInfo && !dockerInfo.driverVersion.startsWith((0, _userAgent.getPlaywrightVersion)(true176 /* majorMinorOnly */177 ) + '.')) {178 // We are running in a docker container with unmatching version.179 // In this case, we know how to install dependencies in it.180 const pwVersion = (0, _userAgent.getPlaywrightVersion)();181 const requiredDockerImage = dockerInfo.dockerImageName.replace(dockerInfo.driverVersion, pwVersion);182 errorLines.push(...[`This is most likely due to docker image version not matching Playwright version:`, `- Playwright: ${pwVersion}`, `- Docker: ${dockerInfo.driverVersion}`, ``, `Either:`, `- (recommended) use docker image "${requiredDockerImage}"`, `- (alternative 1) run the following command inside docker to install missing dependencies:`, ``, ` ${maybeSudo}${(0, _.buildPlaywrightCLICommand)(sdkLanguage, 'install-deps')}`, ``, `- (alternative 2) use Aptitude inside docker:`, ``, ` ${maybeSudo}apt-get install ${[...missingPackages].join('\\\n ')}`, ``, `<3 Playwright Team`]);183 } else if (missingPackages.size && !missingDeps.size) {184 // Only known dependencies are missing for browsers.185 // Suggest installation with a Playwright CLI.186 errorLines.push(...[`Please install them with the following command:`, ``, ` ${maybeSudo}${(0, _.buildPlaywrightCLICommand)(sdkLanguage, 'install-deps')}`, ``, `Alternatively, use Aptitude:`, ` ${maybeSudo}apt-get install ${[...missingPackages].join('\\\n ')}`, ``, `<3 Playwright Team`]);187 } else {188 // Unhappy path: we either run on unknown distribution, or we failed to resolve all missing189 // libraries to package names.190 // Print missing libraries only:191 errorLines.push(...[`Missing libraries:`, ...[...allMissingDeps].map(dep => ' ' + dep)]);192 }193 throw new Error('\n' + utils.wrapInASCIIBox(errorLines.join('\n'), 1));194}195function isSharedLib(basename) {196 switch (os.platform()) {197 case 'linux':198 return basename.endsWith('.so') || basename.includes('.so.');199 case 'win32':200 return basename.endsWith('.dll');201 default:202 return false;203 }204}205async function executablesOrSharedLibraries(directoryPath) {206 if (!_fs.default.existsSync(directoryPath)) return [];207 const allPaths = (await _fs.default.promises.readdir(directoryPath)).map(file => _path.default.resolve(directoryPath, file));208 const allStats = await Promise.all(allPaths.map(aPath => _fs.default.promises.stat(aPath)));209 const filePaths = allPaths.filter((aPath, index) => allStats[index].isFile());210 const executablersOrLibraries = (await Promise.all(filePaths.map(async filePath => {211 const basename = _path.default.basename(filePath).toLowerCase();212 if (isSharedLib(basename)) return filePath;213 if (await checkExecutable(filePath)) return filePath;214 return false;215 }))).filter(Boolean);216 return executablersOrLibraries;217}218async function missingFileDependenciesWindows(filePath) {219 const executable = _path.default.join(__dirname, '..', '..', '..', 'bin', 'PrintDeps.exe');220 const dirname = _path.default.dirname(filePath);221 const {222 stdout,223 code224 } = await (0, _spawnAsync.spawnAsync)(executable, [filePath], {225 cwd: dirname,226 env: { ...process.env,227 LD_LIBRARY_PATH: process.env.LD_LIBRARY_PATH ? `${process.env.LD_LIBRARY_PATH}:${dirname}` : dirname228 }229 });230 if (code !== 0) return [];231 const missingDeps = stdout.split('\n').map(line => line.trim()).filter(line => line.endsWith('not found') && line.includes('=>')).map(line => line.split('=>')[0].trim().toLowerCase());232 return missingDeps;233}234async function missingFileDependencies(filePath, extraLDPaths) {235 const dirname = _path.default.dirname(filePath);236 let LD_LIBRARY_PATH = extraLDPaths.join(':');237 if (process.env.LD_LIBRARY_PATH) LD_LIBRARY_PATH = `${process.env.LD_LIBRARY_PATH}:${LD_LIBRARY_PATH}`;238 const {239 stdout,240 code241 } = await (0, _spawnAsync.spawnAsync)('ldd', [filePath], {242 cwd: dirname,243 env: { ...process.env,244 LD_LIBRARY_PATH245 }246 });247 if (code !== 0) return [];248 const missingDeps = stdout.split('\n').map(line => line.trim()).filter(line => line.endsWith('not found') && line.includes('=>')).map(line => line.split('=>')[0].trim());249 return missingDeps;250}251async function missingDLOPENLibraries(libraries) {252 if (!libraries.length) return []; // NOTE: Using full-qualified path to `ldconfig` since `/sbin` is not part of the253 // default PATH in CRON.254 // @see https://github.com/microsoft/playwright/issues/3397255 const {256 stdout,257 code,258 error259 } = await (0, _spawnAsync.spawnAsync)('/sbin/ldconfig', ['-p'], {});260 if (code !== 0 || error) return [];261 const isLibraryAvailable = library => stdout.toLowerCase().includes(library.toLowerCase());262 return libraries.filter(library => !isLibraryAvailable(library));263}264const MANUAL_LIBRARY_TO_PACKAGE_NAME_UBUNTU = {265 // libgstlibav.so (the only actual library provided by gstreamer1.0-libav) is not266 // in the ldconfig cache, so we detect the actual library required for playing h.264267 // and if it's missing recommend installing missing gstreamer lib.268 // gstreamer1.0-libav -> libavcodec57 -> libx264-152269 'libx264.so': 'gstreamer1.0-libav'270};271function quoteProcessArgs(args) {272 return args.map(arg => {273 if (arg.includes(' ')) return `"${arg}"`;274 return arg;275 });276}277async function transformCommandsForRoot(commands) {278 const isRoot = process.getuid() === 0;279 if (isRoot) return {280 command: 'sh',281 args: ['-c', `${commands.join('&& ')}`],282 elevatedPermissions: false283 };284 const sudoExists = await (0, _spawnAsync.spawnAsync)('which', ['sudo']);285 if (sudoExists.code === 0) return {286 command: 'sudo',287 args: ['--', 'sh', '-c', `${commands.join('&& ')}`],288 elevatedPermissions: true289 };290 return {291 command: 'su',...
Using AI Code Generation
1const { transformCommandsForRoot } = require('@playwright/test/lib/utils/transformTest');2const { transformTestFile } = require('@playwright/test/lib/utils/transformTestFile');3const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');4const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');5const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');6const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');7const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');8const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');9const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');10const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');11const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');12const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');13const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');14const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');15const { transformTestInfo } = require('@playwright/test/lib/utils/transformTestInfo');16const {
Using AI Code Generation
1const { transformCommandsForRoot } = require('@playwright/test/lib/test');2const { test, expect } = require('@playwright/test');3test('My test', async ({ page }) => {4 const commands = await page.$eval('body', (body) => {5 const commands = [];6 for (const child of body.children) {7 commands.push({8 selector: `css=${child.tagName}`,9 });10 }11 return commands;12 });13 const transformedCommands = transformCommandsForRoot(page, commands);14 for (const command of transformedCommands) {15 await command.run();16 }17});18### `transformCommandsForRoot(page: Page, commands: ActionSequenceCommand[]): ActionSequenceCommand[]`
Using AI Code Generation
1const { transformCommandsForRoot } = require('playwright/lib/utils/transformCommands');2const { test } = require('playwright');3test('test', async ({ page }) => {4 const { commands } = await transformCommandsForRoot(page, async () => {5 await page.click('text="Get started"');6 });7 console.log(commands);8});
Using AI Code Generation
1const { transformCommandsForRoot } = require('@playwright/test/lib/test');2const { expect } = require('@playwright/test');3test('test', async ({ page }) => {4 {5 },6 {7 },8 {9 },10 {11 },12 {13 },14 {15 },16 {17 },18 {19 },20 {21 },22 {23 },24 {25 },26 {27 },28 {29 },30 {31 },32 {33 },34 {35 },36 {37 },38 {39 },40 {41 },42 {43 },44 {45 },46 {47 },48 {
Using AI Code Generation
1const { transformCommandsForRoot } = require('playwright-core/lib/server/frames');2 {3 options: {},4 },5];6const result = transformCommandsForRoot(commands, 'iframe');7console.log(result);8[ { name: 'click', selector: 'iframe >> button', options: {} } ]
Using AI Code Generation
1const { transformCommandsForRoot } = require('playwright/lib/server/frames');2 { name: 'click', selector: '#submit' },3 { name: 'click', selector: '#submit' }4];5const root = document.querySelector('#root');6const transformedCommands = transformCommandsForRoot(root, commands);7console.log(transformedCommands);
Using AI Code Generation
1const { transformCommandsForRoot } = require('playwright/lib/internal/transformers/transformer');2const { parse } = require('playwright/lib/internal/protocol/protocol');3const { generateTest } = require('playwright/lib/internal/generator/generator');4const { testGenerator } = require('playwright/lib/internal/generator/testGenerator');5const { testInfo } = require('playwright/lib/internal/generator/testInfo');6const { testModifier } = require('playwright/lib/internal/generator/testModifier');7const { testStep } = require('playwright/lib/internal/generator/testStep');8const { testType } = require('playwright/lib/internal/generator/testType');9const { testExpectation } = require('playwright/lib/internal/generator/testExpectation');10const { testExpectationNot } = require('playwright/lib/internal/generator/testExpectationNot');11const commands = parse(`12 {13 "params": {14 }15 }16 {17 "params": {18 }19 }20 {21 "params": {22 }23 }24`);25const transformedCommands = transformCommandsForRoot(commands);26const steps = transformedCommands.map(command => {27 const modifier = testModifier('test');28 const type = testType('page');29 const info = testInfo(command);30 const expectation = testExpectation(command);31 const expectationNot = testExpectationNot(command);32 const step = testStep(modifier, type, info, expectation, expectationNot);33 return step;34});35const generator = testGenerator(steps);36const test = generateTest(generator);37console.log(test);
LambdaTest’s Playwright tutorial will give you a broader idea about the Playwright automation framework, its unique features, and use cases with examples to exceed your understanding of Playwright testing. This tutorial will give A to Z guidance, from installing the Playwright framework to some best practices and advanced concepts.
Get 100 minutes of automation test minutes FREE!!