@xenon-device-management/xenon 1.17.2 → 1.17.3

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/lib/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.17.2",
3
+ "version": "1.17.3",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {
@@ -51,7 +51,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
51
51
  return (mod && mod.__esModule) ? mod : { "default": mod };
52
52
  };
53
53
  Object.defineProperty(exports, "__esModule", { value: true });
54
- exports.SessionLifecycleService = void 0;
54
+ exports.SessionLifecycleService = exports.XCTRUNNER_SUFFIX = void 0;
55
+ exports.stripXctrunnerSuffix = stripXctrunnerSuffix;
55
56
  const typedi_1 = require("typedi");
56
57
  const uuid_1 = require("uuid");
57
58
  const lodash_1 = __importDefault(require("lodash"));
@@ -88,6 +89,26 @@ const commandsQueueGuard = new async_lock_1.default();
88
89
  // Serializes concurrent deleteSession cleanup for the same sessionId so
89
90
  // that onSessionStopped events don't fire twice if two clients race.
90
91
  const sessionCleanupLock = new async_lock_1.default();
92
+ /** The suffix appium-webdriveragent appends to `updatedWDABundleId`. */
93
+ exports.XCTRUNNER_SUFFIX = '.xctrunner';
94
+ /**
95
+ * Normalise an installed WebDriverAgent bundle id for `appium:updatedWDABundleId`.
96
+ *
97
+ * The driver derives its keep-list entry as
98
+ * `${updatedWDABundleId ?? WDA_RUNNER_BUNDLE_ID}${'.xctrunner'}`, so the
99
+ * capability wants the id *without* the runner suffix — it puts it back. Handing
100
+ * it the id exactly as installed yields `…xctrunner.xctrunner`, which matches
101
+ * nothing, and the app the keep-list was meant to protect is uninstalled.
102
+ *
103
+ * Only a trailing occurrence is removed: a bundle id may legitimately contain
104
+ * the word elsewhere, and `String.replace` without an anchor would cut the
105
+ * first one it found.
106
+ */
107
+ function stripXctrunnerSuffix(bundleId) {
108
+ return bundleId.endsWith(exports.XCTRUNNER_SUFFIX)
109
+ ? bundleId.slice(0, -exports.XCTRUNNER_SUFFIX.length)
110
+ : bundleId;
111
+ }
91
112
  let SessionLifecycleService = class SessionLifecycleService {
92
113
  constructor() {
93
114
  this.logger = logger_1.default.scope('SessionLifecycleService');
@@ -377,9 +398,19 @@ let SessionLifecycleService = class SessionLifecycleService {
377
398
  // `webDriverAgentUrl` alone is enough to reuse a running WDA, and it does
378
399
  // not enter that cleanup path — so when the bundle id is unknown, the safe
379
400
  // move is to say less, not more.
401
+ //
402
+ // The suffix matters as much as the value. The keep-list entry is
403
+ // `bundleIdForXctest`, which the driver builds as
404
+ // `${updatedWDABundleId ?? WDA_RUNNER_BUNDLE_ID}${'.xctrunner'}` — so this
405
+ // capability wants the id WITHOUT the runner suffix, and the driver adds
406
+ // it back. Passing the installed id verbatim produced a keep-list of
407
+ // `com.qasecret.WebDriverAgentRunner.xctrunner.xctrunner`, which matched
408
+ // nothing on the device, and the real runner was uninstalled anyway. That
409
+ // is the same normalisation the driver applies to its own prebuilt path:
410
+ // `updatedWDABundleId = candidateBundleId.replace('.xctrunner', '')`.
380
411
  if (bundleId) {
381
412
  target['appium:usePreinstalledWDA'] = true;
382
- target['appium:updatedWDABundleId'] = bundleId;
413
+ target['appium:updatedWDABundleId'] = stripXctrunnerSuffix(bundleId);
383
414
  }
384
415
  else {
385
416
  logger_1.default.warn(`[Xenon] Could not identify the WebDriverAgent bundle on this device; reusing it by URL only. ` +
@@ -34,7 +34,22 @@ describe('WDA capability injection', () => {
34
34
  const caps = { alwaysMatch: {}, firstMatch: [{}] };
35
35
  inject(caps, WDA_URL, BUNDLE);
36
36
  (0, chai_1.expect)(caps.alwaysMatch['appium:usePreinstalledWDA']).to.equal(true);
37
- (0, chai_1.expect)(caps.alwaysMatch['appium:updatedWDABundleId']).to.equal(BUNDLE);
37
+ (0, chai_1.expect)(caps.alwaysMatch['appium:updatedWDABundleId']).to.equal('com.qasecret.WebDriverAgentRunner');
38
+ });
39
+ it('sends the id the driver will rebuild into the installed one', () => {
40
+ // This is the whole contract, and getting it wrong is not a near miss:
41
+ // the driver's keep-list is `updatedWDABundleId + '.xctrunner'`, so an
42
+ // id that is off by that suffix protects a bundle that does not exist
43
+ // and the real runner is uninstalled from the device.
44
+ const caps = { alwaysMatch: {}, firstMatch: [{}] };
45
+ inject(caps, WDA_URL, BUNDLE);
46
+ const keepListEntry = caps.alwaysMatch['appium:updatedWDABundleId'] + SessionLifecycleService_1.XCTRUNNER_SUFFIX;
47
+ (0, chai_1.expect)(keepListEntry).to.equal(BUNDLE);
48
+ });
49
+ it('leaves an id that already lacks the suffix alone', () => {
50
+ const caps = { alwaysMatch: {}, firstMatch: [{}] };
51
+ inject(caps, WDA_URL, 'com.qasecret.WebDriverAgentRunner');
52
+ (0, chai_1.expect)(caps.alwaysMatch['appium:updatedWDABundleId'] + SessionLifecycleService_1.XCTRUNNER_SUFFIX).to.equal(BUNDLE);
38
53
  });
39
54
  it('never claims a preinstalled WDA it cannot name', () => {
40
55
  // The destructive combination. `webDriverAgentUrl` alone still reuses the
@@ -73,6 +88,10 @@ describe('WDA capability injection', () => {
73
88
  (0, chai_1.expect)(caps.firstMatch[0]['appium:usePreinstalledWDA']).to.equal(undefined);
74
89
  (0, chai_1.expect)(caps.alwaysMatch['appium:webDriverAgentUrl']).to.equal(WDA_URL);
75
90
  });
91
+ it('only strips a trailing suffix, never one embedded in the id', () => {
92
+ (0, chai_1.expect)((0, SessionLifecycleService_1.stripXctrunnerSuffix)('com.x.xctrunner.WebDriverAgentRunner.xctrunner')).to.equal('com.x.xctrunner.WebDriverAgentRunner');
93
+ (0, chai_1.expect)((0, SessionLifecycleService_1.stripXctrunnerSuffix)('com.x.WebDriverAgentRunner')).to.equal('com.x.WebDriverAgentRunner');
94
+ });
76
95
  it('strips the caps that conflict with reusing a WDA by URL', () => {
77
96
  const caps = {
78
97
  alwaysMatch: { 'appium:wdaLocalPort': 8100, 'appium:derivedDataPath': '/tmp/dd' },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.17.2",
3
+ "version": "1.17.3",
4
4
  "description": "Xenon - Intelligent Mobile Infrastructure. A self-healing device orchestration platform for Appium.",
5
5
  "main": "./lib/src/index.js",
6
6
  "exports": {