@xenon-device-management/xenon 1.26.2 → 1.27.0

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.
Files changed (79) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{ApiKeyGate-vELAdQLu.js → ApiKeyGate-CdwAz8U0.js} +1 -1
  3. package/lib/public/assets/{BugReportButton-ySiZDywe.js → BugReportButton-BRpZbizS.js} +1 -1
  4. package/lib/public/assets/{DeviceMosaicView-Chtp0wAI.js → DeviceMosaicView-DIliYF7k.js} +1 -1
  5. package/lib/public/assets/{EmptyState-CYQYScPo.js → EmptyState-DdGslmm0.js} +1 -1
  6. package/lib/public/assets/{FieldGroup-Dea68RfI.js → FieldGroup-Bb3NBVy1.js} +1 -1
  7. package/lib/public/assets/{Modal-BgzTzImP.js → Modal-B1wiaZoC.js} +1 -1
  8. package/lib/public/assets/{SegmentedControl-DyRq9blY.js → SegmentedControl-CSSdDwVG.js} +1 -1
  9. package/lib/public/assets/{SettingCard-CardwBu3.js → SettingCard-B5QGLufn.js} +1 -1
  10. package/lib/public/assets/{Table-BczCxsDm.js → Table-CaLvNt65.js} +1 -1
  11. package/lib/public/assets/{activity-CS-Op-T6.js → activity-BKpt4jQ5.js} +1 -1
  12. package/lib/public/assets/{ai-settings-CIvB7rNM.js → ai-settings-DXab66Uw.js} +3 -3
  13. package/lib/public/assets/{api-keys-peJzllzQ.js → api-keys-BKOBEq40.js} +1 -1
  14. package/lib/public/assets/{apps-__WvcJaP.js → apps-h1-WF2M3.js} +3 -3
  15. package/lib/public/assets/{arrow-left-Dx-cXFLT.js → arrow-left-CsL4cGlx.js} +1 -1
  16. package/lib/public/assets/{arrow-right-Ax_FfBMv.js → arrow-right-ms3VXPTM.js} +1 -1
  17. package/lib/public/assets/{arrow-up-right-B6uJmGeA.js → arrow-up-right-DsPkHtnY.js} +1 -1
  18. package/lib/public/assets/{auth-shell-BQqcjjC9.js → auth-shell-Di20xJer.js} +2 -2
  19. package/lib/public/assets/{builds-page-BA-_iEjx.js → builds-page-B7Ykr6Y7.js} +1 -1
  20. package/lib/public/assets/{button-DcbnByKB.js → button-B4yBI9rz.js} +1 -1
  21. package/lib/public/assets/{calendar-C3pYg1V7.js → calendar-CDhdbn6g.js} +1 -1
  22. package/lib/public/assets/{check-DKdLfzhJ.js → check-CQ6W-pr3.js} +1 -1
  23. package/lib/public/assets/{chevron-left-Bb9PBLG5.js → chevron-left-Brw18ZbJ.js} +1 -1
  24. package/lib/public/assets/{chevron-right-DJcpeY_o.js → chevron-right-_5hhohkO.js} +1 -1
  25. package/lib/public/assets/{circle-check-DY6ntqp3.js → circle-check-DFS84uuw.js} +1 -1
  26. package/lib/public/assets/{circle-x-DgK9drRH.js → circle-x--eZQbJ-L.js} +1 -1
  27. package/lib/public/assets/{clock-I9zEVPan.js → clock-BKQop8v4.js} +1 -1
  28. package/lib/public/assets/{copy-Dy3oRuWT.js → copy-C6MtTTlz.js} +1 -1
  29. package/lib/public/assets/device-explorer-DTHiUDlu.js +246 -0
  30. package/lib/public/assets/device-explorer-ISQgiqG9.css +1 -0
  31. package/lib/public/assets/{download-BotTmDty.js → download-CJQADlfa.js} +1 -1
  32. package/lib/public/assets/{forgot-password-BaWiD2U2.js → forgot-password-BDwj629H.js} +1 -1
  33. package/lib/public/assets/{funnel-D2Qw4nTX.js → funnel-DZ7jzsbh.js} +1 -1
  34. package/lib/public/assets/{index-CI9Nz3HY.js → index-BpueX0rJ.js} +2 -2
  35. package/lib/public/assets/{input-cBBGau4X.js → input-CjSO5fIy.js} +1 -1
  36. package/lib/public/assets/{keycodes-CY4uwulo.js → keycodes-DX_YyhNk.js} +1 -1
  37. package/lib/public/assets/{layers-MHwJM2Ll.js → layers-DeJ98GnJ.js} +1 -1
  38. package/lib/public/assets/{lock-Bpc8rJFu.js → lock-D7AfKT4W.js} +1 -1
  39. package/lib/public/assets/{login-BmcyszP5.js → login-DzvYxcU2.js} +1 -1
  40. package/lib/public/assets/{maintenance-settings-DMFVuToe.js → maintenance-settings-CI8PjeAD.js} +2 -2
  41. package/lib/public/assets/{monitor-irjK6PRV.js → monitor-COjPL4Nw.js} +1 -1
  42. package/lib/public/assets/mouse-pointer-2-JHGsHIlv.js +6 -0
  43. package/lib/public/assets/{network-CVZ32MhH.js → network-CHdKReD2.js} +1 -1
  44. package/lib/public/assets/{overview-DRRSIpnD.js → overview-BFi5MYtk.js} +1 -1
  45. package/lib/public/assets/{page-header-Bl7uTiQF.js → page-header-Dlf-n7I6.js} +1 -1
  46. package/lib/public/assets/{plus-C3lvaMcL.js → plus-BO31f8er.js} +1 -1
  47. package/lib/public/assets/{profile-page-B3wsnR1n.js → profile-page-C2mhKOSp.js} +1 -1
  48. package/lib/public/assets/{reset-password-BIGj_ULj.js → reset-password-D2-nKd2R.js} +1 -1
  49. package/lib/public/assets/{runbook-page-DEznNZhc.js → runbook-page-Dua237ld.js} +1 -1
  50. package/lib/public/assets/{select-BpuZWZuE.js → select-r2t6ViSf.js} +1 -1
  51. package/lib/public/assets/{selector-detail-page-ZCvmtQ5Y.js → selector-detail-page-BADJhfZc.js} +1 -1
  52. package/lib/public/assets/{selector-health-D-hvfY2E.js → selector-health-3LaUwIOS.js} +1 -1
  53. package/lib/public/assets/{selector-health-page-C0ZqZ_VT.js → selector-health-page-hCruYbXz.js} +1 -1
  54. package/lib/public/assets/{session-detail-page-Bv7IwFTQ.js → session-detail-page-ovBT1YRs.js} +1 -1
  55. package/lib/public/assets/settings-CIK56OMn.js +6 -0
  56. package/lib/public/assets/{status-pill-outline-B5dWsaer.js → status-pill-outline-CG_1PTcd.js} +1 -1
  57. package/lib/public/assets/{tablet-DxwkBlhd.js → tablet-mcews5C3.js} +1 -1
  58. package/lib/public/assets/{teams-D3s8GhkG.js → teams-Cf8a8-Uo.js} +1 -1
  59. package/lib/public/assets/{trash-2-Dyf4Jcyk.js → trash-2-CsJaXAJF.js} +1 -1
  60. package/lib/public/assets/{upload-B6ZJ1_f1.js → upload-CL1XK43J.js} +1 -1
  61. package/lib/public/assets/{use-password-reset-mode-B-oOrt1d.js → use-password-reset-mode-gRcAFXVy.js} +1 -1
  62. package/lib/public/assets/{users-QfiFclLn.js → users-24eVEQFo.js} +1 -1
  63. package/lib/public/assets/{users-BfvPE2wX.js → users-CgxBmVs9.js} +1 -1
  64. package/lib/public/assets/{video-off-C2quR4KF.js → video-off-LUd5fEht.js} +1 -1
  65. package/lib/public/assets/{webhook-settings-BjbGi-Pi.js → webhook-settings-KzrG-pNv.js} +1 -1
  66. package/lib/public/assets/{zap-C2lxP7TK.js → zap-BA1OUWAL.js} +1 -1
  67. package/lib/public/index.html +1 -1
  68. package/lib/src/app/routers/control.js +5 -0
  69. package/lib/src/device-managers/AndroidDeviceManager.js +31 -95
  70. package/lib/src/device-managers/android/clipboardBroadcast.js +24 -0
  71. package/lib/src/device-managers/clipboardErrors.js +15 -0
  72. package/lib/test/unit/android-clipboard.spec.js +147 -0
  73. package/lib/test/unit/clipboard-route.spec.js +110 -0
  74. package/lib/tsconfig.tsbuildinfo +1 -1
  75. package/package.json +1 -1
  76. package/lib/public/assets/device-explorer-BPyGYs0c.js +0 -246
  77. package/lib/public/assets/device-explorer-C9qg30Jn.css +0 -1
  78. package/lib/public/assets/mouse-pointer-2-CYkC-Dyq.js +0 -11
  79. package/lib/public/assets/settings-DCR9vnQ5.js +0 -1
