@xenon-device-management/xenon 1.17.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/package.json +1 -1
- package/lib/src/XenonCapabilityManager.js +30 -6
- package/lib/src/device-managers/ios/IOSDiscoveryService.js +31 -4
- package/lib/src/services/PortAllocator.js +27 -0
- package/lib/test/unit/port-exhaustion.spec.js +205 -0
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
package/lib/package.json
CHANGED
|
@@ -56,6 +56,7 @@ exports.getXenonCapabilities = getXenonCapabilities;
|
|
|
56
56
|
const get_port_1 = __importDefault(require("get-port"));
|
|
57
57
|
const lodash_1 = __importDefault(require("lodash"));
|
|
58
58
|
const typedi_1 = require("typedi");
|
|
59
|
+
const PortAllocator_1 = require("./services/PortAllocator");
|
|
59
60
|
const logger_1 = __importDefault(require("./logger"));
|
|
60
61
|
var XENON_CAPABILITIES;
|
|
61
62
|
(function (XENON_CAPABILITIES) {
|
|
@@ -128,18 +129,19 @@ function androidCapabilities(caps, freeDevice) {
|
|
|
128
129
|
}
|
|
129
130
|
function iOSCapabilities(caps, freeDevice) {
|
|
130
131
|
return __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
var _a, _b;
|
|
131
133
|
const fm = ensureFirstMatch(caps);
|
|
132
134
|
fm['appium:udid'] = freeDevice.udid;
|
|
133
135
|
fm['platformName'] = freeDevice.platform;
|
|
134
136
|
fm['appium:deviceName'] = freeDevice.name;
|
|
135
137
|
fm['appium:platformVersion'] = freeDevice.sdk;
|
|
136
|
-
if (!fm['appium:wdaLocalPort']) {
|
|
137
|
-
fm['appium:wdaLocalPort'] = freeDevice.wdaLocalPort;
|
|
138
|
-
}
|
|
139
|
-
if (!fm['appium:mjpegServerPort']) {
|
|
140
|
-
fm['appium:mjpegServerPort'] = freeDevice.mjpegServerPort;
|
|
141
|
-
}
|
|
142
138
|
fm['appium:derivedDataPath'] = freeDevice.derivedDataPath;
|
|
139
|
+
// Whether this session will stand up its own WebDriverAgent, or ride the one
|
|
140
|
+
// the stream service already has. Decided before any port is assigned: a
|
|
141
|
+
// session that reuses the stream's WDA must not be handed ports, and
|
|
142
|
+
// acquiring them first only to delete them below would burn a lease out of a
|
|
143
|
+
// hundred on every such session.
|
|
144
|
+
let reusingStreamWda = false;
|
|
143
145
|
// Technical Optimization: Reuse existing WDA tunnel if Stream Service is active
|
|
144
146
|
// This prevents "Port Occupied" errors when the dashboard is open and speeds up startup by 15-30s
|
|
145
147
|
try {
|
|
@@ -150,6 +152,7 @@ function iOSCapabilities(caps, freeDevice) {
|
|
|
150
152
|
if (streamStatus && (streamStatus.status === 'running' || streamStatus.status === 'starting')) {
|
|
151
153
|
const wdaUrl = `http://127.0.0.1:${streamStatus.wdaPort}`;
|
|
152
154
|
fm['appium:webDriverAgentUrl'] = wdaUrl;
|
|
155
|
+
reusingStreamWda = true;
|
|
153
156
|
// If we are reusing the WDA, we MUST NOT pass wdaLocalPort or mjpegServerPort
|
|
154
157
|
// as XCUITestDriver will still try to verify they are free and fail if busy.
|
|
155
158
|
delete fm['appium:wdaLocalPort'];
|
|
@@ -164,6 +167,27 @@ function iOSCapabilities(caps, freeDevice) {
|
|
|
164
167
|
catch (e) {
|
|
165
168
|
logger_1.default.warn(`[Xenon] ⚠️ Failed to check Stream Service: ${e.message}`);
|
|
166
169
|
}
|
|
170
|
+
// Ports, at the one moment we know they are needed and by which device.
|
|
171
|
+
//
|
|
172
|
+
// Discovery no longer leases one to every simulator on the machine — it
|
|
173
|
+
// cannot, there are more simulators than ports — so the device picked for
|
|
174
|
+
// this session may arrive without one. Acquiring here is deliberate: it is
|
|
175
|
+
// the first point at which a specific device has been chosen.
|
|
176
|
+
//
|
|
177
|
+
// Exhaustion raises rather than passing undefined through. Without a port
|
|
178
|
+
// XCUITest falls back to its own default of 8100, which is the same number
|
|
179
|
+
// for every device, so a silent skip trades a clear failure for two sessions
|
|
180
|
+
// quietly fighting over one port.
|
|
181
|
+
if (!reusingStreamWda) {
|
|
182
|
+
if (!fm['appium:wdaLocalPort']) {
|
|
183
|
+
fm['appium:wdaLocalPort'] =
|
|
184
|
+
(_a = freeDevice.wdaLocalPort) !== null && _a !== void 0 ? _a : (yield typedi_1.Container.get(PortAllocator_1.PortAllocator).acquire('wda', freeDevice.udid));
|
|
185
|
+
}
|
|
186
|
+
if (!fm['appium:mjpegServerPort']) {
|
|
187
|
+
fm['appium:mjpegServerPort'] =
|
|
188
|
+
(_b = freeDevice.mjpegServerPort) !== null && _b !== void 0 ? _b : (yield typedi_1.Container.get(PortAllocator_1.PortAllocator).acquire('mjpeg', freeDevice.udid));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
167
191
|
// Senior Resiliency: Inject higher defaults for WebDriverAgent in enterprise environments
|
|
168
192
|
if (!isCapabilityAlreadyPresent(caps, 'appium:wdaLaunchTimeout')) {
|
|
169
193
|
// 180s is safer for physical devices that might need WDA signing/installation
|
|
@@ -55,6 +55,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
55
55
|
};
|
|
56
56
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
57
57
|
exports.IOSDiscoveryService = void 0;
|
|
58
|
+
exports.simulatorNeedsPortNow = simulatorNeedsPortNow;
|
|
58
59
|
const node_simctl_1 = __importDefault(require("node-simctl"));
|
|
59
60
|
const lodash_1 = require("lodash");
|
|
60
61
|
const appium_ios_device_1 = require("appium-ios-device");
|
|
@@ -73,6 +74,23 @@ const config_1 = require("../../config");
|
|
|
73
74
|
const device_service_1 = require("../../data-service/device-service");
|
|
74
75
|
const iOSTracker_1 = require("../iOSTracker");
|
|
75
76
|
const networkAddresses_1 = require("../../helpers/networkAddresses");
|
|
77
|
+
/**
|
|
78
|
+
* Should this simulator be given wda/mjpeg ports the moment we notice it?
|
|
79
|
+
*
|
|
80
|
+
* Every simulator installed on the machine is discovered, booted or not, and a
|
|
81
|
+
* Mac carries far more of them than the port ranges hold — 158 against 100
|
|
82
|
+
* where this surfaced. A shut-down simulator is not running WebDriverAgent and
|
|
83
|
+
* will not until someone boots it, so it gets nothing here; `iOSCapabilities`
|
|
84
|
+
* acquires a port at session time for whichever device is actually chosen.
|
|
85
|
+
*
|
|
86
|
+
* Draining the range did not merely waste ports. Discovery threw once it ran
|
|
87
|
+
* dry, so IOSDeviceManager returned no devices at all, and the physically
|
|
88
|
+
* attached iPhone on the same Mac was reaped as stale for not being in its own
|
|
89
|
+
* device list.
|
|
90
|
+
*/
|
|
91
|
+
function simulatorNeedsPortNow(state) {
|
|
92
|
+
return state === 'Booted';
|
|
93
|
+
}
|
|
76
94
|
let IOSDiscoveryService = class IOSDiscoveryService {
|
|
77
95
|
constructor(context) {
|
|
78
96
|
this.context = context;
|
|
@@ -160,8 +178,11 @@ let IOSDiscoveryService = class IOSDiscoveryService {
|
|
|
160
178
|
const host = this.pluginArgs.remoteMachineProxyIP
|
|
161
179
|
? String(this.pluginArgs.remoteMachineProxyIP)
|
|
162
180
|
: `http://${this.pluginArgs.bindHostOrIp}:${this.hostPort}`;
|
|
163
|
-
|
|
164
|
-
|
|
181
|
+
// A real device is going to want these, so ask now — but not at the cost
|
|
182
|
+
// of the whole discovery pass. See tryAcquire: an exhausted range used to
|
|
183
|
+
// throw out of here and take the device list with it.
|
|
184
|
+
const wdaLocalPort = (storeDevice === null || storeDevice === void 0 ? void 0 : storeDevice.wdaLocalPort) || (yield typedi_1.Container.get(PortAllocator_1.PortAllocator).tryAcquire('wda', udid));
|
|
185
|
+
const mjpegServerPort = (storeDevice === null || storeDevice === void 0 ? void 0 : storeDevice.mjpegServerPort) || (yield typedi_1.Container.get(PortAllocator_1.PortAllocator).tryAcquire('mjpeg', udid));
|
|
165
186
|
const totalUtilizationTimeMilliSec = yield (0, device_utils_1.getUtilizationTime)(udid);
|
|
166
187
|
let sdk = 'Unknown';
|
|
167
188
|
let name = 'iPhone';
|
|
@@ -229,8 +250,14 @@ let IOSDiscoveryService = class IOSDiscoveryService {
|
|
|
229
250
|
return yield Promise.all(simulators.map((d) => __awaiter(this, void 0, void 0, function* () {
|
|
230
251
|
var _a;
|
|
231
252
|
const storeDevice = yield store.findDevice({ udid: d.udid });
|
|
232
|
-
|
|
233
|
-
|
|
253
|
+
const willRunWda = simulatorNeedsPortNow(d.state);
|
|
254
|
+
return Object.assign(Object.assign({}, d), { wdaLocalPort: (storeDevice === null || storeDevice === void 0 ? void 0 : storeDevice.wdaLocalPort) ||
|
|
255
|
+
(willRunWda
|
|
256
|
+
? yield typedi_1.Container.get(PortAllocator_1.PortAllocator).tryAcquire('wda', d.udid)
|
|
257
|
+
: undefined), mjpegServerPort: (storeDevice === null || storeDevice === void 0 ? void 0 : storeDevice.mjpegServerPort) ||
|
|
258
|
+
(willRunWda
|
|
259
|
+
? yield typedi_1.Container.get(PortAllocator_1.PortAllocator).tryAcquire('mjpeg', d.udid)
|
|
260
|
+
: undefined), busy: false, realDevice: false, platform: (((_a = d.name) === null || _a === void 0 ? void 0 : _a.toLowerCase().includes('tv')) ? 'tvos' : 'ios'), deviceType: 'simulator', host: `http://${this.pluginArgs.bindHostOrIp}:${this.hostPort}`, ip: nodeLanIp, totalUtilizationTimeMilliSec: yield (0, device_utils_1.getUtilizationTime)(d.udid), sessionStartTime: 0 });
|
|
234
261
|
})));
|
|
235
262
|
});
|
|
236
263
|
}
|
|
@@ -111,6 +111,33 @@ let PortAllocator = class PortAllocator {
|
|
|
111
111
|
throw new PortRangeExhaustedError(purpose);
|
|
112
112
|
});
|
|
113
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* `acquire`, but exhaustion is `undefined` rather than a throw.
|
|
116
|
+
*
|
|
117
|
+
* For callers where a port is nice-to-have rather than required — device
|
|
118
|
+
* discovery being the one that matters. A device that cannot get a port yet
|
|
119
|
+
* is still a device, and must still be listed: when an exhausted range threw
|
|
120
|
+
* out of the discovery pass, the whole platform's device list came back
|
|
121
|
+
* empty and `removeStaleDevices` then deleted a physically-attached iPhone
|
|
122
|
+
* for not being in it.
|
|
123
|
+
*
|
|
124
|
+
* Only exhaustion is swallowed. A database or probe failure is a different
|
|
125
|
+
* kind of problem and still raises.
|
|
126
|
+
*/
|
|
127
|
+
tryAcquire(purpose_1, udid_1) {
|
|
128
|
+
return __awaiter(this, arguments, void 0, function* (purpose, udid, opts = {}) {
|
|
129
|
+
try {
|
|
130
|
+
return yield this.acquire(purpose, udid, opts);
|
|
131
|
+
}
|
|
132
|
+
catch (err) {
|
|
133
|
+
if (err instanceof PortRangeExhaustedError) {
|
|
134
|
+
this.log.warn(`No ${purpose} port available for ${udid}; continuing without one. It will be acquired when the device actually needs it.`);
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
114
141
|
/**
|
|
115
142
|
* Soft-block a port so the next `acquire` for the same purpose skips it.
|
|
116
143
|
* Used when bind fails (EADDRINUSE) even though our lease owned the number —
|
|
@@ -0,0 +1,205 @@
|
|
|
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 PortAllocator_1 = require("../../src/services/PortAllocator");
|
|
52
|
+
const IOSDiscoveryService_1 = require("../../src/device-managers/ios/IOSDiscoveryService");
|
|
53
|
+
const XenonCapabilityManager_1 = require("../../src/XenonCapabilityManager");
|
|
54
|
+
const typedi_1 = require("typedi");
|
|
55
|
+
const prisma_1 = require("../../src/prisma");
|
|
56
|
+
/**
|
|
57
|
+
* A Mac carries far more simulators than these ranges hold — 158 against 100
|
|
58
|
+
* where this surfaced. Discovery leased a wda and an mjpeg port to every one
|
|
59
|
+
* of them, drained both ranges, and then threw; IOSDeviceManager returned no
|
|
60
|
+
* devices at all, and the physically-attached iPhone on the same Mac was
|
|
61
|
+
* reaped as stale for not appearing in its own device list.
|
|
62
|
+
*/
|
|
63
|
+
describe('port exhaustion during iOS discovery', () => {
|
|
64
|
+
beforeEach(() => {
|
|
65
|
+
sinon_1.default.stub(prisma_1.prisma.portLease, 'findMany').resolves([]);
|
|
66
|
+
sinon_1.default.stub(prisma_1.prisma.portLease, 'findFirst').resolves(null);
|
|
67
|
+
sinon_1.default.stub(prisma_1.prisma.portLease, 'deleteMany').resolves({ count: 0 });
|
|
68
|
+
sinon_1.default.stub(prisma_1.prisma.portLease, 'delete').resolves({});
|
|
69
|
+
sinon_1.default.stub(prisma_1.prisma.portLease, 'update').resolves({});
|
|
70
|
+
});
|
|
71
|
+
afterEach(() => sinon_1.default.restore());
|
|
72
|
+
function exhaustedAllocator() {
|
|
73
|
+
const a = new PortAllocator_1.PortAllocator();
|
|
74
|
+
a.configure({ wda: [8100, 8101] });
|
|
75
|
+
// Every port in the range already leased to somebody else.
|
|
76
|
+
prisma_1.prisma.portLease.findMany.resolves([{ port: 8100 }, { port: 8101 }]);
|
|
77
|
+
return a;
|
|
78
|
+
}
|
|
79
|
+
it('acquire still raises when the range is exhausted', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
80
|
+
// The strict form is unchanged — callers that genuinely need a port must
|
|
81
|
+
// still hear about it.
|
|
82
|
+
let err;
|
|
83
|
+
yield exhaustedAllocator()
|
|
84
|
+
.acquire('wda', 'udid-1')
|
|
85
|
+
.catch((e) => (err = e));
|
|
86
|
+
(0, chai_1.expect)(err).to.be.instanceOf(PortAllocator_1.PortRangeExhaustedError);
|
|
87
|
+
}));
|
|
88
|
+
it('tryAcquire reports exhaustion as undefined instead', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
89
|
+
(0, chai_1.expect)(yield exhaustedAllocator().tryAcquire('wda', 'udid-1')).to.equal(undefined);
|
|
90
|
+
}));
|
|
91
|
+
it('tryAcquire does not swallow a failure that is not exhaustion', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
92
|
+
// A database or probe failure is a different problem and must not be
|
|
93
|
+
// quietly turned into "no port available".
|
|
94
|
+
const a = new PortAllocator_1.PortAllocator();
|
|
95
|
+
a.configure({ wda: [8100, 8101] });
|
|
96
|
+
prisma_1.prisma.portLease.findMany.rejects(new Error('database is locked'));
|
|
97
|
+
let message = '';
|
|
98
|
+
yield a.tryAcquire('wda', 'udid-1').catch((e) => (message = e.message));
|
|
99
|
+
(0, chai_1.expect)(message).to.equal('database is locked');
|
|
100
|
+
}));
|
|
101
|
+
it('one device exhausting the range does not stop the next from being listed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
102
|
+
// The behaviour that matters: discovery maps over devices, and the pass
|
|
103
|
+
// has to survive a device that cannot get a port.
|
|
104
|
+
const a = exhaustedAllocator();
|
|
105
|
+
const discovered = yield Promise.all(['sim-1', 'sim-2', 'iphone'].map((udid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
106
|
+
return ({
|
|
107
|
+
udid,
|
|
108
|
+
wdaLocalPort: yield a.tryAcquire('wda', udid),
|
|
109
|
+
});
|
|
110
|
+
})));
|
|
111
|
+
(0, chai_1.expect)(discovered.map((d) => d.udid)).to.deep.equal(['sim-1', 'sim-2', 'iphone']);
|
|
112
|
+
(0, chai_1.expect)(discovered.every((d) => d.wdaLocalPort === undefined)).to.equal(true);
|
|
113
|
+
}));
|
|
114
|
+
});
|
|
115
|
+
/**
|
|
116
|
+
* The other half: not needing the ports in the first place. A shut-down
|
|
117
|
+
* simulator is not running WebDriverAgent and will not until someone boots it.
|
|
118
|
+
*/
|
|
119
|
+
describe('who gets a port at discovery time', () => {
|
|
120
|
+
const acquiredFor = [];
|
|
121
|
+
const allocator = {
|
|
122
|
+
tryAcquire: (_purpose, udid) => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
+
acquiredFor.push(udid);
|
|
124
|
+
return 8100 + acquiredFor.length;
|
|
125
|
+
}),
|
|
126
|
+
};
|
|
127
|
+
// The real predicate from the discovery service, not a copy of it — a
|
|
128
|
+
// restatement here would keep passing after the rule changed.
|
|
129
|
+
function portFor(sim) {
|
|
130
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
+
return (sim.stored ||
|
|
132
|
+
((0, IOSDiscoveryService_1.simulatorNeedsPortNow)(sim.state) ? yield allocator.tryAcquire('wda', sim.udid) : undefined));
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
beforeEach(() => (acquiredFor.length = 0));
|
|
136
|
+
it('leases to a booted simulator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
137
|
+
(0, chai_1.expect)(yield portFor({ udid: 'booted-1', state: 'Booted' })).to.be.a('number');
|
|
138
|
+
(0, chai_1.expect)(acquiredFor).to.deep.equal(['booted-1']);
|
|
139
|
+
}));
|
|
140
|
+
it('leases nothing to a shut-down simulator', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
141
|
+
(0, chai_1.expect)(yield portFor({ udid: 'off-1', state: 'Shutdown' })).to.equal(undefined);
|
|
142
|
+
(0, chai_1.expect)(acquiredFor).to.deep.equal([]);
|
|
143
|
+
}));
|
|
144
|
+
it('keeps a port the device already has, whatever its state', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
145
|
+
(0, chai_1.expect)(yield portFor({ udid: 'off-2', state: 'Shutdown', stored: 8137 })).to.equal(8137);
|
|
146
|
+
(0, chai_1.expect)(acquiredFor).to.deep.equal([]);
|
|
147
|
+
}));
|
|
148
|
+
it('does not drain the range across a machine full of idle simulators', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
149
|
+
const sims = Array.from({ length: 158 }, (_, i) => ({ udid: `sim-${i}`, state: 'Shutdown' }));
|
|
150
|
+
yield Promise.all(sims.map(portFor));
|
|
151
|
+
(0, chai_1.expect)(acquiredFor.length).to.equal(0);
|
|
152
|
+
}));
|
|
153
|
+
});
|
|
154
|
+
/**
|
|
155
|
+
* Discovery no longer hands a port to every simulator, so the device chosen
|
|
156
|
+
* for a session can arrive without one. This is where it gets one.
|
|
157
|
+
*/
|
|
158
|
+
describe('iOSCapabilities port acquisition', () => {
|
|
159
|
+
const device = {
|
|
160
|
+
udid: 'sim-1',
|
|
161
|
+
name: 'iPhone 15',
|
|
162
|
+
realDevice: false,
|
|
163
|
+
sdk: '17.5',
|
|
164
|
+
platform: 'ios',
|
|
165
|
+
};
|
|
166
|
+
let acquireStub;
|
|
167
|
+
beforeEach(() => {
|
|
168
|
+
acquireStub = sinon_1.default.stub(PortAllocator_1.PortAllocator.prototype, 'acquire');
|
|
169
|
+
acquireStub.withArgs('wda').resolves(8123);
|
|
170
|
+
acquireStub.withArgs('mjpeg').resolves(9123);
|
|
171
|
+
});
|
|
172
|
+
afterEach(() => sinon_1.default.restore());
|
|
173
|
+
it('acquires when the chosen device arrived without ports', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
174
|
+
const caps = { alwaysMatch: {}, firstMatch: [{}] };
|
|
175
|
+
yield (0, XenonCapabilityManager_1.iOSCapabilities)(caps, device);
|
|
176
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:wdaLocalPort']).to.equal(8123);
|
|
177
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:mjpegServerPort']).to.equal(9123);
|
|
178
|
+
}));
|
|
179
|
+
it('uses the port the device already holds rather than taking another', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
180
|
+
const caps = { alwaysMatch: {}, firstMatch: [{}] };
|
|
181
|
+
yield (0, XenonCapabilityManager_1.iOSCapabilities)(caps, Object.assign(Object.assign({}, device), { wdaLocalPort: 8150, mjpegServerPort: 9150 }));
|
|
182
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:wdaLocalPort']).to.equal(8150);
|
|
183
|
+
(0, chai_1.expect)(acquireStub.calledWith('wda')).to.equal(false);
|
|
184
|
+
}));
|
|
185
|
+
it('leaves a caller-supplied port alone', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
186
|
+
const caps = { alwaysMatch: {}, firstMatch: [{ 'appium:wdaLocalPort': 8199 }] };
|
|
187
|
+
yield (0, XenonCapabilityManager_1.iOSCapabilities)(caps, device);
|
|
188
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:wdaLocalPort']).to.equal(8199);
|
|
189
|
+
(0, chai_1.expect)(acquireStub.calledWith('wda')).to.equal(false);
|
|
190
|
+
}));
|
|
191
|
+
it('takes no lease at all when the session will reuse the stream service WDA', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
192
|
+
// That branch deletes both ports a few lines later. Acquiring first would
|
|
193
|
+
// burn one out of a hundred on every session opened while the dashboard
|
|
194
|
+
// has a preview up — the exact pressure this change exists to relieve.
|
|
195
|
+
const { default: IOSStreamService } = yield Promise.resolve().then(() => __importStar(require('../../src/device-managers/ios/IOSStreamService')));
|
|
196
|
+
sinon_1.default
|
|
197
|
+
.stub(typedi_1.Container.get(IOSStreamService), 'getStreamStatus')
|
|
198
|
+
.returns({ status: 'running', wdaPort: 8100 });
|
|
199
|
+
const caps = { alwaysMatch: {}, firstMatch: [{}] };
|
|
200
|
+
yield (0, XenonCapabilityManager_1.iOSCapabilities)(caps, device);
|
|
201
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:webDriverAgentUrl']).to.equal('http://127.0.0.1:8100');
|
|
202
|
+
(0, chai_1.expect)(caps.firstMatch[0]['appium:wdaLocalPort']).to.equal(undefined);
|
|
203
|
+
(0, chai_1.expect)(acquireStub.called).to.equal(false);
|
|
204
|
+
}));
|
|
205
|
+
});
|
package/lib/tsconfig.tsbuildinfo
CHANGED
|
@@ -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/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/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/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/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/IOSStreamService.ts","../src/device-managers/ios/WDAClient.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/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/logcatParse.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/annotation-render.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/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/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/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.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-render.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/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-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/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/package-resolver.spec.ts","../test/unit/plugin.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-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/remux-to-standard-mp4.spec.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-ticket-identity.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/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/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/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/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/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/IOSStreamService.ts","../src/device-managers/ios/WDAClient.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/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/logcatParse.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/annotation-render.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/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/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/aggregate-hotspots-tuple-key.spec.ts","../test/unit/android-h264-config.spec.ts","../test/unit/android-h264-service.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-render.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/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-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/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/package-resolver.spec.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-source-ended.spec.ts","../test/unit/recording-store.spec.ts","../test/unit/remux-to-standard-mp4.spec.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-ticket-identity.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/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