@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 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.73",
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.querySelectorAll(sel));
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
- if (match.length !== 1) { return match.length; }
354690
- match[0].click();
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) => log.info(`\u{1FA7A} ${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.73",
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.querySelectorAll(sel));
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
- if (match.length !== 1) { return match.length; }
354695
- match[0].click();
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) => log.info(`\u{1FA7A} ${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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@validate.qa/runner",
3
- "version": "1.0.73",
3
+ "version": "1.0.74",
4
4
  "description": "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
5
5
  "bin": {
6
6
  "validate-runner": "dist/cli.js"