@@ -70,6 +70,7 @@ const streamType_1 = require("./streamType");
70
70
  const iosStreamPort_1 = require("./iosStreamPort");
71
71
  const androidH264Config_1 = require("./androidH264Config");
72
72
  const recording_store_1 = require("../../services/recording/recording-store");
73
+ const clipboardErrors_1 = require("../../device-managers/clipboardErrors");
73
74
  const scopeGuard_1 = require("../../middleware/scopeGuard");
74
75
  const roleGuard_1 = require("../../middleware/roleGuard");
75
76
  const deviceAccessGuard_1 = require("../../middleware/deviceAccessGuard");
@@ -360,6 +361,10 @@ router.post('/:udid/clipboard', (req, res) => __awaiter(void 0, void 0, void 0,
360
361
  return res.status(200).send({ success: true });
361
362
  }
362
363
  catch (err) {
364
+ // The device can't do it at all (Android): 501, not a failure to retry.
365
+ if (err instanceof clipboardErrors_1.ClipboardUnsupportedError) {
366
+ return res.status(501).send({ error: err.message });
367
+ }
363
368
  logger_1.default.error(`Manual control setClipboard failed: ${err.message}`);
364
369
  return res.status(500).send({ error: err.message });
365
370
  }
@@ -58,6 +58,8 @@ const displayState_1 = require("./android/displayState");
58
58
  const networkAddresses_1 = require("../helpers/networkAddresses");
59
59
  const appium_adb_1 = require("appium-adb");
60
60
  const logger_1 = __importDefault(require("../logger"));
61
+ const clipboardBroadcast_1 = require("./android/clipboardBroadcast");
62
+ const clipboardErrors_1 = require("./clipboardErrors");
61
63
  const lodash_1 = __importDefault(require("lodash"));
62
64
  const support_1 = require("@appium/support");
63
65
  const ChromeDriverManager_1 = __importDefault(require("./ChromeDriverManager"));
@@ -837,108 +839,42 @@ let AndroidDeviceManager = class AndroidDeviceManager {
837
839
  }
838
840
  });
839
841
  }
842
+ /**
843
+ * Reads the clipboard through Appium Settings. Android 10+ lets only the
844
+ * default input method read it, so Appium Settings is the IME for the length
845
+ * of one broadcast (see withAppiumIME). Failures are thrown, not swallowed:
846
+ * an empty string used to stand for both "empty" and "couldn't read".
847
+ */
840
848
  getClipboard(udid) {
841
849
  return __awaiter(this, void 0, void 0, function* () {
842
850
  const { adbInstance } = yield this.getAdb();
843
851
  if (!adbInstance)
844
- return '';
845
- try {
846
- // Wrap the targeted broadcast in the Appium IME context
847
- return yield this.withAppiumIME(adbInstance, udid, () => __awaiter(this, void 0, void 0, function* () {
848
- // 1. Try Targeted Broadcast method (Reliable for modern Android)
849
- const result = yield adbInstance.adbExec([
850
- '-s',
851
- udid,
852
- 'shell',
853
- 'am',
854
- 'broadcast',
855
- '-a',
856
- 'com.appium.settings.clipboard.get',
857
- '-n',
858
- 'io.appium.settings/.receivers.ClipboardReceiver',
859
- ]);
860
- // Parse result like: Broadcast completed: result=-1, data="BASE64_DATA"
861
- const dataMatch = /data="([^"]*)"/.exec(result);
862
- if (dataMatch) {
863
- const rawData = dataMatch[1];
864
- if (!rawData)
865
- return '';
866
- // Appium Settings returns Base64 for robustness
867
- try {
868
- const decoded = Buffer.from(rawData, 'base64').toString('utf8');
869
- // If it looks like printable text after decoding, use it
870
- if (/^[\x20-\x7E\s\u00A0-\uFFFF]*$/.test(decoded))
871
- return decoded;
872
- return rawData;
873
- }
874
- catch (e) {
875
- return rawData;
876
- }
877
- }
878
- // 2. Fallback: Query the content provider (Legacy/Alternative)
879
- const queryResult = yield adbInstance.adbExec([
880
- '-s',
881
- udid,
882
- 'shell',
883
- 'content',
884
- 'query',
885
- '--uri',
886
- 'content://io.appium.settings.clipboard/clipboard',
887
- ]);
888
- // Extract value using a more flexible regex that handles different formats
889
- const valMatch = /value=([^\s,]*)/i.exec(queryResult);
890
- if (valMatch) {
891
- const val = valMatch[1];
892
- // Most content providers return base64 for safety
893
- try {
894
- const decoded = Buffer.from(val, 'base64').toString('utf8');
895
- // Basic sanity check: if it contains non-printable characters, it might not have been base64
896
- if (/^[\x20-\x7E\s]*$/.test(decoded))
897
- return decoded;
898
- return val;
899
- }
900
- catch (e) {
901
- return val;
902
- }
903
- }
904
- return '';
905
- }));
906
- }
907
- catch (err) {
908
- logger_1.default.warn(`Failed to fetch Android clipboard for ${udid}: ${err instanceof Error ? err.message : err}`);
909
- }
910
- return '';
852
+ throw new Error('ADB is not available');
853
+ const output = yield this.withAppiumIME(adbInstance, udid, () => adbInstance.adbExec([
854
+ '-s',
855
+ udid,
856
+ 'shell',
857
+ 'am',
858
+ 'broadcast',
859
+ '-n',
860
+ clipboardBroadcast_1.CLIPBOARD_RECEIVER,
861
+ '-a',
862
+ clipboardBroadcast_1.CLIPBOARD_GET_ACTION,
863
+ ]));
864
+ return (0, clipboardBroadcast_1.parseClipboardBroadcast)(output);
911
865
  });
