@ada-mcp/mcp-server 0.1.19 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.cjs +187 -28
- package/package.json +1 -1
- package/plugins/driver-selenium.cjs +40 -0
package/dist/cli.cjs
CHANGED
|
@@ -3005,14 +3005,55 @@ async function resolveNativeDriversDir(workspaceRoot) {
|
|
|
3005
3005
|
}
|
|
3006
3006
|
return import_node_path4.default.join(root, DEFAULT_NATIVE_DRIVERS_DIR);
|
|
3007
3007
|
}
|
|
3008
|
-
function
|
|
3008
|
+
function geckodriverMirrorBase() {
|
|
3009
|
+
const fromEnv = process.env.ADA_GECKODRIVER_MIRROR?.trim();
|
|
3010
|
+
return (fromEnv || DEFAULT_GECKODRIVER_MIRROR).replace(/\/$/, "");
|
|
3011
|
+
}
|
|
3012
|
+
function geckodriverPlatformAsset(tag) {
|
|
3013
|
+
const t = tag.startsWith("v") ? tag : `v${tag}`;
|
|
3009
3014
|
if (process.platform === "win32") {
|
|
3010
|
-
|
|
3015
|
+
const winSuffix = process.arch === "arm64" ? "win-aarch64" : process.arch === "ia32" ? "win32" : "win64";
|
|
3016
|
+
return { fileName: `geckodriver-${t}-${winSuffix}.zip`, archiveKind: "zip" };
|
|
3011
3017
|
}
|
|
3012
3018
|
if (process.platform === "darwin") {
|
|
3013
|
-
|
|
3019
|
+
const macSuffix = process.arch === "arm64" ? "macos-aarch64" : "macos";
|
|
3020
|
+
return { fileName: `geckodriver-${t}-${macSuffix}.tar.gz`, archiveKind: "tar.gz" };
|
|
3021
|
+
}
|
|
3022
|
+
const linuxSuffix = process.arch === "arm64" ? "linux-aarch64" : process.arch === "ia32" ? "linux32" : "linux64";
|
|
3023
|
+
return { fileName: `geckodriver-${t}-${linuxSuffix}.tar.gz`, archiveKind: "tar.gz" };
|
|
3024
|
+
}
|
|
3025
|
+
function parseSemverTuple(version2) {
|
|
3026
|
+
const m = version2.replace(/^v/i, "").match(/^(\d+)\.(\d+)\.(\d+)/);
|
|
3027
|
+
if (!m) {
|
|
3028
|
+
return null;
|
|
3029
|
+
}
|
|
3030
|
+
return [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
3031
|
+
}
|
|
3032
|
+
function compareSemverDesc(a, b) {
|
|
3033
|
+
const pa = parseSemverTuple(a);
|
|
3034
|
+
const pb = parseSemverTuple(b);
|
|
3035
|
+
if (!pa || !pb) {
|
|
3036
|
+
return 0;
|
|
3037
|
+
}
|
|
3038
|
+
for (let i = 0; i < 3; i += 1) {
|
|
3039
|
+
if (pa[i] !== pb[i]) {
|
|
3040
|
+
return pb[i] - pa[i];
|
|
3041
|
+
}
|
|
3014
3042
|
}
|
|
3015
|
-
return
|
|
3043
|
+
return 0;
|
|
3044
|
+
}
|
|
3045
|
+
async function fetchGeckodriverLatestFromMirror(mirrorBase) {
|
|
3046
|
+
const res = await fetch(`${mirrorBase}/`);
|
|
3047
|
+
if (!res.ok) {
|
|
3048
|
+
return null;
|
|
3049
|
+
}
|
|
3050
|
+
const html = await res.text();
|
|
3051
|
+
const tags = /* @__PURE__ */ new Set();
|
|
3052
|
+
for (const m of html.matchAll(/href="v(\d+\.\d+\.\d+)\//gi)) {
|
|
3053
|
+
tags.add(`v${m[1]}`);
|
|
3054
|
+
}
|
|
3055
|
+
const sorted = Array.from(tags).sort(compareSemverDesc);
|
|
3056
|
+
return sorted[0] ?? null;
|
|
3016
3057
|
}
|
|
3017
3058
|
function platformChromeLabel() {
|
|
3018
3059
|
if (process.platform === "win32") {
|
|
@@ -3197,6 +3238,21 @@ async function extractZip(zipPath, destDir) {
|
|
|
3197
3238
|
}
|
|
3198
3239
|
await runCommand("unzip", ["-o", zipPath, "-d", destDir]);
|
|
3199
3240
|
}
|
|
3241
|
+
async function extractTarGz(archivePath, destDir) {
|
|
3242
|
+
await import_promises4.default.mkdir(destDir, { recursive: true });
|
|
3243
|
+
if (process.platform === "win32") {
|
|
3244
|
+
await runCommand("tar", ["-xzf", archivePath, "-C", destDir]);
|
|
3245
|
+
return;
|
|
3246
|
+
}
|
|
3247
|
+
await runCommand("tar", ["-xzf", archivePath, "-C", destDir]);
|
|
3248
|
+
}
|
|
3249
|
+
async function extractDriverArchive(archivePath, destDir, kind) {
|
|
3250
|
+
if (kind === "zip") {
|
|
3251
|
+
await extractZip(archivePath, destDir);
|
|
3252
|
+
return;
|
|
3253
|
+
}
|
|
3254
|
+
await extractTarGz(archivePath, destDir);
|
|
3255
|
+
}
|
|
3200
3256
|
async function findFileRecursive(dir, fileName) {
|
|
3201
3257
|
const entries = await import_promises4.default.readdir(dir, { withFileTypes: true });
|
|
3202
3258
|
for (const ent of entries) {
|
|
@@ -3224,13 +3280,26 @@ async function fetchGeckodriverReleaseVersion(requested) {
|
|
|
3224
3280
|
if (requested && requested !== "latest") {
|
|
3225
3281
|
return requested.startsWith("v") ? requested : `v${requested}`;
|
|
3226
3282
|
}
|
|
3227
|
-
const
|
|
3228
|
-
if (
|
|
3229
|
-
|
|
3283
|
+
const mirrorLatest = await fetchGeckodriverLatestFromMirror(geckodriverMirrorBase());
|
|
3284
|
+
if (mirrorLatest) {
|
|
3285
|
+
return mirrorLatest;
|
|
3230
3286
|
}
|
|
3231
|
-
|
|
3232
|
-
|
|
3233
|
-
|
|
3287
|
+
try {
|
|
3288
|
+
const res = await fetch("https://api.github.com/repos/mozilla/geckodriver/releases/latest");
|
|
3289
|
+
if (res.ok) {
|
|
3290
|
+
const json3 = await res.json();
|
|
3291
|
+
const tag = json3.tag_name ?? "v0.36.0";
|
|
3292
|
+
return tag.startsWith("v") ? tag : `v${tag}`;
|
|
3293
|
+
}
|
|
3294
|
+
} catch {
|
|
3295
|
+
}
|
|
3296
|
+
return "v0.36.0";
|
|
3297
|
+
}
|
|
3298
|
+
function buildGeckodriverDownloadUrls(tag) {
|
|
3299
|
+
const { fileName, archiveKind } = geckodriverPlatformAsset(tag);
|
|
3300
|
+
const mirror = `${geckodriverMirrorBase()}/${tag}/${fileName}`;
|
|
3301
|
+
const github = `${GITHUB_GECKODRIVER_RELEASES}/download/${tag}/${fileName}`;
|
|
3302
|
+
return { mirror, github, fileName, archiveKind };
|
|
3234
3303
|
}
|
|
3235
3304
|
async function listChromedriverCfTVersions() {
|
|
3236
3305
|
const res = await fetch(CHROME_FOR_TESTING_JSON);
|
|
@@ -3474,26 +3543,39 @@ async function downloadToFile(url2, destPath) {
|
|
|
3474
3543
|
async function downloadGeckodriver(driversDir, versionInput, onLogLine) {
|
|
3475
3544
|
const tag = await fetchGeckodriverReleaseVersion(versionInput);
|
|
3476
3545
|
const version2 = tag.replace(/^v/, "");
|
|
3477
|
-
const
|
|
3478
|
-
const assetName = `geckodriver-${tag}-${suffix}`.replace("vv", "v");
|
|
3479
|
-
const url2 = `https://github.com/mozilla/geckodriver/releases/download/${tag}/geckodriver-${tag}-${suffix}`;
|
|
3546
|
+
const { mirror, github, fileName, archiveKind } = buildGeckodriverDownloadUrls(tag);
|
|
3480
3547
|
await import_promises4.default.mkdir(driversDir, { recursive: true });
|
|
3481
|
-
const
|
|
3548
|
+
const archiveExt = archiveKind === "zip" ? "zip" : "tar.gz";
|
|
3549
|
+
const archivePath = import_node_path4.default.join(driversDir, `_download_geckodriver_${version2}.${archiveExt}`);
|
|
3482
3550
|
const extractDir = import_node_path4.default.join(driversDir, `_extract_geckodriver_${version2}`);
|
|
3483
|
-
onLogLine?.(`[selenium]
|
|
3484
|
-
onLogLine?.(`[selenium]
|
|
3485
|
-
|
|
3551
|
+
onLogLine?.(`[selenium] ?? geckodriver ${tag}?${fileName}?? ${driversDir}`);
|
|
3552
|
+
onLogLine?.(`[selenium] ??: ${mirror}`);
|
|
3553
|
+
let downloaded = false;
|
|
3554
|
+
try {
|
|
3555
|
+
await downloadToFile(mirror, archivePath);
|
|
3556
|
+
downloaded = true;
|
|
3557
|
+
} catch (mirrorError) {
|
|
3558
|
+
onLogLine?.(
|
|
3559
|
+
`[selenium][warn] ?????????: ${mirrorError instanceof Error ? mirrorError.message : String(mirrorError)}`
|
|
3560
|
+
);
|
|
3561
|
+
onLogLine?.(`[selenium] ?? GitHub: ${github}`);
|
|
3562
|
+
await downloadToFile(github, archivePath);
|
|
3563
|
+
downloaded = true;
|
|
3564
|
+
}
|
|
3565
|
+
if (!downloaded) {
|
|
3566
|
+
throw new Error(`geckodriver download failed for ${tag}`);
|
|
3567
|
+
}
|
|
3486
3568
|
await import_promises4.default.rm(extractDir, { recursive: true, force: true });
|
|
3487
|
-
await
|
|
3569
|
+
await extractDriverArchive(archivePath, extractDir, archiveKind);
|
|
3488
3570
|
const found = await findFileRecursive(extractDir, geckodriverExeName());
|
|
3489
3571
|
if (!found) {
|
|
3490
|
-
throw new Error(`geckodriver binary not found after extracting ${
|
|
3572
|
+
throw new Error(`geckodriver binary not found after extracting ${fileName}`);
|
|
3491
3573
|
}
|
|
3492
3574
|
const dest = import_node_path4.default.join(driversDir, geckodriverExeName());
|
|
3493
3575
|
await copyExecutable(found, dest);
|
|
3494
|
-
await import_promises4.default.rm(
|
|
3576
|
+
await import_promises4.default.rm(archivePath, { force: true });
|
|
3495
3577
|
await import_promises4.default.rm(extractDir, { recursive: true, force: true });
|
|
3496
|
-
onLogLine?.(`[selenium] geckodriver
|
|
3578
|
+
onLogLine?.(`[selenium] geckodriver ???: ${dest}`);
|
|
3497
3579
|
return { path: dest, version: tag };
|
|
3498
3580
|
}
|
|
3499
3581
|
async function downloadChromedriver(driversDir, versionInput, onLogLine) {
|
|
@@ -3653,7 +3735,7 @@ async function ensureNativeWebDrivers(options = {}) {
|
|
|
3653
3735
|
}
|
|
3654
3736
|
return resolved;
|
|
3655
3737
|
}
|
|
3656
|
-
var import_node_child_process, import_promises4, import_node_path4, DEFAULT_NATIVE_DRIVERS_DIR, CHROME_FOR_TESTING_JSON;
|
|
3738
|
+
var import_node_child_process, import_promises4, import_node_path4, DEFAULT_NATIVE_DRIVERS_DIR, CHROME_FOR_TESTING_JSON, DEFAULT_GECKODRIVER_MIRROR, GITHUB_GECKODRIVER_RELEASES, SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES;
|
|
3657
3739
|
var init_src2 = __esm({
|
|
3658
3740
|
"../../packages/native-drivers/src/index.ts"() {
|
|
3659
3741
|
"use strict";
|
|
@@ -3662,6 +3744,46 @@ var init_src2 = __esm({
|
|
|
3662
3744
|
import_node_path4 = __toESM(require("node:path"), 1);
|
|
3663
3745
|
DEFAULT_NATIVE_DRIVERS_DIR = "dirver";
|
|
3664
3746
|
CHROME_FOR_TESTING_JSON = "https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json";
|
|
3747
|
+
DEFAULT_GECKODRIVER_MIRROR = "https://mirrors.huaweicloud.com/geckodriver";
|
|
3748
|
+
GITHUB_GECKODRIVER_RELEASES = "https://github.com/mozilla/geckodriver/releases";
|
|
3749
|
+
SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES = [
|
|
3750
|
+
{
|
|
3751
|
+
browser: "Chrome/Chromium",
|
|
3752
|
+
platforms: "Windows/Linux/macOS",
|
|
3753
|
+
vendor: "\u8C37\u6B4C",
|
|
3754
|
+
url: "https://chromedriver.storage.googleapis.com/index.html"
|
|
3755
|
+
},
|
|
3756
|
+
{
|
|
3757
|
+
browser: "Firefox",
|
|
3758
|
+
platforms: "Windows/Linux/macOS",
|
|
3759
|
+
vendor: "Mozilla / ?????",
|
|
3760
|
+
url: `${DEFAULT_GECKODRIVER_MIRROR}/v0.36.0/?????????????? ${GITHUB_GECKODRIVER_RELEASES}?`
|
|
3761
|
+
},
|
|
3762
|
+
{
|
|
3763
|
+
browser: "Edge",
|
|
3764
|
+
platforms: "win10",
|
|
3765
|
+
vendor: "\u5FAE\u8F6F",
|
|
3766
|
+
url: "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"
|
|
3767
|
+
},
|
|
3768
|
+
{
|
|
3769
|
+
browser: "Internet Explorer",
|
|
3770
|
+
platforms: "Windows",
|
|
3771
|
+
vendor: "Selenium \u9879\u76EE\u7EC4",
|
|
3772
|
+
url: "https://selenium-release.storage.googleapis.com/index.html"
|
|
3773
|
+
},
|
|
3774
|
+
{
|
|
3775
|
+
browser: "Safari",
|
|
3776
|
+
platforms: "macOS El Capitan \u53CA\u66F4\u9AD8\u7248\u672C",
|
|
3777
|
+
vendor: "\u82F9\u679C",
|
|
3778
|
+
url: "\uFF08\u7CFB\u7EDF\u5185\u7F6E\uFF0C\u65E0\u9700\u5355\u72EC\u4E0B\u8F7D\uFF09"
|
|
3779
|
+
},
|
|
3780
|
+
{
|
|
3781
|
+
browser: "Opera",
|
|
3782
|
+
platforms: "Windows/macOS/Linux",
|
|
3783
|
+
vendor: "Opera",
|
|
3784
|
+
url: "https://github.com/operasoftware/operachromiumdriver/releases"
|
|
3785
|
+
}
|
|
3786
|
+
];
|
|
3665
3787
|
}
|
|
3666
3788
|
});
|
|
3667
3789
|
|
|
@@ -4128,6 +4250,32 @@ function appiumDriverPackageName(driver) {
|
|
|
4128
4250
|
}
|
|
4129
4251
|
return null;
|
|
4130
4252
|
}
|
|
4253
|
+
function resolveAppiumDriverInstallTargets(driver, appiumMajor, compatibleSpecs) {
|
|
4254
|
+
const pkg = appiumDriverPackageName(driver);
|
|
4255
|
+
if (appiumMajor !== null && appiumMajor >= 3) {
|
|
4256
|
+
if (!APPIUM3_BUILTIN_DRIVER_NAMES.has(driver)) {
|
|
4257
|
+
const envHarmony = process.env.ADA_APPIUM_DRIVER_SPEC_HARMONYOS?.trim();
|
|
4258
|
+
if (driver === "harmonyos" && (envHarmony || pkg)) {
|
|
4259
|
+
return [envHarmony || pkg];
|
|
4260
|
+
}
|
|
4261
|
+
return pkg ? [pkg] : [driver];
|
|
4262
|
+
}
|
|
4263
|
+
const envOverride = driver === "uiautomator2" ? process.env.ADA_APPIUM_DRIVER_SPEC_UIAUTOMATOR2?.trim() : driver === "xcuitest" ? process.env.ADA_APPIUM_DRIVER_SPEC_XCUITEST?.trim() : "";
|
|
4264
|
+
if (envOverride) {
|
|
4265
|
+
return [envOverride, driver];
|
|
4266
|
+
}
|
|
4267
|
+
return [driver];
|
|
4268
|
+
}
|
|
4269
|
+
const baseTarget = pkg ?? driver;
|
|
4270
|
+
return compatibleSpecs.length > 0 ? compatibleSpecs : [baseTarget];
|
|
4271
|
+
}
|
|
4272
|
+
function buildAppiumDriverInstallArgs(target, appiumMajor) {
|
|
4273
|
+
const useNpmPackageSpec = appiumMajor === null || appiumMajor < 3 || target.includes("@") || target.startsWith("appium-") || target.includes("/");
|
|
4274
|
+
if (useNpmPackageSpec) {
|
|
4275
|
+
return ["exec", "appium", "driver", "install", "--source=npm", target];
|
|
4276
|
+
}
|
|
4277
|
+
return ["exec", "appium", "driver", "install", target];
|
|
4278
|
+
}
|
|
4131
4279
|
async function getAppiumMajorVersion() {
|
|
4132
4280
|
let version2 = "";
|
|
4133
4281
|
try {
|
|
@@ -4553,13 +4701,14 @@ async function runAppiumDriverInstallWithPriority(config2, driver, onLogLine) {
|
|
|
4553
4701
|
onLogLine?.(`[appium] \u5B89\u88C5\u9A71\u52A8: ${driver}`);
|
|
4554
4702
|
const compatibleSpecs = await resolveCompatibleDriverSpecs(driver);
|
|
4555
4703
|
const appiumMajor = await getAppiumMajorVersion();
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
const uniqueTargets =
|
|
4704
|
+
if (appiumMajor !== null && appiumMajor >= 3) {
|
|
4705
|
+
onLogLine?.(`[appium] \u68C0\u6D4B\u5230 Appium ${appiumMajor}.x\uFF0C\u4F7F\u7528\u5B98\u65B9\u9A71\u52A8\u540D\u5B89\u88C5\uFF08\u5982 uiautomator2\uFF09`);
|
|
4706
|
+
}
|
|
4707
|
+
const uniqueTargets = resolveAppiumDriverInstallTargets(driver, appiumMajor, compatibleSpecs);
|
|
4560
4708
|
let lastError = void 0;
|
|
4561
4709
|
for (const target of uniqueTargets) {
|
|
4562
|
-
const installArgs =
|
|
4710
|
+
const installArgs = buildAppiumDriverInstallArgs(target, appiumMajor);
|
|
4711
|
+
onLogLine?.(`[appium] \u6267\u884C: npm ${installArgs.join(" ")}`);
|
|
4563
4712
|
const strategies = [
|
|
4564
4713
|
{
|
|
4565
4714
|
name: "npm",
|
|
@@ -5182,7 +5331,7 @@ async function getDependencyHealth(config2) {
|
|
|
5182
5331
|
missingAppiumDrivers
|
|
5183
5332
|
};
|
|
5184
5333
|
}
|
|
5185
|
-
var import_node_module, import_node_fs, import_node_child_process2, import_promises5, import_node_path5, require2, PINNED_PLAYWRIGHT_VERSION, PINNED_ZOD_VERSION, depsHumanLog, DEFAULT_NPM_REGISTRY_CANDIDATES, detectedBestRegistryByKey, PROGRESS_STEPS, PROGRESS_HUMAN_LABELS, DEFAULT_PLAYWRIGHT_HOST_CANDIDATES, CHINA_NPM_REGISTRY_HINTS, CHINA_PLAYWRIGHT_HOST_PRIORITY, PLAYWRIGHT_HOST_FALLBACK, PW_INSTALL_TARGETS;
|
|
5334
|
+
var import_node_module, import_node_fs, import_node_child_process2, import_promises5, import_node_path5, require2, PINNED_PLAYWRIGHT_VERSION, PINNED_ZOD_VERSION, depsHumanLog, DEFAULT_NPM_REGISTRY_CANDIDATES, APPIUM3_BUILTIN_DRIVER_NAMES, detectedBestRegistryByKey, PROGRESS_STEPS, PROGRESS_HUMAN_LABELS, DEFAULT_PLAYWRIGHT_HOST_CANDIDATES, CHINA_NPM_REGISTRY_HINTS, CHINA_PLAYWRIGHT_HOST_PRIORITY, PLAYWRIGHT_HOST_FALLBACK, PW_INSTALL_TARGETS;
|
|
5186
5335
|
var init_dependency_installer = __esm({
|
|
5187
5336
|
"../ada-agent/src/dependency-installer.ts"() {
|
|
5188
5337
|
import_node_module = require("node:module");
|
|
@@ -5202,6 +5351,16 @@ var init_dependency_installer = __esm({
|
|
|
5202
5351
|
"https://repo.huaweicloud.com/repository/npm",
|
|
5203
5352
|
"https://registry.npmjs.org"
|
|
5204
5353
|
];
|
|
5354
|
+
APPIUM3_BUILTIN_DRIVER_NAMES = /* @__PURE__ */ new Set([
|
|
5355
|
+
"uiautomator2",
|
|
5356
|
+
"xcuitest",
|
|
5357
|
+
"espresso",
|
|
5358
|
+
"mac2",
|
|
5359
|
+
"windows",
|
|
5360
|
+
"safari",
|
|
5361
|
+
"gecko",
|
|
5362
|
+
"chromium"
|
|
5363
|
+
]);
|
|
5205
5364
|
detectedBestRegistryByKey = /* @__PURE__ */ new Map();
|
|
5206
5365
|
PROGRESS_STEPS = [
|
|
5207
5366
|
"deps.ensure.start",
|
package/package.json
CHANGED
|
@@ -232,6 +232,46 @@ var import_node_child_process = require("node:child_process");
|
|
|
232
232
|
var import_promises = __toESM(require("node:fs/promises"), 1);
|
|
233
233
|
var import_node_path = __toESM(require("node:path"), 1);
|
|
234
234
|
var DEFAULT_NATIVE_DRIVERS_DIR = "dirver";
|
|
235
|
+
var DEFAULT_GECKODRIVER_MIRROR = "https://mirrors.huaweicloud.com/geckodriver";
|
|
236
|
+
var GITHUB_GECKODRIVER_RELEASES = "https://github.com/mozilla/geckodriver/releases";
|
|
237
|
+
var SELENIUM_DRIVER_MANUAL_DOWNLOAD_REFERENCES = [
|
|
238
|
+
{
|
|
239
|
+
browser: "Chrome/Chromium",
|
|
240
|
+
platforms: "Windows/Linux/macOS",
|
|
241
|
+
vendor: "\u8C37\u6B4C",
|
|
242
|
+
url: "https://chromedriver.storage.googleapis.com/index.html"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
browser: "Firefox",
|
|
246
|
+
platforms: "Windows/Linux/macOS",
|
|
247
|
+
vendor: "Mozilla / ?????",
|
|
248
|
+
url: `${DEFAULT_GECKODRIVER_MIRROR}/v0.36.0/?????????????? ${GITHUB_GECKODRIVER_RELEASES}?`
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
browser: "Edge",
|
|
252
|
+
platforms: "win10",
|
|
253
|
+
vendor: "\u5FAE\u8F6F",
|
|
254
|
+
url: "https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
browser: "Internet Explorer",
|
|
258
|
+
platforms: "Windows",
|
|
259
|
+
vendor: "Selenium \u9879\u76EE\u7EC4",
|
|
260
|
+
url: "https://selenium-release.storage.googleapis.com/index.html"
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
browser: "Safari",
|
|
264
|
+
platforms: "macOS El Capitan \u53CA\u66F4\u9AD8\u7248\u672C",
|
|
265
|
+
vendor: "\u82F9\u679C",
|
|
266
|
+
url: "\uFF08\u7CFB\u7EDF\u5185\u7F6E\uFF0C\u65E0\u9700\u5355\u72EC\u4E0B\u8F7D\uFF09"
|
|
267
|
+
},
|
|
268
|
+
{
|
|
269
|
+
browser: "Opera",
|
|
270
|
+
platforms: "Windows/macOS/Linux",
|
|
271
|
+
vendor: "Opera",
|
|
272
|
+
url: "https://github.com/operasoftware/operachromiumdriver/releases"
|
|
273
|
+
}
|
|
274
|
+
];
|
|
235
275
|
async function fileExists(filePath) {
|
|
236
276
|
try {
|
|
237
277
|
await import_promises.default.access(filePath);
|