@validate.qa/runner 1.0.76 → 1.0.77
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 +63 -24
- package/dist/cli.mjs +63 -24
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -353034,7 +353034,7 @@ var require_package4 = __commonJS({
|
|
|
353034
353034
|
"package.json"(exports2, module2) {
|
|
353035
353035
|
module2.exports = {
|
|
353036
353036
|
name: "@validate.qa/runner",
|
|
353037
|
-
version: "1.0.
|
|
353037
|
+
version: "1.0.77",
|
|
353038
353038
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
353039
353039
|
bin: {
|
|
353040
353040
|
"validate-runner": "dist/cli.js"
|
|
@@ -354700,17 +354700,13 @@ async function clickCssInCurrentContext(sessionPath, css) {
|
|
|
354700
354700
|
}
|
|
354701
354701
|
async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
354702
354702
|
const script = `
|
|
354703
|
+
if (!document.body) { return 0; }
|
|
354703
354704
|
var t = String(arguments[0]).trim().replace(/\\s+/g, ' ');
|
|
354704
|
-
|
|
354705
|
+
// String() coercion is load-bearing: e.value is a NUMBER for <progress>/
|
|
354706
|
+
// <meter>/<li value>, and (70).trim() would throw, aborting the whole
|
|
354707
|
+
// script (and thus the fallback) on any page containing one.
|
|
354708
|
+
var norm = function (e) { return String(e.textContent || e.value || '').trim().replace(/\\s+/g, ' '); };
|
|
354705
354709
|
var vis = function (e) { var r = e.getBoundingClientRect(); return r.width > 0 && r.height > 0; };
|
|
354706
|
-
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354707
|
-
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354708
|
-
// Deepest-only: drop any match that contains another match (same text).
|
|
354709
|
-
var deepest = match.filter(function (e) {
|
|
354710
|
-
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354711
|
-
});
|
|
354712
|
-
if (deepest.length !== 1) { return deepest.length; }
|
|
354713
|
-
var el = deepest[0];
|
|
354714
354710
|
var interactive = function (e) {
|
|
354715
354711
|
var tag = e.tagName;
|
|
354716
354712
|
if (tag === 'BUTTON' || tag === 'A' || tag === 'INPUT' || tag === 'SELECT' || tag === 'SUMMARY') { return true; }
|
|
@@ -354719,6 +354715,33 @@ async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
|
354719
354715
|
if (e.hasAttribute && (e.hasAttribute('onclick') || (e.hasAttribute('tabindex') && e.getAttribute('tabindex') !== '-1'))) { return true; }
|
|
354720
354716
|
try { return window.getComputedStyle(e).cursor === 'pointer'; } catch (err) { return false; }
|
|
354721
354717
|
};
|
|
354718
|
+
// Is this match itself interactive, or wrapped by an interactive ancestor
|
|
354719
|
+
// that contains ONLY this text?
|
|
354720
|
+
var hasInteractiveHost = function (e) {
|
|
354721
|
+
var hop = e;
|
|
354722
|
+
for (var i = 0; i < 5 && hop && hop !== document.body; i++) {
|
|
354723
|
+
if (norm(hop) !== t) { return false; }
|
|
354724
|
+
if (interactive(hop)) { return true; }
|
|
354725
|
+
hop = hop.parentElement;
|
|
354726
|
+
}
|
|
354727
|
+
return false;
|
|
354728
|
+
};
|
|
354729
|
+
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354730
|
+
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354731
|
+
// Deepest-only: drop any match that contains another match (same text).
|
|
354732
|
+
var deepest = match.filter(function (e) {
|
|
354733
|
+
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354734
|
+
});
|
|
354735
|
+
var candidates = deepest;
|
|
354736
|
+
if (candidates.length > 1) {
|
|
354737
|
+
// Disambiguate: a NON-interactive duplicate (page heading, badge, label
|
|
354738
|
+
// echoing a control's caption) must not veto the one real control. Only
|
|
354739
|
+
// when several INTERACTIVE hosts share the text is it truly ambiguous.
|
|
354740
|
+
var interactiveOnly = candidates.filter(hasInteractiveHost);
|
|
354741
|
+
if (interactiveOnly.length >= 1) { candidates = interactiveOnly; }
|
|
354742
|
+
}
|
|
354743
|
+
if (candidates.length !== 1) { return candidates.length; }
|
|
354744
|
+
var el = candidates[0];
|
|
354722
354745
|
// Prefer the outermost interactive ancestor that wraps ONLY this text.
|
|
354723
354746
|
var target = el;
|
|
354724
354747
|
var hop = el;
|
|
@@ -354892,6 +354915,7 @@ var QUARANTINE_MAX_MS = (() => {
|
|
|
354892
354915
|
return Number.isFinite(raw) && raw > 0 ? raw : 10 * 60 * 1e3;
|
|
354893
354916
|
})();
|
|
354894
354917
|
var quarantinedAt = /* @__PURE__ */ new Map();
|
|
354918
|
+
var nextQuarantineToken = 1;
|
|
354895
354919
|
var DeviceQuarantinedError = class extends Error {
|
|
354896
354920
|
constructor(deviceId) {
|
|
354897
354921
|
super(
|
|
@@ -354901,14 +354925,21 @@ var DeviceQuarantinedError = class extends Error {
|
|
|
354901
354925
|
}
|
|
354902
354926
|
};
|
|
354903
354927
|
function quarantineDevice(deviceId, now = Date.now()) {
|
|
354904
|
-
|
|
354928
|
+
const token = nextQuarantineToken++;
|
|
354929
|
+
quarantinedAt.set(deviceId, { at: now, token });
|
|
354930
|
+
return token;
|
|
354905
354931
|
}
|
|
354906
|
-
function unquarantineDevice(deviceId) {
|
|
354907
|
-
|
|
354932
|
+
function unquarantineDevice(deviceId, token) {
|
|
354933
|
+
if (token === void 0) {
|
|
354934
|
+
quarantinedAt.delete(deviceId);
|
|
354935
|
+
return;
|
|
354936
|
+
}
|
|
354937
|
+
const entry = quarantinedAt.get(deviceId);
|
|
354938
|
+
if (entry && entry.token === token) quarantinedAt.delete(deviceId);
|
|
354908
354939
|
}
|
|
354909
354940
|
function isDeviceQuarantined(deviceId, now = Date.now()) {
|
|
354910
354941
|
if (typeof deviceId !== "string") return false;
|
|
354911
|
-
const since = quarantinedAt.get(deviceId);
|
|
354942
|
+
const since = quarantinedAt.get(deviceId)?.at;
|
|
354912
354943
|
if (since === void 0) return false;
|
|
354913
354944
|
if (now - since >= QUARANTINE_MAX_MS) {
|
|
354914
354945
|
quarantinedAt.delete(deviceId);
|
|
@@ -357266,7 +357297,8 @@ async function executeTap(sessionId, step, platform3, isCrossPlatform = false) {
|
|
|
357266
357297
|
const bounds = boundsForRun(step, platform3, isCrossPlatform);
|
|
357267
357298
|
if (step.target) {
|
|
357268
357299
|
try {
|
|
357269
|
-
const
|
|
357300
|
+
const explicitTimeout = readStepTimeout(step);
|
|
357301
|
+
const elementId = await findElement(sessionId, step.target, isPermissionTap ? explicitTimeout ?? PERMISSION_DIALOG_TIMEOUT_MS : explicitTimeout, {
|
|
357270
357302
|
platform: platform3,
|
|
357271
357303
|
recordedBounds: bounds
|
|
357272
357304
|
});
|
|
@@ -358360,9 +358392,15 @@ let timer = null;
|
|
|
358360
358392
|
async function post() {
|
|
358361
358393
|
if (!url || !headers || !body) return; // inert until the first real heartbeat
|
|
358362
358394
|
try {
|
|
358395
|
+
// The keepalive discards the response body, so it must identify itself:
|
|
358396
|
+
// the server's heartbeat handler destructively drains queued runner
|
|
358397
|
+
// control commands (kill-pid/kill-orphans) into the response, and a
|
|
358398
|
+
// drained command this worker throws away would be lost for a full
|
|
358399
|
+
// re-issue window. The header tells the server to keep the queue intact
|
|
358400
|
+
// and let the main loop (which executes commands) drain it.
|
|
358363
358401
|
await fetch(url, {
|
|
358364
358402
|
method: 'POST',
|
|
358365
|
-
headers,
|
|
358403
|
+
headers: { ...headers, 'x-validateqa-keepalive': '1' },
|
|
358366
358404
|
body,
|
|
358367
358405
|
signal: AbortSignal.timeout(10000),
|
|
358368
358406
|
});
|
|
@@ -360700,6 +360738,7 @@ var MobileRunWatchdog = class {
|
|
|
360700
360738
|
phase = "idle";
|
|
360701
360739
|
released = false;
|
|
360702
360740
|
quarantined = false;
|
|
360741
|
+
quarantineToken;
|
|
360703
360742
|
cancelAbortTimer = null;
|
|
360704
360743
|
cancelGraceTimer = null;
|
|
360705
360744
|
/** Current phase (exposed for tests / observability). */
|
|
@@ -360728,7 +360767,8 @@ var MobileRunWatchdog = class {
|
|
|
360728
360767
|
this.clearAbortTimer();
|
|
360729
360768
|
if (this.options.deviceId) {
|
|
360730
360769
|
this.quarantined = true;
|
|
360731
|
-
this.options.callbacks.quarantine(this.options.deviceId);
|
|
360770
|
+
const token = this.options.callbacks.quarantine(this.options.deviceId);
|
|
360771
|
+
this.quarantineToken = typeof token === "number" ? token : void 0;
|
|
360732
360772
|
this.options.callbacks.abort(this.options.deviceId, this.options.runId, reason);
|
|
360733
360773
|
} else {
|
|
360734
360774
|
this.options.callbacks.log("warn", `Run ${this.options.runId} ${reason} \u2014 no leased device to abort; awaiting the run's own settle.`);
|
|
@@ -360753,7 +360793,7 @@ var MobileRunWatchdog = class {
|
|
|
360753
360793
|
}
|
|
360754
360794
|
if (this.quarantined && this.options.deviceId) {
|
|
360755
360795
|
this.quarantined = false;
|
|
360756
|
-
this.options.callbacks.unquarantine(this.options.deviceId);
|
|
360796
|
+
this.options.callbacks.unquarantine(this.options.deviceId, this.quarantineToken);
|
|
360757
360797
|
if (wasForceReleased) {
|
|
360758
360798
|
this.options.callbacks.log("info", `Run ${this.options.runId} finally settled \u2014 lifted the quarantine on device ${this.options.deviceId}.`);
|
|
360759
360799
|
}
|
|
@@ -360771,7 +360811,8 @@ var MobileRunWatchdog = class {
|
|
|
360771
360811
|
if (this.options.deviceId) {
|
|
360772
360812
|
if (!this.quarantined) {
|
|
360773
360813
|
this.quarantined = true;
|
|
360774
|
-
this.options.callbacks.quarantine(this.options.deviceId);
|
|
360814
|
+
const token = this.options.callbacks.quarantine(this.options.deviceId);
|
|
360815
|
+
this.quarantineToken = typeof token === "number" ? token : void 0;
|
|
360775
360816
|
}
|
|
360776
360817
|
this.options.callbacks.log(
|
|
360777
360818
|
"warn",
|
|
@@ -364417,11 +364458,9 @@ async function startRunner(opts) {
|
|
|
364417
364458
|
if (sessionId) void deleteAppiumSession(sessionId);
|
|
364418
364459
|
},
|
|
364419
364460
|
release: applyRelease,
|
|
364420
|
-
quarantine: (deviceId) =>
|
|
364421
|
-
|
|
364422
|
-
|
|
364423
|
-
unquarantine: (deviceId) => {
|
|
364424
|
-
unquarantineDevice(deviceId);
|
|
364461
|
+
quarantine: (deviceId) => quarantineDevice(deviceId),
|
|
364462
|
+
unquarantine: (deviceId, token) => {
|
|
364463
|
+
unquarantineDevice(deviceId, token);
|
|
364425
364464
|
},
|
|
364426
364465
|
log: (level, message) => {
|
|
364427
364466
|
if (level === "warn") log.warn(message);
|
package/dist/cli.mjs
CHANGED
|
@@ -353039,7 +353039,7 @@ var require_package4 = __commonJS({
|
|
|
353039
353039
|
"package.json"(exports, module) {
|
|
353040
353040
|
module.exports = {
|
|
353041
353041
|
name: "@validate.qa/runner",
|
|
353042
|
-
version: "1.0.
|
|
353042
|
+
version: "1.0.77",
|
|
353043
353043
|
description: "validate local test runner - execute Playwright tests on your machine, connected to validate.qa cloud.",
|
|
353044
353044
|
bin: {
|
|
353045
353045
|
"validate-runner": "dist/cli.js"
|
|
@@ -354705,17 +354705,13 @@ async function clickCssInCurrentContext(sessionPath, css) {
|
|
|
354705
354705
|
}
|
|
354706
354706
|
async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
354707
354707
|
const script = `
|
|
354708
|
+
if (!document.body) { return 0; }
|
|
354708
354709
|
var t = String(arguments[0]).trim().replace(/\\s+/g, ' ');
|
|
354709
|
-
|
|
354710
|
+
// String() coercion is load-bearing: e.value is a NUMBER for <progress>/
|
|
354711
|
+
// <meter>/<li value>, and (70).trim() would throw, aborting the whole
|
|
354712
|
+
// script (and thus the fallback) on any page containing one.
|
|
354713
|
+
var norm = function (e) { return String(e.textContent || e.value || '').trim().replace(/\\s+/g, ' '); };
|
|
354710
354714
|
var vis = function (e) { var r = e.getBoundingClientRect(); return r.width > 0 && r.height > 0; };
|
|
354711
|
-
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354712
|
-
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354713
|
-
// Deepest-only: drop any match that contains another match (same text).
|
|
354714
|
-
var deepest = match.filter(function (e) {
|
|
354715
|
-
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354716
|
-
});
|
|
354717
|
-
if (deepest.length !== 1) { return deepest.length; }
|
|
354718
|
-
var el = deepest[0];
|
|
354719
354715
|
var interactive = function (e) {
|
|
354720
354716
|
var tag = e.tagName;
|
|
354721
354717
|
if (tag === 'BUTTON' || tag === 'A' || tag === 'INPUT' || tag === 'SELECT' || tag === 'SUMMARY') { return true; }
|
|
@@ -354724,6 +354720,33 @@ async function clickByVisibleTextInCurrentContext(sessionPath, text) {
|
|
|
354724
354720
|
if (e.hasAttribute && (e.hasAttribute('onclick') || (e.hasAttribute('tabindex') && e.getAttribute('tabindex') !== '-1'))) { return true; }
|
|
354725
354721
|
try { return window.getComputedStyle(e).cursor === 'pointer'; } catch (err) { return false; }
|
|
354726
354722
|
};
|
|
354723
|
+
// Is this match itself interactive, or wrapped by an interactive ancestor
|
|
354724
|
+
// that contains ONLY this text?
|
|
354725
|
+
var hasInteractiveHost = function (e) {
|
|
354726
|
+
var hop = e;
|
|
354727
|
+
for (var i = 0; i < 5 && hop && hop !== document.body; i++) {
|
|
354728
|
+
if (norm(hop) !== t) { return false; }
|
|
354729
|
+
if (interactive(hop)) { return true; }
|
|
354730
|
+
hop = hop.parentElement;
|
|
354731
|
+
}
|
|
354732
|
+
return false;
|
|
354733
|
+
};
|
|
354734
|
+
var all = Array.prototype.slice.call(document.body.getElementsByTagName('*'));
|
|
354735
|
+
var match = all.filter(function (e) { return norm(e) === t && vis(e); });
|
|
354736
|
+
// Deepest-only: drop any match that contains another match (same text).
|
|
354737
|
+
var deepest = match.filter(function (e) {
|
|
354738
|
+
return !match.some(function (o) { return o !== e && e.contains(o); });
|
|
354739
|
+
});
|
|
354740
|
+
var candidates = deepest;
|
|
354741
|
+
if (candidates.length > 1) {
|
|
354742
|
+
// Disambiguate: a NON-interactive duplicate (page heading, badge, label
|
|
354743
|
+
// echoing a control's caption) must not veto the one real control. Only
|
|
354744
|
+
// when several INTERACTIVE hosts share the text is it truly ambiguous.
|
|
354745
|
+
var interactiveOnly = candidates.filter(hasInteractiveHost);
|
|
354746
|
+
if (interactiveOnly.length >= 1) { candidates = interactiveOnly; }
|
|
354747
|
+
}
|
|
354748
|
+
if (candidates.length !== 1) { return candidates.length; }
|
|
354749
|
+
var el = candidates[0];
|
|
354727
354750
|
// Prefer the outermost interactive ancestor that wraps ONLY this text.
|
|
354728
354751
|
var target = el;
|
|
354729
354752
|
var hop = el;
|
|
@@ -354897,6 +354920,7 @@ var QUARANTINE_MAX_MS = (() => {
|
|
|
354897
354920
|
return Number.isFinite(raw) && raw > 0 ? raw : 10 * 60 * 1e3;
|
|
354898
354921
|
})();
|
|
354899
354922
|
var quarantinedAt = /* @__PURE__ */ new Map();
|
|
354923
|
+
var nextQuarantineToken = 1;
|
|
354900
354924
|
var DeviceQuarantinedError = class extends Error {
|
|
354901
354925
|
constructor(deviceId) {
|
|
354902
354926
|
super(
|
|
@@ -354906,14 +354930,21 @@ var DeviceQuarantinedError = class extends Error {
|
|
|
354906
354930
|
}
|
|
354907
354931
|
};
|
|
354908
354932
|
function quarantineDevice(deviceId, now = Date.now()) {
|
|
354909
|
-
|
|
354933
|
+
const token = nextQuarantineToken++;
|
|
354934
|
+
quarantinedAt.set(deviceId, { at: now, token });
|
|
354935
|
+
return token;
|
|
354910
354936
|
}
|
|
354911
|
-
function unquarantineDevice(deviceId) {
|
|
354912
|
-
|
|
354937
|
+
function unquarantineDevice(deviceId, token) {
|
|
354938
|
+
if (token === void 0) {
|
|
354939
|
+
quarantinedAt.delete(deviceId);
|
|
354940
|
+
return;
|
|
354941
|
+
}
|
|
354942
|
+
const entry = quarantinedAt.get(deviceId);
|
|
354943
|
+
if (entry && entry.token === token) quarantinedAt.delete(deviceId);
|
|
354913
354944
|
}
|
|
354914
354945
|
function isDeviceQuarantined(deviceId, now = Date.now()) {
|
|
354915
354946
|
if (typeof deviceId !== "string") return false;
|
|
354916
|
-
const since = quarantinedAt.get(deviceId);
|
|
354947
|
+
const since = quarantinedAt.get(deviceId)?.at;
|
|
354917
354948
|
if (since === void 0) return false;
|
|
354918
354949
|
if (now - since >= QUARANTINE_MAX_MS) {
|
|
354919
354950
|
quarantinedAt.delete(deviceId);
|
|
@@ -357274,7 +357305,8 @@ async function executeTap(sessionId, step, platform3, isCrossPlatform = false) {
|
|
|
357274
357305
|
const bounds = boundsForRun(step, platform3, isCrossPlatform);
|
|
357275
357306
|
if (step.target) {
|
|
357276
357307
|
try {
|
|
357277
|
-
const
|
|
357308
|
+
const explicitTimeout = readStepTimeout(step);
|
|
357309
|
+
const elementId = await findElement(sessionId, step.target, isPermissionTap ? explicitTimeout ?? PERMISSION_DIALOG_TIMEOUT_MS : explicitTimeout, {
|
|
357278
357310
|
platform: platform3,
|
|
357279
357311
|
recordedBounds: bounds
|
|
357280
357312
|
});
|
|
@@ -358368,9 +358400,15 @@ let timer = null;
|
|
|
358368
358400
|
async function post() {
|
|
358369
358401
|
if (!url || !headers || !body) return; // inert until the first real heartbeat
|
|
358370
358402
|
try {
|
|
358403
|
+
// The keepalive discards the response body, so it must identify itself:
|
|
358404
|
+
// the server's heartbeat handler destructively drains queued runner
|
|
358405
|
+
// control commands (kill-pid/kill-orphans) into the response, and a
|
|
358406
|
+
// drained command this worker throws away would be lost for a full
|
|
358407
|
+
// re-issue window. The header tells the server to keep the queue intact
|
|
358408
|
+
// and let the main loop (which executes commands) drain it.
|
|
358371
358409
|
await fetch(url, {
|
|
358372
358410
|
method: 'POST',
|
|
358373
|
-
headers,
|
|
358411
|
+
headers: { ...headers, 'x-validateqa-keepalive': '1' },
|
|
358374
358412
|
body,
|
|
358375
358413
|
signal: AbortSignal.timeout(10000),
|
|
358376
358414
|
});
|
|
@@ -360708,6 +360746,7 @@ var MobileRunWatchdog = class {
|
|
|
360708
360746
|
phase = "idle";
|
|
360709
360747
|
released = false;
|
|
360710
360748
|
quarantined = false;
|
|
360749
|
+
quarantineToken;
|
|
360711
360750
|
cancelAbortTimer = null;
|
|
360712
360751
|
cancelGraceTimer = null;
|
|
360713
360752
|
/** Current phase (exposed for tests / observability). */
|
|
@@ -360736,7 +360775,8 @@ var MobileRunWatchdog = class {
|
|
|
360736
360775
|
this.clearAbortTimer();
|
|
360737
360776
|
if (this.options.deviceId) {
|
|
360738
360777
|
this.quarantined = true;
|
|
360739
|
-
this.options.callbacks.quarantine(this.options.deviceId);
|
|
360778
|
+
const token = this.options.callbacks.quarantine(this.options.deviceId);
|
|
360779
|
+
this.quarantineToken = typeof token === "number" ? token : void 0;
|
|
360740
360780
|
this.options.callbacks.abort(this.options.deviceId, this.options.runId, reason);
|
|
360741
360781
|
} else {
|
|
360742
360782
|
this.options.callbacks.log("warn", `Run ${this.options.runId} ${reason} \u2014 no leased device to abort; awaiting the run's own settle.`);
|
|
@@ -360761,7 +360801,7 @@ var MobileRunWatchdog = class {
|
|
|
360761
360801
|
}
|
|
360762
360802
|
if (this.quarantined && this.options.deviceId) {
|
|
360763
360803
|
this.quarantined = false;
|
|
360764
|
-
this.options.callbacks.unquarantine(this.options.deviceId);
|
|
360804
|
+
this.options.callbacks.unquarantine(this.options.deviceId, this.quarantineToken);
|
|
360765
360805
|
if (wasForceReleased) {
|
|
360766
360806
|
this.options.callbacks.log("info", `Run ${this.options.runId} finally settled \u2014 lifted the quarantine on device ${this.options.deviceId}.`);
|
|
360767
360807
|
}
|
|
@@ -360779,7 +360819,8 @@ var MobileRunWatchdog = class {
|
|
|
360779
360819
|
if (this.options.deviceId) {
|
|
360780
360820
|
if (!this.quarantined) {
|
|
360781
360821
|
this.quarantined = true;
|
|
360782
|
-
this.options.callbacks.quarantine(this.options.deviceId);
|
|
360822
|
+
const token = this.options.callbacks.quarantine(this.options.deviceId);
|
|
360823
|
+
this.quarantineToken = typeof token === "number" ? token : void 0;
|
|
360783
360824
|
}
|
|
360784
360825
|
this.options.callbacks.log(
|
|
360785
360826
|
"warn",
|
|
@@ -364425,11 +364466,9 @@ async function startRunner(opts) {
|
|
|
364425
364466
|
if (sessionId) void deleteAppiumSession(sessionId);
|
|
364426
364467
|
},
|
|
364427
364468
|
release: applyRelease,
|
|
364428
|
-
quarantine: (deviceId) =>
|
|
364429
|
-
|
|
364430
|
-
|
|
364431
|
-
unquarantine: (deviceId) => {
|
|
364432
|
-
unquarantineDevice(deviceId);
|
|
364469
|
+
quarantine: (deviceId) => quarantineDevice(deviceId),
|
|
364470
|
+
unquarantine: (deviceId, token) => {
|
|
364471
|
+
unquarantineDevice(deviceId, token);
|
|
364433
364472
|
},
|
|
364434
364473
|
log: (level, message) => {
|
|
364435
364474
|
if (level === "warn") log.warn(message);
|
package/package.json
CHANGED