@validate.qa/runner 1.0.73 → 1.0.74
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 +37 -7
- package/dist/cli.mjs +37 -7
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -353014,7 +353014,7 @@ var require_package4 = __commonJS({
|
|
|
353014
353014
|
"package.json"(exports2, module2) {
|
|
353015
353015
|
module2.exports = {
|
|
353016
353016
|
name: "@validate.qa/runner",
|
|
353017
|
-
version: "1.0.
|
|
353017
|
+
version: "1.0.74",
|
|
353018
353018
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
353019
353019
|
bin: {
|
|
353020
353020
|
"validate-runner": "dist/cli.js"
|
|
@@ -354681,13 +354681,33 @@ async function clickCssInCurrentContext(sessionPath, css) {
|
|
|
354681
354681
|
async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
354682
354682
|
const script = `
|
|
354683
354683
|
var t = String(arguments[0]).trim().replace(/\\s+/g, ' ');
|
|
354684
|
-
var sel = 'button, a, [role="tab"], [role="button"], [onclick], .stream-tab, .ux-interactive, input[type="submit"], input[type="button"]';
|
|
354685
354684
|
var norm = function (e) { return (e.textContent || e.value || '').trim().replace(/\\s+/g, ' '); };
|
|
354686
354685
|
var vis = function (e) { var r = e.getBoundingClientRect(); return r.width > 0 && r.height > 0; };
|
|
354687
|
-
var all = Array.prototype.slice.call(document.
|
|
354686
|
+
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354688
354687
|
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354689
|
-
|
|
354690
|
-
match
|
|
354688
|
+
// Deepest-only: drop any match that contains another match (same text).
|
|
354689
|
+
var deepest = match.filter(function (e) {
|
|
354690
|
+
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354691
|
+
});
|
|
354692
|
+
if (deepest.length !== 1) { return deepest.length; }
|
|
354693
|
+
var el = deepest[0];
|
|
354694
|
+
var interactive = function (e) {
|
|
354695
|
+
var tag = e.tagName;
|
|
354696
|
+
if (tag === 'BUTTON' || tag === 'A' || tag === 'INPUT' || tag === 'SELECT' || tag === 'SUMMARY') { return true; }
|
|
354697
|
+
var role = e.getAttribute && e.getAttribute('role');
|
|
354698
|
+
if (role === 'button' || role === 'tab' || role === 'link' || role === 'menuitem' || role === 'option') { return true; }
|
|
354699
|
+
if (e.hasAttribute && (e.hasAttribute('onclick') || (e.hasAttribute('tabindex') && e.getAttribute('tabindex') !== '-1'))) { return true; }
|
|
354700
|
+
try { return window.getComputedStyle(e).cursor === 'pointer'; } catch (err) { return false; }
|
|
354701
|
+
};
|
|
354702
|
+
// Prefer the outermost interactive ancestor that wraps ONLY this text.
|
|
354703
|
+
var target = el;
|
|
354704
|
+
var hop = el;
|
|
354705
|
+
for (var i = 0; i < 5 && hop && hop !== document.body; i++) {
|
|
354706
|
+
if (norm(hop) !== t) { break; }
|
|
354707
|
+
if (interactive(hop)) { target = hop; }
|
|
354708
|
+
hop = hop.parentElement;
|
|
354709
|
+
}
|
|
354710
|
+
target.click();
|
|
354691
354711
|
return 1;
|
|
354692
354712
|
`;
|
|
354693
354713
|
const result = await appiumRequest(`${sessionPath}/execute/sync`, {
|
|
@@ -363156,7 +363176,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363156
363176
|
surface: "mobile",
|
|
363157
363177
|
mobilePlatform: target.platform,
|
|
363158
363178
|
...assignedDeviceId ? { deviceId: assignedDeviceId } : {},
|
|
363159
|
-
...leasedDeviceName ? { deviceName: leasedDeviceName } : {}
|
|
363179
|
+
...leasedDeviceName ? { deviceName: leasedDeviceName } : {},
|
|
363180
|
+
// A mobile AI heal spends its first phase in model analysis with NO
|
|
363181
|
+
// Appium session, so the dashboard mirror is legitimately dark — say
|
|
363182
|
+
// so instead of leaving an eternal "mirror starting" placeholder.
|
|
363183
|
+
...runMode === "heal" ? { note: "Heal Phase 1 \u2014 reproducing & analyzing the failure (the device mirror attaches when the live phase starts)" } : {}
|
|
363160
363184
|
});
|
|
363161
363185
|
requestLiveBrowserHeartbeat(true);
|
|
363162
363186
|
const mobileSteps = run2.steps ?? [];
|
|
@@ -363256,7 +363280,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363256
363280
|
// Surface heal liveness: a Phase-1/Phase-2 heal can legitimately run
|
|
363257
363281
|
// for many minutes of model calls with zero device traffic, which
|
|
363258
363282
|
// previously printed nothing between the start banner and the verdict.
|
|
363259
|
-
onProgress: (message) =>
|
|
363283
|
+
onProgress: (message) => {
|
|
363284
|
+
log.info(`\u{1FA7A} ${message}`);
|
|
363285
|
+
liveBrowserHandle.patch({ note: `\u{1FA7A} ${message}`.slice(0, 180) });
|
|
363286
|
+
requestLiveBrowserHeartbeat();
|
|
363287
|
+
},
|
|
363260
363288
|
selectorRegistryContext: run2.selectorRegistryContext ?? null,
|
|
363261
363289
|
runLiveHeal: async (a) => {
|
|
363262
363290
|
let liveSession = null;
|
|
@@ -363308,6 +363336,8 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363308
363336
|
};
|
|
363309
363337
|
}
|
|
363310
363338
|
log.info("\u{1FA7A} Phase 2 (live device) \u2014 opening the live observation session...");
|
|
363339
|
+
liveBrowserHandle.patch({ note: "Heal Phase 2 \u2014 opening the live device session (mirror attaching)" });
|
|
363340
|
+
requestLiveBrowserHeartbeat(true);
|
|
363311
363341
|
try {
|
|
363312
363342
|
await openLiveSession();
|
|
363313
363343
|
const liveDriver = {
|
package/dist/cli.mjs
CHANGED
|
@@ -353019,7 +353019,7 @@ var require_package4 = __commonJS({
|
|
|
353019
353019
|
"package.json"(exports, module) {
|
|
353020
353020
|
module.exports = {
|
|
353021
353021
|
name: "@validate.qa/runner",
|
|
353022
|
-
version: "1.0.
|
|
353022
|
+
version: "1.0.74",
|
|
353023
353023
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
353024
353024
|
bin: {
|
|
353025
353025
|
"validate-runner": "dist/cli.js"
|
|
@@ -354686,13 +354686,33 @@ async function clickCssInCurrentContext(sessionPath, css) {
|
|
|
354686
354686
|
async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
354687
354687
|
const script = `
|
|
354688
354688
|
var t = String(arguments[0]).trim().replace(/\\s+/g, ' ');
|
|
354689
|
-
var sel = 'button, a, [role="tab"], [role="button"], [onclick], .stream-tab, .ux-interactive, input[type="submit"], input[type="button"]';
|
|
354690
354689
|
var norm = function (e) { return (e.textContent || e.value || '').trim().replace(/\\s+/g, ' '); };
|
|
354691
354690
|
var vis = function (e) { var r = e.getBoundingClientRect(); return r.width > 0 && r.height > 0; };
|
|
354692
|
-
var all = Array.prototype.slice.call(document.
|
|
354691
|
+
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354693
354692
|
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354694
|
-
|
|
354695
|
-
match
|
|
354693
|
+
// Deepest-only: drop any match that contains another match (same text).
|
|
354694
|
+
var deepest = match.filter(function (e) {
|
|
354695
|
+
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354696
|
+
});
|
|
354697
|
+
if (deepest.length !== 1) { return deepest.length; }
|
|
354698
|
+
var el = deepest[0];
|
|
354699
|
+
var interactive = function (e) {
|
|
354700
|
+
var tag = e.tagName;
|
|
354701
|
+
if (tag === 'BUTTON' || tag === 'A' || tag === 'INPUT' || tag === 'SELECT' || tag === 'SUMMARY') { return true; }
|
|
354702
|
+
var role = e.getAttribute && e.getAttribute('role');
|
|
354703
|
+
if (role === 'button' || role === 'tab' || role === 'link' || role === 'menuitem' || role === 'option') { return true; }
|
|
354704
|
+
if (e.hasAttribute && (e.hasAttribute('onclick') || (e.hasAttribute('tabindex') && e.getAttribute('tabindex') !== '-1'))) { return true; }
|
|
354705
|
+
try { return window.getComputedStyle(e).cursor === 'pointer'; } catch (err) { return false; }
|
|
354706
|
+
};
|
|
354707
|
+
// Prefer the outermost interactive ancestor that wraps ONLY this text.
|
|
354708
|
+
var target = el;
|
|
354709
|
+
var hop = el;
|
|
354710
|
+
for (var i = 0; i < 5 && hop && hop !== document.body; i++) {
|
|
354711
|
+
if (norm(hop) !== t) { break; }
|
|
354712
|
+
if (interactive(hop)) { target = hop; }
|
|
354713
|
+
hop = hop.parentElement;
|
|
354714
|
+
}
|
|
354715
|
+
target.click();
|
|
354696
354716
|
return 1;
|
|
354697
354717
|
`;
|
|
354698
354718
|
const result = await appiumRequest(`${sessionPath}/execute/sync`, {
|
|
@@ -363164,7 +363184,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363164
363184
|
surface: "mobile",
|
|
363165
363185
|
mobilePlatform: target.platform,
|
|
363166
363186
|
...assignedDeviceId ? { deviceId: assignedDeviceId } : {},
|
|
363167
|
-
...leasedDeviceName ? { deviceName: leasedDeviceName } : {}
|
|
363187
|
+
...leasedDeviceName ? { deviceName: leasedDeviceName } : {},
|
|
363188
|
+
// A mobile AI heal spends its first phase in model analysis with NO
|
|
363189
|
+
// Appium session, so the dashboard mirror is legitimately dark — say
|
|
363190
|
+
// so instead of leaving an eternal "mirror starting" placeholder.
|
|
363191
|
+
...runMode === "heal" ? { note: "Heal Phase 1 \u2014 reproducing & analyzing the failure (the device mirror attaches when the live phase starts)" } : {}
|
|
363168
363192
|
});
|
|
363169
363193
|
requestLiveBrowserHeartbeat(true);
|
|
363170
363194
|
const mobileSteps = run2.steps ?? [];
|
|
@@ -363264,7 +363288,11 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363264
363288
|
// Surface heal liveness: a Phase-1/Phase-2 heal can legitimately run
|
|
363265
363289
|
// for many minutes of model calls with zero device traffic, which
|
|
363266
363290
|
// previously printed nothing between the start banner and the verdict.
|
|
363267
|
-
onProgress: (message) =>
|
|
363291
|
+
onProgress: (message) => {
|
|
363292
|
+
log.info(`\u{1FA7A} ${message}`);
|
|
363293
|
+
liveBrowserHandle.patch({ note: `\u{1FA7A} ${message}`.slice(0, 180) });
|
|
363294
|
+
requestLiveBrowserHeartbeat();
|
|
363295
|
+
},
|
|
363268
363296
|
selectorRegistryContext: run2.selectorRegistryContext ?? null,
|
|
363269
363297
|
runLiveHeal: async (a) => {
|
|
363270
363298
|
let liveSession = null;
|
|
@@ -363316,6 +363344,8 @@ ${finalVerifyResult.logs ?? ""}`;
|
|
|
363316
363344
|
};
|
|
363317
363345
|
}
|
|
363318
363346
|
log.info("\u{1FA7A} Phase 2 (live device) \u2014 opening the live observation session...");
|
|
363347
|
+
liveBrowserHandle.patch({ note: "Heal Phase 2 \u2014 opening the live device session (mirror attaching)" });
|
|
363348
|
+
requestLiveBrowserHeartbeat(true);
|
|
363319
363349
|
try {
|
|
363320
363350
|
await openLiveSession();
|
|
363321
363351
|
const liveDriver = {
|
package/package.json
CHANGED