912
866
  }
913
- setClipboard(udid, content) {
867
+ /**
868
+ * Not possible on Android outside a test session. Appium Settings, the only
869
+ * helper Xenon can use here, has no clipboard-set action (8.0.5 holds just
870
+ * io.appium.settings.clipboard.get), and Appium itself sets the clipboard
871
+ * through a running UiAutomator2 session. The old broadcast reached the
872
+ * *read* receiver, which answered OK, so writes reported success and changed
873
+ * nothing.
874
+ */
875
+ setClipboard() {
914
876
  return __awaiter(this, void 0, void 0, function* () {
915
- const { adbInstance } = yield this.getAdb();
916
- if (!adbInstance)
917
- return;
918
- try {
919
- yield this.withAppiumIME(adbInstance, udid, () => __awaiter(this, void 0, void 0, function* () {
920
- yield adbInstance.adbExec([
921
- '-s',
922
- udid,
923
- 'shell',
924
- 'am',
925
- 'broadcast',
926
- '-a',
927
- 'com.appium.settings.clipboard.set',
928
- '-n',
929
- 'io.appium.settings/.receivers.ClipboardReceiver',
930
- '--es',
931
- 'label',
932
- 'clipboard',
933
- '--es',
934
- 'content',
935
- Buffer.from(content).toString('base64'), // Send as Base64 for safety
936
- ]);
937
- }));
938
- }
939
- catch (err) {
940
- logger_1.default.warn(`Failed to set Android clipboard for ${udid}: ${err instanceof Error ? err.message : err}`);
941
- }
877
+ throw new clipboardErrors_1.ClipboardUnsupportedError('Android doesn’t allow setting the clipboard from here: Appium Settings can only read it.');
942
878
  });
943
879
  }
944
880
  touchAndHold(udid, x, y, duration) {
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CLIPBOARD_GET_ACTION = exports.CLIPBOARD_RECEIVER = void 0;
4
+ exports.parseClipboardBroadcast = parseClipboardBroadcast;
5
+ /** Appium Settings' clipboard receiver and its only clipboard action (read). */
6
+ exports.CLIPBOARD_RECEIVER = 'io.appium.settings/.receivers.ClipboardReceiver';
7
+ exports.CLIPBOARD_GET_ACTION = 'io.appium.settings.clipboard.get';
8
+ /**
9
+ * The clipboard text from `am broadcast … io.appium.settings.clipboard.get`.
10
+ *
11
+ * Appium Settings answers `result=-1, data="<base64>"`, with an empty data for
12
+ * an empty clipboard. Anything else means the broadcast reached no receiver,
13
+ * or the wrong one (a missing app answers `result=0`), so it is an error, not
14
+ * an empty clipboard.
15
+ */
16
+ function parseClipboardBroadcast(output) {
17
+ const answered = /\bresult=-1\b/.test(output);
18
+ const data = /data="([^"]*)"/.exec(output);
19
+ if (!answered || !data) {
20
+ const last = output.trim().split('\n').pop() || 'no output';
21
+ throw new Error(`Appium Settings didn’t return the clipboard. Check that it is installed and up to date (${last}).`);
22
+ }
23
+ return data[1] ? Buffer.from(data[1], 'base64').toString('utf8') : '';
24
+ }
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ClipboardUnsupportedError = void 0;
4
+ /**
5
+ * A clipboard operation this device can't do at all, as opposed to one that
6
+ * failed this time. The control route answers 501 for it: retrying won't help.
7
+ */
8
+ class ClipboardUnsupportedError extends Error {
9
+ constructor(message) {
10
+ super(message);
11
+ this.code = 'clipboard_unsupported';
12
+ this.name = 'ClipboardUnsupportedError';
13
+ }
14
+ }
15
+ exports.ClipboardUnsupportedError = ClipboardUnsupportedError;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ require("reflect-metadata");
16
+ const chai_1 = require("chai");
17
+ const sinon_1 = __importDefault(require("sinon"));
18
+ const AndroidDeviceManager_1 = __importDefault(require("../../src/device-managers/AndroidDeviceManager"));
19
+ const clipboardBroadcast_1 = require("../../src/device-managers/android/clipboardBroadcast");
20
+ const clipboardErrors_1 = require("../../src/device-managers/clipboardErrors");
21
+ /**
22
+ * Device control's clipboard on Android, measured 2026-09-26 on a Galaxy S9+
23
+ * (Android 10, Appium Settings 8.0.5):
24
+ *
25
+ * - Appium Settings can only *read* the clipboard. Its code holds one
26
+ * clipboard action, io.appium.settings.clipboard.get. Our "set" broadcast
27
+ * reached that same receiver, which read the clipboard, answered result=-1,
28
+ * and the server reported success while nothing changed.
29
+ * - The read works, but only while Appium Settings is the default input
30
+ * method (Android 10+ restricts clipboard reads to the IME). After an
31
+ * on-device Copy of "xenonread" it returned data="eGVub25yZWFk".
32
+ * - Both methods swallowed every error, so the route always answered 200.
33
+ */
34
+ const UDID = '381103b720057ece';
35
+ const ORIGINAL_IME = 'com.samsung.android.honeyboard/.service.HoneyBoardService';
36
+ const APPIUM_IME = 'io.appium.settings/.AppiumIME';
37
+ function fakeAdb(broadcast) {
38
+ const calls = [];
39
+ const adbExec = sinon_1.default.stub().callsFake((args) => __awaiter(this, void 0, void 0, function* () {
40
+ calls.push(args);
41
+ const cmd = args.slice(2).join(' ');
42
+ if (cmd === 'shell settings get secure default_input_method')
43
+ return `${ORIGINAL_IME}\n`;
44
+ if (cmd.startsWith('shell am broadcast')) {
45
+ if (broadcast instanceof Error)
46
+ throw broadcast;
47
+ return broadcast;
48
+ }
49
+ return '';
50
+ }));
51
+ return { adbInstance: { adbExec }, calls };
52
+ }
53
+ function managerWith(adb) {
54
+ // The constructor starts device tracking; these tests need only the methods.
55
+ const manager = Object.create(AndroidDeviceManager_1.default.prototype);
56
+ manager.getAdb = () => __awaiter(this, void 0, void 0, function* () { return adb; });
57
+ return manager;
58
+ }
59
+ const imeSets = (calls) => calls.filter((c) => c.slice(2, 5).join(' ') === 'shell ime set').map((c) => c[5]);
60
+ describe('Android clipboard', () => {
61
+ afterEach(() => sinon_1.default.restore());
62
+ describe('parseClipboardBroadcast', () => {
63
+ it('decodes the base64 text Appium Settings returns', () => {
64
+ (0, chai_1.expect)((0, clipboardBroadcast_1.parseClipboardBroadcast)('Broadcasting: Intent { … }\nBroadcast completed: result=-1, data="eGVub25yZWFk"')).to.equal('xenonread');
65
+ });
66
+ it('keeps non-ASCII text', () => {
67
+ const data = Buffer.from('héllo · 世界').toString('base64');
68
+ (0, chai_1.expect)((0, clipboardBroadcast_1.parseClipboardBroadcast)(`Broadcast completed: result=-1, data="${data}"`)).to.equal('héllo · 世界');
69
+ });
70
+ it('treats an empty answer as an empty clipboard', () => {
71
+ (0, chai_1.expect)((0, clipboardBroadcast_1.parseClipboardBroadcast)('Broadcast completed: result=-1, data=""')).to.equal('');
72
+ });
73
+ // A missing receiver answers result=0 with no data; that used to read as
74
+ // an empty clipboard.
75
+ it('refuses an answer that is not a clipboard', () => {
76
+ (0, chai_1.expect)(() => (0, clipboardBroadcast_1.parseClipboardBroadcast)('Broadcast completed: result=0')).to.throw(/Appium Settings didn’t return the clipboard/);
77
+ (0, chai_1.expect)(() => (0, clipboardBroadcast_1.parseClipboardBroadcast)('Broadcast completed: result=0, data="eA=="')).to.throw(/Appium Settings/);
78
+ });
79
+ });
80
+ describe('getClipboard', () => {
81
+ it('reads it with the documented broadcast, as the Appium IME', () => __awaiter(void 0, void 0, void 0, function* () {
82
+ var _a;
83
+ const adb = fakeAdb('Broadcast completed: result=-1, data="eGVub25yZWFk"');
84
+ (0, chai_1.expect)(yield managerWith(adb).getClipboard(UDID)).to.equal('xenonread');
85
+ const broadcast = (_a = adb.calls.find((c) => c.includes('broadcast'))) !== null && _a !== void 0 ? _a : [];
86
+ (0, chai_1.expect)(broadcast).to.include.members([
87
+ '-n',
88
+ 'io.appium.settings/.receivers.ClipboardReceiver',
89
+ '-a',
90
+ 'io.appium.settings.clipboard.get',
91
+ ]);
92
+ (0, chai_1.expect)(imeSets(adb.calls)).to.deep.equal([APPIUM_IME, ORIGINAL_IME]);
93
+ }));
94
+ it('says why when Appium Settings does not answer, and restores the keyboard', () => __awaiter(void 0, void 0, void 0, function* () {
95
+ const adb = fakeAdb('Broadcast completed: result=0');
96
+ let error;
97
+ try {
98
+ yield managerWith(adb).getClipboard(UDID);
99
+ }
100
+ catch (e) {
101
+ error = e;
102
+ }
103
+ (0, chai_1.expect)(error === null || error === void 0 ? void 0 : error.message).to.match(/Appium Settings didn’t return the clipboard/);
104
+ (0, chai_1.expect)(imeSets(adb.calls)).to.deep.equal([APPIUM_IME, ORIGINAL_IME]);
105
+ }));
106
+ it('does not swallow an adb failure', () => __awaiter(void 0, void 0, void 0, function* () {
107
+ const adb = fakeAdb(new Error('device offline'));
108
+ let error;
109
+ try {
110
+ yield managerWith(adb).getClipboard(UDID);
111
+ }
112
+ catch (e) {
113
+ error = e;
114
+ }
115
+ (0, chai_1.expect)(error === null || error === void 0 ? void 0 : error.message).to.equal('device offline');
116
+ (0, chai_1.expect)(imeSets(adb.calls)).to.deep.equal([APPIUM_IME, ORIGINAL_IME]);
117
+ }));
118
+ it('fails when adb is unavailable, instead of returning nothing', () => __awaiter(void 0, void 0, void 0, function* () {
119
+ let error;
120
+ try {
121
+ yield managerWith({ adbInstance: null }).getClipboard(UDID);
122
+ }
123
+ catch (e) {
124
+ error = e;
125
+ }
126
+ (0, chai_1.expect)(error === null || error === void 0 ? void 0 : error.message).to.equal('ADB is not available');
127
+ }));
128
+ });
129
+ describe('setClipboard', () => {
130
+ it('refuses, since Appium Settings can only read the clipboard, and touches nothing', () => __awaiter(void 0, void 0, void 0, function* () {
131
+ var _a;
132
+ const adb = fakeAdb('Broadcast completed: result=-1, data=""');
133
+ let error;
134
+ try {
135
+ // Through the interface, as the control route calls it.
136
+ const manager = managerWith(adb);
137
+ yield ((_a = manager.setClipboard) === null || _a === void 0 ? void 0 : _a.call(manager, UDID, 'xenon-clip-test'));
138
+ }
139
+ catch (e) {
140
+ error = e;
141
+ }
142
+ (0, chai_1.expect)(error).to.be.instanceOf(clipboardErrors_1.ClipboardUnsupportedError);
143
+ (0, chai_1.expect)(error === null || error === void 0 ? void 0 : error.message).to.match(/can only read/);
144
+ (0, chai_1.expect)(adb.calls).to.deep.equal([]);
145
+ }));
146
+ });
147
+ });
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ require("reflect-metadata");
16
+ const chai_1 = require("chai");
17
+ const sinon_1 = __importDefault(require("sinon"));
18
+ const express_1 = __importDefault(require("express"));
19
+ const supertest_1 = __importDefault(require("supertest"));
20
+ const typedi_1 = require("typedi");
21
+ const control_1 = __importDefault(require("../../src/app/routers/control"));
22
+ const device_store_1 = require("../../src/data-service/device-store");
23
+ const ApiKeyService_1 = require("../../src/services/ApiKeyService");
24
+ const device_managers_1 = require("../../src/device-managers");
25
+ const clipboardErrors_1 = require("../../src/device-managers/clipboardErrors");
26
+ const authMiddleware_1 = require("../../src/middleware/authMiddleware");
27
+ /**
28
+ * GET/POST /control/:udid/clipboard answered 200 whatever happened on the
29
+ * device: the Android manager swallowed its errors, and its "set" had no
30
+ * effect at all. The dashboard's toast can only be as honest as the status.
31
+ */
32
+ const UDID = 'DEV-CLIP';
33
+ // The route finds the manager by constructor name.
34
+ class AndroidDeviceManager {
35
+ constructor() {
36
+ this.getClipboard = sinon_1.default.stub();
37
+ this.setClipboard = sinon_1.default.stub();
38
+ }
39
+ }
40
+ function buildApp() {
41
+ const app = (0, express_1.default)();
42
+ app.use(express_1.default.json());
43
+ const apiRouter = express_1.default.Router();
44
+ apiRouter.use((req, _res, next) => {
45
+ req.auth = {
46
+ kind: 'user-session',
47
+ userId: 'usr_me',
48
+ role: 'MEMBER',
49
+ scopes: (0, authMiddleware_1.scopesForRole)('MEMBER'),
50
+ rateLimit: 100,
51
+ };
52
+ next();
53
+ });
54
+ control_1.default.register(apiRouter);
55
+ app.use('/xenon/api', apiRouter);
56
+ return app;
57
+ }
58
+ describe('GET/POST /control/:udid/clipboard', () => {
59
+ let manager;
60
+ beforeEach(() => {
61
+ manager = new AndroidDeviceManager();
62
+ sinon_1.default.stub(device_store_1.DeviceStoreFactory, 'getStore').returns({
63
+ findDevice: () => __awaiter(void 0, void 0, void 0, function* () {
64
+ return ({
65
+ udid: UDID,
66
+ host: '127.0.0.1',
67
+ platform: 'android',
68
+ busy: false,
69
+ session_id: null,
70
+ });
71
+ }),
72
+ });
73
+ typedi_1.Container.set(ApiKeyService_1.ApiKeyService, new ApiKeyService_1.ApiKeyService());
74
+ typedi_1.Container.set(device_managers_1.XenonManager, { deviceInstances: () => __awaiter(void 0, void 0, void 0, function* () { return [manager]; }) });
75
+ });
76
+ afterEach(() => {
77
+ sinon_1.default.restore();
78
+ typedi_1.Container.reset();
79
+ });
80
+ it('returns the clipboard text', () => __awaiter(void 0, void 0, void 0, function* () {
81
+ manager.getClipboard.resolves('xenonread');
82
+ const res = yield (0, supertest_1.default)(buildApp()).get(`/xenon/api/control/${UDID}/clipboard`);
83
+ (0, chai_1.expect)(res.status).to.equal(200);
84
+ (0, chai_1.expect)(res.body).to.deep.equal({ content: 'xenonread' });
85
+ }));
86
+ it('says why a read failed, with a 500', () => __awaiter(void 0, void 0, void 0, function* () {
87
+ manager.getClipboard.rejects(new Error('Appium Settings didn’t return the clipboard.'));
88
+ const res = yield (0, supertest_1.default)(buildApp()).get(`/xenon/api/control/${UDID}/clipboard`);
89
+ (0, chai_1.expect)(res.status).to.equal(500);
90
+ (0, chai_1.expect)(res.body.error).to.match(/Appium Settings/);
91
+ }));
92
+ // Not a failure of this attempt: the platform can't do it, so retrying
93
+ // won't help. 501 says exactly that.
94
+ it('answers 501 when the device cannot set its clipboard', () => __awaiter(void 0, void 0, void 0, function* () {
95
+ manager.setClipboard.rejects(new clipboardErrors_1.ClipboardUnsupportedError('Appium Settings can only read it.'));
96
+ const res = yield (0, supertest_1.default)(buildApp())
97
+ .post(`/xenon/api/control/${UDID}/clipboard`)
98
+ .send({ content: 'x' });
99
+ (0, chai_1.expect)(res.status).to.equal(501);
100
+ (0, chai_1.expect)(res.body).to.deep.equal({ error: 'Appium Settings can only read it.' });
101
+ }));
102
+ it('still answers 500 for any other write failure', () => __awaiter(void 0, void 0, void 0, function* () {
103
+ manager.setClipboard.rejects(new Error('WDA is not running'));
104
+ const res = yield (0, supertest_1.default)(buildApp())
105
+ .post(`/xenon/api/control/${UDID}/clipboard`)
106
+ .send({ content: 'x' });
107
+ (0, chai_1.expect)(res.status).to.equal(500);
108
+ (0, chai_1.expect)(res.body.error).to.equal('WDA is not running');
109
+ }));
110
+ });
@@ -1 +1 @@
1
- {"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/index.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordingRequests.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/streamStartConflict.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/app/ws/logcatWs.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/deviceColumns.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/deviceIdentity.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidIdentity.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/displayState.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSLogStreamService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/appleIdentity.ts","../src/device-managers/ios/iosAppIds.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/deviceAccessGuard.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/profiling/AndroidAppProfiler.ts","../src/proxy/wd-command-proxy.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/DisplayStateService.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/fillMissingScreenSize.ts","../src/services/passwordResetLink.ts","../src/services/passwordResetMode.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/ticketActorAccess.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/inspector/verifyLocator.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseToken.ts","../src/services/logcat/PackageResolver.ts","../src/services/logcat/logSource.ts","../src/services/logcat/logcatParse.ts","../src/services/logcat/ostraceParse.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/activeRecordings.ts","../src/services/recording/annotation-render.ts","../src/services/recording/annotationImage.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/recording/recordingTiming.ts","../src/services/session/sessionIdentity.ts","../src/services/telemetry/attributes.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/artifact-store.ts","../test/helpers/seedUser.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/active-recordings.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-identity.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/android-stream-reuse-service.spec.ts","../test/unit/android-stream-reuse.spec.ts","../test/unit/android-stream-stall-eof.spec.ts","../test/unit/annotation-image.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/apple-identity.spec.ts","../test/unit/apps-download.spec.ts","../test/unit/auth-disabled-resolution.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/commands.spec.js","../test/unit/composite-geometry.spec.ts","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/device-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-columns.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/fill-missing-screen-size.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/helpers.spec.ts","../test/unit/inspector-hierarchy.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/manualLock.test.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/ostrace-parse.spec.ts","../test/unit/package-resolver.spec.ts","../test/unit/passwordResetMode.test.ts","../test/unit/plugin.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-cleanup.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-requests.spec.ts","../test/unit/recording-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/recording-timing.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/reset-link.test.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/schema-required-args.spec.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/session-attribution-wiring.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-stop-recording.spec.ts","../test/unit/stream-ticket-identity.spec.ts","../test/unit/sync-dir.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
1
+ {"root":["../src/InternalHttpClient.ts","../src/PluginContext.ts","../src/XenonCapabilityManager.ts","../src/chromeUtils.ts","../src/config.ts","../src/device-utils.ts","../src/index.ts","../src/logger.ts","../src/plugin.ts","../src/prisma.ts","../src/app/index.ts","../src/app/swagger-docs.ts","../src/app/swagger.ts","../src/app/routers/androidH264Config.ts","../src/app/routers/apikeys.ts","../src/app/routers/apps.ts","../src/app/routers/audit.ts","../src/app/routers/auth.ts","../src/app/routers/bug-report.ts","../src/app/routers/build-export.ts","../src/app/routers/capabilities.ts","../src/app/routers/config.ts","../src/app/routers/control.ts","../src/app/routers/dashboard.ts","../src/app/routers/grid.ts","../src/app/routers/interceptor.ts","../src/app/routers/iosStreamPort.ts","../src/app/routers/ports.ts","../src/app/routers/processes.ts","../src/app/routers/profile.ts","../src/app/routers/profileIdentity.ts","../src/app/routers/projects.ts","../src/app/routers/recordingRequests.ts","../src/app/routers/recordings.ts","../src/app/routers/reservation.ts","../src/app/routers/sdk-leases.ts","../src/app/routers/sdk-version.ts","../src/app/routers/streamStartConflict.ts","../src/app/routers/streamType.ts","../src/app/routers/teams.ts","../src/app/routers/users.ts","../src/app/routers/webhook.ts","../src/app/ws/h264StreamWs.ts","../src/app/ws/logcatWs.ts","../src/commands/handle.ts","../src/commands/index.ts","../src/dashboard/asset-manager.ts","../src/dashboard/commands.ts","../src/dashboard/event-manager.ts","../src/dashboard/services/app-service.ts","../src/dashboard/services/failure-analysis-service.ts","../src/dashboard/services/session-service.ts","../src/data-service/CircuitBreaker.ts","../src/data-service/config-service.ts","../src/data-service/db.ts","../src/data-service/device-service.ts","../src/data-service/device-store.interface.ts","../src/data-service/device-store.ts","../src/data-service/deviceColumns.ts","../src/data-service/pending-sessions-service.ts","../src/data-service/pluginArgs.ts","../src/data-service/prisma-service.ts","../src/data-service/prisma-store.ts","../src/data-service/queue-service.ts","../src/data-service/web-config-service.ts","../src/device-managers/AndroidDeviceManager.ts","../src/device-managers/ChromeDriverManager.ts","../src/device-managers/HealthMonitorService.ts","../src/device-managers/IOSDeviceManager.ts","../src/device-managers/NodeDevices.ts","../src/device-managers/clipboardErrors.ts","../src/device-managers/deviceIdentity.ts","../src/device-managers/iOSTracker.ts","../src/device-managers/index.ts","../src/device-managers/android/AndroidH264StreamService.ts","../src/device-managers/android/AndroidStreamService.ts","../src/device-managers/android/DeviceLockManager.ts","../src/device-managers/android/H264Multiplexer.ts","../src/device-managers/android/LogcatMultiplexer.ts","../src/device-managers/android/LogcatStreamService.ts","../src/device-managers/android/ScrcpyServerSession.ts","../src/device-managers/android/androidIdentity.ts","../src/device-managers/android/androidStreamReuse.ts","../src/device-managers/android/clipboardBroadcast.ts","../src/device-managers/android/displayState.ts","../src/device-managers/android/h264NalParser.ts","../src/device-managers/android/scrcpyVersion.ts","../src/device-managers/cloud/CapabilityManager.ts","../src/device-managers/cloud/Devices.ts","../src/device-managers/ios/IOSDiscoveryService.ts","../src/device-managers/ios/IOSLogStreamService.ts","../src/device-managers/ios/IOSStreamService.ts","../src/device-managers/ios/WDAClient.ts","../src/device-managers/ios/appleIdentity.ts","../src/device-managers/ios/iosAppIds.ts","../src/device-managers/ios/iosBattery.ts","../src/device-managers/ios/iosStreamDiagnostics.ts","../src/device-managers/ios/tunnelProcess.ts","../src/enums/Capabilities.ts","../src/enums/Cloud.ts","../src/enums/Platform.ts","../src/enums/SessionType.ts","../src/enums/SocketEvents.ts","../src/generated/client/default.d.ts","../src/generated/client/default.js","../src/generated/client/edge.d.ts","../src/generated/client/edge.js","../src/generated/client/index-browser.js","../src/generated/client/index.d.ts","../src/generated/client/index.js","../src/generated/client/wasm.d.ts","../src/generated/client/wasm.js","../src/generated/client/runtime/edge-esm.js","../src/generated/client/runtime/edge.js","../src/generated/client/runtime/index-browser.d.ts","../src/generated/client/runtime/index-browser.js","../src/generated/client/runtime/library.d.ts","../src/generated/client/runtime/library.js","../src/generated/client/runtime/react-native.js","../src/generated/client/runtime/wasm.js","../src/helpers/UniversalMjpegProxy.ts","../src/helpers/ffmpegPath.ts","../src/helpers/index.ts","../src/helpers/networkAddresses.ts","../src/helpers/singleFlight.ts","../src/interceptors/CommandInterceptor.ts","../src/interfaces/ICloudManager.ts","../src/interfaces/IDevice.ts","../src/interfaces/IDeviceFilterOptions.ts","../src/interfaces/IDeviceManager.ts","../src/interfaces/IOptions.ts","../src/interfaces/IPluginArgs.ts","../src/interfaces/ISessionCapability.ts","../src/logging/sessionContext.ts","../src/middleware/authMiddleware.ts","../src/middleware/csrfMiddleware.ts","../src/middleware/deviceAccessGuard.ts","../src/middleware/leaseTokenMiddleware.ts","../src/middleware/loginRateLimiter.ts","../src/middleware/rateLimitMiddleware.ts","../src/middleware/roleGuard.ts","../src/middleware/scopeGuard.ts","../src/profiling/AndroidAppProfiler.ts","../src/proxy/wd-command-proxy.ts","../src/scripts/generate-database-migration.ts","../src/scripts/goIosVersion.ts","../src/scripts/initialize-database.ts","../src/scripts/install-go-ios.ts","../src/scripts/prepare-prisma.ts","../src/scripts/run-migrations.ts","../src/services/AICommandService.ts","../src/services/AIService.ts","../src/services/ApiKeyService.ts","../src/services/CircuitBreaker.ts","../src/services/CleanupService.ts","../src/services/DeviceReconciler.ts","../src/services/DisplayStateService.ts","../src/services/EmailService.ts","../src/services/EventBus.ts","../src/services/EventLogService.ts","../src/services/InspectorService.ts","../src/services/InterceptorService.ts","../src/services/MetricsService.ts","../src/services/NetworkConditioningService.ts","../src/services/NotificationService.ts","../src/services/OrphanSweeper.ts","../src/services/PasswordResetService.ts","../src/services/PortAllocator.ts","../src/services/ProcessMetricsService.ts","../src/services/ProcessRegistry.ts","../src/services/RequestLogService.ts","../src/services/ResourceIsolationService.ts","../src/services/SecurityService.ts","../src/services/SelectorStateService.ts","../src/services/SelectorVerificationJob.ts","../src/services/ServerManager.ts","../src/services/SessionHeartbeatService.ts","../src/services/SessionLifecycleService.ts","../src/services/ShutdownCoordinator.ts","../src/services/SocketClient.ts","../src/services/SocketServer.ts","../src/services/TeamService.ts","../src/services/TracingService.ts","../src/services/UserService.ts","../src/services/UserSessionService.ts","../src/services/VideoPipelineService.ts","../src/services/fillMissingScreenSize.ts","../src/services/passwordResetLink.ts","../src/services/passwordResetMode.ts","../src/services/sessionTokenGate.ts","../src/services/artifacts/ArtifactStore.ts","../src/services/autowait/AutowaitService.ts","../src/services/autowait/waitFor.ts","../src/services/bug-report/BugReportService.ts","../src/services/bug-report/archive.ts","../src/services/bug-report/har-collector.ts","../src/services/bug-report/manifest.ts","../src/services/bug-report/readme.ts","../src/services/bug-report/types.ts","../src/services/bug-report/video-slice.ts","../src/services/bug-report/window.ts","../src/services/device-access/SessionOwnerResolver.ts","../src/services/device-access/actor.ts","../src/services/device-access/deviceAccessPolicy.ts","../src/services/device-access/ticketActorAccess.ts","../src/services/healing/FuzzyXmlHealingProvider.ts","../src/services/healing/HealEtalonService.ts","../src/services/healing/HealedLocatorGenerator.ts","../src/services/healing/HealingMetrics.ts","../src/services/healing/HealingOrchestrator.ts","../src/services/healing/LlmHealingProvider.ts","../src/services/healing/OcrHealingProvider.ts","../src/services/healing/ResilioTreeHealingProvider.ts","../src/services/healing/VisualAiHealingProvider.ts","../src/services/healing/types.ts","../src/services/identity/bootstrap.ts","../src/services/identity/sessionCleanupCron.ts","../src/services/identity/userAuthorization.ts","../src/services/inspector/verifyLocator.ts","../src/services/interceptor/AndroidProxyAdapter.ts","../src/services/interceptor/CertManager.ts","../src/services/interceptor/HarBuilder.ts","../src/services/interceptor/HostFilter.ts","../src/services/interceptor/MitmProxyHost.ts","../src/services/interceptor/MockEngine.ts","../src/services/interceptor/RequestBuffer.ts","../src/services/interceptor/SessionArchive.ts","../src/services/interceptor/types.ts","../src/services/lease/LeaseOrphanSweeper.ts","../src/services/lease/LeaseService.ts","../src/services/lease/buildCapabilityBag.ts","../src/services/lease/leaseToken.ts","../src/services/logcat/PackageResolver.ts","../src/services/logcat/logSource.ts","../src/services/logcat/logcatParse.ts","../src/services/logcat/ostraceParse.ts","../src/services/omni-vision/OmniVisionService.ts","../src/services/omni-vision/VisionAssertionService.ts","../src/services/ports/PortAllocatorClient.ts","../src/services/ports/PortAllocatorService.ts","../src/services/recording/RecordingOrchestrator.ts","../src/services/recording/activeRecordings.ts","../src/services/recording/annotation-render.ts","../src/services/recording/annotationImage.ts","../src/services/recording/busy-precheck.ts","../src/services/recording/concurrency-gate.ts","../src/services/recording/ensureMjpegForRecording.ts","../src/services/recording/manualLock.ts","../src/services/recording/probeDuration.ts","../src/services/recording/proof-bundle.ts","../src/services/recording/recording-store.ts","../src/services/recording/recordingCleanup.ts","../src/services/recording/recordingTiming.ts","../src/services/session/sessionIdentity.ts","../src/services/telemetry/attributes.ts","../src/services/token/JwtKeyService.ts","../src/services/token/StreamTicketService.ts","../src/services/token/mcpScopes.ts","../src/sessions/CloudSession.ts","../src/sessions/LocalSession.ts","../src/sessions/RemoteSession.ts","../src/sessions/SessionManager.ts","../src/sessions/XenonSession.ts","../src/types/CLIArgs.ts","../src/types/CloudArgs.ts","../src/types/CloudSchema.ts","../src/types/DeviceType.ts","../src/types/DeviceUpdate.ts","../src/types/IOSDevice.ts","../src/types/Platform.ts","../src/types/SessionStatus.ts","../src/types/express.d.ts","../src/types/healing.d.ts","../src/types/identity.ts","../src/validators/CapabilityValidator.ts","../test/e2e/e2ehelper.ts","../test/e2e/plugin-harness.ts","../test/e2e/plugin.spec.ts","../test/e2e/startup-verification.spec.ts","../test/e2e/telemetry_verification.spec.ts","../test/e2e/video-recording-test.spec.js","../test/e2e/android/conf.spec.js","../test/e2e/android/conf2.spec.js","../test/e2e/android/conf3.spec.js","../test/e2e/hubnode/forward-request.spec.ts","../test/e2e/hubnode/hubnode.spec.ts","../test/e2e/ios/conf1.spec.js","../test/e2e/ios/conf2.spec.js","../test/helpers/artifact-store.ts","../test/helpers/seedUser.ts","../test/helpers/test-container.ts","../test/integration/androidDevices.spec.ts","../test/integration/audit-ingest.spec.ts","../test/integration/auth-flow.spec.ts","../test/integration/auth-rate-limit.spec.ts","../test/integration/bug-report-route.spec.ts","../test/integration/cliArgs.js","../test/integration/cross-workflow.spec.ts","../test/integration/forgot-password-rate-limit.spec.ts","../test/integration/forgot-password.spec.ts","../test/integration/healing-events-sessionfilter.spec.ts","../test/integration/legacy-deprecation-headers.spec.ts","../test/integration/migration.spec.ts","../test/integration/node-pair-auth-rest.spec.ts","../test/integration/ports-router.spec.ts","../test/integration/profile-tokens.spec.ts","../test/integration/recordings-router.spec.ts","../test/integration/reset-revokes-sessions.spec.ts","../test/integration/role-matrix.spec.ts","../test/integration/sdk-leases-router.spec.ts","../test/integration/sdk-version.spec.ts","../test/integration/selector-health-endpoint.spec.ts","../test/integration/selector-state-flow.spec.ts","../test/integration/team-membership-migration.spec.ts","../test/integration/team-visibility-dashboard.spec.ts","../test/integration/team-visibility-grid.spec.ts","../test/integration/team-visibility-recordings.spec.ts","../test/integration/users-flow.spec.ts","../test/integration/users-lockout.spec.ts","../test/integration/ios/01iOSSimulator.spec.ts","../test/integration/ios/02iOSDevices.spec.ts","../test/unit/AndroidDeviceManager.spec.ts","../test/unit/ApiKeyService.test.ts","../test/unit/ArtifactStore.spec.ts","../test/unit/AutowaitService.spec.ts","../test/unit/CapabilitiesRouter.spec.ts","../test/unit/ChromeDriverManager.spec.js","../test/unit/CleanupService.spec.ts","../test/unit/CommandInterceptor.autowait.spec.ts","../test/unit/DeviceModel.spec.ts","../test/unit/EmailService.test.ts","../test/unit/EventLogService.spec.ts","../test/unit/FuzzyXmlHealingProvider.test.ts","../test/unit/GetAdbOriginal.js","../test/unit/HealingCascade.test.ts","../test/unit/IOSDeviceManager.spec.js","../test/unit/JwtKeyService.spec.ts","../test/unit/McpScopes.spec.ts","../test/unit/OrphanSweeper.test.ts","../test/unit/PasswordResetService.test.ts","../test/unit/PortAllocator.test.ts","../test/unit/ProcessRegistry.test.ts","../test/unit/ProjectsRouter.spec.ts","../test/unit/RemoteIOs.spec.js","../test/unit/ResilioTreeHealingProvider.test.ts","../test/unit/SessionHeartbeatWrite.test.ts","../test/unit/SessionLifecycleCaps.spec.ts","../test/unit/SessionTokenGate.spec.ts","../test/unit/StreamTicketService.spec.ts","../test/unit/TeamService.test.ts","../test/unit/TokenEndpoint.spec.ts","../test/unit/UserService.test.ts","../test/unit/UserSessionService.test.ts","../test/unit/XenonCapabilityManager.spec.ts","../test/unit/active-recordings.spec.ts","../test/unit/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-clipboard.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.spec.ts","../test/unit/android-identity.spec.ts","../test/unit/android-stream-adb-path.spec.ts","../test/unit/android-stream-encoder.spec.ts","../test/unit/android-stream-fast-start.spec.ts","../test/unit/android-stream-release.spec.ts","../test/unit/android-stream-reuse-service.spec.ts","../test/unit/android-stream-reuse.spec.ts","../test/unit/android-stream-stall-eof.spec.ts","../test/unit/annotation-image.spec.ts","../test/unit/annotation-render.spec.ts","../test/unit/apple-identity.spec.ts","../test/unit/apps-download.spec.ts","../test/unit/auth-disabled-resolution.spec.ts","../test/unit/auth-me-auth-disabled.test.ts","../test/unit/authMiddleware.bearer.spec.ts","../test/unit/authMiddleware.mcpAudience.spec.ts","../test/unit/authMiddleware.streamTicket.spec.ts","../test/unit/authMiddleware.test.ts","../test/unit/bootstrap-identity.test.ts","../test/unit/build-export.spec.ts","../test/unit/busy-precheck.spec.ts","../test/unit/clipboard-route.spec.ts","../test/unit/commands.spec.js","../test/unit/composite-geometry.spec.ts","../test/unit/concurrency-gate.spec.ts","../test/unit/config.spec.js","../test/unit/device-access-guard.spec.ts","../test/unit/device-access-policy.spec.ts","../test/unit/device-columns.spec.ts","../test/unit/device-service.spec.ts","../test/unit/device-utils.spec.ts","../test/unit/display-state.spec.ts","../test/unit/enrich-devices-team-names.test.ts","../test/unit/event-manager-regression-hook.spec.ts","../test/unit/extract-access-key-token-pair.test.ts","../test/unit/ffmpeg-path.spec.ts","../test/unit/fill-missing-screen-size.spec.ts","../test/unit/findAndLockDevice-leasemerge.spec.ts","../test/unit/go-ios-version.spec.ts","../test/unit/h264-multiplexer.spec.ts","../test/unit/h264-nal-parser.spec.ts","../test/unit/h264-ws-frame.spec.ts","../test/unit/healing-instrumentation.spec.ts","../test/unit/healing-state-endpoints.spec.ts","../test/unit/healing-tier-gate.spec.ts","../test/unit/helpers.spec.ts","../test/unit/inspector-hierarchy.spec.ts","../test/unit/ios-stream-port.spec.ts","../test/unit/ios-tunnel-process.spec.ts","../test/unit/iosBattery.spec.ts","../test/unit/iosStreamDiagnostics.spec.ts","../test/unit/logcat-multiplexer.spec.ts","../test/unit/logcat-parse.spec.ts","../test/unit/logcat-stream-service.spec.ts","../test/unit/logcat-ws.spec.ts","../test/unit/loginRateLimiter.test.ts","../test/unit/manualLock.test.ts","../test/unit/mjpeg-proxy-cache.spec.ts","../test/unit/network-addresses.test.ts","../test/unit/normalize-eol.spec.js","../test/unit/omni-vision.spec.ts","../test/unit/ostrace-parse.spec.ts","../test/unit/package-resolver.spec.ts","../test/unit/passwordResetMode.test.ts","../test/unit/plugin.spec.ts","../test/unit/port-exhaustion.spec.ts","../test/unit/prisma.spec.ts","../test/unit/probe-duration.spec.ts","../test/unit/profile-router.test.ts","../test/unit/profileIdentity.spec.ts","../test/unit/proof-bundle.spec.ts","../test/unit/rateLimitMiddleware.test.ts","../test/unit/recording-cleanup.spec.ts","../test/unit/recording-instrumentation.spec.ts","../test/unit/recording-orchestrator.spec.ts","../test/unit/recording-requests.spec.ts","../test/unit/recording-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/recording-timing.spec.ts","../test/unit/remux-to-standard-mp4.spec.ts","../test/unit/reset-link.test.ts","../test/unit/roleGuard.test.ts","../test/unit/run-migrations-fail-fast.test.ts","../test/unit/run-migrations.test.ts","../test/unit/schema-required-args.spec.ts","../test/unit/scrcpy-server-session.spec.ts","../test/unit/scrcpy-version.spec.ts","../test/unit/selector-state-service.spec.ts","../test/unit/selector-verification-job.spec.ts","../test/unit/session-attribution-wiring.spec.ts","../test/unit/session-identity.spec.ts","../test/unit/session-owner-resolver.spec.ts","../test/unit/shutdown-sync-nets.spec.ts","../test/unit/single-flight.spec.ts","../test/unit/socketServer.bearer.spec.ts","../test/unit/stream-start-conflict.spec.ts","../test/unit/stream-status-type.spec.ts","../test/unit/stream-stop-ownership.spec.ts","../test/unit/stream-stop-recording.spec.ts","../test/unit/stream-ticket-identity.spec.ts","../test/unit/sync-dir.spec.ts","../test/unit/team-filter.test.ts","../test/unit/tracing-service-init.spec.ts","../test/unit/userAuthorization.test.ts","../test/unit/users-router.test.ts","../test/unit/verify-locator.spec.ts","../test/unit/video-pipeline-args.spec.ts","../test/unit/video-pipeline-exit.spec.ts","../test/unit/video-pipeline-outputpath.spec.ts","../test/unit/wda-cap-injection.spec.ts","../test/unit/bug-report/archive.spec.ts","../test/unit/bug-report/har-collector.spec.ts","../test/unit/bug-report/manifest.spec.ts","../test/unit/bug-report/readme.spec.ts","../test/unit/bug-report/route.spec.ts","../test/unit/bug-report/service.spec.ts","../test/unit/bug-report/video-slice.spec.ts","../test/unit/bug-report/window.spec.ts","../test/unit/fixtures/device.config.js","../test/unit/fixtures/devices.js","../test/unit/interceptor/AndroidProxyAdapter.spec.ts","../test/unit/interceptor/CertManager.spec.ts","../test/unit/interceptor/HarBuilder.spec.ts","../test/unit/interceptor/HostFilter.spec.ts","../test/unit/interceptor/MitmProxyHost.spec.ts","../test/unit/interceptor/MockEngine.spec.ts","../test/unit/interceptor/RequestBuffer.spec.ts","../test/unit/interceptor/SessionArchive.spec.ts","../test/unit/lease/LeaseOrphanSweeper.spec.ts","../test/unit/lease/LeaseService.spec.ts","../test/unit/lease/buildCapabilityBag.spec.ts","../test/unit/lease/leaseToken.spec.ts","../test/unit/lease/nodePairAuth.spec.ts","../test/unit/ports/PortAllocatorService.spec.ts"],"version":"5.9.3"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xenon-device-management/xenon",
3
- "version": "1.26.2",
3
+ "version": "1.27.0",
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": {