@xenon-device-management/xenon 1.26.2 → 1.28.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 (85) hide show
  1. package/lib/package.json +1 -1
  2. package/lib/public/assets/{ApiKeyGate-vELAdQLu.js → ApiKeyGate-CYrHWuf9.js} +1 -1
  3. package/lib/public/assets/{BugReportButton-ySiZDywe.js → BugReportButton-CRRZnSs2.js} +1 -1
  4. package/lib/public/assets/{DeviceMosaicView-Chtp0wAI.js → DeviceMosaicView-Dw7dK-Ri.js} +1 -1
  5. package/lib/public/assets/{EmptyState-CYQYScPo.js → EmptyState-BDSDbxbe.js} +1 -1
  6. package/lib/public/assets/{FieldGroup-Dea68RfI.js → FieldGroup-DTSy35Hp.js} +1 -1
  7. package/lib/public/assets/{Modal-BgzTzImP.js → Modal-BC9RPZeO.js} +1 -1
  8. package/lib/public/assets/{SegmentedControl-DyRq9blY.js → SegmentedControl-DUw7pxfw.js} +1 -1
  9. package/lib/public/assets/{SettingCard-CardwBu3.js → SettingCard-DwHb-9y7.js} +1 -1
  10. package/lib/public/assets/{Table-BczCxsDm.js → Table-C167c0iD.js} +1 -1
  11. package/lib/public/assets/{activity-CS-Op-T6.js → activity-C8ktgelv.js} +1 -1
  12. package/lib/public/assets/{ai-settings-CIvB7rNM.js → ai-settings-BtH8D-Vk.js} +3 -3
  13. package/lib/public/assets/{api-keys-peJzllzQ.js → api-keys-D0CPHe_-.js} +1 -1
  14. package/lib/public/assets/{apps-__WvcJaP.js → apps-f6Z9888a.js} +3 -3
  15. package/lib/public/assets/{arrow-left-Dx-cXFLT.js → arrow-left-CEnrTC1h.js} +1 -1
  16. package/lib/public/assets/{arrow-right-Ax_FfBMv.js → arrow-right-DJbja5Vo.js} +1 -1
  17. package/lib/public/assets/{arrow-up-right-B6uJmGeA.js → arrow-up-right-DvIZquNN.js} +1 -1
  18. package/lib/public/assets/{auth-shell-BQqcjjC9.js → auth-shell-5XCL86e9.js} +2 -2
  19. package/lib/public/assets/{builds-page-BA-_iEjx.js → builds-page-DQbsMgZp.js} +1 -1
  20. package/lib/public/assets/{button-DcbnByKB.js → button-CMj-iXRu.js} +1 -1
  21. package/lib/public/assets/{calendar-C3pYg1V7.js → calendar-BKb9JzMb.js} +1 -1
  22. package/lib/public/assets/{check-DKdLfzhJ.js → check-BioFa43z.js} +1 -1
  23. package/lib/public/assets/{chevron-left-Bb9PBLG5.js → chevron-left-BfiSwNHE.js} +1 -1
  24. package/lib/public/assets/{chevron-right-DJcpeY_o.js → chevron-right-BLqjv9Fz.js} +1 -1
  25. package/lib/public/assets/{circle-check-DY6ntqp3.js → circle-check-N7nCeFZH.js} +1 -1
  26. package/lib/public/assets/{circle-x-DgK9drRH.js → circle-x-DzRW2cW-.js} +1 -1
  27. package/lib/public/assets/{clock-I9zEVPan.js → clock-Q8bhs7zV.js} +1 -1
  28. package/lib/public/assets/{copy-Dy3oRuWT.js → copy-Dh1ppPe1.js} +1 -1
  29. package/lib/public/assets/device-explorer-Cbwojnbb.js +277 -0
  30. package/lib/public/assets/device-explorer-CcLOID3w.css +1 -0
  31. package/lib/public/assets/{download-BotTmDty.js → download-Dit5_Lob.js} +1 -1
  32. package/lib/public/assets/{forgot-password-BaWiD2U2.js → forgot-password-yhK1Eo6h.js} +1 -1
  33. package/lib/public/assets/{funnel-D2Qw4nTX.js → funnel-DQo9dvhT.js} +1 -1
  34. package/lib/public/assets/{index-CI9Nz3HY.js → index-kcl0icXA.js} +2 -2
  35. package/lib/public/assets/{input-cBBGau4X.js → input-DwXEwtQD.js} +1 -1
  36. package/lib/public/assets/{keycodes-CY4uwulo.js → keycodes-mlL7WkFd.js} +1 -1
  37. package/lib/public/assets/{layers-MHwJM2Ll.js → layers-DFEJsDA2.js} +1 -1
  38. package/lib/public/assets/{lock-Bpc8rJFu.js → lock-DVGX1wMR.js} +1 -1
  39. package/lib/public/assets/{login-BmcyszP5.js → login-BtczO6mT.js} +1 -1
  40. package/lib/public/assets/{maintenance-settings-DMFVuToe.js → maintenance-settings-BNkCNkdA.js} +2 -2
  41. package/lib/public/assets/{monitor-irjK6PRV.js → monitor-DXiFh_zm.js} +1 -1
  42. package/lib/public/assets/mouse-pointer-2-iiFLrBfo.js +6 -0
  43. package/lib/public/assets/{network-CVZ32MhH.js → network-D-64m0lI.js} +1 -1
  44. package/lib/public/assets/{overview-DRRSIpnD.js → overview-Bs8fij0f.js} +1 -1
  45. package/lib/public/assets/{page-header-Bl7uTiQF.js → page-header-2aP5HfMz.js} +1 -1
  46. package/lib/public/assets/{plus-C3lvaMcL.js → plus-l0nFcN3u.js} +1 -1
  47. package/lib/public/assets/{profile-page-B3wsnR1n.js → profile-page-DRQxEDPv.js} +1 -1
  48. package/lib/public/assets/{reset-password-BIGj_ULj.js → reset-password-TeZbTlY3.js} +1 -1
  49. package/lib/public/assets/{runbook-page-DEznNZhc.js → runbook-page-CfB3Sgqd.js} +1 -1
  50. package/lib/public/assets/{select-BpuZWZuE.js → select-CfLeV0bn.js} +1 -1
  51. package/lib/public/assets/{selector-detail-page-ZCvmtQ5Y.js → selector-detail-page-sjSLgf2y.js} +1 -1
  52. package/lib/public/assets/{selector-health-D-hvfY2E.js → selector-health-DobHOezq.js} +1 -1
  53. package/lib/public/assets/{selector-health-page-C0ZqZ_VT.js → selector-health-page-BeGTmjeJ.js} +1 -1
  54. package/lib/public/assets/{session-detail-page-Bv7IwFTQ.js → session-detail-page-B7Be2Uxw.js} +1 -1
  55. package/lib/public/assets/settings-DWlkn05y.js +6 -0
  56. package/lib/public/assets/{status-pill-outline-B5dWsaer.js → status-pill-outline-DqZaavRm.js} +1 -1
  57. package/lib/public/assets/{tablet-DxwkBlhd.js → tablet-D2ApmdVm.js} +1 -1
  58. package/lib/public/assets/{teams-D3s8GhkG.js → teams-DVm0mUGI.js} +1 -1
  59. package/lib/public/assets/{trash-2-Dyf4Jcyk.js → trash-2-BklI15pS.js} +1 -1
  60. package/lib/public/assets/{upload-B6ZJ1_f1.js → upload-BMYoLWMh.js} +1 -1
  61. package/lib/public/assets/{use-password-reset-mode-B-oOrt1d.js → use-password-reset-mode-Dx_zeU5K.js} +1 -1
  62. package/lib/public/assets/{users-QfiFclLn.js → users-CnVdUoqL.js} +1 -1
  63. package/lib/public/assets/{users-BfvPE2wX.js → users-DqVUPDed.js} +1 -1
  64. package/lib/public/assets/{video-off-C2quR4KF.js → video-off-DEmVhLd9.js} +1 -1
  65. package/lib/public/assets/{webhook-settings-BjbGi-Pi.js → webhook-settings-CHpCrpob.js} +1 -1
  66. package/lib/public/assets/{zap-C2lxP7TK.js → zap-ovWf2UbO.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/HealthMonitorService.js +10 -6
  71. package/lib/src/device-managers/android/AndroidH264StreamService.js +6 -1
  72. package/lib/src/device-managers/android/AndroidStreamService.js +9 -18
  73. package/lib/src/device-managers/android/clipboardBroadcast.js +24 -0
  74. package/lib/src/device-managers/android/previewHold.js +72 -0
  75. package/lib/src/device-managers/clipboardErrors.js +15 -0
  76. package/lib/test/unit/android-clipboard.spec.js +147 -0
  77. package/lib/test/unit/android-preview-hold.spec.js +179 -0
  78. package/lib/test/unit/clipboard-route.spec.js +110 -0
  79. package/lib/test/unit/health-monitor-stream-lookup.spec.js +107 -0
  80. package/lib/tsconfig.tsbuildinfo +1 -1
  81. package/package.json +1 -1
  82. package/lib/public/assets/device-explorer-BPyGYs0c.js +0 -246
  83. package/lib/public/assets/device-explorer-C9qg30Jn.css +0 -1
  84. package/lib/public/assets/mouse-pointer-2-CYkC-Dyq.js +0 -11
  85. package/lib/public/assets/settings-DCR9vnQ5.js +0 -1
@@ -0,0 +1,179 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
+ return new (P || (P = Promise))(function (resolve, reject) {
38
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
39
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
40
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
41
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
42
+ });
43
+ };
44
+ var __importDefault = (this && this.__importDefault) || function (mod) {
45
+ return (mod && mod.__esModule) ? mod : { "default": mod };
46
+ };
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ require("reflect-metadata");
49
+ const chai_1 = require("chai");
50
+ const sinon_1 = __importDefault(require("sinon"));
51
+ const typedi_1 = require("typedi");
52
+ const deviceService = __importStar(require("../../src/data-service/device-service"));
53
+ const device_store_1 = require("../../src/data-service/device-store");
54
+ const recording_store_1 = require("../../src/services/recording/recording-store");
55
+ const AndroidStreamService_1 = __importDefault(require("../../src/device-managers/android/AndroidStreamService"));
56
+ const AndroidH264StreamService_1 = __importDefault(require("../../src/device-managers/android/AndroidH264StreamService"));
57
+ const previewHold_1 = require("../../src/device-managers/android/previewHold");
58
+ const UDID = 'android-1';
59
+ const HOLD = `manual_user-1_${UDID}`;
60
+ describe('Android live-preview hold', () => {
61
+ let unblock;
62
+ let device;
63
+ let use;
64
+ beforeEach(() => {
65
+ device = { udid: UDID, host: 'h', session_id: HOLD, busy: true };
66
+ use = { h264Clients: 0, mjpegViewers: 0, recording: false };
67
+ unblock = sinon_1.default.stub(deviceService, 'unblockDevice').resolves();
68
+ sinon_1.default.stub(device_store_1.DeviceStoreFactory, 'getStore').returns({
69
+ findDevice: () => __awaiter(void 0, void 0, void 0, function* () { return device; }),
70
+ });
71
+ const real = typedi_1.Container.get.bind(typedi_1.Container);
72
+ sinon_1.default.stub(typedi_1.Container, 'get').callsFake((token) => {
73
+ // By class: TypeDI 0.10 ignores @Service({ name }), so a lookup by name
74
+ // throws in the running server even though a name stub here would pass.
75
+ if (token === AndroidH264StreamService_1.default) {
76
+ return {
77
+ getMultiplexer: () => (use.h264Clients ? { clientCount: use.h264Clients } : undefined),
78
+ };
79
+ }
80
+ if (token === AndroidStreamService_1.default) {
81
+ return { getStreamStatus: () => ({ viewerCount: use.mjpegViewers }) };
82
+ }
83
+ if (token === recording_store_1.RecordingStore)
84
+ return { isRecording: () => __awaiter(void 0, void 0, void 0, function* () { return use.recording; }) };
85
+ return real(token);
86
+ });
87
+ });
88
+ afterEach(() => sinon_1.default.restore());
89
+ describe('mayReleasePreviewHold', () => {
90
+ const idle = { sessionId: HOLD, h264Clients: 0, mjpegViewers: 0, recording: false };
91
+ it('allows a preview hold that nothing uses', () => {
92
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(idle)).to.equal(true);
93
+ });
94
+ it('keeps it while anyone watches, over either transport, or a recording runs', () => {
95
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(Object.assign(Object.assign({}, idle), { h264Clients: 1 }))).to.equal(false);
96
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(Object.assign(Object.assign({}, idle), { mjpegViewers: 1 }))).to.equal(false);
97
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(Object.assign(Object.assign({}, idle), { recording: true }))).to.equal(false);
98
+ });
99
+ it('never touches an Appium session, or a device nobody holds', () => {
100
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(Object.assign(Object.assign({}, idle), { sessionId: 'd4098122-appium' }))).to.equal(false);
101
+ (0, chai_1.expect)((0, previewHold_1.mayReleasePreviewHold)(Object.assign(Object.assign({}, idle), { sessionId: null }))).to.equal(false);
102
+ });
103
+ });
104
+ describe('releaseIdlePreviewHold', () => {
105
+ it('releases the hold when nothing uses the device', () => __awaiter(void 0, void 0, void 0, function* () {
106
+ (0, chai_1.expect)(yield (0, previewHold_1.releaseIdlePreviewHold)(UDID)).to.equal(true);
107
+ (0, chai_1.expect)(unblock.calledOnceWith(UDID, 'h')).to.equal(true);
108
+ }));
109
+ it('keeps the hold while an H.264 viewer, an MJPEG viewer or a recording remains', () => __awaiter(void 0, void 0, void 0, function* () {
110
+ for (const busy of [{ h264Clients: 1 }, { mjpegViewers: 1 }, { recording: true }]) {
111
+ Object.assign(use, { h264Clients: 0, mjpegViewers: 0, recording: false }, busy);
112
+ (0, chai_1.expect)(yield (0, previewHold_1.releaseIdlePreviewHold)(UDID), JSON.stringify(busy)).to.equal(false);
113
+ }
114
+ (0, chai_1.expect)(unblock.called).to.equal(false);
115
+ }));
116
+ });
117
+ // Before: the H.264 service stopped an unwatched stream after 10 minutes
118
+ // but left the hold, so with H.264 preview on, a closed tab's hold was
119
+ // never released by the server.
120
+ describe('H.264 idle stop', () => {
121
+ let clock;
122
+ beforeEach(() => {
123
+ clock = sinon_1.default.useFakeTimers({ now: Date.now(), toFake: ['setInterval', 'Date'] });
124
+ });
125
+ afterEach(() => clock.restore());
126
+ it('releases the hold once nobody has watched for 10 minutes', () => __awaiter(void 0, void 0, void 0, function* () {
127
+ const svc = new AndroidH264StreamService_1.default();
128
+ const kill = sinon_1.default.spy();
129
+ svc.sessions.set(UDID, { status: 'running', mux: { clientCount: 0 }, capture: { kill } });
130
+ yield clock.tickAsync(60000); // first sweep notes it is empty
131
+ yield clock.tickAsync(11 * 60000);
132
+ (0, chai_1.expect)(kill.called, 'capture stopped').to.equal(true);
133
+ (0, chai_1.expect)(unblock.calledOnceWith(UDID, 'h'), 'hold released').to.equal(true);
134
+ }));
135
+ it('keeps the hold if a recording holds the device', () => __awaiter(void 0, void 0, void 0, function* () {
136
+ use.recording = true;
137
+ const svc = new AndroidH264StreamService_1.default();
138
+ svc.sessions.set(UDID, {
139
+ status: 'running',
140
+ mux: { clientCount: 0 },
141
+ capture: { kill() { } },
142
+ });
143
+ yield clock.tickAsync(12 * 60000);
144
+ (0, chai_1.expect)(unblock.called).to.equal(false);
145
+ }));
146
+ });
147
+ describe('MJPEG stream', () => {
148
+ // Before: checked once an hour, so an abandoned hold lasted up to 70 minutes.
149
+ it('checks for an idle stream every minute', () => __awaiter(void 0, void 0, void 0, function* () {
150
+ const clock = sinon_1.default.useFakeTimers({ now: Date.now(), toFake: ['setInterval', 'Date'] });
151
+ try {
152
+ const svc = new AndroidStreamService_1.default();
153
+ const stop = sinon_1.default.stub(svc, 'stopStream').resolves();
154
+ svc.sessions.set(UDID, {
155
+ udid: UDID,
156
+ status: 'running',
157
+ viewerCount: 0,
158
+ lastViewerAt: Date.now() - 11 * 60000,
159
+ });
160
+ yield clock.tickAsync(60000);
161
+ (0, chai_1.expect)(stop.calledOnceWith(UDID)).to.equal(true);
162
+ }
163
+ finally {
164
+ clock.restore();
165
+ }
166
+ }));
167
+ // One hold covers both transports: stopping an idle MJPEG stream must not
168
+ // drop it under someone watching over H.264.
169
+ it('does not drop the hold on stop while an H.264 viewer remains', () => __awaiter(void 0, void 0, void 0, function* () {
170
+ use.h264Clients = 1;
171
+ const svc = Object.create(AndroidStreamService_1.default.prototype);
172
+ svc.sessions = new Map([
173
+ [UDID, { udid: UDID, status: 'running', server: null, viewerCount: 0, lastViewerAt: 0 }],
174
+ ]);
175
+ yield svc.stopStream(UDID);
176
+ (0, chai_1.expect)(unblock.called).to.equal(false);
177
+ }));
178
+ });
179
+ });
@@ -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
+ });
@@ -0,0 +1,107 @@
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 typedi_1 = require("typedi");
19
+ const HealthMonitorService_1 = require("../../src/device-managers/HealthMonitorService");
20
+ const device_managers_1 = require("../../src/device-managers");
21
+ const device_store_1 = require("../../src/data-service/device-store");
22
+ const SessionManager_1 = require("../../src/sessions/SessionManager");
23
+ const AndroidStreamService_1 = __importDefault(require("../../src/device-managers/android/AndroidStreamService"));
24
+ const IOSStreamService_1 = __importDefault(require("../../src/device-managers/ios/IOSStreamService"));
25
+ // Named like the real managers: the monitor picks one by constructor.name.
26
+ class AndroidDeviceManager {
27
+ constructor() {
28
+ this.checkHealth = () => __awaiter(this, void 0, void 0, function* () { return ({ healthStatus: 'Healthy' }); });
29
+ }
30
+ }
31
+ class IOSDeviceManager {
32
+ constructor() {
33
+ this.checkHealth = () => __awaiter(this, void 0, void 0, function* () { return ({ healthStatus: 'Healthy' }); });
34
+ }
35
+ }
36
+ // A device busy with an Appium session this process no longer knows about,
37
+ // which is the case the monitor reclaims, unless a stream is still running.
38
+ function lostSessionDevice(platform) {
39
+ return {
40
+ udid: `${platform}-1`,
41
+ host: 'http://127.0.0.1:4723',
42
+ platform,
43
+ busy: true,
44
+ session_id: 'appium-session-not-in-memory',
45
+ cloud: false,
46
+ };
47
+ }
48
+ describe('HealthMonitorService — stream lookups', () => {
49
+ let updateDevice;
50
+ let device;
51
+ let androidStatus;
52
+ let iosStatus;
53
+ const reclaimed = () => updateDevice.getCalls().some((c) => { var _a, _b; return ((_a = c.args[2]) === null || _a === void 0 ? void 0 : _a.busy) === false && !((_b = c.args[2]) === null || _b === void 0 ? void 0 : _b.session_id); });
54
+ beforeEach(() => {
55
+ sinon_1.default.stub(process, 'kill');
56
+ updateDevice = sinon_1.default.spy(() => __awaiter(void 0, void 0, void 0, function* () { return undefined; }));
57
+ sinon_1.default.stub(device_store_1.DeviceStoreFactory, 'getStore').returns({
58
+ getAllDevices: () => __awaiter(void 0, void 0, void 0, function* () { return [device]; }),
59
+ updateDevice,
60
+ });
61
+ sinon_1.default.stub(SessionManager_1.SESSION_MANAGER, 'isValidSession').returns(false);
62
+ androidStatus = sinon_1.default.stub().returns({ status: 'running' });
63
+ iosStatus = sinon_1.default.stub().returns({ status: 'running' });
64
+ const real = typedi_1.Container.get.bind(typedi_1.Container);
65
+ // Only the class tokens answer. TypeDI 0.10 ignores @Service({ name }), so
66
+ // a lookup by name falls through to the real container and throws, as it
67
+ // does in the server.
68
+ sinon_1.default.stub(typedi_1.Container, 'get').callsFake((token) => {
69
+ if (token === device_managers_1.XenonManager) {
70
+ return {
71
+ deviceInstances: () => __awaiter(void 0, void 0, void 0, function* () { return [new AndroidDeviceManager(), new IOSDeviceManager()]; }),
72
+ };
73
+ }
74
+ if (token === AndroidStreamService_1.default)
75
+ return { getStreamStatus: androidStatus };
76
+ if (token === IOSStreamService_1.default)
77
+ return { getStreamStatus: iosStatus };
78
+ return real(token);
79
+ });
80
+ });
81
+ afterEach(() => sinon_1.default.restore());
82
+ const run = () => new HealthMonitorService_1.HealthMonitorService({}).checkAllDevices();
83
+ it('leaves an Android device with a running stream alone', () => __awaiter(void 0, void 0, void 0, function* () {
84
+ device = lostSessionDevice('android');
85
+ yield run();
86
+ (0, chai_1.expect)(reclaimed(), 'reclaimed a device with a live stream').to.equal(false);
87
+ (0, chai_1.expect)(androidStatus.called, 'asked the stream service').to.equal(true);
88
+ }));
89
+ it('leaves an iOS device with a running stream alone', () => __awaiter(void 0, void 0, void 0, function* () {
90
+ device = lostSessionDevice('ios');
91
+ yield run();
92
+ (0, chai_1.expect)(reclaimed(), 'reclaimed a device with a live stream').to.equal(false);
93
+ (0, chai_1.expect)(iosStatus.called, 'asked the stream service').to.equal(true);
94
+ }));
95
+ it('cancels a reclaim when the stream appears before the final re-check', () => __awaiter(void 0, void 0, void 0, function* () {
96
+ device = lostSessionDevice('android');
97
+ androidStatus.onFirstCall().returns(undefined);
98
+ yield run();
99
+ (0, chai_1.expect)(reclaimed()).to.equal(false);
100
+ }));
101
+ it('still reclaims a device with no stream', () => __awaiter(void 0, void 0, void 0, function* () {
102
+ device = lostSessionDevice('android');
103
+ androidStatus.returns(undefined);
104
+ yield run();
105
+ (0, chai_1.expect)(reclaimed()).to.equal(true);
106
+ }));
107
+ });
@@ -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/previewHold.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-preview-hold.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/health-monitor-stream-lookup.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.28.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": {