doc-detective 4.27.0 → 4.29.0
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.js +13 -4
- package/dist/cli.js.map +1 -1
- package/dist/common/src/detectTests.d.ts +9 -0
- package/dist/common/src/detectTests.d.ts.map +1 -1
- package/dist/common/src/detectTests.js +22 -9
- package/dist/common/src/detectTests.js.map +1 -1
- package/dist/common/src/schemas/schemas.json +85 -1
- package/dist/common/src/types/generated/report_v3.d.ts +34 -0
- package/dist/common/src/types/generated/report_v3.d.ts.map +1 -1
- package/dist/core/detectTests.d.ts.map +1 -1
- package/dist/core/detectTests.js +37 -13
- package/dist/core/detectTests.js.map +1 -1
- package/dist/core/expressions.d.ts.map +1 -1
- package/dist/core/expressions.js +24 -1
- package/dist/core/expressions.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- package/dist/core/index.js.map +1 -1
- package/dist/core/resolveTests.js +23 -12
- package/dist/core/resolveTests.js.map +1 -1
- package/dist/core/telem.d.ts +2 -1
- package/dist/core/telem.d.ts.map +1 -1
- package/dist/core/telem.js +26 -2
- package/dist/core/telem.js.map +1 -1
- package/dist/core/tests/androidEmulator.d.ts.map +1 -1
- package/dist/core/tests/androidEmulator.js +13 -0
- package/dist/core/tests/androidEmulator.js.map +1 -1
- package/dist/core/tests/appSurface.d.ts +25 -0
- package/dist/core/tests/appSurface.d.ts.map +1 -1
- package/dist/core/tests/appSurface.js +14 -11
- package/dist/core/tests/appSurface.js.map +1 -1
- package/dist/core/tests/iosSimulator.d.ts.map +1 -1
- package/dist/core/tests/iosSimulator.js +13 -0
- package/dist/core/tests/iosSimulator.js.map +1 -1
- package/dist/core/tests/mobileBrowser.d.ts +4 -1
- package/dist/core/tests/mobileBrowser.d.ts.map +1 -1
- package/dist/core/tests/mobileBrowser.js +14 -7
- package/dist/core/tests/mobileBrowser.js.map +1 -1
- package/dist/core/tests.d.ts +83 -2
- package/dist/core/tests.d.ts.map +1 -1
- package/dist/core/tests.js +572 -70
- package/dist/core/tests.js.map +1 -1
- package/dist/core/utils.d.ts +3 -2
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +37 -29
- package/dist/core/utils.js.map +1 -1
- package/dist/core/warmPhase.d.ts +161 -0
- package/dist/core/warmPhase.d.ts.map +1 -0
- package/dist/core/warmPhase.js +341 -0
- package/dist/core/warmPhase.js.map +1 -0
- package/dist/hints/context.d.ts +16 -0
- package/dist/hints/context.d.ts.map +1 -1
- package/dist/hints/context.js +34 -0
- package/dist/hints/context.js.map +1 -1
- package/dist/hints/hints.d.ts.map +1 -1
- package/dist/hints/hints.js +17 -0
- package/dist/hints/hints.js.map +1 -1
- package/dist/hints/types.d.ts +14 -0
- package/dist/hints/types.d.ts.map +1 -1
- package/dist/index.cjs +1146 -359
- package/dist/runtime/cacheDir.d.ts +5 -0
- package/dist/runtime/cacheDir.d.ts.map +1 -1
- package/dist/runtime/cacheDir.js +3 -0
- package/dist/runtime/cacheDir.js.map +1 -1
- package/dist/runtime/iosInstaller.d.ts +44 -1
- package/dist/runtime/iosInstaller.d.ts.map +1 -1
- package/dist/runtime/iosInstaller.js +381 -13
- package/dist/runtime/iosInstaller.js.map +1 -1
- package/dist/runtime/lock.d.ts +56 -0
- package/dist/runtime/lock.d.ts.map +1 -0
- package/dist/runtime/lock.js +218 -0
- package/dist/runtime/lock.js.map +1 -0
- package/dist/runtime/wdaProducts.d.ts +147 -0
- package/dist/runtime/wdaProducts.d.ts.map +1 -0
- package/dist/runtime/wdaProducts.js +234 -0
- package/dist/runtime/wdaProducts.js.map +1 -0
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -3
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -383844,6 +383844,71 @@ var init_schemas = __esm({
|
|
|
383844
383844
|
}
|
|
383845
383845
|
]
|
|
383846
383846
|
}
|
|
383847
|
+
},
|
|
383848
|
+
warm: {
|
|
383849
|
+
type: "object",
|
|
383850
|
+
description: "Results of the run's inline warm phase \u2014 the always-on, best-effort provisioning pass (dependency installs, device boots, session probes) performed between test resolution and test execution. A failed task never gates the run; the per-context paths retry or skip with their normal semantics. Absent when the run ended before the phase (for example, when no specs matched). System-populated.",
|
|
383851
|
+
readOnly: true,
|
|
383852
|
+
additionalProperties: false,
|
|
383853
|
+
required: [
|
|
383854
|
+
"durationMs",
|
|
383855
|
+
"tasks"
|
|
383856
|
+
],
|
|
383857
|
+
properties: {
|
|
383858
|
+
durationMs: {
|
|
383859
|
+
type: "number",
|
|
383860
|
+
description: "Wall-clock duration of the warm phase in milliseconds. Tasks overlap, so this is less than the sum of the per-task durations."
|
|
383861
|
+
},
|
|
383862
|
+
tasks: {
|
|
383863
|
+
type: "array",
|
|
383864
|
+
description: "One entry per executed warm task.",
|
|
383865
|
+
items: {
|
|
383866
|
+
type: "object",
|
|
383867
|
+
additionalProperties: false,
|
|
383868
|
+
required: [
|
|
383869
|
+
"name",
|
|
383870
|
+
"kind",
|
|
383871
|
+
"outcome",
|
|
383872
|
+
"durationMs"
|
|
383873
|
+
],
|
|
383874
|
+
properties: {
|
|
383875
|
+
name: {
|
|
383876
|
+
type: "string",
|
|
383877
|
+
description: "Task identity, e.g. `browser-install:chrome` or `device-boot:android:<default>:<latest>`."
|
|
383878
|
+
},
|
|
383879
|
+
kind: {
|
|
383880
|
+
type: "string",
|
|
383881
|
+
enum: [
|
|
383882
|
+
"driver-install",
|
|
383883
|
+
"browser-install",
|
|
383884
|
+
"device-boot",
|
|
383885
|
+
"wda-check",
|
|
383886
|
+
"session-probe",
|
|
383887
|
+
"chromedriver-prefetch"
|
|
383888
|
+
],
|
|
383889
|
+
description: "What the task pre-pays: a native app driver install, a browser install, a simulator/emulator boot, the managed WebDriverAgent availability check, the concurrent-run driver session probe, or the android mobile-web chromedriver download."
|
|
383890
|
+
},
|
|
383891
|
+
outcome: {
|
|
383892
|
+
type: "string",
|
|
383893
|
+
enum: [
|
|
383894
|
+
"warmed",
|
|
383895
|
+
"skipped",
|
|
383896
|
+
"failed"
|
|
383897
|
+
],
|
|
383898
|
+
description: "`warmed` \u2014 the work was performed (for device boots, the boot was initiated); `skipped` \u2014 nothing to do or the environment isn't ready (the consuming context handles it as usual); `failed` \u2014 the attempt failed (logged as a warning; never fails the run)."
|
|
383899
|
+
},
|
|
383900
|
+
durationMs: {
|
|
383901
|
+
type: "number",
|
|
383902
|
+
description: "Wall-clock duration of this task in milliseconds."
|
|
383903
|
+
},
|
|
383904
|
+
note: {
|
|
383905
|
+
type: "string",
|
|
383906
|
+
description: "Human-readable detail about the outcome."
|
|
383907
|
+
}
|
|
383908
|
+
}
|
|
383909
|
+
}
|
|
383910
|
+
}
|
|
383911
|
+
}
|
|
383847
383912
|
}
|
|
383848
383913
|
},
|
|
383849
383914
|
required: [
|
|
@@ -383865,7 +383930,26 @@ var init_schemas = __esm({
|
|
|
383865
383930
|
}
|
|
383866
383931
|
]
|
|
383867
383932
|
}
|
|
383868
|
-
]
|
|
383933
|
+
],
|
|
383934
|
+
warm: {
|
|
383935
|
+
durationMs: 4211,
|
|
383936
|
+
tasks: [
|
|
383937
|
+
{
|
|
383938
|
+
name: "browser-install:chrome",
|
|
383939
|
+
kind: "browser-install",
|
|
383940
|
+
outcome: "skipped",
|
|
383941
|
+
durationMs: 2,
|
|
383942
|
+
note: "'chrome' is already available"
|
|
383943
|
+
},
|
|
383944
|
+
{
|
|
383945
|
+
name: "session-probe",
|
|
383946
|
+
kind: "session-probe",
|
|
383947
|
+
outcome: "warmed",
|
|
383948
|
+
durationMs: 4205,
|
|
383949
|
+
note: "1 combination ok"
|
|
383950
|
+
}
|
|
383951
|
+
]
|
|
383952
|
+
}
|
|
383869
383953
|
},
|
|
383870
383954
|
{
|
|
383871
383955
|
specs: [
|
|
@@ -632440,6 +632524,8 @@ function readInstalledRecord(ctx = {}) {
|
|
|
632440
632524
|
};
|
|
632441
632525
|
if (isPlainObject(parsed?.android))
|
|
632442
632526
|
record.android = parsed.android;
|
|
632527
|
+
if (isPlainObject(parsed?.ios))
|
|
632528
|
+
record.ios = parsed.ios;
|
|
632443
632529
|
if (isPlainObject(parsed?.tools))
|
|
632444
632530
|
record.tools = parsed.tools;
|
|
632445
632531
|
return record;
|
|
@@ -633975,21 +634061,23 @@ async function loadEnvs(envsFile) {
|
|
|
633975
634061
|
return { status: "FAIL", description: "Invalid file." };
|
|
633976
634062
|
}
|
|
633977
634063
|
}
|
|
634064
|
+
function logLevelEnabled(config, level) {
|
|
634065
|
+
if (config.logLevel === "error" && level === "error")
|
|
634066
|
+
return true;
|
|
634067
|
+
if (config.logLevel === "warning" && (level === "error" || level === "warning"))
|
|
634068
|
+
return true;
|
|
634069
|
+
if (config.logLevel === "info" && (level === "error" || level === "warning" || level === "info"))
|
|
634070
|
+
return true;
|
|
634071
|
+
if (config.logLevel === "debug" && (level === "error" || level === "warning" || level === "info" || level === "debug"))
|
|
634072
|
+
return true;
|
|
634073
|
+
return false;
|
|
634074
|
+
}
|
|
633978
634075
|
async function log(config, level, message) {
|
|
633979
634076
|
if (message === void 0) {
|
|
633980
634077
|
message = config;
|
|
633981
634078
|
config = {};
|
|
633982
634079
|
}
|
|
633983
|
-
|
|
633984
|
-
if (config.logLevel === "error" && level === "error") {
|
|
633985
|
-
logLevelMatch = true;
|
|
633986
|
-
} else if (config.logLevel === "warning" && (level === "error" || level === "warning")) {
|
|
633987
|
-
logLevelMatch = true;
|
|
633988
|
-
} else if (config.logLevel === "info" && (level === "error" || level === "warning" || level === "info")) {
|
|
633989
|
-
logLevelMatch = true;
|
|
633990
|
-
} else if (config.logLevel === "debug" && (level === "error" || level === "warning" || level === "info" || level === "debug")) {
|
|
633991
|
-
logLevelMatch = true;
|
|
633992
|
-
}
|
|
634080
|
+
const logLevelMatch = logLevelEnabled(config, level);
|
|
633993
634081
|
if (logLevelMatch) {
|
|
633994
634082
|
if (typeof message === "string") {
|
|
633995
634083
|
let logMessage = `(${level.toUpperCase()}) ${message}`;
|
|
@@ -634074,8 +634162,7 @@ function replaceEnvs(stringOrObject) {
|
|
|
634074
634162
|
stringOrObject[key] = replaceEnvs(stringOrObject[key]);
|
|
634075
634163
|
});
|
|
634076
634164
|
} else if (typeof stringOrObject === "string") {
|
|
634077
|
-
const
|
|
634078
|
-
const matches = stringOrObject.match(variableRegex);
|
|
634165
|
+
const matches = stringOrObject.match(ENV_VAR_REGEX);
|
|
634079
634166
|
if (!matches)
|
|
634080
634167
|
return stringOrObject;
|
|
634081
634168
|
matches.forEach((match) => {
|
|
@@ -634319,7 +634406,7 @@ function llevenshteinDistance(s, t) {
|
|
|
634319
634406
|
}
|
|
634320
634407
|
return arr[t.length][s.length];
|
|
634321
634408
|
}
|
|
634322
|
-
var import_node_fs7, import_node_os2, import_node_path5, import_node_crypto2, import_promises, import_node_net, import_axios, import_node_child_process4, BACKGROUND_BUFFER_LIMIT, PTY_PACKAGE, READY_POLL_INTERVAL_MS, TRANSIENT_SESSION_ERROR, SESSION_TIMEOUT_ABORT, TRANSIENT_PROCESS_INIT_EXIT_CODES, SETTLE_CEILING_MAX_MS, PRESERVED_TEMP_ENTRIES, FETCH_BINARY_DEFAULTS, posixBashProbe;
|
|
634409
|
+
var import_node_fs7, import_node_os2, import_node_path5, import_node_crypto2, import_promises, import_node_net, import_axios, import_node_child_process4, BACKGROUND_BUFFER_LIMIT, PTY_PACKAGE, READY_POLL_INTERVAL_MS, TRANSIENT_SESSION_ERROR, SESSION_TIMEOUT_ABORT, TRANSIENT_PROCESS_INIT_EXIT_CODES, SETTLE_CEILING_MAX_MS, PRESERVED_TEMP_ENTRIES, FETCH_BINARY_DEFAULTS, ENV_VAR_REGEX, posixBashProbe;
|
|
634323
634410
|
var init_utils = __esm({
|
|
634324
634411
|
"dist/core/utils.js"() {
|
|
634325
634412
|
"use strict";
|
|
@@ -634361,6 +634448,7 @@ var init_utils = __esm({
|
|
|
634361
634448
|
maxBodyLength: 50 * 1024 * 1024,
|
|
634362
634449
|
maxRedirects: 5
|
|
634363
634450
|
};
|
|
634451
|
+
ENV_VAR_REGEX = /\$[a-zA-Z0-9_]+(?![a-zA-Z0-9_$])/g;
|
|
634364
634452
|
}
|
|
634365
634453
|
});
|
|
634366
634454
|
|
|
@@ -634500,12 +634588,12 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634500
634588
|
}
|
|
634501
634589
|
if (!force && existing && isStillFresh(existing.latestCheckedAt, now)) {
|
|
634502
634590
|
if (existing.latestKnownVersion === existing.installedVersion) {
|
|
634503
|
-
const
|
|
634504
|
-
return { path:
|
|
634591
|
+
const path29 = await locateExecutable(browsersModule, name, existing.installedVersion, cacheDir, platform);
|
|
634592
|
+
return { path: path29, version: existing.installedVersion, outdated: false };
|
|
634505
634593
|
}
|
|
634506
|
-
const
|
|
634594
|
+
const path28 = await locateExecutable(browsersModule, name, existing.installedVersion, cacheDir, platform);
|
|
634507
634595
|
logger(`${name} ${existing.installedVersion} installed in ${cacheDir}; "${BROWSER_CHANNELS[name]}" channel is now ${existing.latestKnownVersion}. Run \`doc-detective install browsers ${name} --force\` to update.`, "warn");
|
|
634508
|
-
return { path:
|
|
634596
|
+
return { path: path28, version: existing.installedVersion, outdated: true };
|
|
634509
634597
|
}
|
|
634510
634598
|
let latest;
|
|
634511
634599
|
try {
|
|
@@ -634513,8 +634601,8 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634513
634601
|
} catch (err) {
|
|
634514
634602
|
logger(`Channel resolution for ${name} skipped: ${String(err)}`, "debug");
|
|
634515
634603
|
if (existing) {
|
|
634516
|
-
const
|
|
634517
|
-
return { path:
|
|
634604
|
+
const path28 = await locateExecutable(browsersModule, name, existing.installedVersion, cacheDir, platform);
|
|
634605
|
+
return { path: path28, version: existing.installedVersion, outdated: false };
|
|
634518
634606
|
}
|
|
634519
634607
|
throw err;
|
|
634520
634608
|
}
|
|
@@ -634525,8 +634613,8 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634525
634613
|
latestCheckedAt: now.toISOString()
|
|
634526
634614
|
};
|
|
634527
634615
|
writeInstalledRecord(record, ctx);
|
|
634528
|
-
const
|
|
634529
|
-
return { path:
|
|
634616
|
+
const path28 = await locateExecutable(browsersModule, name, latest, cacheDir, platform);
|
|
634617
|
+
return { path: path28, version: latest, outdated: false };
|
|
634530
634618
|
}
|
|
634531
634619
|
if (!force && existing) {
|
|
634532
634620
|
record.browsers[name] = {
|
|
@@ -634536,8 +634624,8 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634536
634624
|
};
|
|
634537
634625
|
writeInstalledRecord(record, ctx);
|
|
634538
634626
|
logger(`${name} ${existing.installedVersion} installed in ${cacheDir}; "${BROWSER_CHANNELS[name]}" channel is now ${latest}. Run \`doc-detective install browsers ${name} --force\` to update.`, "warn");
|
|
634539
|
-
const
|
|
634540
|
-
return { path:
|
|
634627
|
+
const path28 = await locateExecutable(browsersModule, name, existing.installedVersion, cacheDir, platform);
|
|
634628
|
+
return { path: path28, version: existing.installedVersion, outdated: true };
|
|
634541
634629
|
}
|
|
634542
634630
|
logger(`Installing ${name} ${latest} into ${cacheDir}`, "info");
|
|
634543
634631
|
await browsersModule.install({
|
|
@@ -634545,9 +634633,9 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634545
634633
|
buildId: latest,
|
|
634546
634634
|
cacheDir
|
|
634547
634635
|
});
|
|
634548
|
-
let
|
|
634549
|
-
if (name === "chromedriver" && isAllowedDriverPath(
|
|
634550
|
-
let verify = await verifyDriverBinary(name,
|
|
634636
|
+
let path27 = await locateExecutable(browsersModule, name, latest, cacheDir, platform);
|
|
634637
|
+
if (name === "chromedriver" && isAllowedDriverPath(path27)) {
|
|
634638
|
+
let verify = await verifyDriverBinary(name, path27, { exec: deps.verifyExec });
|
|
634551
634639
|
if (!verify.ok) {
|
|
634552
634640
|
logger(`Installed ${name} ${latest} failed validation (${verify.error}); reinstalling once.`, "warn");
|
|
634553
634641
|
try {
|
|
@@ -634556,11 +634644,11 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634556
634644
|
logger(`Failed to prune broken ${name} ${latest}: ${String(err)}`, "debug");
|
|
634557
634645
|
}
|
|
634558
634646
|
await browsersModule.install({ browser: name, buildId: latest, cacheDir });
|
|
634559
|
-
|
|
634560
|
-
verify = await verifyDriverBinary(name,
|
|
634647
|
+
path27 = await locateExecutable(browsersModule, name, latest, cacheDir, platform);
|
|
634648
|
+
verify = await verifyDriverBinary(name, path27, { exec: deps.verifyExec });
|
|
634561
634649
|
}
|
|
634562
634650
|
if (!verify.ok) {
|
|
634563
|
-
throw new Error(`${name} ${latest} is present but non-functional after a reinstall (${verify.error}). It may be a partial or corrupt download; delete ${
|
|
634651
|
+
throw new Error(`${name} ${latest} is present but non-functional after a reinstall (${verify.error}). It may be a partial or corrupt download; delete ${path27} or reinstall.`);
|
|
634564
634652
|
}
|
|
634565
634653
|
}
|
|
634566
634654
|
if (existing && existing.installedVersion !== latest) {
|
|
@@ -634581,7 +634669,7 @@ async function ensureBrowserInstalledImpl(name, options = {}) {
|
|
|
634581
634669
|
latestCheckedAt: now.toISOString()
|
|
634582
634670
|
};
|
|
634583
634671
|
writeInstalledRecord(record, ctx);
|
|
634584
|
-
return { path:
|
|
634672
|
+
return { path: path27, version: latest, outdated: false };
|
|
634585
634673
|
}
|
|
634586
634674
|
async function locateExecutable(browsersModule, name, buildId, cacheDir, platform) {
|
|
634587
634675
|
if (typeof browsersModule.computeExecutablePath === "function") {
|
|
@@ -635027,10 +635115,10 @@ async function getOperation(definition = {}, operationId = "", responseCode = ""
|
|
|
635027
635115
|
if (!operationId) {
|
|
635028
635116
|
throw new Error("OperationId is required.");
|
|
635029
635117
|
}
|
|
635030
|
-
for (const
|
|
635031
|
-
for (const method in definition.paths[
|
|
635032
|
-
if (definition.paths[
|
|
635033
|
-
const operation = definition.paths[
|
|
635118
|
+
for (const path27 in definition.paths) {
|
|
635119
|
+
for (const method in definition.paths[path27]) {
|
|
635120
|
+
if (definition.paths[path27][method].operationId === operationId) {
|
|
635121
|
+
const operation = definition.paths[path27][method];
|
|
635034
635122
|
if (!server) {
|
|
635035
635123
|
if (definition.servers && definition.servers.length > 0) {
|
|
635036
635124
|
server = definition.servers[0].url;
|
|
@@ -635038,9 +635126,9 @@ async function getOperation(definition = {}, operationId = "", responseCode = ""
|
|
|
635038
635126
|
throw new Error("No server URL provided and no servers defined in the OpenAPI definition.");
|
|
635039
635127
|
}
|
|
635040
635128
|
}
|
|
635041
|
-
const example = await compileExample(operation, server +
|
|
635129
|
+
const example = await compileExample(operation, server + path27, responseCode, exampleKey);
|
|
635042
635130
|
const schemas2 = getSchemas(operation, responseCode);
|
|
635043
|
-
return { path:
|
|
635131
|
+
return { path: path27, method, definition: operation, schemas: schemas2, example };
|
|
635044
635132
|
}
|
|
635045
635133
|
}
|
|
635046
635134
|
}
|
|
@@ -635061,15 +635149,15 @@ function getSchemas(definition = {}, responseCode = "") {
|
|
|
635061
635149
|
schemas2.response = definition.responses[responseCode].content[Object.keys(definition.responses[responseCode].content)[0]].schema;
|
|
635062
635150
|
return schemas2;
|
|
635063
635151
|
}
|
|
635064
|
-
async function compileExample(operation = {},
|
|
635152
|
+
async function compileExample(operation = {}, path27 = "", responseCode = "", exampleKey = "") {
|
|
635065
635153
|
if (!operation) {
|
|
635066
635154
|
throw new Error("Operation is required.");
|
|
635067
635155
|
}
|
|
635068
|
-
if (!
|
|
635156
|
+
if (!path27) {
|
|
635069
635157
|
throw new Error("Path is required.");
|
|
635070
635158
|
}
|
|
635071
635159
|
let example = {
|
|
635072
|
-
url:
|
|
635160
|
+
url: path27,
|
|
635073
635161
|
request: { parameters: {}, headers: {}, body: {} },
|
|
635074
635162
|
response: { headers: {}, body: {} }
|
|
635075
635163
|
};
|
|
@@ -636494,17 +636582,24 @@ function detectFileTypeFromContent(content) {
|
|
|
636494
636582
|
}
|
|
636495
636583
|
|
|
636496
636584
|
// dist/common/src/detectTests.js
|
|
636585
|
+
var compiledRegExpCache = /* @__PURE__ */ new Map();
|
|
636497
636586
|
function safeRegExp(pattern, flags) {
|
|
636498
636587
|
if (typeof pattern !== "string" || pattern.length === 0)
|
|
636499
636588
|
return null;
|
|
636500
636589
|
if (pattern.length > 1500)
|
|
636501
636590
|
return null;
|
|
636502
|
-
const
|
|
636591
|
+
const cacheKey = pattern + " " + flags;
|
|
636592
|
+
const cached = compiledRegExpCache.get(cacheKey);
|
|
636593
|
+
if (cached !== void 0)
|
|
636594
|
+
return cached;
|
|
636595
|
+
let compiled;
|
|
636503
636596
|
try {
|
|
636504
|
-
|
|
636597
|
+
compiled = new RegExp(pattern, flags);
|
|
636505
636598
|
} catch {
|
|
636506
|
-
|
|
636599
|
+
compiled = null;
|
|
636507
636600
|
}
|
|
636601
|
+
compiledRegExpCache.set(cacheKey, compiled);
|
|
636602
|
+
return compiled;
|
|
636508
636603
|
}
|
|
636509
636604
|
var HASH_EXCLUDED_KEYS = /* @__PURE__ */ new Set([
|
|
636510
636605
|
"location",
|
|
@@ -638217,12 +638312,16 @@ function generateSpecId(filePath) {
|
|
|
638217
638312
|
const normalizedPath = relativePath.split(import_node_path11.default.sep).join("/").replace(/^\.\//, "").replace(/[^a-zA-Z0-9._\-\/]/g, "_");
|
|
638218
638313
|
return normalizedPath;
|
|
638219
638314
|
}
|
|
638220
|
-
|
|
638221
|
-
|
|
638222
|
-
|
|
638223
|
-
|
|
638224
|
-
allowedExtensions = allowedExtensions.concat(fileType.extensions);
|
|
638315
|
+
function buildAllowedExtensions(config) {
|
|
638316
|
+
const allowed = /* @__PURE__ */ new Set(["json", "yaml", "yml"]);
|
|
638317
|
+
(config.fileTypes || []).forEach((fileType) => {
|
|
638318
|
+
fileType.extensions.forEach((ext) => allowed.add(ext));
|
|
638225
638319
|
});
|
|
638320
|
+
return allowed;
|
|
638321
|
+
}
|
|
638322
|
+
async function isValidSourceFile({ config, files, source, allowedExtensions }) {
|
|
638323
|
+
log(config, "debug", `validation: ${source}`);
|
|
638324
|
+
const allowed = allowedExtensions;
|
|
638226
638325
|
if (files.indexOf(source) >= 0)
|
|
638227
638326
|
return false;
|
|
638228
638327
|
if (import_node_path11.default.extname(source) === ".json" || import_node_path11.default.extname(source) === ".yaml" || import_node_path11.default.extname(source) === ".yml") {
|
|
@@ -638269,7 +638368,7 @@ async function isValidSourceFile({ config, files, source }) {
|
|
|
638269
638368
|
}
|
|
638270
638369
|
}
|
|
638271
638370
|
const extension = import_node_path11.default.extname(source).substring(1);
|
|
638272
|
-
if (!
|
|
638371
|
+
if (!allowed.has(extension)) {
|
|
638273
638372
|
log(config, "debug", `${source} extension isn't specified in a \`config.fileTypes\` object. Skipping.`);
|
|
638274
638373
|
return false;
|
|
638275
638374
|
}
|
|
@@ -638321,6 +638420,7 @@ async function qualifyFiles({ config }) {
|
|
|
638321
638420
|
return [];
|
|
638322
638421
|
}
|
|
638323
638422
|
const ignoredDitaMaps = [];
|
|
638423
|
+
const allowedExtensions = buildAllowedExtensions(config);
|
|
638324
638424
|
if (!config._herettoPathMapping) {
|
|
638325
638425
|
config._herettoPathMapping = {};
|
|
638326
638426
|
}
|
|
@@ -638388,8 +638488,9 @@ async function qualifyFiles({ config }) {
|
|
|
638388
638488
|
let isFile = false;
|
|
638389
638489
|
let isDir = false;
|
|
638390
638490
|
try {
|
|
638391
|
-
|
|
638392
|
-
|
|
638491
|
+
const stat = import_node_fs13.default.statSync(source);
|
|
638492
|
+
isFile = stat.isFile();
|
|
638493
|
+
isDir = stat.isDirectory();
|
|
638393
638494
|
} catch {
|
|
638394
638495
|
log(config, "warning", `Cannot access path: ${source}. Skipping.`);
|
|
638395
638496
|
continue;
|
|
@@ -638404,7 +638505,7 @@ async function qualifyFiles({ config }) {
|
|
|
638404
638505
|
continue;
|
|
638405
638506
|
}
|
|
638406
638507
|
const resolved = import_node_path11.default.resolve(source);
|
|
638407
|
-
if (isFile && await isValidSourceFile({ config, files, source: resolved })) {
|
|
638508
|
+
if (isFile && await isValidSourceFile({ config, files, allowedExtensions, source: resolved })) {
|
|
638408
638509
|
files.push(resolved);
|
|
638409
638510
|
if (!phaseByFile.has(resolved))
|
|
638410
638511
|
phaseByFile.set(resolved, phase);
|
|
@@ -638417,9 +638518,10 @@ async function qualifyFiles({ config }) {
|
|
|
638417
638518
|
const content = import_node_path11.default.resolve(dir + "/" + object);
|
|
638418
638519
|
if (content.includes("node_modules"))
|
|
638419
638520
|
continue;
|
|
638420
|
-
const
|
|
638421
|
-
const
|
|
638422
|
-
|
|
638521
|
+
const stat = import_node_fs13.default.statSync(content);
|
|
638522
|
+
const isFile2 = stat.isFile();
|
|
638523
|
+
const isDir2 = stat.isDirectory();
|
|
638524
|
+
if (isFile2 && await isValidSourceFile({ config, files, allowedExtensions, source: content })) {
|
|
638423
638525
|
const resolved2 = import_node_path11.default.resolve(content);
|
|
638424
638526
|
files.push(resolved2);
|
|
638425
638527
|
if (!phaseByFile.has(resolved2))
|
|
@@ -638783,12 +638885,14 @@ function resolveContexts({ contexts, test, config }) {
|
|
|
638783
638885
|
if (resolvedContexts.length === 0) {
|
|
638784
638886
|
resolvedContexts.push({});
|
|
638785
638887
|
}
|
|
638786
|
-
|
|
638888
|
+
if (logLevelEnabled(config, "debug"))
|
|
638889
|
+
log(config, "debug", `Resolved contexts for test ${test.testId}:
|
|
638787
638890
|
${JSON.stringify(resolvedContexts, null, 2)}`);
|
|
638788
638891
|
return resolvedContexts;
|
|
638789
638892
|
}
|
|
638790
638893
|
async function fetchOpenApiDocuments({ config, documentArray }) {
|
|
638791
|
-
|
|
638894
|
+
if (logLevelEnabled(config, "debug"))
|
|
638895
|
+
log(config, "debug", `Fetching OpenAPI documents:
|
|
638792
638896
|
${JSON.stringify(documentArray, null, 2)}`);
|
|
638793
638897
|
const openApiDocuments = [];
|
|
638794
638898
|
if (config?.integrations?.openApi?.length > 0)
|
|
@@ -638809,7 +638913,8 @@ ${JSON.stringify(documentArray, null, 2)}`);
|
|
|
638809
638913
|
openApiDocuments.push(definition);
|
|
638810
638914
|
}
|
|
638811
638915
|
}
|
|
638812
|
-
|
|
638916
|
+
if (logLevelEnabled(config, "debug"))
|
|
638917
|
+
log(config, "debug", `Fetched OpenAPI documents:
|
|
638813
638918
|
${JSON.stringify(openApiDocuments, null, 2)}`);
|
|
638814
638919
|
return openApiDocuments;
|
|
638815
638920
|
}
|
|
@@ -638829,7 +638934,8 @@ async function resolveContext({ config, test, context, usedContextIds, openApi }
|
|
|
638829
638934
|
context.contextId = context.contextId ? uniqueId(context.contextId, usedContextIds) : deriveContextId({ context, usedIds: usedContextIds });
|
|
638830
638935
|
const contextId = context.contextId;
|
|
638831
638936
|
usedContextIds.add(contextId);
|
|
638832
|
-
|
|
638937
|
+
if (logLevelEnabled(config, "debug"))
|
|
638938
|
+
log(config, "debug", `RESOLVING CONTEXT ID ${contextId}:
|
|
638833
638939
|
${JSON.stringify(context, null, 2)}`);
|
|
638834
638940
|
const resolvedContext = {
|
|
638835
638941
|
...context,
|
|
@@ -638842,13 +638948,15 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
638842
638948
|
steps: [...test.steps],
|
|
638843
638949
|
contextId
|
|
638844
638950
|
};
|
|
638845
|
-
|
|
638951
|
+
if (logLevelEnabled(config, "debug"))
|
|
638952
|
+
log(config, "debug", `RESOLVED CONTEXT ${contextId}:
|
|
638846
638953
|
${JSON.stringify(resolvedContext, null, 2)}`);
|
|
638847
638954
|
return resolvedContext;
|
|
638848
638955
|
}
|
|
638849
638956
|
async function resolveTest({ config, spec, test }) {
|
|
638850
638957
|
const testId = test.testId || `${spec.specId}~${contentHash(test)}`;
|
|
638851
|
-
|
|
638958
|
+
if (logLevelEnabled(config, "debug"))
|
|
638959
|
+
log(config, "debug", `RESOLVING TEST ID ${testId}:
|
|
638852
638960
|
${JSON.stringify(test, null, 2)}`);
|
|
638853
638961
|
const resolvedTest = {
|
|
638854
638962
|
...test,
|
|
@@ -638878,13 +638986,15 @@ ${JSON.stringify(test, null, 2)}`);
|
|
|
638878
638986
|
});
|
|
638879
638987
|
resolvedTest.contexts.push(resolvedContext);
|
|
638880
638988
|
}
|
|
638881
|
-
|
|
638989
|
+
if (logLevelEnabled(config, "debug"))
|
|
638990
|
+
log(config, "debug", `RESOLVED TEST ${testId}:
|
|
638882
638991
|
${JSON.stringify(resolvedTest, null, 2)}`);
|
|
638883
638992
|
return resolvedTest;
|
|
638884
638993
|
}
|
|
638885
638994
|
async function resolveSpec({ config, spec }) {
|
|
638886
638995
|
const specId = spec.specId || (spec.contentPath ? generateSpecId(spec.contentPath) : import_node_crypto5.default.randomUUID());
|
|
638887
|
-
|
|
638996
|
+
if (logLevelEnabled(config, "debug"))
|
|
638997
|
+
log(config, "debug", `RESOLVING SPEC ID ${specId}:
|
|
638888
638998
|
${JSON.stringify(spec, null, 2)}`);
|
|
638889
638999
|
const resolvedSpec = {
|
|
638890
639000
|
...spec,
|
|
@@ -638904,12 +639014,14 @@ ${JSON.stringify(spec, null, 2)}`);
|
|
|
638904
639014
|
});
|
|
638905
639015
|
resolvedSpec.tests.push(resolvedTest);
|
|
638906
639016
|
}
|
|
638907
|
-
|
|
639017
|
+
if (logLevelEnabled(config, "debug"))
|
|
639018
|
+
log(config, "debug", `RESOLVED SPEC ${specId}:
|
|
638908
639019
|
${JSON.stringify(resolvedSpec, null, 2)}`);
|
|
638909
639020
|
return resolvedSpec;
|
|
638910
639021
|
}
|
|
638911
639022
|
async function resolveTests({ config, detectedTests }) {
|
|
638912
|
-
|
|
639023
|
+
if (logLevelEnabled(config, "debug"))
|
|
639024
|
+
log(config, "debug", `RESOLVING DETECTED TEST SPECS:
|
|
638913
639025
|
${JSON.stringify(detectedTests, null, 2)}`);
|
|
638914
639026
|
const resolvedTests = {
|
|
638915
639027
|
resolvedTestsId: import_node_crypto5.default.randomUUID(),
|
|
@@ -638921,7 +639033,8 @@ ${JSON.stringify(detectedTests, null, 2)}`);
|
|
|
638921
639033
|
const resolvedSpec = await resolveSpec({ config, spec });
|
|
638922
639034
|
resolvedTests.specs.push(resolvedSpec);
|
|
638923
639035
|
}
|
|
638924
|
-
|
|
639036
|
+
if (logLevelEnabled(config, "debug"))
|
|
639037
|
+
log(config, "debug", `RESOLVED TEST SPECS:
|
|
638925
639038
|
${JSON.stringify(resolvedTests, null, 2)}`);
|
|
638926
639039
|
return resolvedTests;
|
|
638927
639040
|
}
|
|
@@ -638931,7 +639044,7 @@ init_utils();
|
|
|
638931
639044
|
|
|
638932
639045
|
// dist/core/tests.js
|
|
638933
639046
|
var import_tree_kill3 = __toESM(require("tree-kill"), 1);
|
|
638934
|
-
var
|
|
639047
|
+
var import_node_fs29 = __toESM(require("node:fs"), 1);
|
|
638935
639048
|
init_loader();
|
|
638936
639049
|
init_browsers();
|
|
638937
639050
|
init_browserStepKeys();
|
|
@@ -639644,12 +639757,116 @@ async function resolveCloseTargets(driver, ref, opts = {}) {
|
|
|
639644
639757
|
}
|
|
639645
639758
|
|
|
639646
639759
|
// dist/core/tests/appSurface.js
|
|
639647
|
-
var
|
|
639648
|
-
var
|
|
639649
|
-
var
|
|
639760
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
639761
|
+
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
639762
|
+
var import_node_child_process10 = require("node:child_process");
|
|
639650
639763
|
init_loader();
|
|
639651
639764
|
init_appium();
|
|
639652
639765
|
init_cacheDir();
|
|
639766
|
+
|
|
639767
|
+
// dist/runtime/wdaProducts.js
|
|
639768
|
+
var import_node_child_process7 = require("node:child_process");
|
|
639769
|
+
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
639770
|
+
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
639771
|
+
init_cacheDir();
|
|
639772
|
+
init_loader();
|
|
639773
|
+
function parseXcodebuildVersion(output) {
|
|
639774
|
+
const text = String(output ?? "");
|
|
639775
|
+
const version = /^\s*Xcode\s+(\S+)/m.exec(text)?.[1];
|
|
639776
|
+
const build = /^\s*Build version\s+(\S+)/m.exec(text)?.[1];
|
|
639777
|
+
if (!version || !build)
|
|
639778
|
+
return null;
|
|
639779
|
+
return { version, build };
|
|
639780
|
+
}
|
|
639781
|
+
function getWdaRoot(ctx = {}) {
|
|
639782
|
+
return import_node_path12.default.join(getCacheDir(ctx), "ios", "wda");
|
|
639783
|
+
}
|
|
639784
|
+
function sanitizeKeySegment(value) {
|
|
639785
|
+
return (value || "unknown").trim().replace(/[^A-Za-z0-9._-]+/g, "-") || "unknown";
|
|
639786
|
+
}
|
|
639787
|
+
function computeWdaKey(xcode, driverVersion) {
|
|
639788
|
+
return `xcode-${sanitizeKeySegment(xcode.version)}-${sanitizeKeySegment(xcode.build)}-driver-${sanitizeKeySegment(driverVersion)}`;
|
|
639789
|
+
}
|
|
639790
|
+
var RUNNER_APP_RELATIVE = import_node_path12.default.join("DerivedData", "Build", "Products", "Debug-iphonesimulator", "WebDriverAgentRunner-Runner.app");
|
|
639791
|
+
var PRODUCTS_MARKER = "products.json";
|
|
639792
|
+
var LAST_USED_STAMP = "last-used";
|
|
639793
|
+
function readProductsMarker(keyDir, fs28) {
|
|
639794
|
+
try {
|
|
639795
|
+
const parsed = JSON.parse(String(fs28.readFileSync(import_node_path12.default.join(keyDir, PRODUCTS_MARKER))));
|
|
639796
|
+
if (typeof parsed?.key !== "string" || typeof parsed?.driverVersion !== "string") {
|
|
639797
|
+
return null;
|
|
639798
|
+
}
|
|
639799
|
+
if (!fs28.existsSync(import_node_path12.default.join(keyDir, RUNNER_APP_RELATIVE)))
|
|
639800
|
+
return null;
|
|
639801
|
+
return parsed;
|
|
639802
|
+
} catch {
|
|
639803
|
+
return null;
|
|
639804
|
+
}
|
|
639805
|
+
}
|
|
639806
|
+
function touchLastUsed(keyDir, fs28, now) {
|
|
639807
|
+
try {
|
|
639808
|
+
fs28.writeFileSync(import_node_path12.default.join(keyDir, LAST_USED_STAMP), String(now()));
|
|
639809
|
+
} catch {
|
|
639810
|
+
}
|
|
639811
|
+
}
|
|
639812
|
+
var MIN_PREBUILT_WDA_DRIVER_MAJOR = 10;
|
|
639813
|
+
var cachedXcodeProbe;
|
|
639814
|
+
function probeXcodeVersionCached() {
|
|
639815
|
+
if (cachedXcodeProbe === void 0) {
|
|
639816
|
+
try {
|
|
639817
|
+
const result = (0, import_node_child_process7.spawnSync)("xcodebuild", ["-version"], {
|
|
639818
|
+
encoding: "utf8",
|
|
639819
|
+
windowsHide: true,
|
|
639820
|
+
timeout: 15e3
|
|
639821
|
+
});
|
|
639822
|
+
cachedXcodeProbe = result.status === 0 ? parseXcodebuildVersion(result.stdout) : null;
|
|
639823
|
+
} catch {
|
|
639824
|
+
cachedXcodeProbe = null;
|
|
639825
|
+
}
|
|
639826
|
+
}
|
|
639827
|
+
return cachedXcodeProbe;
|
|
639828
|
+
}
|
|
639829
|
+
function locateManagedWda(options = {}) {
|
|
639830
|
+
const { ctx = {}, fs: fs28 = import_node_fs14.default, platform = process.platform, probeXcode = probeXcodeVersionCached, resolveDriverVersion = resolveHeavyDepVersion, now = Date.now } = options;
|
|
639831
|
+
try {
|
|
639832
|
+
if (platform !== "darwin")
|
|
639833
|
+
return null;
|
|
639834
|
+
const driverVersion = resolveDriverVersion("appium-xcuitest-driver", ctx);
|
|
639835
|
+
if (!driverVersion)
|
|
639836
|
+
return null;
|
|
639837
|
+
const driverMajor = Number.parseInt(driverVersion, 10);
|
|
639838
|
+
if (!Number.isFinite(driverMajor) || driverMajor < MIN_PREBUILT_WDA_DRIVER_MAJOR) {
|
|
639839
|
+
return null;
|
|
639840
|
+
}
|
|
639841
|
+
const xcode = probeXcode();
|
|
639842
|
+
if (!xcode)
|
|
639843
|
+
return null;
|
|
639844
|
+
const wdaRoot = import_node_path12.default.normalize(options.wdaRootDir ?? getWdaRoot(ctx));
|
|
639845
|
+
const key = computeWdaKey(xcode, driverVersion);
|
|
639846
|
+
const keyDir = import_node_path12.default.join(wdaRoot, key);
|
|
639847
|
+
const marker = readProductsMarker(keyDir, fs28);
|
|
639848
|
+
if (!marker || marker.key !== key)
|
|
639849
|
+
return null;
|
|
639850
|
+
touchLastUsed(keyDir, fs28, now);
|
|
639851
|
+
return { key, derivedDataPath: import_node_path12.default.join(keyDir, "DerivedData") };
|
|
639852
|
+
} catch {
|
|
639853
|
+
return null;
|
|
639854
|
+
}
|
|
639855
|
+
}
|
|
639856
|
+
function applyManagedWdaCapabilities(capabilities, locateWda) {
|
|
639857
|
+
const derivedDataPath = process.env.DOC_DETECTIVE_IOS_WDA_DERIVED_DATA_PATH;
|
|
639858
|
+
if (derivedDataPath && derivedDataPath.trim()) {
|
|
639859
|
+
capabilities["appium:derivedDataPath"] = derivedDataPath.trim();
|
|
639860
|
+
return;
|
|
639861
|
+
}
|
|
639862
|
+
const managed = locateWda?.();
|
|
639863
|
+
if (managed) {
|
|
639864
|
+
capabilities["appium:derivedDataPath"] = managed.derivedDataPath;
|
|
639865
|
+
capabilities["appium:usePrebuiltWDA"] = true;
|
|
639866
|
+
}
|
|
639867
|
+
}
|
|
639868
|
+
|
|
639869
|
+
// dist/core/tests/appSurface.js
|
|
639653
639870
|
init_utils();
|
|
639654
639871
|
|
|
639655
639872
|
// dist/core/tests/appWindows.js
|
|
@@ -640088,17 +640305,17 @@ async function closeAppWindow({ entry, selector }) {
|
|
|
640088
640305
|
}
|
|
640089
640306
|
|
|
640090
640307
|
// dist/core/tests/androidEmulator.js
|
|
640091
|
-
var
|
|
640308
|
+
var import_node_child_process9 = require("node:child_process");
|
|
640092
640309
|
|
|
640093
640310
|
// dist/runtime/androidInstaller.js
|
|
640094
|
-
var
|
|
640311
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
640095
640312
|
var import_node_os6 = __toESM(require("node:os"), 1);
|
|
640096
|
-
var
|
|
640097
|
-
var
|
|
640313
|
+
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
640314
|
+
var import_node_child_process8 = require("node:child_process");
|
|
640098
640315
|
init_cacheDir();
|
|
640099
640316
|
|
|
640100
640317
|
// dist/runtime/androidSdk.js
|
|
640101
|
-
var
|
|
640318
|
+
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
640102
640319
|
init_cacheDir();
|
|
640103
640320
|
function trimTrailingSeparators(s) {
|
|
640104
640321
|
let end = s.length;
|
|
@@ -640142,7 +640359,7 @@ function usable(tools) {
|
|
|
640142
640359
|
}
|
|
640143
640360
|
function detectAndroidSdk(ctx = {}, deps = {}) {
|
|
640144
640361
|
const env = deps.env ?? process.env;
|
|
640145
|
-
const existsSync2 = deps.existsSync ??
|
|
640362
|
+
const existsSync2 = deps.existsSync ?? import_node_fs15.default.existsSync;
|
|
640146
640363
|
const platform = deps.platform ?? process.platform;
|
|
640147
640364
|
const cacheRoot = safeCacheDir(ctx);
|
|
640148
640365
|
const cacheAndroidSdk = deps.cacheAndroidSdk ?? (cacheRoot ? joinFor(platform, cacheRoot, "android-sdk") : void 0);
|
|
@@ -640248,11 +640465,11 @@ function resolveJavaHome(extractDir, entries, platform = process.platform) {
|
|
|
640248
640465
|
const top = entries.find((e) => /jdk|jre/i.test(e));
|
|
640249
640466
|
if (!top)
|
|
640250
640467
|
return null;
|
|
640251
|
-
const base =
|
|
640252
|
-
return platform === "darwin" ?
|
|
640468
|
+
const base = import_node_path13.default.join(extractDir, top);
|
|
640469
|
+
return platform === "darwin" ? import_node_path13.default.join(base, "Contents", "Home") : base;
|
|
640253
640470
|
}
|
|
640254
640471
|
function javaBinPath(javaHome, platform = process.platform) {
|
|
640255
|
-
return
|
|
640472
|
+
return import_node_path13.default.join(javaHome, "bin", platform === "win32" ? "java.exe" : "java");
|
|
640256
640473
|
}
|
|
640257
640474
|
function cmdlineToolsUrl(platform) {
|
|
640258
640475
|
const token = platform === "win32" ? "win" : platform === "darwin" ? "mac" : "linux";
|
|
@@ -640293,9 +640510,9 @@ function pickSystemImage(images, { osVersion, abi }) {
|
|
|
640293
640510
|
return candidates.length > 0 ? candidates[0].pkg : null;
|
|
640294
640511
|
}
|
|
640295
640512
|
function listInstalledSystemImages(sdkRoot, deps = {}) {
|
|
640296
|
-
const existsSync2 = deps.existsSync ??
|
|
640297
|
-
const readdirSync = deps.readdirSync ?? ((p) =>
|
|
640298
|
-
const base =
|
|
640513
|
+
const existsSync2 = deps.existsSync ?? import_node_fs16.default.existsSync;
|
|
640514
|
+
const readdirSync = deps.readdirSync ?? ((p) => import_node_fs16.default.readdirSync(p));
|
|
640515
|
+
const base = import_node_path13.default.join(sdkRoot, "system-images");
|
|
640299
640516
|
if (!existsSync2(base))
|
|
640300
640517
|
return [];
|
|
640301
640518
|
const out = [];
|
|
@@ -640308,14 +640525,14 @@ function listInstalledSystemImages(sdkRoot, deps = {}) {
|
|
|
640308
640525
|
for (const api of apis) {
|
|
640309
640526
|
let tags = [];
|
|
640310
640527
|
try {
|
|
640311
|
-
tags = readdirSync(
|
|
640528
|
+
tags = readdirSync(import_node_path13.default.join(base, api));
|
|
640312
640529
|
} catch {
|
|
640313
640530
|
continue;
|
|
640314
640531
|
}
|
|
640315
640532
|
for (const tag of tags) {
|
|
640316
640533
|
let abis = [];
|
|
640317
640534
|
try {
|
|
640318
|
-
abis = readdirSync(
|
|
640535
|
+
abis = readdirSync(import_node_path13.default.join(base, api, tag));
|
|
640319
640536
|
} catch {
|
|
640320
640537
|
continue;
|
|
640321
640538
|
}
|
|
@@ -640331,22 +640548,22 @@ function systemImageDir(sdkRoot, pkg) {
|
|
|
640331
640548
|
const parts = pkg.split(";");
|
|
640332
640549
|
if (parts.length !== 4 || parts[0] !== "system-images")
|
|
640333
640550
|
return null;
|
|
640334
|
-
const base =
|
|
640335
|
-
const dir =
|
|
640336
|
-
const rel =
|
|
640337
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
640551
|
+
const base = import_node_path13.default.join(sdkRoot, "system-images");
|
|
640552
|
+
const dir = import_node_path13.default.join(base, parts[1], parts[2], parts[3]);
|
|
640553
|
+
const rel = import_node_path13.default.relative(base, dir);
|
|
640554
|
+
if (rel === "" || rel.startsWith("..") || import_node_path13.default.isAbsolute(rel))
|
|
640338
640555
|
return null;
|
|
640339
640556
|
return dir;
|
|
640340
640557
|
}
|
|
640341
640558
|
function isSystemImageComplete(sdkRoot, pkg, deps = {}) {
|
|
640342
|
-
const existsSync2 = deps.existsSync ??
|
|
640559
|
+
const existsSync2 = deps.existsSync ?? import_node_fs16.default.existsSync;
|
|
640343
640560
|
const dir = systemImageDir(sdkRoot, pkg);
|
|
640344
640561
|
if (!dir)
|
|
640345
640562
|
return false;
|
|
640346
|
-
return SYSTEM_IMAGE_MARKERS.every((marker) => existsSync2(
|
|
640563
|
+
return SYSTEM_IMAGE_MARKERS.every((marker) => existsSync2(import_node_path13.default.join(dir, marker)));
|
|
640347
640564
|
}
|
|
640348
640565
|
function wipeSystemImage(sdkRoot, pkg, deps = {}) {
|
|
640349
|
-
const rmSync = deps.rmSync ??
|
|
640566
|
+
const rmSync = deps.rmSync ?? import_node_fs16.default.rmSync;
|
|
640350
640567
|
const dir = systemImageDir(sdkRoot, pkg);
|
|
640351
640568
|
if (!dir)
|
|
640352
640569
|
return;
|
|
@@ -640444,7 +640661,7 @@ async function runSdkInstallWithRetry(run2, command, args, opts = {}, deps = {})
|
|
|
640444
640661
|
}
|
|
640445
640662
|
function applyJavaEnv(javaHome, platform) {
|
|
640446
640663
|
process.env.JAVA_HOME = javaHome;
|
|
640447
|
-
const bin =
|
|
640664
|
+
const bin = import_node_path13.default.join(javaHome, "bin");
|
|
640448
640665
|
const sep = platform === "win32" ? ";" : ":";
|
|
640449
640666
|
if (!(process.env.PATH ?? "").split(sep).includes(bin)) {
|
|
640450
640667
|
process.env.PATH = `${bin}${sep}${process.env.PATH ?? ""}`;
|
|
@@ -640479,7 +640696,7 @@ async function installAndroid({ yes = false, force = false, dryRun = false, osVe
|
|
|
640479
640696
|
const abi = hostAbi(deps.arch);
|
|
640480
640697
|
const detect = deps.detect ?? detectAndroidSdk;
|
|
640481
640698
|
const fsDeps = deps.fs ?? {};
|
|
640482
|
-
const cacheSdkRoot =
|
|
640699
|
+
const cacheSdkRoot = import_node_path13.default.join(getCacheDir(ctx), "android-sdk");
|
|
640483
640700
|
const detected = detect(ctx, {});
|
|
640484
640701
|
const installedImages = detected ? listInstalledSystemImages(detected.sdkRoot, fsDeps) : [];
|
|
640485
640702
|
const needAvailable = pickSystemImage(installedImages, { osVersion, abi }) === null;
|
|
@@ -640519,7 +640736,7 @@ async function installAndroid({ yes = false, force = false, dryRun = false, osVe
|
|
|
640519
640736
|
logger("Android SDK licenses: https://developer.android.com/studio/terms", "info");
|
|
640520
640737
|
return [{ kind: "android", assetId: "confirmation", action: "declined" }];
|
|
640521
640738
|
}
|
|
640522
|
-
const cacheJreRoot =
|
|
640739
|
+
const cacheJreRoot = import_node_path13.default.join(getCacheDir(ctx), "jre");
|
|
640523
640740
|
const java = await ensureJava({
|
|
640524
640741
|
javaPresent: deps.javaPresent ?? realJavaPresent,
|
|
640525
640742
|
cacheJreRoot,
|
|
@@ -640635,7 +640852,7 @@ function actionAssetId(a) {
|
|
|
640635
640852
|
}
|
|
640636
640853
|
function toolPath(sdkRoot, tool, platform) {
|
|
640637
640854
|
const suffix = platform === "win32" ? ".bat" : "";
|
|
640638
|
-
return
|
|
640855
|
+
return import_node_path13.default.join(sdkRoot, "cmdline-tools", "latest", "bin", tool + suffix);
|
|
640639
640856
|
}
|
|
640640
640857
|
var SAFE_SHELL_TOKEN = /^[A-Za-z0-9 ._:;=\\/@+~()-]*$/;
|
|
640641
640858
|
function winShellCommand(command, args) {
|
|
@@ -640670,16 +640887,16 @@ function nowIso() {
|
|
|
640670
640887
|
}
|
|
640671
640888
|
function realJavaPresent() {
|
|
640672
640889
|
try {
|
|
640673
|
-
const res = (0,
|
|
640890
|
+
const res = (0, import_node_child_process8.spawnSync)("java", ["-version"], { stdio: "ignore" });
|
|
640674
640891
|
return res.status === 0;
|
|
640675
640892
|
} catch {
|
|
640676
640893
|
return false;
|
|
640677
640894
|
}
|
|
640678
640895
|
}
|
|
640679
640896
|
function androidAvdHome() {
|
|
640680
|
-
const home =
|
|
640897
|
+
const home = import_node_path13.default.join(import_node_os6.default.homedir(), ".android", "avd");
|
|
640681
640898
|
try {
|
|
640682
|
-
|
|
640899
|
+
import_node_fs16.default.mkdirSync(home, { recursive: true });
|
|
640683
640900
|
} catch {
|
|
640684
640901
|
}
|
|
640685
640902
|
return home;
|
|
@@ -640690,12 +640907,12 @@ async function realRun(command, args, opts = {}) {
|
|
|
640690
640907
|
ANDROID_AVD_HOME: androidAvdHome()
|
|
640691
640908
|
};
|
|
640692
640909
|
const useShell = process.platform === "win32" && /\.(bat|cmd)$/i.test(command);
|
|
640693
|
-
const child = useShell ? (0,
|
|
640910
|
+
const child = useShell ? (0, import_node_child_process8.spawn)(winShellCommand(command, args), {
|
|
640694
640911
|
cwd: opts.cwd,
|
|
640695
640912
|
stdio: ["pipe", "pipe", "pipe"],
|
|
640696
640913
|
shell: true,
|
|
640697
640914
|
env
|
|
640698
|
-
}) : (0,
|
|
640915
|
+
}) : (0, import_node_child_process8.spawn)(command, args, {
|
|
640699
640916
|
cwd: opts.cwd,
|
|
640700
640917
|
stdio: ["pipe", "pipe", "pipe"],
|
|
640701
640918
|
env
|
|
@@ -640713,20 +640930,20 @@ async function realRun(command, args, opts = {}) {
|
|
|
640713
640930
|
});
|
|
640714
640931
|
}
|
|
640715
640932
|
function realDetectCachedJavaHome(cacheJreRoot) {
|
|
640716
|
-
if (!
|
|
640933
|
+
if (!import_node_fs16.default.existsSync(cacheJreRoot))
|
|
640717
640934
|
return null;
|
|
640718
|
-
const entries =
|
|
640935
|
+
const entries = import_node_fs16.default.readdirSync(cacheJreRoot);
|
|
640719
640936
|
const home = resolveJavaHome(cacheJreRoot, entries, process.platform);
|
|
640720
|
-
return home &&
|
|
640937
|
+
return home && import_node_fs16.default.existsSync(javaBinPath(home)) ? home : null;
|
|
640721
640938
|
}
|
|
640722
640939
|
async function realBootstrapJava(cacheJreRoot) {
|
|
640723
640940
|
const url = jreDownloadUrl();
|
|
640724
|
-
const tmpDir =
|
|
640941
|
+
const tmpDir = import_node_fs16.default.mkdtempSync(import_node_path13.default.join(import_node_os6.default.tmpdir(), "dd-jre-"));
|
|
640725
640942
|
try {
|
|
640726
|
-
const archive =
|
|
640943
|
+
const archive = import_node_path13.default.join(tmpDir, jreArchiveFilename());
|
|
640727
640944
|
await downloadFile(url, archive);
|
|
640728
|
-
|
|
640729
|
-
|
|
640945
|
+
import_node_fs16.default.rmSync(cacheJreRoot, { recursive: true, force: true });
|
|
640946
|
+
import_node_fs16.default.mkdirSync(cacheJreRoot, { recursive: true });
|
|
640730
640947
|
await extractZip(archive, cacheJreRoot);
|
|
640731
640948
|
const home = realDetectCachedJavaHome(cacheJreRoot);
|
|
640732
640949
|
if (!home) {
|
|
@@ -640734,31 +640951,31 @@ async function realBootstrapJava(cacheJreRoot) {
|
|
|
640734
640951
|
}
|
|
640735
640952
|
return home;
|
|
640736
640953
|
} finally {
|
|
640737
|
-
|
|
640954
|
+
import_node_fs16.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
640738
640955
|
}
|
|
640739
640956
|
}
|
|
640740
640957
|
async function realBootstrap(url, destSdkRoot) {
|
|
640741
|
-
const tmpDir =
|
|
640958
|
+
const tmpDir = import_node_fs16.default.mkdtempSync(import_node_path13.default.join(import_node_os6.default.tmpdir(), "dd-android-cli-"));
|
|
640742
640959
|
try {
|
|
640743
|
-
const zipPath =
|
|
640960
|
+
const zipPath = import_node_path13.default.join(tmpDir, "cmdline-tools.zip");
|
|
640744
640961
|
await downloadFile(url, zipPath);
|
|
640745
|
-
const extractDir =
|
|
640746
|
-
|
|
640962
|
+
const extractDir = import_node_path13.default.join(tmpDir, "extracted");
|
|
640963
|
+
import_node_fs16.default.mkdirSync(extractDir, { recursive: true });
|
|
640747
640964
|
await extractZip(zipPath, extractDir);
|
|
640748
|
-
const inner =
|
|
640749
|
-
if (!
|
|
640965
|
+
const inner = import_node_path13.default.join(extractDir, "cmdline-tools");
|
|
640966
|
+
if (!import_node_fs16.default.existsSync(inner)) {
|
|
640750
640967
|
throw new Error("unexpected command-line tools archive layout (no top-level cmdline-tools/)");
|
|
640751
640968
|
}
|
|
640752
|
-
const dest =
|
|
640753
|
-
|
|
640754
|
-
|
|
640969
|
+
const dest = import_node_path13.default.join(destSdkRoot, "cmdline-tools", "latest");
|
|
640970
|
+
import_node_fs16.default.mkdirSync(import_node_path13.default.dirname(dest), { recursive: true });
|
|
640971
|
+
import_node_fs16.default.rmSync(dest, { recursive: true, force: true });
|
|
640755
640972
|
try {
|
|
640756
|
-
|
|
640973
|
+
import_node_fs16.default.renameSync(inner, dest);
|
|
640757
640974
|
} catch {
|
|
640758
|
-
|
|
640975
|
+
import_node_fs16.default.cpSync(inner, dest, { recursive: true });
|
|
640759
640976
|
}
|
|
640760
640977
|
} finally {
|
|
640761
|
-
|
|
640978
|
+
import_node_fs16.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
640762
640979
|
}
|
|
640763
640980
|
}
|
|
640764
640981
|
|
|
@@ -640978,6 +641195,13 @@ async function teardownDeviceRegistry(registry, kill4) {
|
|
|
640978
641195
|
for (const entry of registry.values()) {
|
|
640979
641196
|
if (!entry.bootedByUs)
|
|
640980
641197
|
continue;
|
|
641198
|
+
if (entry.ready) {
|
|
641199
|
+
try {
|
|
641200
|
+
await entry.ready;
|
|
641201
|
+
} catch {
|
|
641202
|
+
continue;
|
|
641203
|
+
}
|
|
641204
|
+
}
|
|
640981
641205
|
try {
|
|
640982
641206
|
await kill4(entry);
|
|
640983
641207
|
} catch {
|
|
@@ -640987,7 +641211,7 @@ async function teardownDeviceRegistry(registry, kill4) {
|
|
|
640987
641211
|
}
|
|
640988
641212
|
function runTool(command, args, timeout = 3e4, env) {
|
|
640989
641213
|
return new Promise((resolve) => {
|
|
640990
|
-
(0,
|
|
641214
|
+
(0, import_node_child_process9.execFile)(command, args, { timeout, env }, (error, stdout) => {
|
|
640991
641215
|
resolve({ code: error?.code ?? 0, stdout: String(stdout ?? "") });
|
|
640992
641216
|
});
|
|
640993
641217
|
});
|
|
@@ -641031,11 +641255,11 @@ async function realCreateAvd(avdmanagerPath, { name, systemImage, device }, env)
|
|
|
641031
641255
|
"--force"
|
|
641032
641256
|
];
|
|
641033
641257
|
await new Promise((resolve, reject) => {
|
|
641034
|
-
const child = useShell ? (0,
|
|
641258
|
+
const child = useShell ? (0, import_node_child_process9.spawn)(winShellCommand(avdmanagerPath, args), {
|
|
641035
641259
|
stdio: ["pipe", "ignore", "pipe"],
|
|
641036
641260
|
shell: true,
|
|
641037
641261
|
env
|
|
641038
|
-
}) : (0,
|
|
641262
|
+
}) : (0, import_node_child_process9.spawn)(avdmanagerPath, args, { stdio: ["pipe", "ignore", "pipe"], env });
|
|
641039
641263
|
let err = "";
|
|
641040
641264
|
child.stderr?.on("data", (d) => err += d.toString());
|
|
641041
641265
|
child.on("error", reject);
|
|
@@ -641048,7 +641272,7 @@ async function realBootEmulator(emulatorPath, adbPath, desc, port, env, timeout
|
|
|
641048
641272
|
const udid = udidForPort(port);
|
|
641049
641273
|
const bootDesc = { ...desc, headless: effectiveHeadless(desc) };
|
|
641050
641274
|
const bootArgs = emulatorBootArgs(bootDesc, port);
|
|
641051
|
-
const child = (0,
|
|
641275
|
+
const child = (0, import_node_child_process9.spawn)(emulatorPath, bootArgs, {
|
|
641052
641276
|
detached: false,
|
|
641053
641277
|
stdio: ["ignore", "pipe", "pipe"],
|
|
641054
641278
|
env
|
|
@@ -641088,7 +641312,7 @@ function buildAcquireDeviceDeps(sdk, abi, log3) {
|
|
|
641088
641312
|
const emulator = sdk.emulator ?? "emulator";
|
|
641089
641313
|
const avdmanager = sdk.avdmanager ?? "avdmanager";
|
|
641090
641314
|
const javaPresent = () => {
|
|
641091
|
-
const { status } = (0,
|
|
641315
|
+
const { status } = (0, import_node_child_process9.spawnSync)("java", ["-version"], { stdio: "ignore" });
|
|
641092
641316
|
return status === 0;
|
|
641093
641317
|
};
|
|
641094
641318
|
const env = {
|
|
@@ -641736,7 +641960,7 @@ var APP_DRIVER_PLATFORMS = {
|
|
|
641736
641960
|
if (extras?.udid)
|
|
641737
641961
|
capabilities["appium:udid"] = extras.udid;
|
|
641738
641962
|
if (descriptor.install) {
|
|
641739
|
-
capabilities["appium:app"] =
|
|
641963
|
+
capabilities["appium:app"] = import_node_path14.default.resolve(descriptor.install);
|
|
641740
641964
|
}
|
|
641741
641965
|
if (descriptor.activity) {
|
|
641742
641966
|
capabilities["appium:appActivity"] = descriptor.activity;
|
|
@@ -641779,20 +642003,17 @@ var APP_DRIVER_PLATFORMS = {
|
|
|
641779
642003
|
if (classifyAppIdentifier(appId) === "id") {
|
|
641780
642004
|
capabilities["appium:bundleId"] = appId;
|
|
641781
642005
|
} else {
|
|
641782
|
-
capabilities["appium:app"] =
|
|
642006
|
+
capabilities["appium:app"] = import_node_path14.default.resolve(appId);
|
|
641783
642007
|
}
|
|
641784
642008
|
if (descriptor.install) {
|
|
641785
|
-
capabilities["appium:app"] =
|
|
642009
|
+
capabilities["appium:app"] = import_node_path14.default.resolve(descriptor.install);
|
|
641786
642010
|
}
|
|
641787
642011
|
if (extras?.udid)
|
|
641788
642012
|
capabilities["appium:udid"] = extras.udid;
|
|
641789
642013
|
const timeout = descriptor.timeout ?? 6e4;
|
|
641790
642014
|
capabilities["appium:wdaLaunchTimeout"] = Math.max(timeout, 12e4);
|
|
641791
642015
|
capabilities["appium:wdaConnectionTimeout"] = Math.max(timeout, 12e4);
|
|
641792
|
-
|
|
641793
|
-
if (derivedDataPath && derivedDataPath.trim()) {
|
|
641794
|
-
capabilities["appium:derivedDataPath"] = derivedDataPath.trim();
|
|
641795
|
-
}
|
|
642016
|
+
applyManagedWdaCapabilities(capabilities, extras?.locateWda);
|
|
641796
642017
|
return capabilities;
|
|
641797
642018
|
},
|
|
641798
642019
|
unsupportedFields: [
|
|
@@ -641852,18 +642073,18 @@ function resolveAppSurfaceRef(surface, appSession) {
|
|
|
641852
642073
|
return null;
|
|
641853
642074
|
}
|
|
641854
642075
|
function invalidateStaleAppiumManifest(home, driverPackage) {
|
|
641855
|
-
const cacheDir =
|
|
642076
|
+
const cacheDir = import_node_path14.default.join(home, "node_modules", ".cache", "appium");
|
|
641856
642077
|
try {
|
|
641857
|
-
const manifest =
|
|
642078
|
+
const manifest = import_node_fs17.default.readFileSync(import_node_path14.default.join(cacheDir, "extensions.yaml"), "utf8");
|
|
641858
642079
|
if (!manifest.includes(driverPackage)) {
|
|
641859
|
-
|
|
642080
|
+
import_node_fs17.default.rmSync(cacheDir, { recursive: true, force: true });
|
|
641860
642081
|
}
|
|
641861
642082
|
} catch {
|
|
641862
642083
|
}
|
|
641863
642084
|
}
|
|
641864
642085
|
async function probeMacAccessibility() {
|
|
641865
642086
|
return await new Promise((resolve) => {
|
|
641866
|
-
(0,
|
|
642087
|
+
(0, import_node_child_process10.execFile)("osascript", [
|
|
641867
642088
|
"-l",
|
|
641868
642089
|
"JavaScript",
|
|
641869
642090
|
"-e",
|
|
@@ -641879,7 +642100,7 @@ async function probeMacAccessibility() {
|
|
|
641879
642100
|
function probeIosToolchain(deps = {}) {
|
|
641880
642101
|
const platform = deps.platform ?? process.platform;
|
|
641881
642102
|
const run2 = deps.run ?? ((command, args) => {
|
|
641882
|
-
const result = (0,
|
|
642103
|
+
const result = (0, import_node_child_process10.spawnSync)(command, args, {
|
|
641883
642104
|
encoding: "utf8",
|
|
641884
642105
|
windowsHide: true,
|
|
641885
642106
|
// xcrun/simctl gets 2 minutes for the cold CoreSimulator warm-up;
|
|
@@ -642170,7 +642391,8 @@ async function startAppSurface({ config, step, appSession, platform, serverDeps
|
|
|
642170
642391
|
const deviceSession = sessions.get(deviceName);
|
|
642171
642392
|
if (!deviceSession) {
|
|
642172
642393
|
const capabilities = platformDriver.buildCapabilities(descriptor, appId, {
|
|
642173
|
-
udid: acquired.entry.udid
|
|
642394
|
+
udid: acquired.entry.udid,
|
|
642395
|
+
locateWda: serverDeps.locateWda ?? (() => locateManagedWda({ ctx: { cacheDir: config?.cacheDir } }))
|
|
642174
642396
|
});
|
|
642175
642397
|
Object.assign(capabilities, descriptor.driverOptions ?? {});
|
|
642176
642398
|
try {
|
|
@@ -642189,7 +642411,7 @@ async function startAppSurface({ config, step, appSession, platform, serverDeps
|
|
|
642189
642411
|
driver = deviceSession.driver;
|
|
642190
642412
|
try {
|
|
642191
642413
|
if (descriptor.install)
|
|
642192
|
-
await driver.installApp(
|
|
642414
|
+
await driver.installApp(import_node_path14.default.resolve(descriptor.install));
|
|
642193
642415
|
if (descriptor.activity) {
|
|
642194
642416
|
await driver.execute("mobile: startActivity", {
|
|
642195
642417
|
appPackage: appId,
|
|
@@ -642355,7 +642577,7 @@ function defaultForceKill(pid) {
|
|
|
642355
642577
|
function queryWindowsProcessTable() {
|
|
642356
642578
|
return new Promise((resolve, reject) => {
|
|
642357
642579
|
const script = 'Get-CimInstance Win32_Process | ForEach-Object { "$($_.ProcessId),$($_.ParentProcessId)" }';
|
|
642358
|
-
(0,
|
|
642580
|
+
(0, import_node_child_process10.execFile)("powershell.exe", ["-NoProfile", "-NonInteractive", "-Command", script], { windowsHide: true, timeout: 1e4, maxBuffer: 16 * 1024 * 1024 }, (error, stdout) => {
|
|
642359
642581
|
if (error)
|
|
642360
642582
|
return reject(error);
|
|
642361
642583
|
const rows = [];
|
|
@@ -642830,10 +643052,10 @@ init_validate();
|
|
|
642830
643052
|
init_loader();
|
|
642831
643053
|
|
|
642832
643054
|
// dist/core/tests/ffmpegRecorder.js
|
|
642833
|
-
var
|
|
643055
|
+
var import_node_child_process11 = require("node:child_process");
|
|
642834
643056
|
var import_node_os7 = __toESM(require("node:os"), 1);
|
|
642835
|
-
var
|
|
642836
|
-
var
|
|
643057
|
+
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
643058
|
+
var import_node_fs18 = __toESM(require("node:fs"), 1);
|
|
642837
643059
|
var import_node_crypto6 = __toESM(require("node:crypto"), 1);
|
|
642838
643060
|
init_loader();
|
|
642839
643061
|
init_utils();
|
|
@@ -642912,7 +643134,7 @@ function browserCaptureTitle(contextId) {
|
|
|
642912
643134
|
return `RECORD_ME_${safeContextId(contextId)}`;
|
|
642913
643135
|
}
|
|
642914
643136
|
function browserDownloadDir(contextId) {
|
|
642915
|
-
return
|
|
643137
|
+
return import_node_path15.default.join(import_node_os7.default.tmpdir(), "doc-detective", "recordings", safeContextId(contextId));
|
|
642916
643138
|
}
|
|
642917
643139
|
function engineFields(record) {
|
|
642918
643140
|
const engine = record && typeof record === "object" ? record.engine : void 0;
|
|
@@ -643051,11 +643273,11 @@ async function resolveCropGeometry({ driver, target }) {
|
|
|
643051
643273
|
return null;
|
|
643052
643274
|
}
|
|
643053
643275
|
function ffmpegPathEnv(ffmpegPath, baseEnv = process.env) {
|
|
643054
|
-
const dir =
|
|
643276
|
+
const dir = import_node_path15.default.dirname(ffmpegPath);
|
|
643055
643277
|
const pathKey = Object.keys(baseEnv).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
643056
643278
|
const existing = baseEnv[pathKey];
|
|
643057
643279
|
return {
|
|
643058
|
-
[pathKey]: existing ? `${dir}${
|
|
643280
|
+
[pathKey]: existing ? `${dir}${import_node_path15.default.delimiter}${existing}` : dir
|
|
643059
643281
|
};
|
|
643060
643282
|
}
|
|
643061
643283
|
function parseCaptureFrameSize(stderr) {
|
|
@@ -643079,7 +643301,7 @@ async function detectDisplayPointSize() {
|
|
|
643079
643301
|
if (process.platform !== "darwin")
|
|
643080
643302
|
return null;
|
|
643081
643303
|
return await new Promise((resolve) => {
|
|
643082
|
-
(0,
|
|
643304
|
+
(0, import_node_child_process11.execFile)("osascript", [
|
|
643083
643305
|
"-l",
|
|
643084
643306
|
"JavaScript",
|
|
643085
643307
|
"-e",
|
|
@@ -643225,7 +643447,7 @@ async function detectMacScreenIndex(ffmpegPath) {
|
|
|
643225
643447
|
resolve(v);
|
|
643226
643448
|
};
|
|
643227
643449
|
try {
|
|
643228
|
-
proc = (0,
|
|
643450
|
+
proc = (0, import_node_child_process11.spawn)(ffmpegPath, ["-f", "avfoundation", "-list_devices", "true", "-i", ""], { stdio: ["ignore", "ignore", "pipe"] });
|
|
643229
643451
|
proc.stderr?.on("data", (d) => {
|
|
643230
643452
|
out += d.toString();
|
|
643231
643453
|
});
|
|
@@ -643254,7 +643476,7 @@ async function detectX11ScreenSize(display) {
|
|
|
643254
643476
|
};
|
|
643255
643477
|
try {
|
|
643256
643478
|
const env = display ? { ...process.env, DISPLAY: display } : process.env;
|
|
643257
|
-
proc = (0,
|
|
643479
|
+
proc = (0, import_node_child_process11.spawn)("xdpyinfo", [], { env, stdio: ["ignore", "pipe", "ignore"] });
|
|
643258
643480
|
proc.stdout?.on("data", (d) => {
|
|
643259
643481
|
out += d.toString();
|
|
643260
643482
|
});
|
|
@@ -643272,7 +643494,7 @@ async function detectX11ScreenSize(display) {
|
|
|
643272
643494
|
async function checkSystemBinary(name) {
|
|
643273
643495
|
return new Promise((resolve) => {
|
|
643274
643496
|
try {
|
|
643275
|
-
const proc = (0,
|
|
643497
|
+
const proc = (0, import_node_child_process11.spawn)(name, ["-help"], { stdio: "ignore" });
|
|
643276
643498
|
proc.on("error", () => resolve(false));
|
|
643277
643499
|
proc.on("close", () => resolve(true));
|
|
643278
643500
|
} catch {
|
|
@@ -643289,7 +643511,7 @@ async function startXvfb(display, opts = {}) {
|
|
|
643289
643511
|
const w = opts.width ?? defW;
|
|
643290
643512
|
const h = opts.height ?? defH;
|
|
643291
643513
|
const startMs = Date.now();
|
|
643292
|
-
const proc = (0,
|
|
643514
|
+
const proc = (0, import_node_child_process11.spawn)("Xvfb", [display, "-screen", "0", `${w}x${h}x24`, "-nolisten", "tcp"], { stdio: "ignore" });
|
|
643293
643515
|
let spawnErr = null;
|
|
643294
643516
|
proc.on("error", (e) => {
|
|
643295
643517
|
spawnErr = e;
|
|
@@ -643301,7 +643523,7 @@ async function startXvfb(display, opts = {}) {
|
|
|
643301
643523
|
if (proc.exitCode !== null)
|
|
643302
643524
|
throw new Error(`Xvfb exited early on ${display} (code ${proc.exitCode})`);
|
|
643303
643525
|
try {
|
|
643304
|
-
if (
|
|
643526
|
+
if (import_node_fs18.default.statSync(lock).mtimeMs >= startMs)
|
|
643305
643527
|
return proc;
|
|
643306
643528
|
} catch {
|
|
643307
643529
|
}
|
|
@@ -643573,11 +643795,11 @@ function hasUnresolvedMetaReference(expression, context) {
|
|
|
643573
643795
|
}
|
|
643574
643796
|
return false;
|
|
643575
643797
|
}
|
|
643576
|
-
function getMetaValue(
|
|
643798
|
+
function getMetaValue(path27, context) {
|
|
643577
643799
|
if (!context) {
|
|
643578
643800
|
return void 0;
|
|
643579
643801
|
}
|
|
643580
|
-
const [basePath, jsonPointer] =
|
|
643802
|
+
const [basePath, jsonPointer] = path27.split("#");
|
|
643581
643803
|
const resolvedPath = resolvePathTemplateVariables(basePath, context);
|
|
643582
643804
|
let value = getNestedProperty(context, resolvedPath);
|
|
643583
643805
|
if (jsonPointer && value) {
|
|
@@ -643594,9 +643816,9 @@ function getMetaValue(path26, context) {
|
|
|
643594
643816
|
}
|
|
643595
643817
|
return value;
|
|
643596
643818
|
}
|
|
643597
|
-
function resolvePathTemplateVariables(
|
|
643819
|
+
function resolvePathTemplateVariables(path27, context) {
|
|
643598
643820
|
const templateRegex = /\{\{(\w+)\}\}/g;
|
|
643599
|
-
return
|
|
643821
|
+
return path27.replace(templateRegex, (match, varName) => {
|
|
643600
643822
|
if (context && context.id && varName === "id") {
|
|
643601
643823
|
return context.id;
|
|
643602
643824
|
}
|
|
@@ -643633,10 +643855,10 @@ async function resolveEmbeddedExpressions(str, context) {
|
|
|
643633
643855
|
parts.push(str.slice(lastIdx));
|
|
643634
643856
|
return parts.join("");
|
|
643635
643857
|
}
|
|
643636
|
-
function getNestedProperty(obj,
|
|
643637
|
-
if (!obj || !
|
|
643858
|
+
function getNestedProperty(obj, path27) {
|
|
643859
|
+
if (!obj || !path27)
|
|
643638
643860
|
return void 0;
|
|
643639
|
-
const parts =
|
|
643861
|
+
const parts = path27.split(".");
|
|
643640
643862
|
let current = obj;
|
|
643641
643863
|
for (const part of parts) {
|
|
643642
643864
|
if (current === null || current === void 0)
|
|
@@ -643673,6 +643895,7 @@ function containsOperators(expression, allowOperators = false) {
|
|
|
643673
643895
|
}
|
|
643674
643896
|
return false;
|
|
643675
643897
|
}
|
|
643898
|
+
var compiledEvaluatorCache = /* @__PURE__ */ new Map();
|
|
643676
643899
|
async function evaluateExpression(expression, context) {
|
|
643677
643900
|
try {
|
|
643678
643901
|
expression = preprocessExpression(expression);
|
|
@@ -643746,7 +643969,13 @@ async function evaluateExpression(expression, context) {
|
|
|
643746
643969
|
}
|
|
643747
643970
|
})
|
|
643748
643971
|
};
|
|
643749
|
-
const
|
|
643972
|
+
const argNames = Object.keys(evalContext);
|
|
643973
|
+
const cacheKey = `${argNames.join(",")}\0${expression}`;
|
|
643974
|
+
let evaluator = compiledEvaluatorCache.get(cacheKey);
|
|
643975
|
+
if (!evaluator) {
|
|
643976
|
+
evaluator = new Function(...argNames, `return ${expression};`);
|
|
643977
|
+
compiledEvaluatorCache.set(cacheKey, evaluator);
|
|
643978
|
+
}
|
|
643750
643979
|
return evaluator(...Object.values(evalContext));
|
|
643751
643980
|
} catch (error) {
|
|
643752
643981
|
log(`Error evaluating expression '${expression}': ${error.message}`, "error");
|
|
@@ -645317,8 +645546,8 @@ async function startBackgroundProcessSurface({ config, descriptor, processRegist
|
|
|
645317
645546
|
}
|
|
645318
645547
|
|
|
645319
645548
|
// dist/core/tests/runShell.js
|
|
645320
|
-
var
|
|
645321
|
-
var
|
|
645549
|
+
var import_node_fs19 = __toESM(require("node:fs"), 1);
|
|
645550
|
+
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
645322
645551
|
async function runShell({ config, step, driver, processRegistry }) {
|
|
645323
645552
|
const result = {
|
|
645324
645553
|
status: "PASS",
|
|
@@ -645431,19 +645660,19 @@ async function runShell({ config, step, driver, processRegistry }) {
|
|
|
645431
645660
|
descriptions.push(stdioMatched ? `Found expected output (${step.runShell.stdio}) in stdio.` : isRegex ? `Couldn't find expected output (${step.runShell.stdio}) in actual output (stdout or stderr).` : `Couldn't find expected output (${step.runShell.stdio}) in stdio (stdout or stderr).`);
|
|
645432
645661
|
}
|
|
645433
645662
|
if (step.runShell.path) {
|
|
645434
|
-
const dir =
|
|
645435
|
-
if (!
|
|
645436
|
-
|
|
645663
|
+
const dir = import_node_path16.default.dirname(step.runShell.path);
|
|
645664
|
+
if (!import_node_fs19.default.existsSync(dir)) {
|
|
645665
|
+
import_node_fs19.default.mkdirSync(dir, { recursive: true });
|
|
645437
645666
|
}
|
|
645438
645667
|
let filePath = step.runShell.path;
|
|
645439
645668
|
log(config, "debug", `Saving stdio to file: ${filePath}`);
|
|
645440
|
-
if (!
|
|
645441
|
-
|
|
645669
|
+
if (!import_node_fs19.default.existsSync(filePath)) {
|
|
645670
|
+
import_node_fs19.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
645442
645671
|
} else {
|
|
645443
645672
|
if (step.runShell.overwrite == "false") {
|
|
645444
645673
|
descriptions.push(`Didn't save output. File already exists.`);
|
|
645445
645674
|
}
|
|
645446
|
-
const existingFile =
|
|
645675
|
+
const existingFile = import_node_fs19.default.readFileSync(filePath, "utf8");
|
|
645447
645676
|
const fractionalDiff = calculateFractionalDifference(existingFile, result.outputs.stdio.stdout);
|
|
645448
645677
|
log(config, "debug", `Fractional difference: ${fractionalDiff}`);
|
|
645449
645678
|
result.outputs.variation = fractionalDiff;
|
|
@@ -645453,13 +645682,13 @@ async function runShell({ config, step, driver, processRegistry }) {
|
|
|
645453
645682
|
});
|
|
645454
645683
|
if (fractionalDiff > step.runShell.maxVariation) {
|
|
645455
645684
|
if (step.runShell.overwrite == "aboveVariation") {
|
|
645456
|
-
|
|
645685
|
+
import_node_fs19.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
645457
645686
|
descriptions.push(`Saved output to file.`);
|
|
645458
645687
|
}
|
|
645459
645688
|
descriptions.push(`The difference between the existing output and the new output (${fractionalDiff.toFixed(2)}) is greater than the max accepted variation (${step.runShell.maxVariation}).`);
|
|
645460
645689
|
} else {
|
|
645461
645690
|
if (step.runShell.overwrite == "true") {
|
|
645462
|
-
|
|
645691
|
+
import_node_fs19.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
645463
645692
|
descriptions.push(`Saved output to file.`);
|
|
645464
645693
|
}
|
|
645465
645694
|
descriptions.push(`Saved-file variation (${fractionalDiff.toFixed(2)}) is within the max accepted variation (${step.runShell.maxVariation}).`);
|
|
@@ -645806,8 +646035,8 @@ async function swipeSurface({ config, step, driver, appSession }) {
|
|
|
645806
646035
|
// dist/core/tests/saveScreenshot.js
|
|
645807
646036
|
init_validate();
|
|
645808
646037
|
init_utils();
|
|
645809
|
-
var
|
|
645810
|
-
var
|
|
646038
|
+
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
646039
|
+
var import_node_fs20 = __toESM(require("node:fs"), 1);
|
|
645811
646040
|
init_loader();
|
|
645812
646041
|
var _pngjs = null;
|
|
645813
646042
|
var _sharp = null;
|
|
@@ -645958,7 +646187,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
645958
646187
|
if (typeof step.screenshot.path === "undefined") {
|
|
645959
646188
|
step.screenshot.path = `${step.stepId}.png`;
|
|
645960
646189
|
if (step.screenshot.directory) {
|
|
645961
|
-
step.screenshot.path =
|
|
646190
|
+
step.screenshot.path = import_node_path17.default.resolve(step.screenshot.directory, step.screenshot.path);
|
|
645962
646191
|
}
|
|
645963
646192
|
}
|
|
645964
646193
|
step.screenshot = {
|
|
@@ -645994,17 +646223,17 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
645994
646223
|
} catch {
|
|
645995
646224
|
urlPathname = originalUrlPath;
|
|
645996
646225
|
}
|
|
645997
|
-
const rawBase =
|
|
646226
|
+
const rawBase = import_node_path17.default.basename(urlPathname.split("?")[0].split("#")[0].replace(/\\/g, "/"));
|
|
645998
646227
|
const safeBase = sanitizeFilesystemName(rawBase, `${step.stepId}.png`);
|
|
645999
|
-
dir =
|
|
646000
|
-
if (!
|
|
646001
|
-
|
|
646228
|
+
dir = import_node_path17.default.join(process.cwd(), "doc-detective-runs", getOrInitRunTimestamp(config));
|
|
646229
|
+
if (!import_node_fs20.default.existsSync(dir)) {
|
|
646230
|
+
import_node_fs20.default.mkdirSync(dir, { recursive: true });
|
|
646002
646231
|
}
|
|
646003
646232
|
const captureId = `${step.stepId || "screenshot"}_${Date.now()}`;
|
|
646004
|
-
filePath =
|
|
646005
|
-
const resolvedDir =
|
|
646006
|
-
const resolvedFile =
|
|
646007
|
-
if (!resolvedFile.startsWith(resolvedDir +
|
|
646233
|
+
filePath = import_node_path17.default.join(dir, `${captureId}_${safeBase}`);
|
|
646234
|
+
const resolvedDir = import_node_path17.default.resolve(dir);
|
|
646235
|
+
const resolvedFile = import_node_path17.default.resolve(filePath);
|
|
646236
|
+
if (!resolvedFile.startsWith(resolvedDir + import_node_path17.default.sep)) {
|
|
646008
646237
|
result.status = "FAIL";
|
|
646009
646238
|
result.description = `Refusing to write screenshot outside run folder: ${resolvedFile}`;
|
|
646010
646239
|
return result;
|
|
@@ -646013,11 +646242,11 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646013
646242
|
log(config, "debug", `Screenshot path is a URL (${redactedUrl}); overwrite is ignored, running comparison only.`);
|
|
646014
646243
|
}
|
|
646015
646244
|
} else {
|
|
646016
|
-
dir =
|
|
646017
|
-
if (!
|
|
646018
|
-
|
|
646245
|
+
dir = import_node_path17.default.dirname(step.screenshot.path);
|
|
646246
|
+
if (!import_node_fs20.default.existsSync(dir)) {
|
|
646247
|
+
import_node_fs20.default.mkdirSync(dir, { recursive: true });
|
|
646019
646248
|
}
|
|
646020
|
-
if (
|
|
646249
|
+
if (import_node_fs20.default.existsSync(filePath)) {
|
|
646021
646250
|
if (step.screenshot.overwrite == "false") {
|
|
646022
646251
|
result.status = "SKIPPED";
|
|
646023
646252
|
result.description = `File already exists: ${filePath}`;
|
|
@@ -646025,7 +646254,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646025
646254
|
return result;
|
|
646026
646255
|
} else {
|
|
646027
646256
|
existFilePath = filePath;
|
|
646028
|
-
filePath =
|
|
646257
|
+
filePath = import_node_path17.default.join(dir, `${step.stepId}_${Date.now()}.png`);
|
|
646029
646258
|
}
|
|
646030
646259
|
}
|
|
646031
646260
|
}
|
|
@@ -646127,8 +646356,8 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646127
646356
|
} catch (error) {
|
|
646128
646357
|
result.status = "FAIL";
|
|
646129
646358
|
result.description = `Couldn't save screenshot. ${error}`;
|
|
646130
|
-
if (existFilePath && filePath !== existFilePath &&
|
|
646131
|
-
|
|
646359
|
+
if (existFilePath && filePath !== existFilePath && import_node_fs20.default.existsSync(filePath)) {
|
|
646360
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646132
646361
|
}
|
|
646133
646362
|
return result;
|
|
646134
646363
|
} finally {
|
|
@@ -646183,7 +646412,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646183
646412
|
rect.width = clamped.width;
|
|
646184
646413
|
rect.height = clamped.height;
|
|
646185
646414
|
log(config, "debug", { padded_rect: rect });
|
|
646186
|
-
const croppedPath =
|
|
646415
|
+
const croppedPath = import_node_path17.default.join(dir, `cropped_${step.stepId || Date.now()}.png`);
|
|
646187
646416
|
try {
|
|
646188
646417
|
await sharp(filePath).extract({
|
|
646189
646418
|
left: rect.x,
|
|
@@ -646191,12 +646420,12 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646191
646420
|
width: rect.width,
|
|
646192
646421
|
height: rect.height
|
|
646193
646422
|
}).toFile(croppedPath);
|
|
646194
|
-
|
|
646423
|
+
import_node_fs20.default.renameSync(croppedPath, filePath);
|
|
646195
646424
|
} catch (error) {
|
|
646196
646425
|
result.status = "FAIL";
|
|
646197
646426
|
result.description = `Couldn't crop image. ${error}`;
|
|
646198
|
-
if (existFilePath && filePath !== existFilePath &&
|
|
646199
|
-
|
|
646427
|
+
if (existFilePath && filePath !== existFilePath && import_node_fs20.default.existsSync(filePath)) {
|
|
646428
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646200
646429
|
}
|
|
646201
646430
|
return result;
|
|
646202
646431
|
}
|
|
@@ -646204,7 +646433,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646204
646433
|
if (existFilePath) {
|
|
646205
646434
|
if (step.screenshot.overwrite == "true" && !isUrlPath) {
|
|
646206
646435
|
result.description += ` Overwrote existing file.`;
|
|
646207
|
-
|
|
646436
|
+
import_node_fs20.default.renameSync(filePath, existFilePath);
|
|
646208
646437
|
result.outputs.screenshotPath = existFilePath;
|
|
646209
646438
|
result.outputs.changed = true;
|
|
646210
646439
|
if (step.screenshot.sourceIntegration) {
|
|
@@ -646217,13 +646446,13 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646217
646446
|
let img1;
|
|
646218
646447
|
let img2;
|
|
646219
646448
|
try {
|
|
646220
|
-
img1 = PNG.sync.read(
|
|
646221
|
-
img2 = PNG.sync.read(
|
|
646449
|
+
img1 = PNG.sync.read(import_node_fs20.default.readFileSync(existFilePath));
|
|
646450
|
+
img2 = PNG.sync.read(import_node_fs20.default.readFileSync(filePath));
|
|
646222
646451
|
} catch (error) {
|
|
646223
646452
|
result.status = "FAIL";
|
|
646224
646453
|
result.description = isUrlPath ? `Couldn't decode PNG for comparison. The URL reference (${redactedUrl}) may not be a valid PNG. ${error}` : `Couldn't decode PNG for comparison. ${error}`;
|
|
646225
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
646226
|
-
|
|
646454
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs20.default.existsSync(filePath)) {
|
|
646455
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646227
646456
|
}
|
|
646228
646457
|
return result;
|
|
646229
646458
|
}
|
|
@@ -646235,8 +646464,8 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646235
646464
|
});
|
|
646236
646465
|
if (!aspectRatioMatch) {
|
|
646237
646466
|
result.description = `Couldn't compare images. Images have different aspect ratios.`;
|
|
646238
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
646239
|
-
|
|
646467
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs20.default.existsSync(filePath)) {
|
|
646468
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646240
646469
|
}
|
|
646241
646470
|
return await evaluateApplicable();
|
|
646242
646471
|
}
|
|
@@ -646263,8 +646492,8 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646263
646492
|
} catch (error) {
|
|
646264
646493
|
result.status = "FAIL";
|
|
646265
646494
|
result.description = `Couldn't load screenshot comparison dependency (pixelmatch). ${error?.message ?? error}`;
|
|
646266
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
646267
|
-
|
|
646495
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs20.default.existsSync(filePath)) {
|
|
646496
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646268
646497
|
}
|
|
646269
646498
|
return result;
|
|
646270
646499
|
}
|
|
@@ -646282,7 +646511,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646282
646511
|
});
|
|
646283
646512
|
if (fractionalDiff > step.screenshot.maxVariation) {
|
|
646284
646513
|
if (step.screenshot.overwrite == "aboveVariation" && !isUrlPath) {
|
|
646285
|
-
|
|
646514
|
+
import_node_fs20.default.renameSync(filePath, existFilePath);
|
|
646286
646515
|
}
|
|
646287
646516
|
result.description += ` The difference between the existing screenshot and new screenshot (${fractionalDiff.toFixed(2)}) is greater than the max accepted variation (${step.screenshot.maxVariation}).`;
|
|
646288
646517
|
if (isUrlPath) {
|
|
@@ -646307,7 +646536,7 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646307
646536
|
result.outputs.sourceIntegration = step.screenshot.sourceIntegration;
|
|
646308
646537
|
}
|
|
646309
646538
|
if (step.screenshot.overwrite != "true") {
|
|
646310
|
-
|
|
646539
|
+
import_node_fs20.default.unlinkSync(filePath);
|
|
646311
646540
|
}
|
|
646312
646541
|
}
|
|
646313
646542
|
}
|
|
@@ -646326,10 +646555,10 @@ async function saveScreenshot({ config, step, driver, appSession }) {
|
|
|
646326
646555
|
// dist/core/tests/startRecording.js
|
|
646327
646556
|
init_validate();
|
|
646328
646557
|
init_utils();
|
|
646329
|
-
var
|
|
646558
|
+
var import_node_child_process12 = require("node:child_process");
|
|
646330
646559
|
var import_node_crypto7 = require("node:crypto");
|
|
646331
|
-
var
|
|
646332
|
-
var
|
|
646560
|
+
var import_node_path18 = __toESM(require("node:path"), 1);
|
|
646561
|
+
var import_node_fs21 = __toESM(require("node:fs"), 1);
|
|
646333
646562
|
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
646334
646563
|
async function startRecording({ config, context, step, driver, recordingHost, appSession, deps = {} }) {
|
|
646335
646564
|
let result = {
|
|
@@ -646398,7 +646627,7 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646398
646627
|
if (typeof step.record.path === "undefined") {
|
|
646399
646628
|
step.record.path = `${step.stepId}.mp4`;
|
|
646400
646629
|
if (step.record.directory) {
|
|
646401
|
-
step.record.path =
|
|
646630
|
+
step.record.path = import_node_path18.default.resolve(step.record.directory, step.record.path);
|
|
646402
646631
|
}
|
|
646403
646632
|
}
|
|
646404
646633
|
step.record = {
|
|
@@ -646406,18 +646635,18 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646406
646635
|
overwrite: step.record.overwrite || "false"
|
|
646407
646636
|
};
|
|
646408
646637
|
let filePath = step.record.path;
|
|
646409
|
-
const baseName =
|
|
646410
|
-
const dir =
|
|
646411
|
-
if (!
|
|
646412
|
-
|
|
646638
|
+
const baseName = import_node_path18.default.basename(filePath, import_node_path18.default.extname(filePath));
|
|
646639
|
+
const dir = import_node_path18.default.dirname(step.record.path);
|
|
646640
|
+
if (!import_node_fs21.default.existsSync(dir)) {
|
|
646641
|
+
import_node_fs21.default.mkdirSync(dir, { recursive: true });
|
|
646413
646642
|
}
|
|
646414
|
-
if (
|
|
646643
|
+
if (import_node_fs21.default.existsSync(filePath) && step.record.overwrite == "false") {
|
|
646415
646644
|
result.status = "SKIPPED";
|
|
646416
646645
|
result.description = `File already exists: ${filePath}`;
|
|
646417
646646
|
return result;
|
|
646418
646647
|
}
|
|
646419
646648
|
const normalizeActiveTarget = (p) => {
|
|
646420
|
-
const resolved =
|
|
646649
|
+
const resolved = import_node_path18.default.resolve(p);
|
|
646421
646650
|
return process.platform === "win32" || process.platform === "darwin" ? resolved.toLowerCase() : resolved;
|
|
646422
646651
|
};
|
|
646423
646652
|
const normalizedTarget = normalizeActiveTarget(filePath);
|
|
@@ -646505,13 +646734,13 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646505
646734
|
}
|
|
646506
646735
|
const captureTitle = browserCaptureTitle(context.contextId);
|
|
646507
646736
|
const downloadDir = browserDownloadDir(context.contextId);
|
|
646508
|
-
if (!
|
|
646509
|
-
|
|
646737
|
+
if (!import_node_fs21.default.existsSync(downloadDir)) {
|
|
646738
|
+
import_node_fs21.default.mkdirSync(downloadDir, { recursive: true });
|
|
646510
646739
|
}
|
|
646511
|
-
const downloadPath =
|
|
646512
|
-
if (
|
|
646740
|
+
const downloadPath = import_node_path18.default.join(downloadDir, `${baseName}.webm`);
|
|
646741
|
+
if (import_node_fs21.default.existsSync(downloadPath)) {
|
|
646513
646742
|
try {
|
|
646514
|
-
|
|
646743
|
+
import_node_fs21.default.unlinkSync(downloadPath);
|
|
646515
646744
|
} catch {
|
|
646516
646745
|
}
|
|
646517
646746
|
}
|
|
@@ -646651,10 +646880,10 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646651
646880
|
} catch {
|
|
646652
646881
|
}
|
|
646653
646882
|
}
|
|
646654
|
-
const tempDir =
|
|
646655
|
-
if (!
|
|
646656
|
-
|
|
646657
|
-
const tempPath =
|
|
646883
|
+
const tempDir = import_node_path18.default.join(import_node_os8.default.tmpdir(), "doc-detective", "recordings");
|
|
646884
|
+
if (!import_node_fs21.default.existsSync(tempDir))
|
|
646885
|
+
import_node_fs21.default.mkdirSync(tempDir, { recursive: true });
|
|
646886
|
+
const tempPath = import_node_path18.default.join(tempDir, `${safeContextId(context.contextId)}-${baseName}-${(0, import_node_crypto7.randomUUID)().slice(0, 8)}.mkv`);
|
|
646658
646887
|
let ffmpegPath;
|
|
646659
646888
|
try {
|
|
646660
646889
|
ffmpegPath = await (deps.getFfmpegPath ?? getFfmpegPath)({
|
|
@@ -646685,7 +646914,7 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646685
646914
|
screenSize
|
|
646686
646915
|
});
|
|
646687
646916
|
log(config, "debug", `ffmpeg recording: platform=${process.platform} target=${plan.target}${screenIndex !== void 0 ? ` screen=${screenIndex}` : ""}${context.__display ? ` display=${context.__display}` : ""} -> ${tempPath}`);
|
|
646688
|
-
const proc = (deps.spawn ??
|
|
646917
|
+
const proc = (deps.spawn ?? import_node_child_process12.spawn)(ffmpegPath, args, {
|
|
646689
646918
|
stdio: ["pipe", "ignore", "pipe"]
|
|
646690
646919
|
});
|
|
646691
646920
|
let spawnError = null;
|
|
@@ -646724,10 +646953,10 @@ async function startRecording({ config, context, step, driver, recordingHost, ap
|
|
|
646724
646953
|
// dist/core/tests/stopRecording.js
|
|
646725
646954
|
init_validate();
|
|
646726
646955
|
init_utils();
|
|
646727
|
-
var
|
|
646956
|
+
var import_node_child_process13 = require("node:child_process");
|
|
646728
646957
|
var import_node_crypto8 = require("node:crypto");
|
|
646729
|
-
var
|
|
646730
|
-
var
|
|
646958
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
646959
|
+
var import_node_fs22 = __toESM(require("node:fs"), 1);
|
|
646731
646960
|
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
646732
646961
|
async function stopRecording({ config, step, driver, deps = {} }) {
|
|
646733
646962
|
let result = {
|
|
@@ -646922,14 +647151,14 @@ async function stopRecording({ config, step, driver, deps = {} }) {
|
|
|
646922
647151
|
dropHandle();
|
|
646923
647152
|
return result;
|
|
646924
647153
|
}
|
|
646925
|
-
if (
|
|
646926
|
-
|
|
647154
|
+
if (import_node_path19.default.extname(recording.targetPath) === ".mp4") {
|
|
647155
|
+
import_node_fs22.default.writeFileSync(recording.targetPath, buffer);
|
|
646927
647156
|
} else {
|
|
646928
|
-
const tempDir =
|
|
646929
|
-
if (!
|
|
646930
|
-
|
|
646931
|
-
const tempPath =
|
|
646932
|
-
|
|
647157
|
+
const tempDir = import_node_path19.default.join(import_node_os9.default.tmpdir(), "doc-detective", "recordings");
|
|
647158
|
+
if (!import_node_fs22.default.existsSync(tempDir))
|
|
647159
|
+
import_node_fs22.default.mkdirSync(tempDir, { recursive: true });
|
|
647160
|
+
const tempPath = import_node_path19.default.join(tempDir, `device-${(0, import_node_crypto8.randomUUID)().slice(0, 8)}.mp4`);
|
|
647161
|
+
import_node_fs22.default.writeFileSync(tempPath, buffer);
|
|
646933
647162
|
await transcode({
|
|
646934
647163
|
config,
|
|
646935
647164
|
sourcePath: tempPath,
|
|
@@ -646957,7 +647186,7 @@ async function transcode({ config, sourcePath, targetPath, deleteSource, crop })
|
|
|
646957
647186
|
const cy = `max(0\\,min(${crop.y}\\,ih-${ch}))`;
|
|
646958
647187
|
filters.push(`crop=w=${cw}:h=${ch}:x=${cx}:y=${cy}`);
|
|
646959
647188
|
}
|
|
646960
|
-
if (
|
|
647189
|
+
if (import_node_path19.default.extname(targetPath) === ".gif") {
|
|
646961
647190
|
filters.push("scale=iw:-1:flags=lanczos");
|
|
646962
647191
|
}
|
|
646963
647192
|
if (filters.length > 0) {
|
|
@@ -646966,7 +647195,7 @@ async function transcode({ config, sourcePath, targetPath, deleteSource, crop })
|
|
|
646966
647195
|
ffmpegArgs.push(`${targetPath}`);
|
|
646967
647196
|
const ffmpegPath = await getFfmpegPath({ cacheDir: config?.cacheDir });
|
|
646968
647197
|
await new Promise((resolve, reject) => {
|
|
646969
|
-
const child = (0,
|
|
647198
|
+
const child = (0, import_node_child_process13.spawn)(ffmpegPath, ffmpegArgs);
|
|
646970
647199
|
let stderr = "";
|
|
646971
647200
|
child.stderr?.on("data", (d) => {
|
|
646972
647201
|
stderr = (stderr + d.toString()).slice(-2e3);
|
|
@@ -646975,7 +647204,7 @@ async function transcode({ config, sourcePath, targetPath, deleteSource, crop })
|
|
|
646975
647204
|
if (code === 0) {
|
|
646976
647205
|
if (deleteSource && sourcePath !== targetPath) {
|
|
646977
647206
|
try {
|
|
646978
|
-
|
|
647207
|
+
import_node_fs22.default.unlinkSync(sourcePath);
|
|
646979
647208
|
} catch {
|
|
646980
647209
|
}
|
|
646981
647210
|
}
|
|
@@ -646994,7 +647223,7 @@ async function waitForStableFile(filePath, maxSeconds) {
|
|
|
646994
647223
|
for (let i = 0; i < deadline; i++) {
|
|
646995
647224
|
let size = -1;
|
|
646996
647225
|
try {
|
|
646997
|
-
size =
|
|
647226
|
+
size = import_node_fs22.default.statSync(filePath).size;
|
|
646998
647227
|
} catch {
|
|
646999
647228
|
size = -1;
|
|
647000
647229
|
}
|
|
@@ -647034,8 +647263,8 @@ async function loadVariables({ step }) {
|
|
|
647034
647263
|
// dist/core/tests/saveCookie.js
|
|
647035
647264
|
init_validate();
|
|
647036
647265
|
init_utils();
|
|
647037
|
-
var
|
|
647038
|
-
var
|
|
647266
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
647267
|
+
var import_node_fs23 = __toESM(require("node:fs"), 1);
|
|
647039
647268
|
async function saveCookie({ config, step, driver }) {
|
|
647040
647269
|
let result = {
|
|
647041
647270
|
status: "PASS",
|
|
@@ -647052,7 +647281,7 @@ async function saveCookie({ config, step, driver }) {
|
|
|
647052
647281
|
let cookieName, filePath, directory, overwrite, domain, variable;
|
|
647053
647282
|
if (typeof step.saveCookie === "string") {
|
|
647054
647283
|
if (step.saveCookie.endsWith(".txt")) {
|
|
647055
|
-
cookieName =
|
|
647284
|
+
cookieName = import_node_path20.default.basename(step.saveCookie, ".txt");
|
|
647056
647285
|
filePath = step.saveCookie;
|
|
647057
647286
|
} else {
|
|
647058
647287
|
cookieName = step.saveCookie;
|
|
@@ -647101,15 +647330,15 @@ async function saveCookie({ config, step, driver }) {
|
|
|
647101
647330
|
}
|
|
647102
647331
|
if (filePath) {
|
|
647103
647332
|
const outputDirectory = directory || config.output || process.cwd();
|
|
647104
|
-
const fullPath =
|
|
647105
|
-
if (
|
|
647333
|
+
const fullPath = import_node_path20.default.resolve(outputDirectory, filePath);
|
|
647334
|
+
if (import_node_fs23.default.existsSync(fullPath) && !(overwrite === true || overwrite === "true")) {
|
|
647106
647335
|
result.status = "FAIL";
|
|
647107
647336
|
result.description = `File '${fullPath}' already exists and overwrite is not enabled.`;
|
|
647108
647337
|
return result;
|
|
647109
647338
|
}
|
|
647110
|
-
const dir =
|
|
647111
|
-
if (!
|
|
647112
|
-
|
|
647339
|
+
const dir = import_node_path20.default.dirname(fullPath);
|
|
647340
|
+
if (!import_node_fs23.default.existsSync(dir)) {
|
|
647341
|
+
import_node_fs23.default.mkdirSync(dir, { recursive: true });
|
|
647113
647342
|
}
|
|
647114
647343
|
if (targetCookie) {
|
|
647115
647344
|
const netscapeCookie = formatCookieForNetscape(targetCookie);
|
|
@@ -647117,11 +647346,11 @@ async function saveCookie({ config, step, driver }) {
|
|
|
647117
647346
|
# This is a cookie file saved by Doc Detective
|
|
647118
647347
|
${netscapeCookie}
|
|
647119
647348
|
`;
|
|
647120
|
-
|
|
647349
|
+
import_node_fs23.default.writeFileSync(fullPath, content, "utf8");
|
|
647121
647350
|
result.description = `Saved cookie '${cookieName}' to '${fullPath}'.`;
|
|
647122
647351
|
log(config, "debug", `Saved cookie '${cookieName}' to file: ${fullPath}`);
|
|
647123
647352
|
} else {
|
|
647124
|
-
|
|
647353
|
+
import_node_fs23.default.writeFileSync(fullPath, "# No cookie data\n", "utf8");
|
|
647125
647354
|
result.description = `Created empty cookie file at '${fullPath}'.`;
|
|
647126
647355
|
log(config, "debug", `Created empty cookie file: ${fullPath}`);
|
|
647127
647356
|
}
|
|
@@ -647148,8 +647377,8 @@ function formatCookieForNetscape(cookie) {
|
|
|
647148
647377
|
// dist/core/tests/loadCookie.js
|
|
647149
647378
|
init_validate();
|
|
647150
647379
|
init_utils();
|
|
647151
|
-
var
|
|
647152
|
-
var
|
|
647380
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
647381
|
+
var import_node_fs24 = __toESM(require("node:fs"), 1);
|
|
647153
647382
|
async function loadCookie({ config, step, driver }) {
|
|
647154
647383
|
let result = {
|
|
647155
647384
|
status: "PASS",
|
|
@@ -647166,7 +647395,7 @@ async function loadCookie({ config, step, driver }) {
|
|
|
647166
647395
|
let cookieName, filePath, directory, domain, variable;
|
|
647167
647396
|
if (typeof step.loadCookie === "string") {
|
|
647168
647397
|
if (step.loadCookie.endsWith(".txt")) {
|
|
647169
|
-
cookieName =
|
|
647398
|
+
cookieName = import_node_path21.default.basename(step.loadCookie, ".txt");
|
|
647170
647399
|
filePath = step.loadCookie;
|
|
647171
647400
|
} else {
|
|
647172
647401
|
cookieName = step.loadCookie;
|
|
@@ -647179,9 +647408,9 @@ async function loadCookie({ config, step, driver }) {
|
|
|
647179
647408
|
domain = step.loadCookie.domain;
|
|
647180
647409
|
variable = step.loadCookie.variable;
|
|
647181
647410
|
if (filePath && !cookieName) {
|
|
647182
|
-
const ext =
|
|
647411
|
+
const ext = import_node_path21.default.extname(filePath).toLowerCase();
|
|
647183
647412
|
if (ext === ".txt") {
|
|
647184
|
-
cookieName =
|
|
647413
|
+
cookieName = import_node_path21.default.basename(filePath, ext);
|
|
647185
647414
|
}
|
|
647186
647415
|
}
|
|
647187
647416
|
}
|
|
@@ -647204,14 +647433,14 @@ async function loadCookie({ config, step, driver }) {
|
|
|
647204
647433
|
}
|
|
647205
647434
|
} else if (filePath) {
|
|
647206
647435
|
const inputDirectory = directory || config.output || process.cwd();
|
|
647207
|
-
const fullPath =
|
|
647208
|
-
if (!
|
|
647436
|
+
const fullPath = import_node_path21.default.resolve(inputDirectory, filePath);
|
|
647437
|
+
if (!import_node_fs24.default.existsSync(fullPath)) {
|
|
647209
647438
|
result.status = "FAIL";
|
|
647210
647439
|
result.description = `Cookie file '${fullPath}' not found`;
|
|
647211
647440
|
return result;
|
|
647212
647441
|
}
|
|
647213
647442
|
try {
|
|
647214
|
-
const fileContent =
|
|
647443
|
+
const fileContent = import_node_fs24.default.readFileSync(fullPath, "utf8");
|
|
647215
647444
|
const cookies = parseNetscapeCookieFile(fileContent);
|
|
647216
647445
|
if (cookies.length === 0) {
|
|
647217
647446
|
result.status = "FAIL";
|
|
@@ -647377,8 +647606,8 @@ function isDomainCompatible(currentDomain, cookieDomain) {
|
|
|
647377
647606
|
// dist/core/tests/httpRequest.js
|
|
647378
647607
|
init_validate();
|
|
647379
647608
|
var import_axios5 = __toESM(require("axios"), 1);
|
|
647380
|
-
var
|
|
647381
|
-
var
|
|
647609
|
+
var import_node_fs25 = __toESM(require("node:fs"), 1);
|
|
647610
|
+
var import_node_path22 = __toESM(require("node:path"), 1);
|
|
647382
647611
|
var import_ajv2 = __toESM(require("ajv"), 1);
|
|
647383
647612
|
init_openapi();
|
|
647384
647613
|
init_utils();
|
|
@@ -647408,9 +647637,9 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
647408
647637
|
delete step.httpRequest.openApi.definition;
|
|
647409
647638
|
} else if (openApiDefinitions.length > 0) {
|
|
647410
647639
|
findOperation: for (const openApiConfig of openApiDefinitions) {
|
|
647411
|
-
for (const
|
|
647412
|
-
for (const method in openApiConfig.definition.paths[
|
|
647413
|
-
if (openApiConfig.definition.paths[
|
|
647640
|
+
for (const path27 in openApiConfig.definition.paths) {
|
|
647641
|
+
for (const method in openApiConfig.definition.paths[path27]) {
|
|
647642
|
+
if (openApiConfig.definition.paths[path27][method].operationId === step.httpRequest.openApi.operationId) {
|
|
647414
647643
|
openApiDefinition = openApiConfig.definition;
|
|
647415
647644
|
step.httpRequest.openApi = {
|
|
647416
647645
|
...openApiConfig,
|
|
@@ -647724,20 +647953,20 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
647724
647953
|
}
|
|
647725
647954
|
}
|
|
647726
647955
|
if (step.httpRequest.path) {
|
|
647727
|
-
const dir =
|
|
647728
|
-
if (!
|
|
647729
|
-
|
|
647956
|
+
const dir = import_node_path22.default.dirname(step.httpRequest.path);
|
|
647957
|
+
if (!import_node_fs25.default.existsSync(dir)) {
|
|
647958
|
+
import_node_fs25.default.mkdirSync(dir, { recursive: true });
|
|
647730
647959
|
}
|
|
647731
647960
|
let filePath = step.httpRequest.path;
|
|
647732
647961
|
log(config, "debug", `Saving output to file: ${filePath}`);
|
|
647733
|
-
if (!
|
|
647734
|
-
await
|
|
647962
|
+
if (!import_node_fs25.default.existsSync(filePath)) {
|
|
647963
|
+
await import_node_fs25.default.promises.writeFile(filePath, JSON.stringify(response.data, null, 2));
|
|
647735
647964
|
descriptions.push(`Saved output to file.`);
|
|
647736
647965
|
} else {
|
|
647737
647966
|
if (step.httpRequest.overwrite == "false") {
|
|
647738
647967
|
descriptions.push(`Didn't save output. File already exists.`);
|
|
647739
647968
|
}
|
|
647740
|
-
const existingFile =
|
|
647969
|
+
const existingFile = import_node_fs25.default.readFileSync(filePath, "utf8");
|
|
647741
647970
|
const fractionalDiff = calculateFractionalDifference(existingFile, JSON.stringify(response.data, null, 2));
|
|
647742
647971
|
log(config, "debug", `Fractional difference: ${fractionalDiff}`);
|
|
647743
647972
|
result.outputs.variation = fractionalDiff;
|
|
@@ -647747,13 +647976,13 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
647747
647976
|
});
|
|
647748
647977
|
if (fractionalDiff > step.httpRequest.maxVariation) {
|
|
647749
647978
|
if (step.httpRequest.overwrite == "aboveVariation") {
|
|
647750
|
-
await
|
|
647979
|
+
await import_node_fs25.default.promises.writeFile(filePath, JSON.stringify(response.data, null, 2));
|
|
647751
647980
|
descriptions.push(`Saved response to file.`);
|
|
647752
647981
|
}
|
|
647753
647982
|
descriptions.push(`The difference between the existing saved response and the new response (${fractionalDiff.toFixed(2)}) is greater than the max accepted variation (${step.httpRequest.maxVariation}).`);
|
|
647754
647983
|
} else {
|
|
647755
647984
|
if (step.httpRequest.overwrite == "true") {
|
|
647756
|
-
|
|
647985
|
+
import_node_fs25.default.writeFileSync(filePath, JSON.stringify(response.data, null, 2));
|
|
647757
647986
|
descriptions.push(`Saved response to file.`);
|
|
647758
647987
|
}
|
|
647759
647988
|
}
|
|
@@ -647766,8 +647995,8 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
647766
647995
|
result.description = descriptions.join(" ").trim();
|
|
647767
647996
|
return result;
|
|
647768
647997
|
}
|
|
647769
|
-
function fieldExistsAtPath(obj,
|
|
647770
|
-
const segments =
|
|
647998
|
+
function fieldExistsAtPath(obj, path27) {
|
|
647999
|
+
const segments = path27.match(/[^.[\]]+/g);
|
|
647771
648000
|
if (!segments) {
|
|
647772
648001
|
return false;
|
|
647773
648002
|
}
|
|
@@ -647957,8 +648186,8 @@ async function clickElement({ config, step, driver, appSession }) {
|
|
|
647957
648186
|
// dist/core/tests/runCode.js
|
|
647958
648187
|
init_validate();
|
|
647959
648188
|
init_utils();
|
|
647960
|
-
var
|
|
647961
|
-
var
|
|
648189
|
+
var import_node_fs26 = __toESM(require("node:fs"), 1);
|
|
648190
|
+
var import_node_path23 = __toESM(require("node:path"), 1);
|
|
647962
648191
|
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
647963
648192
|
function createTempScript(code, language) {
|
|
647964
648193
|
let extension;
|
|
@@ -647983,9 +648212,9 @@ function createTempScript(code, language) {
|
|
|
647983
648212
|
extension = "";
|
|
647984
648213
|
}
|
|
647985
648214
|
const tmpDir = import_node_os10.default.tmpdir();
|
|
647986
|
-
const tmpFile =
|
|
648215
|
+
const tmpFile = import_node_path23.default.join(tmpDir, `doc-detective-${Date.now()}${extension}`);
|
|
647987
648216
|
try {
|
|
647988
|
-
|
|
648217
|
+
import_node_fs26.default.writeFileSync(tmpFile, code);
|
|
647989
648218
|
} catch (error) {
|
|
647990
648219
|
throw new Error(`Failed to create temporary script: ${error.message}`);
|
|
647991
648220
|
}
|
|
@@ -648090,7 +648319,7 @@ async function runCode({ config, step, driver, processRegistry }) {
|
|
|
648090
648319
|
if (typeof step.runCode.stdio !== "undefined")
|
|
648091
648320
|
runShellOptions.stdio = step.runCode.stdio;
|
|
648092
648321
|
if (typeof step.runCode.path !== "undefined") {
|
|
648093
|
-
runShellOptions.path = step.runCode.directory ?
|
|
648322
|
+
runShellOptions.path = step.runCode.directory ? import_node_path23.default.join(step.runCode.directory, step.runCode.path) : step.runCode.path;
|
|
648094
648323
|
}
|
|
648095
648324
|
if (step.runCode.background) {
|
|
648096
648325
|
runShellOptions.background = step.runCode.background;
|
|
@@ -648119,7 +648348,7 @@ async function runCode({ config, step, driver, processRegistry }) {
|
|
|
648119
648348
|
} finally {
|
|
648120
648349
|
if (!deferTempCleanup) {
|
|
648121
648350
|
try {
|
|
648122
|
-
|
|
648351
|
+
import_node_fs26.default.unlinkSync(scriptPath);
|
|
648123
648352
|
log(config, "debug", `Removed temporary script: ${scriptPath}`);
|
|
648124
648353
|
} catch (error) {
|
|
648125
648354
|
log(config, "warning", `Failed to remove temporary script: ${scriptPath}`);
|
|
@@ -648133,7 +648362,7 @@ async function runCode({ config, step, driver, processRegistry }) {
|
|
|
648133
648362
|
init_validate();
|
|
648134
648363
|
init_utils();
|
|
648135
648364
|
var import_tree_kill2 = __toESM(require("tree-kill"), 1);
|
|
648136
|
-
var
|
|
648365
|
+
var import_node_fs27 = __toESM(require("node:fs"), 1);
|
|
648137
648366
|
async function closeSurface({ config, step, driver, processRegistry, appSession }) {
|
|
648138
648367
|
const result = {
|
|
648139
648368
|
status: "PASS",
|
|
@@ -648282,7 +648511,7 @@ async function closeSurface({ config, step, driver, processRegistry, appSession
|
|
|
648282
648511
|
}
|
|
648283
648512
|
if (entry.tempPath) {
|
|
648284
648513
|
try {
|
|
648285
|
-
|
|
648514
|
+
import_node_fs27.default.unlinkSync(entry.tempPath);
|
|
648286
648515
|
} catch {
|
|
648287
648516
|
}
|
|
648288
648517
|
}
|
|
@@ -648535,7 +648764,7 @@ async function applyViewport(driver, viewport) {
|
|
|
648535
648764
|
}
|
|
648536
648765
|
|
|
648537
648766
|
// dist/core/tests/mobileBrowser.js
|
|
648538
|
-
var
|
|
648767
|
+
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
648539
648768
|
var SUPPORTED_MOBILE_BROWSER = {
|
|
648540
648769
|
android: "chrome",
|
|
648541
648770
|
ios: "safari"
|
|
@@ -648568,6 +648797,10 @@ function mobileBrowserConfigError(browser) {
|
|
|
648568
648797
|
}
|
|
648569
648798
|
return null;
|
|
648570
648799
|
}
|
|
648800
|
+
var CHROMEDRIVER_AUTODOWNLOAD_ARGS = [
|
|
648801
|
+
"--allow-insecure",
|
|
648802
|
+
"uiautomator2:chromedriver_autodownload"
|
|
648803
|
+
];
|
|
648571
648804
|
function mobileBrowserGate({ platform, browser, hasBrowserStep, hasAppStep }) {
|
|
648572
648805
|
if (!hasBrowserStep)
|
|
648573
648806
|
return { action: "proceed", browserName: null };
|
|
@@ -648592,7 +648825,7 @@ function mobileBrowserGate({ platform, browser, hasBrowserStep, hasAppStep }) {
|
|
|
648592
648825
|
}
|
|
648593
648826
|
return { action: "proceed", browserName };
|
|
648594
648827
|
}
|
|
648595
|
-
function buildMobileBrowserCapabilities({ platform, udid, cacheDir, timeout }) {
|
|
648828
|
+
function buildMobileBrowserCapabilities({ platform, udid, cacheDir, timeout, locateWda = () => locateManagedWda({ ctx: { cacheDir } }) }) {
|
|
648596
648829
|
if (platform === "android") {
|
|
648597
648830
|
return {
|
|
648598
648831
|
platformName: "Android",
|
|
@@ -648610,7 +648843,7 @@ function buildMobileBrowserCapabilities({ platform, udid, cacheDir, timeout }) {
|
|
|
648610
648843
|
// --allow-insecure=uiautomator2:chromedriver_autodownload. The
|
|
648611
648844
|
// download lands in the Doc Detective cache so later runs reuse it.
|
|
648612
648845
|
"appium:chromedriverAutodownload": true,
|
|
648613
|
-
"appium:chromedriverExecutableDir":
|
|
648846
|
+
"appium:chromedriverExecutableDir": import_node_path24.default.join(cacheDir, MOBILE_CHROMEDRIVER_DIR)
|
|
648614
648847
|
};
|
|
648615
648848
|
}
|
|
648616
648849
|
const capabilities = {
|
|
@@ -648624,18 +648857,225 @@ function buildMobileBrowserCapabilities({ platform, udid, cacheDir, timeout }) {
|
|
|
648624
648857
|
const effectiveTimeout = timeout ?? 9e5;
|
|
648625
648858
|
capabilities["appium:wdaLaunchTimeout"] = Math.max(effectiveTimeout, 12e4);
|
|
648626
648859
|
capabilities["appium:wdaConnectionTimeout"] = Math.max(effectiveTimeout, 12e4);
|
|
648627
|
-
|
|
648628
|
-
if (derivedDataPath && derivedDataPath.trim()) {
|
|
648629
|
-
capabilities["appium:derivedDataPath"] = derivedDataPath.trim();
|
|
648630
|
-
}
|
|
648860
|
+
applyManagedWdaCapabilities(capabilities, locateWda);
|
|
648631
648861
|
return capabilities;
|
|
648632
648862
|
}
|
|
648633
648863
|
|
|
648864
|
+
// dist/core/warmPhase.js
|
|
648865
|
+
init_utils();
|
|
648866
|
+
var WARM_POOL_LIMIT = 4;
|
|
648867
|
+
var RUNTIME_INSTALL_RESOURCE = "runtime-install";
|
|
648868
|
+
function deviceIdentity(platform, desc) {
|
|
648869
|
+
if (desc?.name)
|
|
648870
|
+
return `${platform}:name:${desc.name}`;
|
|
648871
|
+
return `${platform}:default:${desc?.deviceType ?? "<any>"}:${desc?.osVersion ?? "<latest>"}`;
|
|
648872
|
+
}
|
|
648873
|
+
function deviceResourceTag(platform, desc) {
|
|
648874
|
+
return `warm-device:${deviceIdentity(platform, desc)}`;
|
|
648875
|
+
}
|
|
648876
|
+
function wrapInitiationEffects(deps, keys, signal) {
|
|
648877
|
+
const wrapped = { ...deps };
|
|
648878
|
+
for (const key of keys) {
|
|
648879
|
+
const original = deps[key];
|
|
648880
|
+
if (typeof original !== "function")
|
|
648881
|
+
continue;
|
|
648882
|
+
wrapped[key] = (...args) => {
|
|
648883
|
+
const result = original(...args);
|
|
648884
|
+
signal();
|
|
648885
|
+
return result;
|
|
648886
|
+
};
|
|
648887
|
+
}
|
|
648888
|
+
return wrapped;
|
|
648889
|
+
}
|
|
648890
|
+
function planWarmTasks({ sizingJobs, runnerDetails, limit, hasAppiumPool, deps }) {
|
|
648891
|
+
const hostPlatform = runnerDetails?.environment?.platform;
|
|
648892
|
+
const tasks = [];
|
|
648893
|
+
const seen = /* @__PURE__ */ new Set();
|
|
648894
|
+
const addTask = (task) => {
|
|
648895
|
+
if (seen.has(task.name))
|
|
648896
|
+
return;
|
|
648897
|
+
seen.add(task.name);
|
|
648898
|
+
tasks.push(task);
|
|
648899
|
+
};
|
|
648900
|
+
let probeEligible = false;
|
|
648901
|
+
let defaultBrowser;
|
|
648902
|
+
const getDefaultBrowser2 = () => defaultBrowser ??= deps.getDefaultBrowser({ runnerDetails });
|
|
648903
|
+
const bootPlannedFor = /* @__PURE__ */ new Set();
|
|
648904
|
+
for (const job of sizingJobs ?? []) {
|
|
648905
|
+
const context = job?.context;
|
|
648906
|
+
if (!context)
|
|
648907
|
+
continue;
|
|
648908
|
+
if (deps.contextRequirementsSkipMessage({ context }))
|
|
648909
|
+
continue;
|
|
648910
|
+
const effPlatform = context.platform || hostPlatform;
|
|
648911
|
+
const mobileTarget = deps.isMobileTargetPlatform(effPlatform);
|
|
648912
|
+
if (mobileTarget) {
|
|
648913
|
+
if (mobileTarget === "ios" && hostPlatform !== "mac")
|
|
648914
|
+
continue;
|
|
648915
|
+
const hasAppStep = deps.isAppDriverRequired({ test: context });
|
|
648916
|
+
const gate = deps.mobileBrowserGate({
|
|
648917
|
+
platform: mobileTarget,
|
|
648918
|
+
browser: context.browser,
|
|
648919
|
+
hasBrowserStep: deps.isBrowserRequired({ test: context }),
|
|
648920
|
+
hasAppStep
|
|
648921
|
+
});
|
|
648922
|
+
if (gate.action !== "proceed")
|
|
648923
|
+
continue;
|
|
648924
|
+
const isMobileWeb = typeof gate.browserName === "string";
|
|
648925
|
+
if (!isMobileWeb && !hasAppStep)
|
|
648926
|
+
continue;
|
|
648927
|
+
const driverPackage = deps.appDriverPlatforms[mobileTarget]?.driverPackage;
|
|
648928
|
+
if (driverPackage) {
|
|
648929
|
+
addTask({
|
|
648930
|
+
name: `driver-install:${driverPackage}`,
|
|
648931
|
+
kind: "driver-install",
|
|
648932
|
+
exclusiveResources: [RUNTIME_INSTALL_RESOURCE],
|
|
648933
|
+
payload: { driverPackage, platform: mobileTarget }
|
|
648934
|
+
});
|
|
648935
|
+
}
|
|
648936
|
+
for (const stepDevice of deps.collectDeviceDescriptors(context)) {
|
|
648937
|
+
const desc = deps.normalizeDeviceDescriptor({
|
|
648938
|
+
contextDevice: context.device,
|
|
648939
|
+
stepDevice,
|
|
648940
|
+
platform: mobileTarget
|
|
648941
|
+
});
|
|
648942
|
+
const identity = deviceIdentity(mobileTarget, desc);
|
|
648943
|
+
const tag = deviceResourceTag(mobileTarget, desc);
|
|
648944
|
+
if (!bootPlannedFor.has(mobileTarget)) {
|
|
648945
|
+
bootPlannedFor.add(mobileTarget);
|
|
648946
|
+
addTask({
|
|
648947
|
+
name: `device-boot:${identity}`,
|
|
648948
|
+
kind: "device-boot",
|
|
648949
|
+
exclusiveResources: [tag],
|
|
648950
|
+
payload: { platform: mobileTarget, desc }
|
|
648951
|
+
});
|
|
648952
|
+
}
|
|
648953
|
+
if (mobileTarget === "android" && isMobileWeb) {
|
|
648954
|
+
addTask({
|
|
648955
|
+
name: `chromedriver-prefetch:${identity}`,
|
|
648956
|
+
kind: "chromedriver-prefetch",
|
|
648957
|
+
exclusiveResources: [tag],
|
|
648958
|
+
payload: { platform: mobileTarget, desc }
|
|
648959
|
+
});
|
|
648960
|
+
}
|
|
648961
|
+
}
|
|
648962
|
+
if (mobileTarget === "ios") {
|
|
648963
|
+
addTask({
|
|
648964
|
+
name: "wda-check",
|
|
648965
|
+
kind: "wda-check",
|
|
648966
|
+
// Read-only (plus the last-used stamp) — contends with nothing.
|
|
648967
|
+
exclusiveResources: [],
|
|
648968
|
+
payload: {}
|
|
648969
|
+
});
|
|
648970
|
+
}
|
|
648971
|
+
continue;
|
|
648972
|
+
}
|
|
648973
|
+
if (deps.isBrowserRequired({ test: context })) {
|
|
648974
|
+
const effBrowser = context.browser ?? getDefaultBrowser2();
|
|
648975
|
+
const browserName = effBrowser?.name;
|
|
648976
|
+
if (browserName && effPlatform === hostPlatform) {
|
|
648977
|
+
probeEligible = true;
|
|
648978
|
+
if (deps.requiredBrowserAssets(browserName).length > 0) {
|
|
648979
|
+
addTask({
|
|
648980
|
+
name: `browser-install:${browserName.toLowerCase()}`,
|
|
648981
|
+
kind: "browser-install",
|
|
648982
|
+
exclusiveResources: [RUNTIME_INSTALL_RESOURCE],
|
|
648983
|
+
payload: { browserName }
|
|
648984
|
+
});
|
|
648985
|
+
}
|
|
648986
|
+
}
|
|
648987
|
+
}
|
|
648988
|
+
if ((effPlatform === "windows" || effPlatform === "mac") && effPlatform === hostPlatform && deps.isAppDriverRequired({ test: context })) {
|
|
648989
|
+
const driverPackage = deps.appDriverPlatforms[effPlatform]?.driverPackage;
|
|
648990
|
+
if (driverPackage) {
|
|
648991
|
+
addTask({
|
|
648992
|
+
name: `driver-install:${driverPackage}`,
|
|
648993
|
+
kind: "driver-install",
|
|
648994
|
+
exclusiveResources: [RUNTIME_INSTALL_RESOURCE],
|
|
648995
|
+
payload: { driverPackage, platform: effPlatform }
|
|
648996
|
+
});
|
|
648997
|
+
}
|
|
648998
|
+
}
|
|
648999
|
+
}
|
|
649000
|
+
if (limit > 1 && hasAppiumPool && probeEligible) {
|
|
649001
|
+
addTask({
|
|
649002
|
+
name: "session-probe",
|
|
649003
|
+
kind: "session-probe",
|
|
649004
|
+
// Its install half mutates the shared caches, exactly like the
|
|
649005
|
+
// dedicated install tasks (usually a memo hit by the time it runs).
|
|
649006
|
+
exclusiveResources: [RUNTIME_INSTALL_RESOURCE],
|
|
649007
|
+
payload: {}
|
|
649008
|
+
});
|
|
649009
|
+
}
|
|
649010
|
+
return tasks;
|
|
649011
|
+
}
|
|
649012
|
+
async function executeWarmTasks({ tasks, registry, runTask, log: log3, now = Date.now }) {
|
|
649013
|
+
const results = [];
|
|
649014
|
+
const start = now();
|
|
649015
|
+
await runResourceAware(tasks, WARM_POOL_LIMIT, registry, async (task) => {
|
|
649016
|
+
const taskStart = now();
|
|
649017
|
+
try {
|
|
649018
|
+
const { outcome, note } = await runTask(task);
|
|
649019
|
+
results.push({
|
|
649020
|
+
name: task.name,
|
|
649021
|
+
kind: task.kind,
|
|
649022
|
+
outcome,
|
|
649023
|
+
durationMs: now() - taskStart,
|
|
649024
|
+
...note ? { note } : {}
|
|
649025
|
+
});
|
|
649026
|
+
if (outcome === "failed") {
|
|
649027
|
+
log3("warning", `Warm task '${task.name}' failed (continuing)${note ? `: ${note}` : "."}`);
|
|
649028
|
+
} else {
|
|
649029
|
+
log3("debug", `Warm task '${task.name}': ${outcome}${note ? ` (${note})` : ""}.`);
|
|
649030
|
+
}
|
|
649031
|
+
} catch (error) {
|
|
649032
|
+
const note = error?.message ?? String(error);
|
|
649033
|
+
results.push({
|
|
649034
|
+
name: task.name,
|
|
649035
|
+
kind: task.kind,
|
|
649036
|
+
outcome: "failed",
|
|
649037
|
+
durationMs: now() - taskStart,
|
|
649038
|
+
note
|
|
649039
|
+
});
|
|
649040
|
+
log3("warning", `Warm task '${task.name}' failed (continuing): ${note}`);
|
|
649041
|
+
}
|
|
649042
|
+
});
|
|
649043
|
+
return { durationMs: now() - start, tasks: results };
|
|
649044
|
+
}
|
|
649045
|
+
function raceBootInitiation({ startAcquire, onError }) {
|
|
649046
|
+
let initiatedResolve;
|
|
649047
|
+
const initiated = new Promise((resolve) => {
|
|
649048
|
+
initiatedResolve = resolve;
|
|
649049
|
+
});
|
|
649050
|
+
const acquired = (async () => {
|
|
649051
|
+
try {
|
|
649052
|
+
const result = await startAcquire(() => initiatedResolve());
|
|
649053
|
+
if (result && typeof result === "object" && "skip" in result) {
|
|
649054
|
+
return { outcome: "skipped", note: result.skip };
|
|
649055
|
+
}
|
|
649056
|
+
return { outcome: "warmed", note: "device ready" };
|
|
649057
|
+
} catch (error) {
|
|
649058
|
+
onError(error);
|
|
649059
|
+
return {
|
|
649060
|
+
outcome: "failed",
|
|
649061
|
+
note: error?.message ?? String(error)
|
|
649062
|
+
};
|
|
649063
|
+
}
|
|
649064
|
+
})();
|
|
649065
|
+
return Promise.race([
|
|
649066
|
+
initiated.then(() => ({
|
|
649067
|
+
outcome: "warmed",
|
|
649068
|
+
note: "boot initiated"
|
|
649069
|
+
})),
|
|
649070
|
+
acquired
|
|
649071
|
+
]);
|
|
649072
|
+
}
|
|
649073
|
+
|
|
648634
649074
|
// dist/core/tests.js
|
|
648635
649075
|
init_cacheDir();
|
|
648636
649076
|
|
|
648637
649077
|
// dist/core/tests/iosSimulator.js
|
|
648638
|
-
var
|
|
649078
|
+
var import_node_child_process14 = require("node:child_process");
|
|
648639
649079
|
function parseSimctlDevices(text) {
|
|
648640
649080
|
let data;
|
|
648641
649081
|
try {
|
|
@@ -648900,6 +649340,13 @@ async function teardownSimulatorRegistry(registry, shutdown) {
|
|
|
648900
649340
|
for (const entry of registry.values()) {
|
|
648901
649341
|
if (!entry.bootedByUs)
|
|
648902
649342
|
continue;
|
|
649343
|
+
if (entry.ready) {
|
|
649344
|
+
try {
|
|
649345
|
+
await entry.ready;
|
|
649346
|
+
} catch {
|
|
649347
|
+
continue;
|
|
649348
|
+
}
|
|
649349
|
+
}
|
|
648903
649350
|
try {
|
|
648904
649351
|
await shutdown(entry);
|
|
648905
649352
|
} catch {
|
|
@@ -648909,7 +649356,7 @@ async function teardownSimulatorRegistry(registry, shutdown) {
|
|
|
648909
649356
|
}
|
|
648910
649357
|
function runSimctl(args, timeout = 6e4) {
|
|
648911
649358
|
return new Promise((resolve) => {
|
|
648912
|
-
(0,
|
|
649359
|
+
(0, import_node_child_process14.execFile)("xcrun", ["simctl", ...args], { timeout, maxBuffer: 32 * 1024 * 1024 }, (error, stdout, stderr) => {
|
|
648913
649360
|
resolve({
|
|
648914
649361
|
// A timeout or spawn error sets no numeric `code` (it's null) — treat
|
|
648915
649362
|
// that as a failure, not success, so a hung `simctl` doesn't look like
|
|
@@ -648966,8 +649413,8 @@ function buildAcquireSimulatorDeps(log3) {
|
|
|
648966
649413
|
// dist/core/tests/runBrowserScript.js
|
|
648967
649414
|
init_validate();
|
|
648968
649415
|
init_utils();
|
|
648969
|
-
var
|
|
648970
|
-
var
|
|
649416
|
+
var import_node_fs28 = __toESM(require("node:fs"), 1);
|
|
649417
|
+
var import_node_path25 = __toESM(require("node:path"), 1);
|
|
648971
649418
|
async function runBrowserScript({ config, step, driver }) {
|
|
648972
649419
|
const result = {
|
|
648973
649420
|
status: "PASS",
|
|
@@ -649042,16 +649489,16 @@ async function runBrowserScript({ config, step, driver }) {
|
|
|
649042
649489
|
}
|
|
649043
649490
|
if (step.runBrowserScript.path) {
|
|
649044
649491
|
try {
|
|
649045
|
-
const dir =
|
|
649046
|
-
if (!
|
|
649047
|
-
|
|
649492
|
+
const dir = import_node_path25.default.dirname(step.runBrowserScript.path);
|
|
649493
|
+
if (!import_node_fs28.default.existsSync(dir)) {
|
|
649494
|
+
import_node_fs28.default.mkdirSync(dir, { recursive: true });
|
|
649048
649495
|
}
|
|
649049
649496
|
const filePath = step.runBrowserScript.path;
|
|
649050
649497
|
log(config, "debug", `Saving script result to file: ${filePath}`);
|
|
649051
|
-
if (!
|
|
649052
|
-
|
|
649498
|
+
if (!import_node_fs28.default.existsSync(filePath)) {
|
|
649499
|
+
import_node_fs28.default.writeFileSync(filePath, serialized);
|
|
649053
649500
|
} else {
|
|
649054
|
-
const existingFile =
|
|
649501
|
+
const existingFile = import_node_fs28.default.readFileSync(filePath, "utf8");
|
|
649055
649502
|
const fractionalDiff = calculateFractionalDifference(existingFile, serialized);
|
|
649056
649503
|
log(config, "debug", `Fractional difference: ${fractionalDiff}`);
|
|
649057
649504
|
result.outputs.variation = fractionalDiff;
|
|
@@ -649061,7 +649508,7 @@ async function runBrowserScript({ config, step, driver }) {
|
|
|
649061
649508
|
});
|
|
649062
649509
|
if (fractionalDiff > step.runBrowserScript.maxVariation) {
|
|
649063
649510
|
if (step.runBrowserScript.overwrite == "aboveVariation" || step.runBrowserScript.overwrite == "true") {
|
|
649064
|
-
|
|
649511
|
+
import_node_fs28.default.writeFileSync(filePath, serialized);
|
|
649065
649512
|
descriptions.push(`Saved output to file.`);
|
|
649066
649513
|
} else {
|
|
649067
649514
|
descriptions.push(`Didn't overwrite the existing file.`);
|
|
@@ -649069,7 +649516,7 @@ async function runBrowserScript({ config, step, driver }) {
|
|
|
649069
649516
|
descriptions.push(`The difference between the existing output and the new output (${fractionalDiff.toFixed(2)}) is greater than the max accepted variation (${step.runBrowserScript.maxVariation}).`);
|
|
649070
649517
|
} else {
|
|
649071
649518
|
if (step.runBrowserScript.overwrite == "true") {
|
|
649072
|
-
|
|
649519
|
+
import_node_fs28.default.writeFileSync(filePath, serialized);
|
|
649073
649520
|
descriptions.push(`Saved output to file.`);
|
|
649074
649521
|
}
|
|
649075
649522
|
}
|
|
@@ -649237,8 +649684,8 @@ async function dragAndDropElement({ config, step, driver }) {
|
|
|
649237
649684
|
}
|
|
649238
649685
|
|
|
649239
649686
|
// dist/core/tests.js
|
|
649240
|
-
var
|
|
649241
|
-
var
|
|
649687
|
+
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
649688
|
+
var import_node_child_process15 = require("node:child_process");
|
|
649242
649689
|
var import_node_crypto9 = require("node:crypto");
|
|
649243
649690
|
init_appium();
|
|
649244
649691
|
init_config();
|
|
@@ -649391,7 +649838,7 @@ function getIntegrationConfig(config, sourceIntegration) {
|
|
|
649391
649838
|
var import_node_http2 = __toESM(require("node:http"), 1);
|
|
649392
649839
|
var import_node_https3 = __toESM(require("node:https"), 1);
|
|
649393
649840
|
var import_node_url6 = require("node:url");
|
|
649394
|
-
var __dirname5 =
|
|
649841
|
+
var __dirname5 = import_node_path26.default.dirname((0, import_node_url6.fileURLToPath)(importMetaUrl));
|
|
649395
649842
|
var KNOWN_BROWSERS = ["firefox", "chrome", "safari", "webkit"];
|
|
649396
649843
|
function killTree(pid, timeoutMs = 5e3) {
|
|
649397
649844
|
return new Promise((resolve) => {
|
|
@@ -649436,6 +649883,20 @@ function combinationKey(context) {
|
|
|
649436
649883
|
function warmUpDecision(prev) {
|
|
649437
649884
|
return prev === "failed" ? "skip" : "attempt";
|
|
649438
649885
|
}
|
|
649886
|
+
function buildWarmPlanDeps() {
|
|
649887
|
+
return {
|
|
649888
|
+
isBrowserRequired,
|
|
649889
|
+
isAppDriverRequired,
|
|
649890
|
+
isMobileTargetPlatform,
|
|
649891
|
+
getDefaultBrowser,
|
|
649892
|
+
requiredBrowserAssets,
|
|
649893
|
+
collectDeviceDescriptors,
|
|
649894
|
+
normalizeDeviceDescriptor,
|
|
649895
|
+
mobileBrowserGate,
|
|
649896
|
+
contextRequirementsSkipMessage,
|
|
649897
|
+
appDriverPlatforms: APP_DRIVER_PLATFORMS
|
|
649898
|
+
};
|
|
649899
|
+
}
|
|
649439
649900
|
function getDriverCapabilities({ runnerDetails, name, options }) {
|
|
649440
649901
|
let capabilities = {};
|
|
649441
649902
|
let args = [];
|
|
@@ -650015,7 +650476,7 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650015
650476
|
const runDir = getRunOutputDir(config, {
|
|
650016
650477
|
create: runArchivesArtifacts(config, specs)
|
|
650017
650478
|
});
|
|
650018
|
-
const runId =
|
|
650479
|
+
const runId = import_node_path26.default.basename(runDir);
|
|
650019
650480
|
const report = {
|
|
650020
650481
|
runId,
|
|
650021
650482
|
runDir,
|
|
@@ -650045,7 +650506,12 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650045
650506
|
skipped: 0
|
|
650046
650507
|
}
|
|
650047
650508
|
},
|
|
650048
|
-
specs: []
|
|
650509
|
+
specs: [],
|
|
650510
|
+
// Inline warm phase results (docs/design/warm-phase.md). Present on the
|
|
650511
|
+
// skeleton so a run that plans nothing (or whose planning fails —
|
|
650512
|
+
// best-effort) still reports the structural empty block; the phase
|
|
650513
|
+
// overwrites it with real task results below.
|
|
650514
|
+
warm: { durationMs: 0, tasks: [] }
|
|
650049
650515
|
};
|
|
650050
650516
|
let limit = resolveConcurrentRunners(config);
|
|
650051
650517
|
log(config, "info", "Running test specs.");
|
|
@@ -650200,6 +650666,7 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650200
650666
|
const serverCount = Math.min(limit, browserPoolJobCount);
|
|
650201
650667
|
log(config, "debug", `Starting ${serverCount} Appium server(s).`);
|
|
650202
650668
|
try {
|
|
650669
|
+
const readinessWaits = [];
|
|
650203
650670
|
for (let i = 0; i < serverCount; i++) {
|
|
650204
650671
|
let display;
|
|
650205
650672
|
if (useXvfbDisplays) {
|
|
@@ -650207,7 +650674,16 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650207
650674
|
xvfbProcesses.push(await startXvfb(display));
|
|
650208
650675
|
log(config, "debug", `Started Xvfb on ${display} for recording.`);
|
|
650209
650676
|
}
|
|
650210
|
-
|
|
650677
|
+
const server = await spawnAppiumServer(appiumEntry, config, display);
|
|
650678
|
+
appiumServers.push(server);
|
|
650679
|
+
const wait2 = appiumIsReady(server.port);
|
|
650680
|
+
wait2.catch(() => {
|
|
650681
|
+
});
|
|
650682
|
+
readinessWaits.push(wait2);
|
|
650683
|
+
}
|
|
650684
|
+
await Promise.all(readinessWaits);
|
|
650685
|
+
for (const server of appiumServers) {
|
|
650686
|
+
log(config, "debug", `Appium is ready on port ${server.port}.`);
|
|
650211
650687
|
}
|
|
650212
650688
|
} catch (error) {
|
|
650213
650689
|
await Promise.all(appiumServers.map((server) => {
|
|
@@ -650230,6 +650706,7 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650230
650706
|
const processRegistry = /* @__PURE__ */ new Map();
|
|
650231
650707
|
const deviceRegistry = createDeviceRegistry();
|
|
650232
650708
|
const simulatorRegistry = createSimulatorRegistry();
|
|
650709
|
+
const resourceRegistry = createResourceRegistry();
|
|
650233
650710
|
const killAllRegistered = async () => {
|
|
650234
650711
|
const entries = [...processRegistry.entries()];
|
|
650235
650712
|
processRegistry.clear();
|
|
@@ -650241,7 +650718,7 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650241
650718
|
}
|
|
650242
650719
|
if (entry?.tempPath) {
|
|
650243
650720
|
try {
|
|
650244
|
-
|
|
650721
|
+
import_node_fs29.default.unlinkSync(entry.tempPath);
|
|
650245
650722
|
} catch {
|
|
650246
650723
|
}
|
|
650247
650724
|
}
|
|
@@ -650266,15 +650743,35 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650266
650743
|
process.on("SIGINT", onSignal);
|
|
650267
650744
|
process.on("SIGTERM", onSignal);
|
|
650268
650745
|
try {
|
|
650269
|
-
|
|
650270
|
-
|
|
650271
|
-
|
|
650272
|
-
config,
|
|
650746
|
+
try {
|
|
650747
|
+
const warmTasks = planWarmTasks({
|
|
650748
|
+
sizingJobs,
|
|
650273
650749
|
runnerDetails,
|
|
650274
|
-
|
|
650275
|
-
|
|
650276
|
-
|
|
650750
|
+
limit,
|
|
650751
|
+
hasAppiumPool: !!appiumPool,
|
|
650752
|
+
deps: buildWarmPlanDeps()
|
|
650277
650753
|
});
|
|
650754
|
+
if (warmTasks.length > 0) {
|
|
650755
|
+
log(config, "debug", `Warm phase: ${warmTasks.length} task(s).`);
|
|
650756
|
+
report.warm = await executeWarmTasks({
|
|
650757
|
+
tasks: warmTasks,
|
|
650758
|
+
registry: resourceRegistry,
|
|
650759
|
+
runTask: buildWarmTaskRunner({
|
|
650760
|
+
config,
|
|
650761
|
+
runnerDetails,
|
|
650762
|
+
sizingJobs,
|
|
650763
|
+
appiumPool,
|
|
650764
|
+
installAttempts,
|
|
650765
|
+
warmUpResults,
|
|
650766
|
+
deviceRegistry,
|
|
650767
|
+
simulatorRegistry,
|
|
650768
|
+
resourceRegistry
|
|
650769
|
+
}),
|
|
650770
|
+
log: (level, message) => log(config, level, message)
|
|
650771
|
+
});
|
|
650772
|
+
}
|
|
650773
|
+
} catch (error) {
|
|
650774
|
+
log(config, "warning", `Warm phase skipped (planning failed; the run proceeds with on-demand provisioning): ${error?.message ?? error}`);
|
|
650278
650775
|
}
|
|
650279
650776
|
const runJob = async (job) => {
|
|
650280
650777
|
try {
|
|
@@ -650326,7 +650823,6 @@ async function runSpecs({ resolvedTests }) {
|
|
|
650326
650823
|
const phase = PHASES.includes(entry.spec?._phase) ? entry.spec._phase : "main";
|
|
650327
650824
|
routedByPhase[phase].push(entry);
|
|
650328
650825
|
}
|
|
650329
|
-
const resourceRegistry = createResourceRegistry();
|
|
650330
650826
|
for (const phase of PHASES) {
|
|
650331
650827
|
if (limit > 1) {
|
|
650332
650828
|
await runResourceAware(jobsByPhase[phase], limit, resourceRegistry, runJob);
|
|
@@ -650640,27 +651136,17 @@ async function warmUpContexts({ jobs, config, runnerDetails, appiumPool, install
|
|
|
650640
651136
|
platform
|
|
650641
651137
|
});
|
|
650642
651138
|
if (!supported && context.platform === platform && Array.isArray(context?.steps) && requiredBrowserAssets(context.browser?.name).length > 0) {
|
|
650643
|
-
|
|
650644
|
-
const outcome = await ensureContextBrowserInstalled({
|
|
651139
|
+
await warmBrowserInstall({
|
|
650645
651140
|
browserName: context.browser?.name,
|
|
650646
651141
|
config,
|
|
650647
|
-
|
|
650648
|
-
|
|
650649
|
-
|
|
650650
|
-
|
|
650651
|
-
|
|
650652
|
-
|
|
650653
|
-
|
|
651142
|
+
runnerDetails,
|
|
651143
|
+
installAttempts
|
|
651144
|
+
});
|
|
651145
|
+
supported = isSupportedContext({
|
|
651146
|
+
context,
|
|
651147
|
+
apps: runnerDetails.availableApps,
|
|
651148
|
+
platform
|
|
650654
651149
|
});
|
|
650655
|
-
if (firstAttempt && (outcome === "installed" || outcome === "failed")) {
|
|
650656
|
-
clearAppCache(config);
|
|
650657
|
-
runnerDetails.availableApps = await getAvailableApps({ config });
|
|
650658
|
-
supported = isSupportedContext({
|
|
650659
|
-
context,
|
|
650660
|
-
apps: runnerDetails.availableApps,
|
|
650661
|
-
platform
|
|
650662
|
-
});
|
|
650663
|
-
}
|
|
650664
651150
|
}
|
|
650665
651151
|
if (!supported)
|
|
650666
651152
|
continue;
|
|
@@ -650702,6 +651188,292 @@ async function warmUpContexts({ jobs, config, runnerDetails, appiumPool, install
|
|
|
650702
651188
|
}
|
|
650703
651189
|
}
|
|
650704
651190
|
}
|
|
651191
|
+
async function warmBrowserInstall({ browserName, config, runnerDetails, installAttempts, deps = {} }) {
|
|
651192
|
+
const appName = normalizeBrowserName(browserName);
|
|
651193
|
+
if (runnerDetails.availableApps?.find((app) => app.name === appName)) {
|
|
651194
|
+
return {
|
|
651195
|
+
outcome: "skipped",
|
|
651196
|
+
note: `'${browserName}' is already available`
|
|
651197
|
+
};
|
|
651198
|
+
}
|
|
651199
|
+
const firstAttempt = !installAttempts.has((browserName ?? "<none>").toLowerCase());
|
|
651200
|
+
const outcome = await ensureContextBrowserInstalled({
|
|
651201
|
+
browserName,
|
|
651202
|
+
config,
|
|
651203
|
+
installAttempts,
|
|
651204
|
+
deps: {
|
|
651205
|
+
ensureBrowser: deps.ensureBrowser ?? ((asset, options) => ensureBrowserInstalled(asset, options)),
|
|
651206
|
+
log
|
|
651207
|
+
},
|
|
651208
|
+
// Repair a present-but-broken driver, not just install-if-missing.
|
|
651209
|
+
repair: true
|
|
651210
|
+
});
|
|
651211
|
+
if (firstAttempt && (outcome === "installed" || outcome === "failed")) {
|
|
651212
|
+
(deps.clearAppCache ?? clearAppCache)(config);
|
|
651213
|
+
runnerDetails.availableApps = await (deps.getAvailableApps ?? getAvailableApps)({ config });
|
|
651214
|
+
}
|
|
651215
|
+
if (outcome === "installed")
|
|
651216
|
+
return { outcome: "warmed" };
|
|
651217
|
+
if (outcome === "failed") {
|
|
651218
|
+
return { outcome: "failed", note: `couldn't install '${browserName}'` };
|
|
651219
|
+
}
|
|
651220
|
+
return {
|
|
651221
|
+
outcome: "skipped",
|
|
651222
|
+
note: `'${browserName}' has no installable assets`
|
|
651223
|
+
};
|
|
651224
|
+
}
|
|
651225
|
+
async function resolveAndroidWarmEnv(config) {
|
|
651226
|
+
try {
|
|
651227
|
+
const abi = hostAbi();
|
|
651228
|
+
const sdk = detectAndroidSdk({ cacheDir: config?.cacheDir });
|
|
651229
|
+
if (!sdk?.emulator)
|
|
651230
|
+
return null;
|
|
651231
|
+
const deviceDeps = buildAcquireDeviceDeps(sdk, abi, (m) => log(config, "debug", m));
|
|
651232
|
+
const running = await deviceDeps.listRunning();
|
|
651233
|
+
const capable = running.length > 0 || await checkEmulatorAcceleration(sdk.emulator);
|
|
651234
|
+
if (!capable)
|
|
651235
|
+
return null;
|
|
651236
|
+
return { sdkRoot: sdk.sdkRoot, deviceDeps };
|
|
651237
|
+
} catch {
|
|
651238
|
+
return null;
|
|
651239
|
+
}
|
|
651240
|
+
}
|
|
651241
|
+
async function probeIosToolchainWarm() {
|
|
651242
|
+
if (process.platform !== "darwin")
|
|
651243
|
+
return probeIosToolchain();
|
|
651244
|
+
const runAsync = (command, args, timeout) => new Promise((resolve) => {
|
|
651245
|
+
let stdout = "";
|
|
651246
|
+
let stderr = "";
|
|
651247
|
+
try {
|
|
651248
|
+
const child = (0, import_node_child_process15.spawn)(command, args, { windowsHide: true, timeout });
|
|
651249
|
+
child.stdout?.on("data", (d) => stdout += String(d));
|
|
651250
|
+
child.stderr?.on("data", (d) => stderr += String(d));
|
|
651251
|
+
child.on("error", () => resolve({ status: null, stdout, stderr }));
|
|
651252
|
+
child.on("close", (status) => resolve({ status, stdout, stderr }));
|
|
651253
|
+
} catch {
|
|
651254
|
+
resolve({ status: null, stdout, stderr });
|
|
651255
|
+
}
|
|
651256
|
+
});
|
|
651257
|
+
const [xcodeSelect, simctl] = await Promise.all([
|
|
651258
|
+
runAsync("xcode-select", ["-p"], 15e3),
|
|
651259
|
+
// Same generous ceiling as the sync probe's xcrun spawn: the first cold
|
|
651260
|
+
// simctl call launches CoreSimulatorService.
|
|
651261
|
+
runAsync("xcrun", ["simctl", "list", "devices", "available"], 12e4)
|
|
651262
|
+
]);
|
|
651263
|
+
return probeIosToolchain({
|
|
651264
|
+
run: (command) => command === "xcrun" ? simctl : xcodeSelect
|
|
651265
|
+
});
|
|
651266
|
+
}
|
|
651267
|
+
function buildWarmTaskRunner({ config, runnerDetails, sizingJobs, appiumPool, installAttempts, warmUpResults, deviceRegistry, simulatorRegistry, resourceRegistry }) {
|
|
651268
|
+
let androidEnv;
|
|
651269
|
+
const getAndroidEnv = () => androidEnv ??= resolveAndroidWarmEnv(config);
|
|
651270
|
+
let iosToolchain;
|
|
651271
|
+
const getIosToolchain = () => iosToolchain ??= probeIosToolchainWarm();
|
|
651272
|
+
const acquireLease = async (names) => {
|
|
651273
|
+
while (!resourceRegistry.tryAcquire(names)) {
|
|
651274
|
+
await resourceRegistry.waitForFree();
|
|
651275
|
+
}
|
|
651276
|
+
let released = false;
|
|
651277
|
+
return () => {
|
|
651278
|
+
if (released)
|
|
651279
|
+
return;
|
|
651280
|
+
released = true;
|
|
651281
|
+
resourceRegistry.release(names);
|
|
651282
|
+
};
|
|
651283
|
+
};
|
|
651284
|
+
const withRuntimeInstallLock = async (fn) => {
|
|
651285
|
+
const release = await acquireLease([RUNTIME_INSTALL_RESOURCE]);
|
|
651286
|
+
try {
|
|
651287
|
+
return await fn();
|
|
651288
|
+
} finally {
|
|
651289
|
+
release();
|
|
651290
|
+
}
|
|
651291
|
+
};
|
|
651292
|
+
let androidPreflight;
|
|
651293
|
+
const getAndroidPreflight = () => androidPreflight ??= withRuntimeInstallLock(() => appSurfacePreflight({ config, platform: "android" }));
|
|
651294
|
+
return async (task) => {
|
|
651295
|
+
switch (task.kind) {
|
|
651296
|
+
case "browser-install":
|
|
651297
|
+
return warmBrowserInstall({
|
|
651298
|
+
browserName: task.payload.browserName,
|
|
651299
|
+
config,
|
|
651300
|
+
runnerDetails,
|
|
651301
|
+
installAttempts
|
|
651302
|
+
});
|
|
651303
|
+
case "driver-install": {
|
|
651304
|
+
if (task.payload.platform === "android") {
|
|
651305
|
+
const env = await getAndroidEnv();
|
|
651306
|
+
if (!env) {
|
|
651307
|
+
return {
|
|
651308
|
+
outcome: "skipped",
|
|
651309
|
+
note: "Android toolchain not ready; the driver install stays with the consuming context"
|
|
651310
|
+
};
|
|
651311
|
+
}
|
|
651312
|
+
}
|
|
651313
|
+
if (task.payload.platform === "ios") {
|
|
651314
|
+
const toolchain = await getIosToolchain();
|
|
651315
|
+
if (!toolchain.ok) {
|
|
651316
|
+
return { outcome: "skipped", note: toolchain.reason };
|
|
651317
|
+
}
|
|
651318
|
+
}
|
|
651319
|
+
const { ensureRuntimeInstalled: ensureRuntimeInstalled2 } = await Promise.resolve().then(() => (init_loader(), loader_exports));
|
|
651320
|
+
await ensureRuntimeInstalled2([task.payload.driverPackage], {
|
|
651321
|
+
ctx: { cacheDir: config?.cacheDir },
|
|
651322
|
+
deps: { logger: (m) => log(config, "debug", m) }
|
|
651323
|
+
});
|
|
651324
|
+
return { outcome: "warmed" };
|
|
651325
|
+
}
|
|
651326
|
+
case "device-boot": {
|
|
651327
|
+
const desc = task.payload.desc;
|
|
651328
|
+
const onError = (error) => log(config, "warning", `Warm boot of '${task.name}' failed (a consuming context will retry): ${error?.message ?? String(error)}`);
|
|
651329
|
+
if (task.payload.platform === "android") {
|
|
651330
|
+
const env = await getAndroidEnv();
|
|
651331
|
+
if (!env) {
|
|
651332
|
+
return {
|
|
651333
|
+
outcome: "skipped",
|
|
651334
|
+
note: "Android toolchain not ready; device setup stays with the consuming context"
|
|
651335
|
+
};
|
|
651336
|
+
}
|
|
651337
|
+
const releaseEmulatorLease = await acquireLease([
|
|
651338
|
+
"android-emulator"
|
|
651339
|
+
]);
|
|
651340
|
+
return raceBootInitiation({
|
|
651341
|
+
onError,
|
|
651342
|
+
startAcquire: (signalInitiated) => {
|
|
651343
|
+
const acquiring = acquireDevice({
|
|
651344
|
+
desc,
|
|
651345
|
+
registry: deviceRegistry,
|
|
651346
|
+
sdkRoot: env.sdkRoot,
|
|
651347
|
+
deps: wrapInitiationEffects(env.deviceDeps, ["createAvd", "boot"], signalInitiated)
|
|
651348
|
+
});
|
|
651349
|
+
acquiring.then(() => releaseEmulatorLease(), () => releaseEmulatorLease());
|
|
651350
|
+
return acquiring;
|
|
651351
|
+
}
|
|
651352
|
+
});
|
|
651353
|
+
}
|
|
651354
|
+
const toolchain = await getIosToolchain();
|
|
651355
|
+
if (!toolchain.ok) {
|
|
651356
|
+
return { outcome: "skipped", note: toolchain.reason };
|
|
651357
|
+
}
|
|
651358
|
+
const simDeps = buildAcquireSimulatorDeps((m) => log(config, "debug", m));
|
|
651359
|
+
return raceBootInitiation({
|
|
651360
|
+
onError,
|
|
651361
|
+
startAcquire: (signalInitiated) => acquireSimulator({
|
|
651362
|
+
desc,
|
|
651363
|
+
registry: simulatorRegistry,
|
|
651364
|
+
deps: wrapInitiationEffects(simDeps, ["create", "boot"], signalInitiated)
|
|
651365
|
+
})
|
|
651366
|
+
});
|
|
651367
|
+
}
|
|
651368
|
+
case "wda-check": {
|
|
651369
|
+
const hit = locateManagedWda({ ctx: { cacheDir: config?.cacheDir } });
|
|
651370
|
+
if (hit) {
|
|
651371
|
+
return {
|
|
651372
|
+
outcome: "warmed",
|
|
651373
|
+
note: `prebuilt WebDriverAgent available (${hit.key})`
|
|
651374
|
+
};
|
|
651375
|
+
}
|
|
651376
|
+
return {
|
|
651377
|
+
outcome: "skipped",
|
|
651378
|
+
note: "no prebuilt WebDriverAgent for the current toolchain \u2014 `doc-detective install ios` prebuilds it"
|
|
651379
|
+
};
|
|
651380
|
+
}
|
|
651381
|
+
case "session-probe": {
|
|
651382
|
+
if (!appiumPool) {
|
|
651383
|
+
return { outcome: "skipped", note: "no browser Appium pool" };
|
|
651384
|
+
}
|
|
651385
|
+
await warmUpContexts({
|
|
651386
|
+
jobs: sizingJobs,
|
|
651387
|
+
config,
|
|
651388
|
+
runnerDetails,
|
|
651389
|
+
appiumPool,
|
|
651390
|
+
installAttempts,
|
|
651391
|
+
warmUpResults
|
|
651392
|
+
});
|
|
651393
|
+
const ok = [...warmUpResults.values()].filter((v) => v === "ok").length;
|
|
651394
|
+
const failed = warmUpResults.size - ok;
|
|
651395
|
+
return {
|
|
651396
|
+
outcome: "warmed",
|
|
651397
|
+
note: `${ok} combination${ok === 1 ? "" : "s"} ok${failed ? `, ${failed} failed` : ""}`
|
|
651398
|
+
};
|
|
651399
|
+
}
|
|
651400
|
+
case "chromedriver-prefetch":
|
|
651401
|
+
return prefetchMobileChromedriver({
|
|
651402
|
+
config,
|
|
651403
|
+
desc: task.payload.desc,
|
|
651404
|
+
deviceRegistry,
|
|
651405
|
+
getAndroidEnv,
|
|
651406
|
+
deps: {
|
|
651407
|
+
// The cache-mutating half (driver install + Appium co-homing)
|
|
651408
|
+
// runs once per run under the manual runtime-install lease, so
|
|
651409
|
+
// the prefetch task itself only holds its device tag while it
|
|
651410
|
+
// awaits readiness and runs the throwaway session.
|
|
651411
|
+
appSurfacePreflight: () => getAndroidPreflight(),
|
|
651412
|
+
acquireEmulatorLease: () => acquireLease(["android-emulator"])
|
|
651413
|
+
}
|
|
651414
|
+
});
|
|
651415
|
+
}
|
|
651416
|
+
};
|
|
651417
|
+
}
|
|
651418
|
+
async function prefetchMobileChromedriver({ config, desc, deviceRegistry, getAndroidEnv, deps = {} }) {
|
|
651419
|
+
const preflight = deps.appSurfacePreflight ?? appSurfacePreflight;
|
|
651420
|
+
const acquire = deps.acquireDevice ?? acquireDevice;
|
|
651421
|
+
const startServer = deps.startAppiumServer ?? startAppiumServer;
|
|
651422
|
+
const startDriver = deps.driverStart ?? driverStart;
|
|
651423
|
+
const kill4 = deps.killTree ?? killTree;
|
|
651424
|
+
const env = await getAndroidEnv();
|
|
651425
|
+
if (!env) {
|
|
651426
|
+
return {
|
|
651427
|
+
outcome: "skipped",
|
|
651428
|
+
note: "Android toolchain not ready; the first mobile-web session downloads chromedriver as needed"
|
|
651429
|
+
};
|
|
651430
|
+
}
|
|
651431
|
+
const pre = await preflight({ config, platform: "android" });
|
|
651432
|
+
if (!pre.ok)
|
|
651433
|
+
return { outcome: "skipped", note: pre.reason };
|
|
651434
|
+
const releaseLease = deps.acquireEmulatorLease ? await deps.acquireEmulatorLease() : void 0;
|
|
651435
|
+
let acquired;
|
|
651436
|
+
try {
|
|
651437
|
+
acquired = await acquire({
|
|
651438
|
+
desc,
|
|
651439
|
+
registry: deviceRegistry,
|
|
651440
|
+
sdkRoot: env.sdkRoot,
|
|
651441
|
+
deps: env.deviceDeps
|
|
651442
|
+
});
|
|
651443
|
+
} finally {
|
|
651444
|
+
releaseLease?.();
|
|
651445
|
+
}
|
|
651446
|
+
if ("skip" in acquired)
|
|
651447
|
+
return { outcome: "skipped", note: acquired.skip };
|
|
651448
|
+
let server;
|
|
651449
|
+
let driver;
|
|
651450
|
+
try {
|
|
651451
|
+
server = await startServer(pre.appiumEntry, config, void 0, {
|
|
651452
|
+
APPIUM_HOME: pre.appiumHome,
|
|
651453
|
+
ANDROID_HOME: env.sdkRoot,
|
|
651454
|
+
ANDROID_SDK_ROOT: env.sdkRoot
|
|
651455
|
+
}, CHROMEDRIVER_AUTODOWNLOAD_ARGS);
|
|
651456
|
+
driver = await startDriver(buildMobileBrowserCapabilities({
|
|
651457
|
+
platform: "android",
|
|
651458
|
+
udid: acquired.entry.udid,
|
|
651459
|
+
cacheDir: getCacheDir({ cacheDir: config?.cacheDir })
|
|
651460
|
+
}), server.port, 2, { cacheDir: config?.cacheDir });
|
|
651461
|
+
return {
|
|
651462
|
+
outcome: "warmed",
|
|
651463
|
+
note: `chromedriver ready for device '${acquired.entry.name}'`
|
|
651464
|
+
};
|
|
651465
|
+
} finally {
|
|
651466
|
+
if (driver) {
|
|
651467
|
+
try {
|
|
651468
|
+
await driver.deleteSession();
|
|
651469
|
+
} catch {
|
|
651470
|
+
}
|
|
651471
|
+
}
|
|
651472
|
+
if (server) {
|
|
651473
|
+
await kill4(server.process?.pid);
|
|
651474
|
+
}
|
|
651475
|
+
}
|
|
651476
|
+
}
|
|
650705
651477
|
function specIsRouted(spec) {
|
|
650706
651478
|
if (!spec || !Array.isArray(spec.tests))
|
|
650707
651479
|
return false;
|
|
@@ -650818,7 +651590,7 @@ function buildAutoRecordStep({ config, spec, test, context }) {
|
|
|
650818
651590
|
return null;
|
|
650819
651591
|
const runDir = getRunOutputDir(config, { create: false });
|
|
650820
651592
|
const contextSegment = capPathSegment(sanitizeFilesystemName(String(context.contextId ?? ""), "context"));
|
|
650821
|
-
const recordPath =
|
|
651593
|
+
const recordPath = import_node_path26.default.join(runDir, "specs", capPathSegment(sanitizeFilesystemName(String(spec.specId ?? ""), "spec")), "tests", capPathSegment(sanitizeFilesystemName(String(test.testId ?? ""), "test")), "contexts", contextSegment, "recordings", `${contextSegment}.mp4`);
|
|
650822
651594
|
return {
|
|
650823
651595
|
// Mobile-target contexts record the device screen through the app driver
|
|
650824
651596
|
// (the internal device plan, resolved from the platform) — pinning ffmpeg
|
|
@@ -650847,7 +651619,7 @@ async function captureAutoScreenshot({ config, driver, spec, test, context, step
|
|
|
650847
651619
|
const action = BROWSER_STEP_KEYS.find((key) => typeof step[key] !== "undefined") || "step";
|
|
650848
651620
|
const sanitizedTestId = sanitizeFilesystemName(String(test.testId ?? ""), "test");
|
|
650849
651621
|
const runDir = getRunOutputDir(config);
|
|
650850
|
-
const dir =
|
|
651622
|
+
const dir = import_node_path26.default.join(runDir, "specs", capPathSegment(sanitizeFilesystemName(String(spec.specId ?? ""), "spec")), "tests", capPathSegment(sanitizedTestId), "contexts", capPathSegment(sanitizeFilesystemName(String(context.contextId ?? ""), "context")), "screenshots");
|
|
650851
651623
|
const stepIdString = sanitizeFilesystemName(String(step.stepId ?? ""), "step");
|
|
650852
651624
|
const stepRef = capPathSegment(stepIdString.startsWith(`${sanitizedTestId}~`) ? stepIdString.slice(sanitizedTestId.length + 1) : stepIdString);
|
|
650853
651625
|
const pad = Math.max(2, String(stepCount).length);
|
|
@@ -650856,7 +651628,7 @@ async function captureAutoScreenshot({ config, driver, spec, test, context, step
|
|
|
650856
651628
|
stepId: `${step.stepId}_auto`,
|
|
650857
651629
|
description: "Automatic post-step screenshot",
|
|
650858
651630
|
screenshot: {
|
|
650859
|
-
path:
|
|
651631
|
+
path: import_node_path26.default.join(dir, fileName),
|
|
650860
651632
|
overwrite: "true"
|
|
650861
651633
|
}
|
|
650862
651634
|
};
|
|
@@ -650869,7 +651641,7 @@ async function captureAutoScreenshot({ config, driver, spec, test, context, step
|
|
|
650869
651641
|
log(config, "warning", `Auto screenshot failed after step ${step.stepId}: ${captureResult.description}`);
|
|
650870
651642
|
return null;
|
|
650871
651643
|
}
|
|
650872
|
-
return
|
|
651644
|
+
return import_node_path26.default.relative(runDir, screenshotStep.screenshot.path).split(import_node_path26.default.sep).join("/");
|
|
650873
651645
|
} catch (error) {
|
|
650874
651646
|
log(config, "warning", `Auto screenshot failed after step ${step.stepId}: ${error?.message ?? error}`);
|
|
650875
651647
|
return null;
|
|
@@ -651049,7 +651821,8 @@ async function runContext({ config, spec, test, context, runnerDetails, appiumPo
|
|
|
651049
651821
|
contextReport.resultDescription = errorMessage;
|
|
651050
651822
|
return contextReport;
|
|
651051
651823
|
}
|
|
651052
|
-
|
|
651824
|
+
if (logLevelEnabled(config, "debug"))
|
|
651825
|
+
clog("debug", `CONTEXT:
|
|
651053
651826
|
${JSON.stringify(context, null, 2)}`);
|
|
651054
651827
|
let driver;
|
|
651055
651828
|
let appiumPort;
|
|
@@ -651068,7 +651841,7 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
651068
651841
|
env.ANDROID_HOME = appSession.androidSdkRoot;
|
|
651069
651842
|
env.ANDROID_SDK_ROOT = appSession.androidSdkRoot;
|
|
651070
651843
|
}
|
|
651071
|
-
const extraArgs = mobileTarget === "android" ?
|
|
651844
|
+
const extraArgs = mobileTarget === "android" ? CHROMEDRIVER_AUTODOWNLOAD_ARGS : [];
|
|
651072
651845
|
let acquired;
|
|
651073
651846
|
try {
|
|
651074
651847
|
const server = await startAppiumServer(appSession.appiumEntry, config, void 0, env, extraArgs);
|
|
@@ -651361,7 +652134,8 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
651361
652134
|
stepExecutionFailed = true;
|
|
651362
652135
|
break;
|
|
651363
652136
|
}
|
|
651364
|
-
|
|
652137
|
+
if (logLevelEnabled(config, "debug"))
|
|
652138
|
+
clog("debug", `STEP:
|
|
651365
652139
|
${JSON.stringify(step, null, 2)}`);
|
|
651366
652140
|
if (step.unsafe && runnerDetails.allowUnsafeSteps === false) {
|
|
651367
652141
|
clog("warning", `Skipping unsafe step: ${step.description} in test ${test.testId} context ${context.contextId}`);
|
|
@@ -651427,7 +652201,8 @@ ${JSON.stringify(step, null, 2)}`);
|
|
|
651427
652201
|
processRegistry,
|
|
651428
652202
|
appSession
|
|
651429
652203
|
});
|
|
651430
|
-
|
|
652204
|
+
if (logLevelEnabled(config, "debug"))
|
|
652205
|
+
clog("debug", `RESULT: ${r.status}
|
|
651431
652206
|
${JSON.stringify(r, null, 2)}`);
|
|
651432
652207
|
r.result = r.status;
|
|
651433
652208
|
r.resultDescription = r.description;
|
|
@@ -651824,7 +652599,7 @@ async function runStep({ config = {}, context = {}, step, driver, metaValues = {
|
|
|
651824
652599
|
}
|
|
651825
652600
|
return actionResult;
|
|
651826
652601
|
}
|
|
651827
|
-
async function
|
|
652602
|
+
async function spawnAppiumServer(appiumEntry, config, display, extraEnv, extraArgs) {
|
|
651828
652603
|
const port = await findFreePort();
|
|
651829
652604
|
log(config, "debug", `Starting Appium on port ${port}`);
|
|
651830
652605
|
const env = display || extraEnv ? {
|
|
@@ -651832,9 +652607,9 @@ async function startAppiumServer(appiumEntry, config, display, extraEnv, extraAr
|
|
|
651832
652607
|
...display ? { DISPLAY: display } : {},
|
|
651833
652608
|
...extraEnv ?? {}
|
|
651834
652609
|
} : process.env;
|
|
651835
|
-
const proc = (0,
|
|
652610
|
+
const proc = (0, import_node_child_process15.spawn)(process.execPath, [appiumEntry, "-a", "127.0.0.1", "-p", String(port), ...extraArgs ?? []], {
|
|
651836
652611
|
windowsHide: true,
|
|
651837
|
-
cwd:
|
|
652612
|
+
cwd: import_node_path26.default.join(__dirname5, "../.."),
|
|
651838
652613
|
env
|
|
651839
652614
|
});
|
|
651840
652615
|
proc.on("error", (err) => {
|
|
@@ -651844,31 +652619,41 @@ async function startAppiumServer(appiumEntry, config, display, extraEnv, extraAr
|
|
|
651844
652619
|
});
|
|
651845
652620
|
proc.stderr.on("data", () => {
|
|
651846
652621
|
});
|
|
652622
|
+
return { port, process: proc, display };
|
|
652623
|
+
}
|
|
652624
|
+
async function startAppiumServer(appiumEntry, config, display, extraEnv, extraArgs) {
|
|
652625
|
+
const server = await spawnAppiumServer(appiumEntry, config, display, extraEnv, extraArgs);
|
|
651847
652626
|
try {
|
|
651848
|
-
await appiumIsReady(port);
|
|
652627
|
+
await appiumIsReady(server.port);
|
|
651849
652628
|
} catch (error) {
|
|
651850
|
-
await killTree(
|
|
652629
|
+
await killTree(server.process?.pid);
|
|
651851
652630
|
throw error;
|
|
651852
652631
|
}
|
|
651853
|
-
log(config, "debug", `Appium is ready on port ${port}.`);
|
|
651854
|
-
return
|
|
652632
|
+
log(config, "debug", `Appium is ready on port ${server.port}.`);
|
|
652633
|
+
return server;
|
|
651855
652634
|
}
|
|
651856
|
-
|
|
651857
|
-
|
|
652635
|
+
var STATUS_PROBE_TIMEOUT_MS = 1e4;
|
|
652636
|
+
async function appiumIsReady(port, timeoutMs = 12e4, deps = {}) {
|
|
652637
|
+
const probe = deps.probe ?? (async (p) => {
|
|
652638
|
+
try {
|
|
652639
|
+
const resp = await import_axios6.default.get(`http://127.0.0.1:${p}/status`, {
|
|
652640
|
+
timeout: STATUS_PROBE_TIMEOUT_MS
|
|
652641
|
+
});
|
|
652642
|
+
return resp.status === 200;
|
|
652643
|
+
} catch {
|
|
652644
|
+
return false;
|
|
652645
|
+
}
|
|
652646
|
+
});
|
|
652647
|
+
const sleep4 = deps.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
651858
652648
|
const start = Date.now();
|
|
651859
|
-
while (
|
|
652649
|
+
while (true) {
|
|
652650
|
+
if (await probe(port))
|
|
652651
|
+
return true;
|
|
651860
652652
|
if (Date.now() - start > timeoutMs) {
|
|
651861
652653
|
throw new Error(`Appium server on port ${port} failed to start within ${timeoutMs / 1e3} seconds`);
|
|
651862
652654
|
}
|
|
651863
|
-
await
|
|
651864
|
-
try {
|
|
651865
|
-
let resp = await import_axios6.default.get(`http://127.0.0.1:${port}/status`);
|
|
651866
|
-
if (resp.status === 200)
|
|
651867
|
-
isReady = true;
|
|
651868
|
-
} catch {
|
|
651869
|
-
}
|
|
652655
|
+
await sleep4(250);
|
|
651870
652656
|
}
|
|
651871
|
-
return isReady;
|
|
651872
652657
|
}
|
|
651873
652658
|
async function driverStart(capabilities, port, maxAttempts = 4, ctx = {}) {
|
|
651874
652659
|
const wdio = await loadHeavyDep("webdriverio", { ctx });
|
|
@@ -651980,9 +652765,9 @@ async function getRunner(options = {}) {
|
|
|
651980
652765
|
if (!appiumEntry) {
|
|
651981
652766
|
throw new Error("appium is not installed. Run `doc-detective install runtime appium` to install it.");
|
|
651982
652767
|
}
|
|
651983
|
-
const appium = (0,
|
|
652768
|
+
const appium = (0, import_node_child_process15.spawn)(process.execPath, [appiumEntry, "-a", "127.0.0.1", "-p", String(appiumPort)], {
|
|
651984
652769
|
windowsHide: true,
|
|
651985
|
-
cwd:
|
|
652770
|
+
cwd: import_node_path26.default.join(__dirname5, "../..")
|
|
651986
652771
|
});
|
|
651987
652772
|
appium.on("error", (err) => {
|
|
651988
652773
|
log(config, "warning", `Appium process error: ${err?.stack ?? err?.message ?? String(err)}`);
|
|
@@ -652058,6 +652843,8 @@ function telemetryNotice(config) {
|
|
|
652058
652843
|
log(config, "info", "Doc Detective collects basic anonymous telemetry to understand product issues and usage. To disable telemetry, set 'telemetry.send' to 'false' in your .doc-detective.json config file.");
|
|
652059
652844
|
}
|
|
652060
652845
|
}
|
|
652846
|
+
var TELEMETRY_FLUSH_TIMEOUT_MS = 2e3;
|
|
652847
|
+
var pendingTelemetryFlush = null;
|
|
652061
652848
|
function sendTelemetry(config, command, results) {
|
|
652062
652849
|
if (config?.telemetry?.send === false)
|
|
652063
652850
|
return;
|
|
@@ -652098,7 +652885,7 @@ function sendTelemetry(config, command, results) {
|
|
|
652098
652885
|
const event = { distinctId, event: command, properties: telemetryData };
|
|
652099
652886
|
const client = new import_posthog_node.PostHog("phc_rjV0MH3nsAd45zFISLgaKAdAXbgDeXt2mOBV2EBHomB", { host: "https://app.posthog.com" });
|
|
652100
652887
|
client.capture(event);
|
|
652101
|
-
client.shutdown();
|
|
652888
|
+
pendingTelemetryFlush = Promise.resolve(client.shutdown(TELEMETRY_FLUSH_TIMEOUT_MS)).then(() => void 0).catch(() => void 0);
|
|
652102
652889
|
}
|
|
652103
652890
|
|
|
652104
652891
|
// dist/core/index.js
|