doc-detective 4.6.0 → 4.7.0-runtime-dependency-detection.1
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 +57 -6
- package/dist/cli.js.map +1 -1
- package/dist/common/src/schemas/schemas.json +6 -18
- package/dist/common/src/types/generated/config_v3.d.ts +2 -1
- package/dist/common/src/types/generated/config_v3.d.ts.map +1 -1
- package/dist/common/src/types/generated/resolvedTests_v3.d.ts +2 -1
- package/dist/common/src/types/generated/resolvedTests_v3.d.ts.map +1 -1
- package/dist/core/config.d.ts +17 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +250 -68
- package/dist/core/config.js.map +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +7 -10
- package/dist/core/index.js.map +1 -1
- package/dist/core/tests.d.ts +41 -1
- package/dist/core/tests.d.ts.map +1 -1
- package/dist/core/tests.js +166 -7
- package/dist/core/tests.js.map +1 -1
- package/dist/debug/command.d.ts +10 -0
- package/dist/debug/command.d.ts.map +1 -0
- package/dist/debug/command.js +72 -0
- package/dist/debug/command.js.map +1 -0
- package/dist/debug/envvars.d.ts +9 -0
- package/dist/debug/envvars.d.ts.map +1 -0
- package/dist/debug/envvars.js +231 -0
- package/dist/debug/envvars.js.map +1 -0
- package/dist/debug/index.d.ts +85 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/index.js +465 -0
- package/dist/debug/index.js.map +1 -0
- package/dist/debug/redact.d.ts +7 -0
- package/dist/debug/redact.d.ts.map +1 -0
- package/dist/debug/redact.js +190 -0
- package/dist/debug/redact.js.map +1 -0
- package/dist/debug/render.d.ts +8 -0
- package/dist/debug/render.d.ts.map +1 -0
- package/dist/debug/render.js +42 -0
- package/dist/debug/render.js.map +1 -0
- package/dist/debug/system.d.ts +24 -0
- package/dist/debug/system.d.ts.map +1 -0
- package/dist/debug/system.js +59 -0
- package/dist/debug/system.js.map +1 -0
- package/dist/debug/tools.d.ts +11 -0
- package/dist/debug/tools.d.ts.map +1 -0
- package/dist/debug/tools.js +170 -0
- package/dist/debug/tools.js.map +1 -0
- 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/index.cjs +393 -151
- package/dist/runtime/browsers.d.ts +14 -0
- package/dist/runtime/browsers.d.ts.map +1 -1
- package/dist/runtime/browsers.js +23 -0
- package/dist/runtime/browsers.js.map +1 -1
- package/dist/runtime/installer.d.ts.map +1 -1
- package/dist/runtime/installer.js +44 -9
- package/dist/runtime/installer.js.map +1 -1
- package/dist/runtime/loader.d.ts +20 -0
- package/dist/runtime/loader.d.ts.map +1 -1
- package/dist/runtime/loader.js +50 -0
- package/dist/runtime/loader.js.map +1 -1
- package/dist/utils.d.ts +2 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +38 -11
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -9923,7 +9923,8 @@ var init_schemas = __esm({
|
|
|
9923
9923
|
title: "Environment details"
|
|
9924
9924
|
},
|
|
9925
9925
|
debug: {
|
|
9926
|
-
description: "
|
|
9926
|
+
description: "Deprecated and ignored. Previously reserved for an interactive step-through debugger that was never implemented. Retained so existing configs continue to validate. For diagnostics, run `doc-detective debug` or set the `DOC_DETECTIVE_DEBUG` environment variable.",
|
|
9927
|
+
deprecated: true,
|
|
9927
9928
|
anyOf: [
|
|
9928
9929
|
{
|
|
9929
9930
|
type: "boolean"
|
|
@@ -9934,8 +9935,7 @@ var init_schemas = __esm({
|
|
|
9934
9935
|
"stepThrough"
|
|
9935
9936
|
]
|
|
9936
9937
|
}
|
|
9937
|
-
]
|
|
9938
|
-
default: false
|
|
9938
|
+
]
|
|
9939
9939
|
},
|
|
9940
9940
|
dryRun: {
|
|
9941
9941
|
description: "If `true`, fully resolve tests (file/env config merge, schema validation, file detection, inline-test extraction) and emit the resolved test plan as JSON, but do not execute any steps. Equivalent to `--dry-run` on the CLI.",
|
|
@@ -18245,12 +18245,6 @@ var init_schemas = __esm({
|
|
|
18245
18245
|
{
|
|
18246
18246
|
debug: false
|
|
18247
18247
|
},
|
|
18248
|
-
{
|
|
18249
|
-
debug: true
|
|
18250
|
-
},
|
|
18251
|
-
{
|
|
18252
|
-
debug: "stepThrough"
|
|
18253
|
-
},
|
|
18254
18248
|
{
|
|
18255
18249
|
integrations: {
|
|
18256
18250
|
docDetectiveApi: {
|
|
@@ -31882,7 +31876,8 @@ var init_schemas = __esm({
|
|
|
31882
31876
|
title: "Environment details"
|
|
31883
31877
|
},
|
|
31884
31878
|
debug: {
|
|
31885
|
-
description: "
|
|
31879
|
+
description: "Deprecated and ignored. Previously reserved for an interactive step-through debugger that was never implemented. Retained so existing configs continue to validate. For diagnostics, run `doc-detective debug` or set the `DOC_DETECTIVE_DEBUG` environment variable.",
|
|
31880
|
+
deprecated: true,
|
|
31886
31881
|
anyOf: [
|
|
31887
31882
|
{
|
|
31888
31883
|
type: "boolean"
|
|
@@ -31893,8 +31888,7 @@ var init_schemas = __esm({
|
|
|
31893
31888
|
"stepThrough"
|
|
31894
31889
|
]
|
|
31895
31890
|
}
|
|
31896
|
-
]
|
|
31897
|
-
default: false
|
|
31891
|
+
]
|
|
31898
31892
|
},
|
|
31899
31893
|
dryRun: {
|
|
31900
31894
|
description: "If `true`, fully resolve tests (file/env config merge, schema validation, file detection, inline-test extraction) and emit the resolved test plan as JSON, but do not execute any steps. Equivalent to `--dry-run` on the CLI.",
|
|
@@ -40204,12 +40198,6 @@ var init_schemas = __esm({
|
|
|
40204
40198
|
{
|
|
40205
40199
|
debug: false
|
|
40206
40200
|
},
|
|
40207
|
-
{
|
|
40208
|
-
debug: true
|
|
40209
|
-
},
|
|
40210
|
-
{
|
|
40211
|
-
debug: "stepThrough"
|
|
40212
|
-
},
|
|
40213
40201
|
{
|
|
40214
40202
|
integrations: {
|
|
40215
40203
|
docDetectiveApi: {
|
|
@@ -130740,7 +130728,9 @@ var loader_exports = {};
|
|
|
130740
130728
|
__export(loader_exports, {
|
|
130741
130729
|
ensureRuntimeInstalled: () => ensureRuntimeInstalled,
|
|
130742
130730
|
loadHeavyDep: () => loadHeavyDep,
|
|
130743
|
-
resolveHeavyDepPath: () => resolveHeavyDepPath
|
|
130731
|
+
resolveHeavyDepPath: () => resolveHeavyDepPath,
|
|
130732
|
+
resolveHeavyDepSource: () => resolveHeavyDepSource,
|
|
130733
|
+
resolveHeavyDepVersion: () => resolveHeavyDepVersion
|
|
130744
130734
|
});
|
|
130745
130735
|
function tryResolveFromShim(name) {
|
|
130746
130736
|
try {
|
|
@@ -130764,6 +130754,36 @@ function tryResolveFromCache(name, ctx = {}) {
|
|
|
130764
130754
|
function resolveHeavyDepPath(name, ctx = {}) {
|
|
130765
130755
|
return tryResolveFromShim(name) ?? tryResolveFromCache(name, ctx);
|
|
130766
130756
|
}
|
|
130757
|
+
function resolveHeavyDepSource(name, ctx = {}) {
|
|
130758
|
+
if (tryResolveFromShim(name))
|
|
130759
|
+
return "shim";
|
|
130760
|
+
if (tryResolveFromCache(name, ctx))
|
|
130761
|
+
return "cache";
|
|
130762
|
+
return null;
|
|
130763
|
+
}
|
|
130764
|
+
function resolveHeavyDepVersion(name, ctx = {}) {
|
|
130765
|
+
const entry = resolveHeavyDepPath(name, ctx);
|
|
130766
|
+
if (!entry)
|
|
130767
|
+
return null;
|
|
130768
|
+
let dir = import_node_path4.default.dirname(entry);
|
|
130769
|
+
for (let i = 0; i < 12; i++) {
|
|
130770
|
+
const pkgJsonPath = import_node_path4.default.join(dir, "package.json");
|
|
130771
|
+
try {
|
|
130772
|
+
if (import_node_fs4.default.existsSync(pkgJsonPath)) {
|
|
130773
|
+
const parsed = JSON.parse(import_node_fs4.default.readFileSync(pkgJsonPath, "utf8"));
|
|
130774
|
+
if (parsed?.name === name && typeof parsed.version === "string") {
|
|
130775
|
+
return parsed.version;
|
|
130776
|
+
}
|
|
130777
|
+
}
|
|
130778
|
+
} catch {
|
|
130779
|
+
}
|
|
130780
|
+
const parent = import_node_path4.default.dirname(dir);
|
|
130781
|
+
if (parent === dir)
|
|
130782
|
+
break;
|
|
130783
|
+
dir = parent;
|
|
130784
|
+
}
|
|
130785
|
+
return null;
|
|
130786
|
+
}
|
|
130767
130787
|
async function loadHeavyDep(name, options = {}) {
|
|
130768
130788
|
const { autoInstall = true, ctx = {}, deps = {} } = options;
|
|
130769
130789
|
let resolved = tryResolveFromShim(name);
|
|
@@ -131426,6 +131446,7 @@ var config_exports = {};
|
|
|
131426
131446
|
__export(config_exports, {
|
|
131427
131447
|
clearAppCache: () => clearAppCache,
|
|
131428
131448
|
getAvailableApps: () => getAvailableApps,
|
|
131449
|
+
getBrowserDiagnostics: () => getBrowserDiagnostics,
|
|
131429
131450
|
getEnvironment: () => getEnvironment,
|
|
131430
131451
|
resolveConcurrentRunners: () => resolveConcurrentRunners,
|
|
131431
131452
|
setConfig: () => setConfig
|
|
@@ -131619,23 +131640,32 @@ function clearAppCache(config) {
|
|
|
131619
131640
|
}
|
|
131620
131641
|
cachedAppsByDir.delete(cacheKeyFor(config));
|
|
131621
131642
|
}
|
|
131622
|
-
async function
|
|
131623
|
-
const browsersDir = getBrowsersDir({ cacheDir: config?.cacheDir });
|
|
131624
|
-
const key = browsersDir;
|
|
131625
|
-
const hit = cachedAppsByDir.get(key);
|
|
131626
|
-
if (hit)
|
|
131627
|
-
return hit;
|
|
131643
|
+
async function probeBrowserEnvironment({ config, browsersDir }) {
|
|
131628
131644
|
setAppiumHome({ cacheDir: config?.cacheDir });
|
|
131629
131645
|
const cwd = process.cwd();
|
|
131630
131646
|
process.chdir(import_node_path7.default.join(__dirname4, "../.."));
|
|
131631
|
-
|
|
131647
|
+
let installedBrowsers = [];
|
|
131648
|
+
let browserDetectionFailed = false;
|
|
131649
|
+
let appiumDriverOutput = "";
|
|
131632
131650
|
try {
|
|
131633
|
-
const
|
|
131634
|
-
|
|
131635
|
-
});
|
|
131636
|
-
const installedBrowsers = await browsers.getInstalledBrowsers({
|
|
131637
|
-
cacheDir: browsersDir
|
|
131651
|
+
const browsersInstalled = resolveHeavyDepPath("@puppeteer/browsers", {
|
|
131652
|
+
cacheDir: config?.cacheDir
|
|
131638
131653
|
});
|
|
131654
|
+
if (browsersInstalled) {
|
|
131655
|
+
try {
|
|
131656
|
+
const browsers = await loadHeavyDep("@puppeteer/browsers", {
|
|
131657
|
+
ctx: { cacheDir: config?.cacheDir },
|
|
131658
|
+
autoInstall: false
|
|
131659
|
+
});
|
|
131660
|
+
installedBrowsers = await browsers.getInstalledBrowsers({
|
|
131661
|
+
cacheDir: browsersDir
|
|
131662
|
+
});
|
|
131663
|
+
} catch (err) {
|
|
131664
|
+
browserDetectionFailed = true;
|
|
131665
|
+
log(config, "warning", `Browser detection failed; continuing without detected browsers: ${err?.message ?? err}`);
|
|
131666
|
+
installedBrowsers = [];
|
|
131667
|
+
}
|
|
131668
|
+
}
|
|
131639
131669
|
const appiumEntry = resolveHeavyDepPath("appium", {
|
|
131640
131670
|
cacheDir: config?.cacheDir
|
|
131641
131671
|
});
|
|
@@ -131672,46 +131702,165 @@ async function getAvailableApps({ config }) {
|
|
|
131672
131702
|
});
|
|
131673
131703
|
});
|
|
131674
131704
|
});
|
|
131675
|
-
|
|
131676
|
-
|
|
131677
|
-
|
|
131678
|
-
|
|
131679
|
-
|
|
131680
|
-
|
|
131681
|
-
|
|
131682
|
-
|
|
131683
|
-
|
|
131684
|
-
|
|
131685
|
-
|
|
131686
|
-
|
|
131705
|
+
appiumDriverOutput = installedAppiumDrivers.stdout + "\n" + installedAppiumDrivers.stderr;
|
|
131706
|
+
} finally {
|
|
131707
|
+
process.chdir(cwd);
|
|
131708
|
+
}
|
|
131709
|
+
return { installedBrowsers, appiumDriverOutput, browserDetectionFailed };
|
|
131710
|
+
}
|
|
131711
|
+
async function getAvailableApps({ config }) {
|
|
131712
|
+
const browsersDir = getBrowsersDir({ cacheDir: config?.cacheDir });
|
|
131713
|
+
const key = browsersDir;
|
|
131714
|
+
const hit = cachedAppsByDir.get(key);
|
|
131715
|
+
if (hit)
|
|
131716
|
+
return hit;
|
|
131717
|
+
const { installedBrowsers, appiumDriverOutput, browserDetectionFailed } = await probeBrowserEnvironment({ config, browsersDir });
|
|
131718
|
+
const apps = [];
|
|
131719
|
+
const chrome = installedBrowsers.find((browser) => browser.browser === "chrome");
|
|
131720
|
+
const chromeVersion = chrome?.buildId;
|
|
131721
|
+
const chromedriver = installedBrowsers.find((browser) => browser.browser === "chromedriver");
|
|
131722
|
+
const appiumChromium = appiumDriverOutput.match(/\n.*chromium.*installed \(npm\).*\n/);
|
|
131723
|
+
if (chrome && chromedriver && appiumChromium) {
|
|
131724
|
+
apps.push({
|
|
131725
|
+
name: "chrome",
|
|
131726
|
+
version: chromeVersion,
|
|
131727
|
+
path: chrome.executablePath,
|
|
131728
|
+
driver: chromedriver.executablePath
|
|
131729
|
+
});
|
|
131730
|
+
}
|
|
131731
|
+
const firefox = installedBrowsers.find((browser) => browser.browser === "firefox");
|
|
131732
|
+
const appiumFirefox = appiumDriverOutput.match(/\n.*gecko.*installed \(npm\).*\n/);
|
|
131733
|
+
if (firefox && appiumFirefox) {
|
|
131734
|
+
apps.push({
|
|
131735
|
+
name: "firefox",
|
|
131736
|
+
version: firefox.buildId,
|
|
131737
|
+
path: firefox.executablePath
|
|
131738
|
+
});
|
|
131739
|
+
}
|
|
131740
|
+
if (config.environment.platform === "mac") {
|
|
131741
|
+
const safariVersion = await spawnCommand("defaults read /Applications/Safari.app/Contents/Info.plist CFBundleShortVersionString");
|
|
131742
|
+
const appiumSafari = appiumDriverOutput.match(/\n.*safari.*installed \(npm\).*\n/);
|
|
131743
|
+
if (safariVersion.exitCode === 0 && appiumSafari) {
|
|
131744
|
+
apps.push({ name: "safari", version: safariVersion.stdout.trim(), path: "" });
|
|
131687
131745
|
}
|
|
131688
|
-
|
|
131689
|
-
|
|
131690
|
-
|
|
131691
|
-
|
|
131692
|
-
|
|
131693
|
-
|
|
131694
|
-
|
|
131695
|
-
|
|
131746
|
+
}
|
|
131747
|
+
if (!browserDetectionFailed)
|
|
131748
|
+
cachedAppsByDir.set(key, apps);
|
|
131749
|
+
return apps;
|
|
131750
|
+
}
|
|
131751
|
+
function probeSafariVersion(timeoutMs) {
|
|
131752
|
+
return new Promise((resolve) => {
|
|
131753
|
+
let child;
|
|
131754
|
+
try {
|
|
131755
|
+
child = (0, import_node_child_process3.spawn)("defaults", [
|
|
131756
|
+
"read",
|
|
131757
|
+
"/Applications/Safari.app/Contents/Info.plist",
|
|
131758
|
+
"CFBundleShortVersionString"
|
|
131759
|
+
], { stdio: ["ignore", "pipe", "ignore"] });
|
|
131760
|
+
} catch {
|
|
131761
|
+
resolve(null);
|
|
131762
|
+
return;
|
|
131696
131763
|
}
|
|
131697
|
-
|
|
131698
|
-
|
|
131699
|
-
|
|
131700
|
-
if (
|
|
131701
|
-
|
|
131764
|
+
let stdout = "";
|
|
131765
|
+
let settled = false;
|
|
131766
|
+
const finish = (value) => {
|
|
131767
|
+
if (settled)
|
|
131768
|
+
return;
|
|
131769
|
+
settled = true;
|
|
131770
|
+
clearTimeout(timer);
|
|
131771
|
+
try {
|
|
131772
|
+
child.kill();
|
|
131773
|
+
} catch {
|
|
131702
131774
|
}
|
|
131775
|
+
resolve(value);
|
|
131776
|
+
};
|
|
131777
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
131778
|
+
timer.unref?.();
|
|
131779
|
+
child.stdout?.on("data", (c) => {
|
|
131780
|
+
stdout += typeof c === "string" ? c : c.toString("utf8");
|
|
131781
|
+
});
|
|
131782
|
+
child.on("error", () => finish(null));
|
|
131783
|
+
child.on("close", (code) => finish(code === 0 ? stdout.trim() : null));
|
|
131784
|
+
});
|
|
131785
|
+
}
|
|
131786
|
+
async function getBrowserDiagnostics({ config }) {
|
|
131787
|
+
let detectionFailed = false;
|
|
131788
|
+
let record;
|
|
131789
|
+
try {
|
|
131790
|
+
record = readInstalledRecord({ cacheDir: config?.cacheDir });
|
|
131791
|
+
} catch {
|
|
131792
|
+
detectionFailed = true;
|
|
131793
|
+
record = { npmPackages: {}, browsers: {} };
|
|
131794
|
+
}
|
|
131795
|
+
const browsersRec = record.browsers || {};
|
|
131796
|
+
const platform = config?.environment?.platform;
|
|
131797
|
+
const brow = (name) => browsersRec[name];
|
|
131798
|
+
const npmInstalled = (name) => Boolean(resolveHeavyDepPath(name, { cacheDir: config?.cacheDir }));
|
|
131799
|
+
const browsers = [];
|
|
131800
|
+
const chrome = brow("chrome");
|
|
131801
|
+
const chromedriver = brow("chromedriver");
|
|
131802
|
+
const appiumChromium = npmInstalled("appium-chromium-driver");
|
|
131803
|
+
browsers.push({
|
|
131804
|
+
name: "chrome",
|
|
131805
|
+
supported: true,
|
|
131806
|
+
available: Boolean(chrome && chromedriver && appiumChromium),
|
|
131807
|
+
components: [
|
|
131808
|
+
{ label: "chrome browser", installed: Boolean(chrome), detail: chrome?.installedVersion },
|
|
131809
|
+
{ label: "chromedriver", installed: Boolean(chromedriver), detail: chromedriver?.installedVersion },
|
|
131810
|
+
{ label: "appium-chromium-driver", installed: appiumChromium }
|
|
131811
|
+
]
|
|
131812
|
+
});
|
|
131813
|
+
const firefox = brow("firefox");
|
|
131814
|
+
const geckodriver = brow("geckodriver");
|
|
131815
|
+
const appiumGecko = npmInstalled("appium-geckodriver");
|
|
131816
|
+
browsers.push({
|
|
131817
|
+
name: "firefox",
|
|
131818
|
+
supported: true,
|
|
131819
|
+
available: Boolean(firefox && geckodriver && appiumGecko),
|
|
131820
|
+
components: [
|
|
131821
|
+
{ label: "firefox browser", installed: Boolean(firefox), detail: firefox?.installedVersion },
|
|
131822
|
+
{ label: "geckodriver", installed: Boolean(geckodriver), detail: geckodriver?.installedVersion },
|
|
131823
|
+
{ label: "appium-geckodriver", installed: appiumGecko }
|
|
131824
|
+
]
|
|
131825
|
+
});
|
|
131826
|
+
const isMac = platform === "mac";
|
|
131827
|
+
const appiumSafari = npmInstalled("appium-safari-driver");
|
|
131828
|
+
let safariApp = false;
|
|
131829
|
+
let safariVersion;
|
|
131830
|
+
let safaridriver = false;
|
|
131831
|
+
if (isMac) {
|
|
131832
|
+
try {
|
|
131833
|
+
const version = await probeSafariVersion(4e3);
|
|
131834
|
+
safariApp = version !== null;
|
|
131835
|
+
safariVersion = version ?? void 0;
|
|
131836
|
+
safaridriver = import_node_fs7.default.existsSync("/usr/bin/safaridriver");
|
|
131837
|
+
} catch {
|
|
131838
|
+
detectionFailed = true;
|
|
131703
131839
|
}
|
|
131704
|
-
} finally {
|
|
131705
|
-
process.chdir(cwd);
|
|
131706
131840
|
}
|
|
131707
|
-
|
|
131708
|
-
|
|
131841
|
+
browsers.push({
|
|
131842
|
+
name: "safari",
|
|
131843
|
+
supported: isMac,
|
|
131844
|
+
available: Boolean(isMac && safariApp && safaridriver && appiumSafari),
|
|
131845
|
+
components: [
|
|
131846
|
+
{ label: "Safari app", installed: safariApp, detail: safariVersion },
|
|
131847
|
+
{
|
|
131848
|
+
label: "safaridriver",
|
|
131849
|
+
installed: safaridriver,
|
|
131850
|
+
detail: safaridriver ? "/usr/bin/safaridriver" : void 0
|
|
131851
|
+
},
|
|
131852
|
+
{ label: "appium-safari-driver", installed: appiumSafari }
|
|
131853
|
+
],
|
|
131854
|
+
note: isMac ? void 0 : "Safari is only available on macOS"
|
|
131855
|
+
});
|
|
131856
|
+
return { browsers, detectionFailed };
|
|
131709
131857
|
}
|
|
131710
|
-
var import_node_os3, import_node_path7, import_node_child_process3, import_node_url5, __dirname4, platformMap, defaultFileTypes, cachedAppsByDir;
|
|
131858
|
+
var import_node_os3, import_node_fs7, import_node_path7, import_node_child_process3, import_node_url5, __dirname4, platformMap, defaultFileTypes, cachedAppsByDir;
|
|
131711
131859
|
var init_config = __esm({
|
|
131712
131860
|
"dist/core/config.js"() {
|
|
131713
131861
|
"use strict";
|
|
131714
131862
|
import_node_os3 = __toESM(require("node:os"), 1);
|
|
131863
|
+
import_node_fs7 = __toESM(require("node:fs"), 1);
|
|
131715
131864
|
init_validate();
|
|
131716
131865
|
init_utils();
|
|
131717
131866
|
import_node_path7 = __toESM(require("node:path"), 1);
|
|
@@ -132005,8 +132154,19 @@ var browsers_exports = {};
|
|
|
132005
132154
|
__export(browsers_exports, {
|
|
132006
132155
|
BROWSER_CHANNELS: () => BROWSER_CHANNELS,
|
|
132007
132156
|
ensureBrowserInstalled: () => ensureBrowserInstalled,
|
|
132008
|
-
getInstalledBrowsers: () => getInstalledBrowsers
|
|
132157
|
+
getInstalledBrowsers: () => getInstalledBrowsers,
|
|
132158
|
+
requiredBrowserAssets: () => requiredBrowserAssets
|
|
132009
132159
|
});
|
|
132160
|
+
function requiredBrowserAssets(name) {
|
|
132161
|
+
switch ((name ?? "").toLowerCase()) {
|
|
132162
|
+
case "chrome":
|
|
132163
|
+
return ["chrome", "chromedriver"];
|
|
132164
|
+
case "firefox":
|
|
132165
|
+
return ["firefox", "geckodriver"];
|
|
132166
|
+
default:
|
|
132167
|
+
return [];
|
|
132168
|
+
}
|
|
132169
|
+
}
|
|
132010
132170
|
async function loadPuppeteerBrowsers(deps, ctx) {
|
|
132011
132171
|
if (deps.browsersModule)
|
|
132012
132172
|
return deps.browsersModule;
|
|
@@ -132384,7 +132544,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
132384
132544
|
init_config();
|
|
132385
132545
|
|
|
132386
132546
|
// dist/core/detectTests.js
|
|
132387
|
-
var
|
|
132547
|
+
var import_node_fs9 = __toESM(require("node:fs"), 1);
|
|
132388
132548
|
var import_node_path9 = __toESM(require("node:path"), 1);
|
|
132389
132549
|
var import_node_os5 = __toESM(require("node:os"), 1);
|
|
132390
132550
|
var import_node_crypto3 = __toESM(require("node:crypto"), 1);
|
|
@@ -133216,7 +133376,7 @@ init_files();
|
|
|
133216
133376
|
init_utils();
|
|
133217
133377
|
|
|
133218
133378
|
// dist/core/integrations/heretto.js
|
|
133219
|
-
var
|
|
133379
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
133220
133380
|
var import_node_path8 = __toESM(require("node:path"), 1);
|
|
133221
133381
|
var import_node_https = __toESM(require("node:https"), 1);
|
|
133222
133382
|
var import_node_http = __toESM(require("node:http"), 1);
|
|
@@ -133377,11 +133537,11 @@ var HerettoUploader = class {
|
|
|
133377
133537
|
return result;
|
|
133378
133538
|
}
|
|
133379
133539
|
}
|
|
133380
|
-
if (!
|
|
133540
|
+
if (!import_node_fs8.default.existsSync(localFilePath)) {
|
|
133381
133541
|
result.description = `Local file not found: ${localFilePath}`;
|
|
133382
133542
|
return result;
|
|
133383
133543
|
}
|
|
133384
|
-
const fileContent =
|
|
133544
|
+
const fileContent = import_node_fs8.default.readFileSync(localFilePath);
|
|
133385
133545
|
const contentType = this.getContentType(localFilePath);
|
|
133386
133546
|
try {
|
|
133387
133547
|
await this.uploadFile({
|
|
@@ -134155,7 +134315,7 @@ async function pollJobStatus(client, fileId, jobId, log3, config) {
|
|
|
134155
134315
|
return null;
|
|
134156
134316
|
}
|
|
134157
134317
|
async function downloadAndExtractOutput(client, fileId, jobId, herettoName, log3, config, deps) {
|
|
134158
|
-
const fsModule = deps?.fsModule ||
|
|
134318
|
+
const fsModule = deps?.fsModule || import_node_fs8.default;
|
|
134159
134319
|
const ZipClass = deps?.ZipClass || import_adm_zip.default;
|
|
134160
134320
|
const tempDir = import_node_path8.default.join(import_node_os4.default.tmpdir(), "doc-detective");
|
|
134161
134321
|
const hash = import_node_crypto2.default.createHash("md5").update(`${herettoName}_${jobId}`).digest("hex");
|
|
@@ -134393,7 +134553,7 @@ async function isValidSourceFile({ config, files, source }) {
|
|
|
134393
134553
|
} else {
|
|
134394
134554
|
beforePath = import_node_path9.default.resolve(test.before);
|
|
134395
134555
|
}
|
|
134396
|
-
if (!
|
|
134556
|
+
if (!import_node_fs9.default.existsSync(beforePath)) {
|
|
134397
134557
|
log(config, "debug", `${beforePath} is specified to run before a test but isn't a valid file. Skipping ${source}.`);
|
|
134398
134558
|
return false;
|
|
134399
134559
|
}
|
|
@@ -134405,7 +134565,7 @@ async function isValidSourceFile({ config, files, source }) {
|
|
|
134405
134565
|
} else {
|
|
134406
134566
|
afterPath = import_node_path9.default.resolve(test.after);
|
|
134407
134567
|
}
|
|
134408
|
-
if (!
|
|
134568
|
+
if (!import_node_fs9.default.existsSync(afterPath)) {
|
|
134409
134569
|
log(config, "debug", `${afterPath} is specified to run after a test but isn't a valid file. Skipping ${source}.`);
|
|
134410
134570
|
return false;
|
|
134411
134571
|
}
|
|
@@ -134423,9 +134583,9 @@ async function processDitaMap({ config, source }) {
|
|
|
134423
134583
|
const hash = import_node_crypto3.default.createHash("md5").update(source).digest("hex");
|
|
134424
134584
|
const tmpBase = import_node_path9.default.join(import_node_os5.default.tmpdir(), "doc-detective");
|
|
134425
134585
|
const outputDir = import_node_path9.default.join(tmpBase, `ditamap_${hash}`);
|
|
134426
|
-
if (!
|
|
134586
|
+
if (!import_node_fs9.default.existsSync(tmpBase)) {
|
|
134427
134587
|
log(config, "debug", `Creating temp directory: ${tmpBase}`);
|
|
134428
|
-
|
|
134588
|
+
import_node_fs9.default.mkdirSync(tmpBase, { recursive: true });
|
|
134429
134589
|
}
|
|
134430
134590
|
const ditaVersion = await spawnCommand("dita", ["--version"]);
|
|
134431
134591
|
if (ditaVersion.exitCode !== 0) {
|
|
@@ -134527,8 +134687,8 @@ async function qualifyFiles({ config }) {
|
|
|
134527
134687
|
let isFile = false;
|
|
134528
134688
|
let isDir = false;
|
|
134529
134689
|
try {
|
|
134530
|
-
isFile =
|
|
134531
|
-
isDir =
|
|
134690
|
+
isFile = import_node_fs9.default.statSync(source).isFile();
|
|
134691
|
+
isDir = import_node_fs9.default.statSync(source).isDirectory();
|
|
134532
134692
|
} catch {
|
|
134533
134693
|
log(config, "warning", `Cannot access path: ${source}. Skipping.`);
|
|
134534
134694
|
continue;
|
|
@@ -134548,13 +134708,13 @@ async function qualifyFiles({ config }) {
|
|
|
134548
134708
|
dirs = [];
|
|
134549
134709
|
dirs[0] = source;
|
|
134550
134710
|
for (const dir of dirs) {
|
|
134551
|
-
const objects =
|
|
134711
|
+
const objects = import_node_fs9.default.readdirSync(dir);
|
|
134552
134712
|
for (const object of objects) {
|
|
134553
134713
|
const content = import_node_path9.default.resolve(dir + "/" + object);
|
|
134554
134714
|
if (content.includes("node_modules"))
|
|
134555
134715
|
continue;
|
|
134556
|
-
const isFile2 =
|
|
134557
|
-
const isDir2 =
|
|
134716
|
+
const isFile2 = import_node_fs9.default.statSync(content).isFile();
|
|
134717
|
+
const isDir2 = import_node_fs9.default.statSync(content).isDirectory();
|
|
134558
134718
|
if (isFile2 && await isValidSourceFile({ config, files, source: content })) {
|
|
134559
134719
|
files.push(import_node_path9.default.resolve(content));
|
|
134560
134720
|
} else if (isDir2 && config.recursive) {
|
|
@@ -134575,7 +134735,7 @@ async function parseTests({ config, files }) {
|
|
|
134575
134735
|
let rawContent;
|
|
134576
134736
|
if (extension === "json" || extension === "yaml" || extension === "yml") {
|
|
134577
134737
|
try {
|
|
134578
|
-
rawContent = await
|
|
134738
|
+
rawContent = await import_node_fs9.default.promises.readFile(file, "utf8");
|
|
134579
134739
|
if (extension === "json") {
|
|
134580
134740
|
content = JSON.parse(rawContent);
|
|
134581
134741
|
} else {
|
|
@@ -134961,6 +135121,7 @@ init_utils();
|
|
|
134961
135121
|
// dist/core/tests.js
|
|
134962
135122
|
var import_tree_kill = __toESM(require("tree-kill"), 1);
|
|
134963
135123
|
init_loader();
|
|
135124
|
+
init_browsers();
|
|
134964
135125
|
var import_node_os8 = __toESM(require("node:os"), 1);
|
|
134965
135126
|
init_utils();
|
|
134966
135127
|
var import_axios6 = __toESM(require("axios"), 1);
|
|
@@ -136221,7 +136382,7 @@ async function waitForDOMStable(driver, idleTime, timeout) {
|
|
|
136221
136382
|
// dist/core/tests/runShell.js
|
|
136222
136383
|
init_validate();
|
|
136223
136384
|
init_utils();
|
|
136224
|
-
var
|
|
136385
|
+
var import_node_fs10 = __toESM(require("node:fs"), 1);
|
|
136225
136386
|
var import_node_path10 = __toESM(require("node:path"), 1);
|
|
136226
136387
|
async function runShell({ config, step }) {
|
|
136227
136388
|
const result = {
|
|
@@ -136296,23 +136457,23 @@ async function runShell({ config, step }) {
|
|
|
136296
136457
|
}
|
|
136297
136458
|
if (step.runShell.path) {
|
|
136298
136459
|
const dir = import_node_path10.default.dirname(step.runShell.path);
|
|
136299
|
-
if (!
|
|
136300
|
-
|
|
136460
|
+
if (!import_node_fs10.default.existsSync(dir)) {
|
|
136461
|
+
import_node_fs10.default.mkdirSync(dir, { recursive: true });
|
|
136301
136462
|
}
|
|
136302
136463
|
let filePath = step.runShell.path;
|
|
136303
136464
|
log(config, "debug", `Saving stdio to file: ${filePath}`);
|
|
136304
|
-
if (!
|
|
136305
|
-
|
|
136465
|
+
if (!import_node_fs10.default.existsSync(filePath)) {
|
|
136466
|
+
import_node_fs10.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
136306
136467
|
} else {
|
|
136307
136468
|
if (step.runShell.overwrite == "false") {
|
|
136308
136469
|
result.description = result.description + ` Didn't save output. File already exists.`;
|
|
136309
136470
|
}
|
|
136310
|
-
const existingFile =
|
|
136471
|
+
const existingFile = import_node_fs10.default.readFileSync(filePath, "utf8");
|
|
136311
136472
|
const fractionalDiff = calculateFractionalDifference(existingFile, result.outputs.stdio.stdout);
|
|
136312
136473
|
log(config, "debug", `Fractional difference: ${fractionalDiff}`);
|
|
136313
136474
|
if (fractionalDiff > step.runShell.maxVariation) {
|
|
136314
136475
|
if (step.runShell.overwrite == "aboveVariation") {
|
|
136315
|
-
|
|
136476
|
+
import_node_fs10.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
136316
136477
|
result.description += ` Saved output to file.`;
|
|
136317
136478
|
}
|
|
136318
136479
|
result.status = "WARNING";
|
|
@@ -136320,7 +136481,7 @@ async function runShell({ config, step }) {
|
|
|
136320
136481
|
return result;
|
|
136321
136482
|
}
|
|
136322
136483
|
if (step.runShell.overwrite == "true") {
|
|
136323
|
-
|
|
136484
|
+
import_node_fs10.default.writeFileSync(filePath, result.outputs.stdio.stdout);
|
|
136324
136485
|
result.description += ` Saved output to file.`;
|
|
136325
136486
|
}
|
|
136326
136487
|
}
|
|
@@ -136505,7 +136666,7 @@ async function checkLink({ config, step }) {
|
|
|
136505
136666
|
init_validate();
|
|
136506
136667
|
init_utils();
|
|
136507
136668
|
var import_node_path11 = __toESM(require("node:path"), 1);
|
|
136508
|
-
var
|
|
136669
|
+
var import_node_fs11 = __toESM(require("node:fs"), 1);
|
|
136509
136670
|
init_loader();
|
|
136510
136671
|
var _pngjs = null;
|
|
136511
136672
|
var _sharp = null;
|
|
@@ -136632,8 +136793,8 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136632
136793
|
const rawBase = import_node_path11.default.basename(urlPathname.split("?")[0].split("#")[0].replace(/\\/g, "/"));
|
|
136633
136794
|
const safeBase = sanitizeFilesystemName(rawBase, `${step.stepId}.png`);
|
|
136634
136795
|
dir = import_node_path11.default.join(process.cwd(), "doc-detective-runs", getOrInitRunTimestamp(config));
|
|
136635
|
-
if (!
|
|
136636
|
-
|
|
136796
|
+
if (!import_node_fs11.default.existsSync(dir)) {
|
|
136797
|
+
import_node_fs11.default.mkdirSync(dir, { recursive: true });
|
|
136637
136798
|
}
|
|
136638
136799
|
const captureId = `${step.stepId || "screenshot"}_${Date.now()}`;
|
|
136639
136800
|
filePath = import_node_path11.default.join(dir, `${captureId}_${safeBase}`);
|
|
@@ -136649,10 +136810,10 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136649
136810
|
}
|
|
136650
136811
|
} else {
|
|
136651
136812
|
dir = import_node_path11.default.dirname(step.screenshot.path);
|
|
136652
|
-
if (!
|
|
136653
|
-
|
|
136813
|
+
if (!import_node_fs11.default.existsSync(dir)) {
|
|
136814
|
+
import_node_fs11.default.mkdirSync(dir, { recursive: true });
|
|
136654
136815
|
}
|
|
136655
|
-
if (
|
|
136816
|
+
if (import_node_fs11.default.existsSync(filePath)) {
|
|
136656
136817
|
if (step.screenshot.overwrite == "false") {
|
|
136657
136818
|
result.status = "SKIPPED";
|
|
136658
136819
|
result.description = `File already exists: ${filePath}`;
|
|
@@ -136748,8 +136909,8 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136748
136909
|
} catch (error) {
|
|
136749
136910
|
result.status = "FAIL";
|
|
136750
136911
|
result.description = `Couldn't save screenshot. ${error}`;
|
|
136751
|
-
if (existFilePath && filePath !== existFilePath &&
|
|
136752
|
-
|
|
136912
|
+
if (existFilePath && filePath !== existFilePath && import_node_fs11.default.existsSync(filePath)) {
|
|
136913
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136753
136914
|
}
|
|
136754
136915
|
return result;
|
|
136755
136916
|
}
|
|
@@ -136801,12 +136962,12 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136801
136962
|
width: rect.width,
|
|
136802
136963
|
height: rect.height
|
|
136803
136964
|
}).toFile(croppedPath);
|
|
136804
|
-
|
|
136965
|
+
import_node_fs11.default.renameSync(croppedPath, filePath);
|
|
136805
136966
|
} catch (error) {
|
|
136806
136967
|
result.status = "FAIL";
|
|
136807
136968
|
result.description = `Couldn't crop image. ${error}`;
|
|
136808
|
-
if (existFilePath && filePath !== existFilePath &&
|
|
136809
|
-
|
|
136969
|
+
if (existFilePath && filePath !== existFilePath && import_node_fs11.default.existsSync(filePath)) {
|
|
136970
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136810
136971
|
}
|
|
136811
136972
|
return result;
|
|
136812
136973
|
}
|
|
@@ -136814,7 +136975,7 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136814
136975
|
if (existFilePath) {
|
|
136815
136976
|
if (step.screenshot.overwrite == "true" && !isUrlPath) {
|
|
136816
136977
|
result.description += ` Overwrote existing file.`;
|
|
136817
|
-
|
|
136978
|
+
import_node_fs11.default.renameSync(filePath, existFilePath);
|
|
136818
136979
|
result.outputs.screenshotPath = existFilePath;
|
|
136819
136980
|
result.outputs.changed = true;
|
|
136820
136981
|
if (step.screenshot.sourceIntegration) {
|
|
@@ -136827,21 +136988,21 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136827
136988
|
let img1;
|
|
136828
136989
|
let img2;
|
|
136829
136990
|
try {
|
|
136830
|
-
img1 = PNG.sync.read(
|
|
136831
|
-
img2 = PNG.sync.read(
|
|
136991
|
+
img1 = PNG.sync.read(import_node_fs11.default.readFileSync(existFilePath));
|
|
136992
|
+
img2 = PNG.sync.read(import_node_fs11.default.readFileSync(filePath));
|
|
136832
136993
|
} catch (error) {
|
|
136833
136994
|
result.status = "FAIL";
|
|
136834
136995
|
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}`;
|
|
136835
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
136836
|
-
|
|
136996
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs11.default.existsSync(filePath)) {
|
|
136997
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136837
136998
|
}
|
|
136838
136999
|
return result;
|
|
136839
137000
|
}
|
|
136840
137001
|
if (!aspectRatiosMatch(img1, img2)) {
|
|
136841
137002
|
result.status = "FAIL";
|
|
136842
137003
|
result.description = `Couldn't compare images. Images have different aspect ratios.`;
|
|
136843
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
136844
|
-
|
|
137004
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs11.default.existsSync(filePath)) {
|
|
137005
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136845
137006
|
}
|
|
136846
137007
|
return result;
|
|
136847
137008
|
}
|
|
@@ -136868,8 +137029,8 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136868
137029
|
} catch (error) {
|
|
136869
137030
|
result.status = "FAIL";
|
|
136870
137031
|
result.description = `Couldn't load screenshot comparison dependency (pixelmatch). ${error?.message ?? error}`;
|
|
136871
|
-
if (!isUrlPath && filePath !== existFilePath &&
|
|
136872
|
-
|
|
137032
|
+
if (!isUrlPath && filePath !== existFilePath && import_node_fs11.default.existsSync(filePath)) {
|
|
137033
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136873
137034
|
}
|
|
136874
137035
|
return result;
|
|
136875
137036
|
}
|
|
@@ -136882,7 +137043,7 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136882
137043
|
});
|
|
136883
137044
|
if (fractionalDiff > step.screenshot.maxVariation) {
|
|
136884
137045
|
if (step.screenshot.overwrite == "aboveVariation" && !isUrlPath) {
|
|
136885
|
-
|
|
137046
|
+
import_node_fs11.default.renameSync(filePath, existFilePath);
|
|
136886
137047
|
}
|
|
136887
137048
|
result.status = "WARNING";
|
|
136888
137049
|
result.description += ` The difference between the existing screenshot and new screenshot (${fractionalDiff.toFixed(2)}) is greater than the max accepted variation (${step.screenshot.maxVariation}).`;
|
|
@@ -136908,7 +137069,7 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136908
137069
|
result.outputs.sourceIntegration = step.screenshot.sourceIntegration;
|
|
136909
137070
|
}
|
|
136910
137071
|
if (step.screenshot.overwrite != "true") {
|
|
136911
|
-
|
|
137072
|
+
import_node_fs11.default.unlinkSync(filePath);
|
|
136912
137073
|
}
|
|
136913
137074
|
}
|
|
136914
137075
|
}
|
|
@@ -136928,7 +137089,7 @@ async function saveScreenshot({ config, step, driver }) {
|
|
|
136928
137089
|
init_validate();
|
|
136929
137090
|
init_utils();
|
|
136930
137091
|
var import_node_path12 = __toESM(require("node:path"), 1);
|
|
136931
|
-
var
|
|
137092
|
+
var import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
136932
137093
|
var import_node_os6 = __toESM(require("node:os"), 1);
|
|
136933
137094
|
async function startRecording({ config, context, step, driver }) {
|
|
136934
137095
|
let result = {
|
|
@@ -136966,10 +137127,10 @@ async function startRecording({ config, context, step, driver }) {
|
|
|
136966
137127
|
let filePath = step.record.path;
|
|
136967
137128
|
const baseName = import_node_path12.default.basename(filePath, import_node_path12.default.extname(filePath));
|
|
136968
137129
|
const dir = import_node_path12.default.dirname(step.record.path);
|
|
136969
|
-
if (!
|
|
136970
|
-
|
|
137130
|
+
if (!import_node_fs12.default.existsSync(dir)) {
|
|
137131
|
+
import_node_fs12.default.mkdirSync(dir, { recursive: true });
|
|
136971
137132
|
}
|
|
136972
|
-
if (
|
|
137133
|
+
if (import_node_fs12.default.existsSync(filePath) && step.record.overwrite == "false") {
|
|
136973
137134
|
result.status = "SKIPPED";
|
|
136974
137135
|
result.description = `File already exists: ${filePath}`;
|
|
136975
137136
|
return result;
|
|
@@ -137093,7 +137254,7 @@ init_validate();
|
|
|
137093
137254
|
init_utils();
|
|
137094
137255
|
var import_node_child_process4 = require("node:child_process");
|
|
137095
137256
|
var import_node_path13 = __toESM(require("node:path"), 1);
|
|
137096
|
-
var
|
|
137257
|
+
var import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
137097
137258
|
init_loader();
|
|
137098
137259
|
async function getFfmpegPath(ctx = {}) {
|
|
137099
137260
|
const mod = await loadHeavyDep("@ffmpeg-installer/ffmpeg", { ctx });
|
|
@@ -137142,11 +137303,11 @@ async function stopRecording({ config, step, driver }) {
|
|
|
137142
137303
|
window.recorder.stop();
|
|
137143
137304
|
});
|
|
137144
137305
|
let waitCount = 0;
|
|
137145
|
-
while (!
|
|
137306
|
+
while (!import_node_fs13.default.existsSync(config.recording.downloadPath) && waitCount < 60) {
|
|
137146
137307
|
await new Promise((r) => setTimeout(r, 1e3));
|
|
137147
137308
|
waitCount++;
|
|
137148
137309
|
}
|
|
137149
|
-
if (!
|
|
137310
|
+
if (!import_node_fs13.default.existsSync(config.recording.downloadPath)) {
|
|
137150
137311
|
result.status = "FAIL";
|
|
137151
137312
|
result.description = "Recording download timed out.";
|
|
137152
137313
|
return result;
|
|
@@ -137171,7 +137332,7 @@ async function stopRecording({ config, step, driver }) {
|
|
|
137171
137332
|
if (code === 0) {
|
|
137172
137333
|
if (targetPath !== downloadPath) {
|
|
137173
137334
|
try {
|
|
137174
|
-
|
|
137335
|
+
import_node_fs13.default.unlinkSync(downloadPath);
|
|
137175
137336
|
} catch {
|
|
137176
137337
|
}
|
|
137177
137338
|
}
|
|
@@ -137217,7 +137378,7 @@ async function loadVariables({ step }) {
|
|
|
137217
137378
|
init_validate();
|
|
137218
137379
|
init_utils();
|
|
137219
137380
|
var import_node_path14 = __toESM(require("node:path"), 1);
|
|
137220
|
-
var
|
|
137381
|
+
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
137221
137382
|
async function saveCookie({ config, step, driver }) {
|
|
137222
137383
|
let result = {
|
|
137223
137384
|
status: "PASS",
|
|
@@ -137284,14 +137445,14 @@ async function saveCookie({ config, step, driver }) {
|
|
|
137284
137445
|
if (filePath) {
|
|
137285
137446
|
const outputDirectory = directory || config.output || process.cwd();
|
|
137286
137447
|
const fullPath = import_node_path14.default.resolve(outputDirectory, filePath);
|
|
137287
|
-
if (
|
|
137448
|
+
if (import_node_fs14.default.existsSync(fullPath) && !(overwrite === true || overwrite === "true")) {
|
|
137288
137449
|
result.status = "FAIL";
|
|
137289
137450
|
result.description = `File '${fullPath}' already exists and overwrite is not enabled.`;
|
|
137290
137451
|
return result;
|
|
137291
137452
|
}
|
|
137292
137453
|
const dir = import_node_path14.default.dirname(fullPath);
|
|
137293
|
-
if (!
|
|
137294
|
-
|
|
137454
|
+
if (!import_node_fs14.default.existsSync(dir)) {
|
|
137455
|
+
import_node_fs14.default.mkdirSync(dir, { recursive: true });
|
|
137295
137456
|
}
|
|
137296
137457
|
if (targetCookie) {
|
|
137297
137458
|
const netscapeCookie = formatCookieForNetscape(targetCookie);
|
|
@@ -137299,11 +137460,11 @@ async function saveCookie({ config, step, driver }) {
|
|
|
137299
137460
|
# This is a cookie file saved by Doc Detective
|
|
137300
137461
|
${netscapeCookie}
|
|
137301
137462
|
`;
|
|
137302
|
-
|
|
137463
|
+
import_node_fs14.default.writeFileSync(fullPath, content, "utf8");
|
|
137303
137464
|
result.description = `Saved cookie '${cookieName}' to '${fullPath}'.`;
|
|
137304
137465
|
log(config, "debug", `Saved cookie '${cookieName}' to file: ${fullPath}`);
|
|
137305
137466
|
} else {
|
|
137306
|
-
|
|
137467
|
+
import_node_fs14.default.writeFileSync(fullPath, "# No cookie data\n", "utf8");
|
|
137307
137468
|
result.description = `Created empty cookie file at '${fullPath}'.`;
|
|
137308
137469
|
log(config, "debug", `Created empty cookie file: ${fullPath}`);
|
|
137309
137470
|
}
|
|
@@ -137331,7 +137492,7 @@ function formatCookieForNetscape(cookie) {
|
|
|
137331
137492
|
init_validate();
|
|
137332
137493
|
init_utils();
|
|
137333
137494
|
var import_node_path15 = __toESM(require("node:path"), 1);
|
|
137334
|
-
var
|
|
137495
|
+
var import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
137335
137496
|
async function loadCookie({ config, step, driver }) {
|
|
137336
137497
|
let result = {
|
|
137337
137498
|
status: "PASS",
|
|
@@ -137387,13 +137548,13 @@ async function loadCookie({ config, step, driver }) {
|
|
|
137387
137548
|
} else if (filePath) {
|
|
137388
137549
|
const inputDirectory = directory || config.output || process.cwd();
|
|
137389
137550
|
const fullPath = import_node_path15.default.resolve(inputDirectory, filePath);
|
|
137390
|
-
if (!
|
|
137551
|
+
if (!import_node_fs15.default.existsSync(fullPath)) {
|
|
137391
137552
|
result.status = "FAIL";
|
|
137392
137553
|
result.description = `Cookie file '${fullPath}' not found`;
|
|
137393
137554
|
return result;
|
|
137394
137555
|
}
|
|
137395
137556
|
try {
|
|
137396
|
-
const fileContent =
|
|
137557
|
+
const fileContent = import_node_fs15.default.readFileSync(fullPath, "utf8");
|
|
137397
137558
|
const cookies = parseNetscapeCookieFile(fileContent);
|
|
137398
137559
|
if (cookies.length === 0) {
|
|
137399
137560
|
result.status = "FAIL";
|
|
@@ -137559,7 +137720,7 @@ function isDomainCompatible(currentDomain, cookieDomain) {
|
|
|
137559
137720
|
// dist/core/tests/httpRequest.js
|
|
137560
137721
|
init_validate();
|
|
137561
137722
|
var import_axios5 = __toESM(require("axios"), 1);
|
|
137562
|
-
var
|
|
137723
|
+
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
137563
137724
|
var import_node_path16 = __toESM(require("node:path"), 1);
|
|
137564
137725
|
var import_ajv2 = __toESM(require("ajv"), 1);
|
|
137565
137726
|
init_openapi();
|
|
@@ -137866,24 +138027,24 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
137866
138027
|
}
|
|
137867
138028
|
if (step.httpRequest.path) {
|
|
137868
138029
|
const dir = import_node_path16.default.dirname(step.httpRequest.path);
|
|
137869
|
-
if (!
|
|
137870
|
-
|
|
138030
|
+
if (!import_node_fs16.default.existsSync(dir)) {
|
|
138031
|
+
import_node_fs16.default.mkdirSync(dir, { recursive: true });
|
|
137871
138032
|
}
|
|
137872
138033
|
let filePath = step.httpRequest.path;
|
|
137873
138034
|
log(config, "debug", `Saving output to file: ${filePath}`);
|
|
137874
|
-
if (!
|
|
137875
|
-
await
|
|
138035
|
+
if (!import_node_fs16.default.existsSync(filePath)) {
|
|
138036
|
+
await import_node_fs16.default.promises.writeFile(filePath, JSON.stringify(response.data, null, 2));
|
|
137876
138037
|
result.description += ` Saved output to file.`;
|
|
137877
138038
|
} else {
|
|
137878
138039
|
if (step.httpRequest.overwrite == "false") {
|
|
137879
138040
|
result.description += ` Didn't save output. File already exists.`;
|
|
137880
138041
|
}
|
|
137881
|
-
const existingFile =
|
|
138042
|
+
const existingFile = import_node_fs16.default.readFileSync(filePath, "utf8");
|
|
137882
138043
|
const fractionalDiff = calculateFractionalDifference(existingFile, JSON.stringify(response.data, null, 2));
|
|
137883
138044
|
log(config, "debug", `Fractional difference: ${fractionalDiff}`);
|
|
137884
138045
|
if (fractionalDiff > step.httpRequest.maxVariation) {
|
|
137885
138046
|
if (step.httpRequest.overwrite == "aboveVariation") {
|
|
137886
|
-
await
|
|
138047
|
+
await import_node_fs16.default.promises.writeFile(filePath, JSON.stringify(response.data, null, 2));
|
|
137887
138048
|
result.description += ` Saved response to file.`;
|
|
137888
138049
|
}
|
|
137889
138050
|
result.status = "WARNING";
|
|
@@ -137891,7 +138052,7 @@ async function httpRequest({ config, step, openApiDefinitions = [] }) {
|
|
|
137891
138052
|
return result;
|
|
137892
138053
|
}
|
|
137893
138054
|
if (step.httpRequest.overwrite == "true") {
|
|
137894
|
-
|
|
138055
|
+
import_node_fs16.default.writeFileSync(filePath, JSON.stringify(response.data, null, 2));
|
|
137895
138056
|
result.description += ` Saved response to file.`;
|
|
137896
138057
|
}
|
|
137897
138058
|
}
|
|
@@ -138068,7 +138229,7 @@ async function clickElement({ config, step, driver }) {
|
|
|
138068
138229
|
// dist/core/tests/runCode.js
|
|
138069
138230
|
init_validate();
|
|
138070
138231
|
init_utils();
|
|
138071
|
-
var
|
|
138232
|
+
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
138072
138233
|
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
138073
138234
|
var import_node_os7 = __toESM(require("node:os"), 1);
|
|
138074
138235
|
function createTempScript(code, language) {
|
|
@@ -138092,7 +138253,7 @@ function createTempScript(code, language) {
|
|
|
138092
138253
|
const tmpDir = import_node_os7.default.tmpdir();
|
|
138093
138254
|
const tmpFile = import_node_path17.default.join(tmpDir, `doc-detective-${Date.now()}${extension}`);
|
|
138094
138255
|
try {
|
|
138095
|
-
|
|
138256
|
+
import_node_fs17.default.writeFileSync(tmpFile, code);
|
|
138096
138257
|
} catch (error) {
|
|
138097
138258
|
throw new Error(`Failed to create temporary script: ${error.message}`);
|
|
138098
138259
|
}
|
|
@@ -138176,7 +138337,7 @@ async function runCode({ config, step }) {
|
|
|
138176
138337
|
result.description = error.message;
|
|
138177
138338
|
} finally {
|
|
138178
138339
|
try {
|
|
138179
|
-
|
|
138340
|
+
import_node_fs17.default.unlinkSync(scriptPath);
|
|
138180
138341
|
log(config, "debug", `Removed temporary script: ${scriptPath}`);
|
|
138181
138342
|
} catch (error) {
|
|
138182
138343
|
log(config, "warn", `Failed to remove temporary script: ${scriptPath}`);
|
|
@@ -138724,6 +138885,14 @@ var driverActions2 = [
|
|
|
138724
138885
|
"type"
|
|
138725
138886
|
];
|
|
138726
138887
|
var KNOWN_BROWSERS = ["firefox", "chrome", "safari", "webkit"];
|
|
138888
|
+
function combinationKey(context) {
|
|
138889
|
+
const rawName = context?.browser?.name;
|
|
138890
|
+
const name = rawName === "webkit" ? "safari" : rawName || "<none>";
|
|
138891
|
+
return `${context?.platform}::${name}`;
|
|
138892
|
+
}
|
|
138893
|
+
function warmUpDecision(prev) {
|
|
138894
|
+
return prev === "failed" ? "skip" : "attempt";
|
|
138895
|
+
}
|
|
138727
138896
|
function getDriverCapabilities({ runnerDetails, name, options }) {
|
|
138728
138897
|
let capabilities = {};
|
|
138729
138898
|
let args = [];
|
|
@@ -139002,8 +139171,10 @@ async function runSpecs({ resolvedTests }) {
|
|
|
139002
139171
|
allowUnsafeSteps: await allowUnsafeSteps({ config })
|
|
139003
139172
|
};
|
|
139004
139173
|
const platform = runnerDetails.environment.platform;
|
|
139005
|
-
|
|
139174
|
+
let availableApps = runnerDetails.availableApps;
|
|
139006
139175
|
const metaValues = { specs: {} };
|
|
139176
|
+
const installAttempts = /* @__PURE__ */ new Map();
|
|
139177
|
+
const warmUpResults = /* @__PURE__ */ new Map();
|
|
139007
139178
|
let appium;
|
|
139008
139179
|
const report = {
|
|
139009
139180
|
summary: {
|
|
@@ -139118,14 +139289,46 @@ async function runSpecs({ resolvedTests }) {
|
|
|
139118
139289
|
testReport.contexts.push(contextReport);
|
|
139119
139290
|
continue;
|
|
139120
139291
|
}
|
|
139121
|
-
|
|
139292
|
+
let supportedContext = isSupportedContext({
|
|
139122
139293
|
context,
|
|
139123
139294
|
apps: availableApps,
|
|
139124
139295
|
platform
|
|
139125
139296
|
});
|
|
139297
|
+
let freshInstallRedetected = false;
|
|
139298
|
+
if (!supportedContext && context.platform === platform && // Mirror isSupportedContext's own guard: isDriverRequired iterates
|
|
139299
|
+
// context.steps, so a malformed context without a steps array would
|
|
139300
|
+
// otherwise crash the loop here instead of skipping cleanly.
|
|
139301
|
+
Array.isArray(context?.steps) && isDriverRequired({ test: context }) && requiredBrowserAssets(context.browser?.name).length > 0) {
|
|
139302
|
+
const firstAttempt = !installAttempts.has((context.browser?.name ?? "<none>").toLowerCase());
|
|
139303
|
+
const outcome = await ensureContextBrowserInstalled({
|
|
139304
|
+
browserName: context.browser?.name,
|
|
139305
|
+
config,
|
|
139306
|
+
installAttempts,
|
|
139307
|
+
deps: {
|
|
139308
|
+
ensureBrowser: (asset, options) => ensureBrowserInstalled(asset, options),
|
|
139309
|
+
log
|
|
139310
|
+
}
|
|
139311
|
+
});
|
|
139312
|
+
if (firstAttempt && (outcome === "installed" || outcome === "failed")) {
|
|
139313
|
+
freshInstallRedetected = true;
|
|
139314
|
+
clearAppCache(config);
|
|
139315
|
+
availableApps = await getAvailableApps({ config });
|
|
139316
|
+
runnerDetails.availableApps = availableApps;
|
|
139317
|
+
supportedContext = isSupportedContext({
|
|
139318
|
+
context,
|
|
139319
|
+
apps: availableApps,
|
|
139320
|
+
platform
|
|
139321
|
+
});
|
|
139322
|
+
}
|
|
139323
|
+
}
|
|
139126
139324
|
if (!supportedContext) {
|
|
139127
|
-
|
|
139128
|
-
|
|
139325
|
+
const errorMessage = freshInstallRedetected ? `Skipping context '${context.browser?.name}' on '${context.platform}': the missing browser dependency was installed but still could not be detected.` : `Skipping context. The current system doesn't support this context: {"platform": "${context.platform}", "apps": ${JSON.stringify(context.apps)}}`;
|
|
139326
|
+
log(config, freshInstallRedetected ? "warning" : "info", errorMessage);
|
|
139327
|
+
contextReport = {
|
|
139328
|
+
...contextReport,
|
|
139329
|
+
result: "SKIPPED",
|
|
139330
|
+
resultDescription: errorMessage
|
|
139331
|
+
};
|
|
139129
139332
|
report.summary.contexts.skipped++;
|
|
139130
139333
|
testReport.contexts.push(contextReport);
|
|
139131
139334
|
continue;
|
|
@@ -139138,6 +139341,19 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
139138
139341
|
}
|
|
139139
139342
|
const driverRequired = isDriverRequired({ test: context });
|
|
139140
139343
|
if (driverRequired) {
|
|
139344
|
+
const combo = combinationKey(context);
|
|
139345
|
+
if (warmUpDecision(warmUpResults.get(combo)) === "skip") {
|
|
139346
|
+
const errorMessage = `Skipping context '${context.browser?.name}' on '${context.platform}': this context combination could not start a driver earlier in this run.`;
|
|
139347
|
+
log(config, "warning", errorMessage);
|
|
139348
|
+
contextReport = {
|
|
139349
|
+
...contextReport,
|
|
139350
|
+
result: "SKIPPED",
|
|
139351
|
+
resultDescription: errorMessage
|
|
139352
|
+
};
|
|
139353
|
+
report.summary.contexts.skipped++;
|
|
139354
|
+
testReport.contexts.push(contextReport);
|
|
139355
|
+
continue;
|
|
139356
|
+
}
|
|
139141
139357
|
let caps = getDriverCapabilities({
|
|
139142
139358
|
runnerDetails,
|
|
139143
139359
|
name: context.browser.name,
|
|
@@ -139170,19 +139386,23 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
139170
139386
|
driver = await driverStart(caps, appiumPort, 4, { cacheDir: config?.cacheDir });
|
|
139171
139387
|
} catch (error2) {
|
|
139172
139388
|
let errorMessage = `Failed to start context '${context.browser?.name}' on '${platform}'.`;
|
|
139173
|
-
if (context.browser?.name === "safari")
|
|
139389
|
+
if (context.browser?.name === "safari" || context.browser?.name === "webkit")
|
|
139174
139390
|
errorMessage = errorMessage + " Make sure you've run `safaridriver --enable` in a terminal and enabled 'Allow Remote Automation' in Safari's Develop menu.";
|
|
139175
139391
|
log(config, "error", errorMessage);
|
|
139392
|
+
if (!warmUpResults.has(combo))
|
|
139393
|
+
warmUpResults.set(combo, "failed");
|
|
139176
139394
|
contextReport = {
|
|
139395
|
+
...contextReport,
|
|
139177
139396
|
result: "SKIPPED",
|
|
139178
|
-
resultDescription: errorMessage
|
|
139179
|
-
...contextReport
|
|
139397
|
+
resultDescription: errorMessage
|
|
139180
139398
|
};
|
|
139181
139399
|
report.summary.contexts.skipped++;
|
|
139182
139400
|
testReport.contexts.push(contextReport);
|
|
139183
139401
|
continue;
|
|
139184
139402
|
}
|
|
139185
139403
|
}
|
|
139404
|
+
if (!warmUpResults.has(combo))
|
|
139405
|
+
warmUpResults.set(combo, "ok");
|
|
139186
139406
|
if (context.browser?.viewport?.width || context.browser?.viewport?.height) {
|
|
139187
139407
|
await setViewportSize(context, driver);
|
|
139188
139408
|
} else if (context.browser?.window?.width || context.browser?.window?.height) {
|
|
@@ -139518,6 +139738,31 @@ async function ensureChromeAvailable(config, deps) {
|
|
|
139518
139738
|
}
|
|
139519
139739
|
return availableApps;
|
|
139520
139740
|
}
|
|
139741
|
+
async function ensureContextBrowserInstalled({ browserName, config, installAttempts, deps }) {
|
|
139742
|
+
const key = (browserName ?? "<none>").toLowerCase();
|
|
139743
|
+
const cached = installAttempts.get(key);
|
|
139744
|
+
if (cached)
|
|
139745
|
+
return cached;
|
|
139746
|
+
const assets = requiredBrowserAssets(browserName);
|
|
139747
|
+
if (assets.length === 0) {
|
|
139748
|
+
installAttempts.set(key, "notInstallable");
|
|
139749
|
+
return "notInstallable";
|
|
139750
|
+
}
|
|
139751
|
+
const ctx = { cacheDir: config?.cacheDir };
|
|
139752
|
+
const logger = (msg, level = "info") => deps.log?.(config, level === "warn" ? "warning" : level, msg);
|
|
139753
|
+
try {
|
|
139754
|
+
deps.log?.(config, "info", `Browser '${browserName}' is not available; attempting on-demand install of: ${assets.join(", ")}.`);
|
|
139755
|
+
for (const asset of assets) {
|
|
139756
|
+
await deps.ensureBrowser(asset, { ctx, deps: { logger } });
|
|
139757
|
+
}
|
|
139758
|
+
installAttempts.set(key, "installed");
|
|
139759
|
+
return "installed";
|
|
139760
|
+
} catch (err) {
|
|
139761
|
+
deps.log?.(config, "warning", `On-demand install for '${browserName}' failed: ${err?.message ?? err}`);
|
|
139762
|
+
installAttempts.set(key, "failed");
|
|
139763
|
+
return "failed";
|
|
139764
|
+
}
|
|
139765
|
+
}
|
|
139521
139766
|
async function getRunner(options = {}) {
|
|
139522
139767
|
const environment = getEnvironment();
|
|
139523
139768
|
const config = { ...options.config, environment };
|
|
@@ -139731,22 +139976,19 @@ async function runTests(config, options = {}) {
|
|
|
139731
139976
|
if (needs.browsers.size > 0) {
|
|
139732
139977
|
try {
|
|
139733
139978
|
const { getAvailableApps: getAvailableApps2, clearAppCache: clearAppCache2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
139734
|
-
const { ensureBrowserInstalled: ensureBrowserInstalled2 } = await Promise.resolve().then(() => (init_browsers(), browsers_exports));
|
|
139979
|
+
const { ensureBrowserInstalled: ensureBrowserInstalled2, requiredBrowserAssets: requiredBrowserAssets2 } = await Promise.resolve().then(() => (init_browsers(), browsers_exports));
|
|
139735
139980
|
const available = await getAvailableApps2({ config });
|
|
139736
139981
|
const availableNames = new Set(available.map((a) => a.name));
|
|
139737
139982
|
let installedAnything = false;
|
|
139738
139983
|
for (const browser of needs.browsers) {
|
|
139739
139984
|
if (availableNames.has(browser))
|
|
139740
139985
|
continue;
|
|
139741
|
-
|
|
139742
|
-
|
|
139743
|
-
await ensureBrowserInstalled2(
|
|
139744
|
-
installedAnything = true;
|
|
139745
|
-
} else if (browser === "firefox") {
|
|
139746
|
-
await ensureBrowserInstalled2("firefox", { ctx, deps: { logger: preflightLogger } });
|
|
139747
|
-
await ensureBrowserInstalled2("geckodriver", { ctx, deps: { logger: preflightLogger } });
|
|
139748
|
-
installedAnything = true;
|
|
139986
|
+
const assets = requiredBrowserAssets2(browser);
|
|
139987
|
+
for (const asset of assets) {
|
|
139988
|
+
await ensureBrowserInstalled2(asset, { ctx, deps: { logger: preflightLogger } });
|
|
139749
139989
|
}
|
|
139990
|
+
if (assets.length > 0)
|
|
139991
|
+
installedAnything = true;
|
|
139750
139992
|
}
|
|
139751
139993
|
if (installedAnything)
|
|
139752
139994
|
clearAppCache2(config);
|