doc-detective 4.4.0 → 4.5.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/bin/runner-entrypoint.js +757 -0
- package/dist/core/tests.d.ts.map +1 -1
- package/dist/core/tests.js +30 -56
- package/dist/core/tests.js.map +1 -1
- package/dist/core/utils.d.ts +2 -1
- package/dist/core/utils.d.ts.map +1 -1
- package/dist/core/utils.js +20 -1
- package/dist/core/utils.js.map +1 -1
- package/dist/index.cjs +39 -40
- package/package.json +3 -2
package/dist/index.cjs
CHANGED
|
@@ -130043,6 +130043,21 @@ var import_promises = __toESM(require("node:dns/promises"), 1);
|
|
|
130043
130043
|
var import_node_net = __toESM(require("node:net"), 1);
|
|
130044
130044
|
var import_axios = __toESM(require("axios"), 1);
|
|
130045
130045
|
var import_node_child_process = require("node:child_process");
|
|
130046
|
+
async function findFreePort() {
|
|
130047
|
+
return new Promise((resolve, reject) => {
|
|
130048
|
+
const server = import_node_net.default.createServer();
|
|
130049
|
+
server.once("error", reject);
|
|
130050
|
+
server.listen(0, "127.0.0.1", () => {
|
|
130051
|
+
const addr = server.address();
|
|
130052
|
+
if (!addr || typeof addr === "string") {
|
|
130053
|
+
server.close(() => reject(new Error("Failed to obtain ephemeral port")));
|
|
130054
|
+
return;
|
|
130055
|
+
}
|
|
130056
|
+
const port = addr.port;
|
|
130057
|
+
server.close(() => resolve(port));
|
|
130058
|
+
});
|
|
130059
|
+
});
|
|
130060
|
+
}
|
|
130046
130061
|
function compileFilter(patterns) {
|
|
130047
130062
|
if (!Array.isArray(patterns) || patterns.length === 0)
|
|
130048
130063
|
return [];
|
|
@@ -137558,7 +137573,6 @@ function getIntegrationConfig(config, sourceIntegration) {
|
|
|
137558
137573
|
|
|
137559
137574
|
// dist/core/tests.js
|
|
137560
137575
|
var import_node_http2 = __toESM(require("node:http"), 1);
|
|
137561
|
-
var import_node_net2 = __toESM(require("node:net"), 1);
|
|
137562
137576
|
var import_node_https2 = __toESM(require("node:https"), 1);
|
|
137563
137577
|
var import_node_url3 = require("node:url");
|
|
137564
137578
|
var __dirname3 = import_node_path15.default.dirname((0, import_node_url3.fileURLToPath)(importMetaUrl));
|
|
@@ -137879,10 +137893,12 @@ async function runSpecs({ resolvedTests }) {
|
|
|
137879
137893
|
specs: []
|
|
137880
137894
|
};
|
|
137881
137895
|
const appiumRequired = isAppiumRequired(specs);
|
|
137896
|
+
let appiumPort;
|
|
137882
137897
|
if (appiumRequired) {
|
|
137883
137898
|
setAppiumHome();
|
|
137884
|
-
await
|
|
137885
|
-
|
|
137899
|
+
appiumPort = await findFreePort();
|
|
137900
|
+
log(config, "debug", `Starting Appium on port ${appiumPort}`);
|
|
137901
|
+
appium = (0, import_node_child_process3.spawn)("npx", ["appium", "-a", "127.0.0.1", "-p", String(appiumPort)], {
|
|
137886
137902
|
shell: true,
|
|
137887
137903
|
windowsHide: true,
|
|
137888
137904
|
cwd: import_node_path15.default.join(__dirname3, "../..")
|
|
@@ -137894,7 +137910,7 @@ async function runSpecs({ resolvedTests }) {
|
|
|
137894
137910
|
});
|
|
137895
137911
|
appium.stderr.on("data", (data) => {
|
|
137896
137912
|
});
|
|
137897
|
-
await appiumIsReady();
|
|
137913
|
+
await appiumIsReady(appiumPort);
|
|
137898
137914
|
log(config, "debug", "Appium is ready.");
|
|
137899
137915
|
}
|
|
137900
137916
|
log(config, "info", "Running test specs.");
|
|
@@ -137967,8 +137983,11 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
137967
137983
|
});
|
|
137968
137984
|
log(config, "debug", "CAPABILITIES:");
|
|
137969
137985
|
log(config, "debug", caps);
|
|
137986
|
+
if (appiumPort === void 0) {
|
|
137987
|
+
throw new Error("Driver requested but Appium was not started. isAppiumRequired(specs) and isDriverRequired(context) disagreed; this is a bug.");
|
|
137988
|
+
}
|
|
137970
137989
|
try {
|
|
137971
|
-
driver = await driverStart(caps);
|
|
137990
|
+
driver = await driverStart(caps, appiumPort);
|
|
137972
137991
|
} catch (error) {
|
|
137973
137992
|
try {
|
|
137974
137993
|
log(config, "warning", `Failed to start context '${context.browser?.name}' on '${platform}'. Retrying as headless.`);
|
|
@@ -137982,7 +138001,7 @@ ${JSON.stringify(context, null, 2)}`);
|
|
|
137982
138001
|
headless: context.browser?.headless !== false
|
|
137983
138002
|
}
|
|
137984
138003
|
});
|
|
137985
|
-
driver = await driverStart(caps);
|
|
138004
|
+
driver = await driverStart(caps, appiumPort);
|
|
137986
138005
|
} catch (error2) {
|
|
137987
138006
|
let errorMessage = `Failed to start context '${context.browser?.name}' on '${platform}'.`;
|
|
137988
138007
|
if (context.browser?.name === "safari")
|
|
@@ -138258,40 +138277,16 @@ async function runStep({ config = {}, context = {}, step, driver, metaValues = {
|
|
|
138258
138277
|
}
|
|
138259
138278
|
return actionResult;
|
|
138260
138279
|
}
|
|
138261
|
-
async function
|
|
138262
|
-
const start = Date.now();
|
|
138263
|
-
while (Date.now() - start < timeoutMs) {
|
|
138264
|
-
const result = await new Promise((resolve) => {
|
|
138265
|
-
const server = import_node_net2.default.createServer();
|
|
138266
|
-
server.once("error", (err) => {
|
|
138267
|
-
if (err && err.code === "EADDRINUSE")
|
|
138268
|
-
resolve("busy");
|
|
138269
|
-
else
|
|
138270
|
-
resolve(err instanceof Error ? err : new Error(String(err)));
|
|
138271
|
-
});
|
|
138272
|
-
server.once("listening", () => {
|
|
138273
|
-
server.close(() => resolve("free"));
|
|
138274
|
-
});
|
|
138275
|
-
server.listen(port, "127.0.0.1");
|
|
138276
|
-
});
|
|
138277
|
-
if (result === "free")
|
|
138278
|
-
return;
|
|
138279
|
-
if (result instanceof Error)
|
|
138280
|
-
throw result;
|
|
138281
|
-
await new Promise((r) => setTimeout(r, 250));
|
|
138282
|
-
}
|
|
138283
|
-
throw new Error(`Timed out after ${timeoutMs}ms waiting for 127.0.0.1:${port} to become free. A prior Appium instance is still bound to the port; the next session create would race the teardown and fail with an opaque ECONNREFUSED.`);
|
|
138284
|
-
}
|
|
138285
|
-
async function appiumIsReady(timeoutMs = 12e4) {
|
|
138280
|
+
async function appiumIsReady(port, timeoutMs = 12e4) {
|
|
138286
138281
|
let isReady = false;
|
|
138287
138282
|
const start = Date.now();
|
|
138288
138283
|
while (!isReady) {
|
|
138289
138284
|
if (Date.now() - start > timeoutMs) {
|
|
138290
|
-
throw new Error(`Appium server failed to start within ${timeoutMs / 1e3} seconds`);
|
|
138285
|
+
throw new Error(`Appium server on port ${port} failed to start within ${timeoutMs / 1e3} seconds`);
|
|
138291
138286
|
}
|
|
138292
138287
|
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
138293
138288
|
try {
|
|
138294
|
-
let resp = await import_axios6.default.get(
|
|
138289
|
+
let resp = await import_axios6.default.get(`http://127.0.0.1:${port}/status`);
|
|
138295
138290
|
if (resp.status === 200)
|
|
138296
138291
|
isReady = true;
|
|
138297
138292
|
} catch {
|
|
@@ -138299,14 +138294,14 @@ async function appiumIsReady(timeoutMs = 12e4) {
|
|
|
138299
138294
|
}
|
|
138300
138295
|
return isReady;
|
|
138301
138296
|
}
|
|
138302
|
-
async function driverStart(capabilities, maxAttempts = 4) {
|
|
138297
|
+
async function driverStart(capabilities, port, maxAttempts = 4) {
|
|
138303
138298
|
let lastError;
|
|
138304
138299
|
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
138305
138300
|
try {
|
|
138306
138301
|
const driver = await wdio.remote({
|
|
138307
138302
|
protocol: "http",
|
|
138308
138303
|
hostname: "127.0.0.1",
|
|
138309
|
-
port
|
|
138304
|
+
port,
|
|
138310
138305
|
path: "/",
|
|
138311
138306
|
logLevel: "error",
|
|
138312
138307
|
capabilities,
|
|
@@ -138343,13 +138338,17 @@ async function getRunner(options = {}) {
|
|
|
138343
138338
|
throw new Error("Chrome browser is not available. Please ensure Chrome is installed and accessible.");
|
|
138344
138339
|
}
|
|
138345
138340
|
setAppiumHome();
|
|
138346
|
-
const
|
|
138341
|
+
const appiumPort = await findFreePort();
|
|
138342
|
+
const appium = (0, import_node_child_process3.spawn)("npx", ["appium", "-a", "127.0.0.1", "-p", String(appiumPort)], {
|
|
138347
138343
|
shell: true,
|
|
138348
138344
|
windowsHide: true,
|
|
138349
138345
|
cwd: import_node_path15.default.join(__dirname3, "../..")
|
|
138350
138346
|
});
|
|
138351
|
-
|
|
138352
|
-
|
|
138347
|
+
appium.on("error", (err) => {
|
|
138348
|
+
log(config, "warning", `Appium process error: ${err?.stack ?? err?.message ?? String(err)}`);
|
|
138349
|
+
});
|
|
138350
|
+
await appiumIsReady(appiumPort);
|
|
138351
|
+
log(config, "debug", `Appium is ready for external driver on port ${appiumPort}.`);
|
|
138353
138352
|
const caps = getDriverCapabilities({
|
|
138354
138353
|
runnerDetails,
|
|
138355
138354
|
name: "chrome",
|
|
@@ -138361,12 +138360,12 @@ async function getRunner(options = {}) {
|
|
|
138361
138360
|
});
|
|
138362
138361
|
let runner;
|
|
138363
138362
|
try {
|
|
138364
|
-
runner = await driverStart(caps);
|
|
138363
|
+
runner = await driverStart(caps, appiumPort);
|
|
138365
138364
|
} catch (error) {
|
|
138366
138365
|
try {
|
|
138367
138366
|
log(config, "warning", "Failed to start Chrome runner. Retrying as headless.");
|
|
138368
138367
|
caps["goog:chromeOptions"].args.push("--headless", "--disable-gpu");
|
|
138369
|
-
runner = await driverStart(caps);
|
|
138368
|
+
runner = await driverStart(caps, appiumPort);
|
|
138370
138369
|
} catch (error2) {
|
|
138371
138370
|
(0, import_tree_kill.default)(appium.pid);
|
|
138372
138371
|
throw new Error(`Failed to start Chrome runner: ${error2.message}`);
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "doc-detective",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "Treat doc content as testable assertions to validate doc accuracy and product UX.",
|
|
5
5
|
"bin": {
|
|
6
|
-
"doc-detective": "bin/doc-detective.js"
|
|
6
|
+
"doc-detective": "bin/doc-detective.js",
|
|
7
|
+
"doc-detective-runner": "bin/runner-entrypoint.js"
|
|
7
8
|
},
|
|
8
9
|
"type": "module",
|
|
9
10
|
"files": [
|