@validate.qa/runner 1.0.21 → 1.0.23
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 +29 -7
- package/dist/cli.mjs +29 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -328483,7 +328483,7 @@ var require_package4 = __commonJS({
|
|
|
328483
328483
|
"package.json"(exports2, module2) {
|
|
328484
328484
|
module2.exports = {
|
|
328485
328485
|
name: "@validate.qa/runner",
|
|
328486
|
-
version: "1.0.
|
|
328486
|
+
version: "1.0.23",
|
|
328487
328487
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
328488
328488
|
bin: {
|
|
328489
328489
|
"validate-runner": "dist/cli.js"
|
|
@@ -330252,6 +330252,11 @@ async function startMobileNetworkCapture(options) {
|
|
|
330252
330252
|
|
|
330253
330253
|
// src/services/appium-executor.ts
|
|
330254
330254
|
var DEFAULT_STEP_TIMEOUT_MS = 1e4;
|
|
330255
|
+
var MOBILE_NEW_COMMAND_TIMEOUT_SECONDS = (() => {
|
|
330256
|
+
const raw = Number(process.env.VALIDATEQA_MOBILE_NEW_COMMAND_TIMEOUT);
|
|
330257
|
+
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 600;
|
|
330258
|
+
})();
|
|
330259
|
+
var COLD_BOOT_ENTRY_TIMEOUT_MS = 3e4;
|
|
330255
330260
|
var VERIFICATION_ACTIONS = /* @__PURE__ */ new Set(["assertVisible", "assertText", "waitForElement"]);
|
|
330256
330261
|
var WD_SESSION_CREATE_TIMEOUT_MS = 12e4;
|
|
330257
330262
|
var WD_ACTION_TIMEOUT_MS = 3e4;
|
|
@@ -330351,6 +330356,14 @@ async function createSession(target) {
|
|
|
330351
330356
|
...target.deviceId ? { "appium:udid": target.deviceId } : {},
|
|
330352
330357
|
...target.platformVersion ? { "appium:platformVersion": target.platformVersion } : {},
|
|
330353
330358
|
"appium:noReset": true,
|
|
330359
|
+
// Appium's default newCommandTimeout is 60s — it kills the session if no
|
|
330360
|
+
// WebDriver command arrives in that window. A discovery session is driven
|
|
330361
|
+
// by an AI loop where a single model turn (or a pause on a permission
|
|
330362
|
+
// dialog) can exceed 60s, so the default silently terminates the session
|
|
330363
|
+
// mid-run and every later command 404s ("invalid session id"), failing the
|
|
330364
|
+
// whole survey. The runner owns session teardown explicitly, so a long
|
|
330365
|
+
// idle window is safe. Env-overridable.
|
|
330366
|
+
"appium:newCommandTimeout": MOBILE_NEW_COMMAND_TIMEOUT_SECONDS,
|
|
330354
330367
|
...realCaps
|
|
330355
330368
|
} : {
|
|
330356
330369
|
platformName: "Android",
|
|
@@ -330359,6 +330372,8 @@ async function createSession(target) {
|
|
|
330359
330372
|
...target.deviceId ? { "appium:udid": target.deviceId } : {},
|
|
330360
330373
|
...target.platformVersion ? { "appium:platformVersion": target.platformVersion } : {},
|
|
330361
330374
|
"appium:noReset": true,
|
|
330375
|
+
// See the iOS branch: the 60s default kills AI-driven discovery sessions.
|
|
330376
|
+
"appium:newCommandTimeout": MOBILE_NEW_COMMAND_TIMEOUT_SECONDS,
|
|
330362
330377
|
...realCaps
|
|
330363
330378
|
};
|
|
330364
330379
|
const result = await wdRequest("/session", {
|
|
@@ -330476,18 +330491,24 @@ async function freshLaunchTargetApp(sessionId, platform3, appId, log2) {
|
|
|
330476
330491
|
}
|
|
330477
330492
|
async function waitForColdBootContent(sessionId, log2, timeoutMs = 2e4) {
|
|
330478
330493
|
const deadline = Date.now() + timeoutMs;
|
|
330479
|
-
const MIN_ELEMENTS =
|
|
330494
|
+
const MIN_ELEMENTS = 12;
|
|
330480
330495
|
let lastCount = 0;
|
|
330496
|
+
let stableFrames = 0;
|
|
330481
330497
|
while (Date.now() < deadline) {
|
|
330482
330498
|
try {
|
|
330483
330499
|
const res = await wdRequest(`/session/${sessionId}/source`);
|
|
330484
330500
|
const xml = typeof res?.value === "string" ? res.value : "";
|
|
330485
330501
|
const count = (xml.match(/<(android\.|XCUIElementType)/g) ?? []).length;
|
|
330486
|
-
|
|
330487
|
-
|
|
330488
|
-
|
|
330489
|
-
|
|
330502
|
+
if (count >= MIN_ELEMENTS && count === lastCount) {
|
|
330503
|
+
stableFrames++;
|
|
330504
|
+
if (stableFrames >= 2) {
|
|
330505
|
+
log2(` Cold-boot ready: UI tree settled at ${count} node(s).`);
|
|
330506
|
+
return;
|
|
330507
|
+
}
|
|
330508
|
+
} else {
|
|
330509
|
+
stableFrames = 0;
|
|
330490
330510
|
}
|
|
330511
|
+
lastCount = count;
|
|
330491
330512
|
} catch {
|
|
330492
330513
|
}
|
|
330493
330514
|
await new Promise((r) => setTimeout(r, 750));
|
|
@@ -331172,7 +331193,8 @@ async function executeMobileTest(options) {
|
|
|
331172
331193
|
);
|
|
331173
331194
|
if (entryStep) {
|
|
331174
331195
|
try {
|
|
331175
|
-
|
|
331196
|
+
const entryTimeout = recordedFromClearedState ? Math.max(DEFAULT_STEP_TIMEOUT_MS, COLD_BOOT_ENTRY_TIMEOUT_MS) : DEFAULT_STEP_TIMEOUT_MS;
|
|
331197
|
+
await findElement(sessionId, entryStep.target, entryTimeout, { identityOnly: true, platform: runPlatform });
|
|
331176
331198
|
} catch (err) {
|
|
331177
331199
|
if (isTransportError(err)) throw err;
|
|
331178
331200
|
entryDrift = true;
|
package/dist/cli.mjs
CHANGED
|
@@ -328488,7 +328488,7 @@ var require_package4 = __commonJS({
|
|
|
328488
328488
|
"package.json"(exports, module) {
|
|
328489
328489
|
module.exports = {
|
|
328490
328490
|
name: "@validate.qa/runner",
|
|
328491
|
-
version: "1.0.
|
|
328491
|
+
version: "1.0.23",
|
|
328492
328492
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
328493
328493
|
bin: {
|
|
328494
328494
|
"validate-runner": "dist/cli.js"
|
|
@@ -330260,6 +330260,11 @@ async function startMobileNetworkCapture(options) {
|
|
|
330260
330260
|
|
|
330261
330261
|
// src/services/appium-executor.ts
|
|
330262
330262
|
var DEFAULT_STEP_TIMEOUT_MS = 1e4;
|
|
330263
|
+
var MOBILE_NEW_COMMAND_TIMEOUT_SECONDS = (() => {
|
|
330264
|
+
const raw = Number(process.env.VALIDATEQA_MOBILE_NEW_COMMAND_TIMEOUT);
|
|
330265
|
+
return Number.isFinite(raw) && raw > 0 ? Math.floor(raw) : 600;
|
|
330266
|
+
})();
|
|
330267
|
+
var COLD_BOOT_ENTRY_TIMEOUT_MS = 3e4;
|
|
330263
330268
|
var VERIFICATION_ACTIONS = /* @__PURE__ */ new Set(["assertVisible", "assertText", "waitForElement"]);
|
|
330264
330269
|
var WD_SESSION_CREATE_TIMEOUT_MS = 12e4;
|
|
330265
330270
|
var WD_ACTION_TIMEOUT_MS = 3e4;
|
|
@@ -330359,6 +330364,14 @@ async function createSession(target) {
|
|
|
330359
330364
|
...target.deviceId ? { "appium:udid": target.deviceId } : {},
|
|
330360
330365
|
...target.platformVersion ? { "appium:platformVersion": target.platformVersion } : {},
|
|
330361
330366
|
"appium:noReset": true,
|
|
330367
|
+
// Appium's default newCommandTimeout is 60s — it kills the session if no
|
|
330368
|
+
// WebDriver command arrives in that window. A discovery session is driven
|
|
330369
|
+
// by an AI loop where a single model turn (or a pause on a permission
|
|
330370
|
+
// dialog) can exceed 60s, so the default silently terminates the session
|
|
330371
|
+
// mid-run and every later command 404s ("invalid session id"), failing the
|
|
330372
|
+
// whole survey. The runner owns session teardown explicitly, so a long
|
|
330373
|
+
// idle window is safe. Env-overridable.
|
|
330374
|
+
"appium:newCommandTimeout": MOBILE_NEW_COMMAND_TIMEOUT_SECONDS,
|
|
330362
330375
|
...realCaps
|
|
330363
330376
|
} : {
|
|
330364
330377
|
platformName: "Android",
|
|
@@ -330367,6 +330380,8 @@ async function createSession(target) {
|
|
|
330367
330380
|
...target.deviceId ? { "appium:udid": target.deviceId } : {},
|
|
330368
330381
|
...target.platformVersion ? { "appium:platformVersion": target.platformVersion } : {},
|
|
330369
330382
|
"appium:noReset": true,
|
|
330383
|
+
// See the iOS branch: the 60s default kills AI-driven discovery sessions.
|
|
330384
|
+
"appium:newCommandTimeout": MOBILE_NEW_COMMAND_TIMEOUT_SECONDS,
|
|
330370
330385
|
...realCaps
|
|
330371
330386
|
};
|
|
330372
330387
|
const result = await wdRequest("/session", {
|
|
@@ -330484,18 +330499,24 @@ async function freshLaunchTargetApp(sessionId, platform3, appId, log2) {
|
|
|
330484
330499
|
}
|
|
330485
330500
|
async function waitForColdBootContent(sessionId, log2, timeoutMs = 2e4) {
|
|
330486
330501
|
const deadline = Date.now() + timeoutMs;
|
|
330487
|
-
const MIN_ELEMENTS =
|
|
330502
|
+
const MIN_ELEMENTS = 12;
|
|
330488
330503
|
let lastCount = 0;
|
|
330504
|
+
let stableFrames = 0;
|
|
330489
330505
|
while (Date.now() < deadline) {
|
|
330490
330506
|
try {
|
|
330491
330507
|
const res = await wdRequest(`/session/${sessionId}/source`);
|
|
330492
330508
|
const xml = typeof res?.value === "string" ? res.value : "";
|
|
330493
330509
|
const count = (xml.match(/<(android\.|XCUIElementType)/g) ?? []).length;
|
|
330494
|
-
|
|
330495
|
-
|
|
330496
|
-
|
|
330497
|
-
|
|
330510
|
+
if (count >= MIN_ELEMENTS && count === lastCount) {
|
|
330511
|
+
stableFrames++;
|
|
330512
|
+
if (stableFrames >= 2) {
|
|
330513
|
+
log2(` Cold-boot ready: UI tree settled at ${count} node(s).`);
|
|
330514
|
+
return;
|
|
330515
|
+
}
|
|
330516
|
+
} else {
|
|
330517
|
+
stableFrames = 0;
|
|
330498
330518
|
}
|
|
330519
|
+
lastCount = count;
|
|
330499
330520
|
} catch {
|
|
330500
330521
|
}
|
|
330501
330522
|
await new Promise((r) => setTimeout(r, 750));
|
|
@@ -331180,7 +331201,8 @@ async function executeMobileTest(options) {
|
|
|
331180
331201
|
);
|
|
331181
331202
|
if (entryStep) {
|
|
331182
331203
|
try {
|
|
331183
|
-
|
|
331204
|
+
const entryTimeout = recordedFromClearedState ? Math.max(DEFAULT_STEP_TIMEOUT_MS, COLD_BOOT_ENTRY_TIMEOUT_MS) : DEFAULT_STEP_TIMEOUT_MS;
|
|
331205
|
+
await findElement(sessionId, entryStep.target, entryTimeout, { identityOnly: true, platform: runPlatform });
|
|
331184
331206
|
} catch (err) {
|
|
331185
331207
|
if (isTransportError(err)) throw err;
|
|
331186
331208
|
entryDrift = true;
|
package/package.json
CHANGED