@houwert/conductor 0.8.0 → 0.10.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.
- package/dist/daemon/server.js +49 -0
- package/dist/drivers/bootstrap.js +180 -22
- package/package.json +1 -2
- package/skills/conductor/SKILL.md +1 -1
- package/skills/skills.yaml +1 -1
- package/drivers/android/conductor-app.apk +0 -0
- package/drivers/android/conductor-server.apk +0 -0
- package/drivers/ios/conductor-driver-ios-config.xctestrun +0 -126
- package/drivers/ios/conductor-driver-ios.zip +0 -0
- package/drivers/ios/conductor-driver-iosUITests-Runner.zip +0 -0
- package/drivers/tvos/conductor-driver-tvos-config.xctestrun +0 -121
- package/drivers/tvos/conductor-driver-tvos.zip +0 -0
- package/drivers/tvos/conductor-driver-tvosUITests-Runner.zip +0 -0
package/dist/daemon/server.js
CHANGED
|
@@ -41,6 +41,26 @@ const cdpUrl = process.env.CONDUCTOR_CDP_URL || undefined;
|
|
|
41
41
|
* URL heuristics.
|
|
42
42
|
*/
|
|
43
43
|
const cdpTargetId = process.env.CONDUCTOR_CDP_TARGET_ID || undefined;
|
|
44
|
+
/**
|
|
45
|
+
* PID of the process that should be considered the daemon's "owner". When set,
|
|
46
|
+
* the daemon polls for this process's existence and shuts down cleanly when it
|
|
47
|
+
* disappears. This prevents orphaned daemons (and their Playwright browsers)
|
|
48
|
+
* from piling up after the host app crashes or quits without calling
|
|
49
|
+
* `daemon-stop`.
|
|
50
|
+
*
|
|
51
|
+
* The daemon runs detached, so `process.ppid` becomes 1 after the parent exits
|
|
52
|
+
* and is useless for this purpose. The owner must be passed explicitly by the
|
|
53
|
+
* host app via the env when it invokes `conductor daemon-start` (or whatever
|
|
54
|
+
* code path ultimately triggers the daemon spawn).
|
|
55
|
+
*/
|
|
56
|
+
const parentPid = (() => {
|
|
57
|
+
const raw = process.env.CONDUCTOR_PARENT_PID;
|
|
58
|
+
if (!raw)
|
|
59
|
+
return undefined;
|
|
60
|
+
const n = parseInt(raw, 10);
|
|
61
|
+
return Number.isFinite(n) && n > 0 ? n : undefined;
|
|
62
|
+
})();
|
|
63
|
+
const PARENT_POLL_INTERVAL_MS = 10000;
|
|
44
64
|
const SOCKET_PATH = (0, protocol_js_1.socketPath)(sessionName);
|
|
45
65
|
const PID_FILE = (0, protocol_js_1.pidFile)(sessionName);
|
|
46
66
|
const LOG_FILE = (0, protocol_js_1.logFile)(sessionName);
|
|
@@ -123,6 +143,7 @@ async function main() {
|
|
|
123
143
|
}
|
|
124
144
|
let idleTimer;
|
|
125
145
|
let healthTimer;
|
|
146
|
+
let parentWatchTimer;
|
|
126
147
|
const idleTimeoutMs = Number(process.env.CONDUCTOR_IDLE_TIMEOUT_MS) || protocol_js_1.IDLE_TIMEOUT_MS;
|
|
127
148
|
function resetIdleTimer() {
|
|
128
149
|
if (idleTimer)
|
|
@@ -135,6 +156,10 @@ async function main() {
|
|
|
135
156
|
async function cleanup() {
|
|
136
157
|
if (healthTimer)
|
|
137
158
|
clearInterval(healthTimer);
|
|
159
|
+
if (parentWatchTimer)
|
|
160
|
+
clearInterval(parentWatchTimer);
|
|
161
|
+
if (idleTimer)
|
|
162
|
+
clearTimeout(idleTimer);
|
|
138
163
|
if (logCollector) {
|
|
139
164
|
logCollector.stop();
|
|
140
165
|
logCollector = null;
|
|
@@ -215,6 +240,30 @@ async function main() {
|
|
|
215
240
|
}, DRIVER_HEALTH_INTERVAL_MS);
|
|
216
241
|
healthTimer.unref(); // Don't keep the process alive just for health checks
|
|
217
242
|
}
|
|
243
|
+
// If the host app told us who it is, shut down when it disappears. This is
|
|
244
|
+
// the primary defence against orphaned daemons + headless Chromiums when the
|
|
245
|
+
// host app crashes or force-quits without calling daemon-stop.
|
|
246
|
+
if (parentPid !== undefined) {
|
|
247
|
+
dlog(`Watching parent pid ${parentPid}`);
|
|
248
|
+
let shuttingDown = false;
|
|
249
|
+
parentWatchTimer = setInterval(() => {
|
|
250
|
+
if (shuttingDown)
|
|
251
|
+
return;
|
|
252
|
+
try {
|
|
253
|
+
process.kill(parentPid, 0);
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
const code = err.code;
|
|
257
|
+
if (code === 'ESRCH') {
|
|
258
|
+
shuttingDown = true;
|
|
259
|
+
dlog(`Parent pid ${parentPid} exited — shutting down`);
|
|
260
|
+
cleanup().then(() => process.exit(0));
|
|
261
|
+
}
|
|
262
|
+
// EPERM means the process exists but we can't signal it — still alive.
|
|
263
|
+
}
|
|
264
|
+
}, PARENT_POLL_INTERVAL_MS);
|
|
265
|
+
parentWatchTimer.unref();
|
|
266
|
+
}
|
|
218
267
|
// ── HTTP server on Unix socket ─────────────────────────────────────────────
|
|
219
268
|
// Replaces the old raw-TCP accept-and-close with a proper HTTP server so we
|
|
220
269
|
// can serve /status (aliveness) and /logs (buffered log entries).
|
|
@@ -35,6 +35,7 @@ exports.uninstallDriver = uninstallDriver;
|
|
|
35
35
|
const child_process_1 = require("child_process");
|
|
36
36
|
const crypto_1 = __importDefault(require("crypto"));
|
|
37
37
|
const http_1 = __importDefault(require("http"));
|
|
38
|
+
const https_1 = __importDefault(require("https"));
|
|
38
39
|
const net_1 = __importDefault(require("net"));
|
|
39
40
|
const os_1 = __importDefault(require("os"));
|
|
40
41
|
const fs_1 = __importDefault(require("fs"));
|
|
@@ -161,40 +162,195 @@ async function getDriverPort(platform, deviceId) {
|
|
|
161
162
|
return port;
|
|
162
163
|
});
|
|
163
164
|
}
|
|
164
|
-
// ──
|
|
165
|
+
// ── Driver paths (bundled dev fallback + runtime download cache) ──────────────
|
|
165
166
|
/**
|
|
166
|
-
* Root of the bundled drivers directory (packages/cli/drivers/).
|
|
167
|
-
*
|
|
168
167
|
* Walk up from __dirname to find the package root (the directory containing
|
|
169
|
-
* package.json).
|
|
170
|
-
* and the test build (dist-tests/src/drivers/bootstrap.js) where __dirname
|
|
171
|
-
* an extra src/ level
|
|
168
|
+
* package.json). Handles both the normal build (dist/drivers/bootstrap.js)
|
|
169
|
+
* and the test build (dist-tests/src/drivers/bootstrap.js) where __dirname
|
|
170
|
+
* has an extra src/ level.
|
|
172
171
|
*/
|
|
173
|
-
function
|
|
172
|
+
function findPackageRoot() {
|
|
174
173
|
let dir = __dirname;
|
|
175
174
|
while (true) {
|
|
176
175
|
if (fs_1.default.existsSync(path_1.default.join(dir, 'package.json'))) {
|
|
177
|
-
return
|
|
176
|
+
return dir;
|
|
178
177
|
}
|
|
179
178
|
const parent = path_1.default.dirname(dir);
|
|
180
179
|
if (parent === dir)
|
|
181
180
|
break;
|
|
182
181
|
dir = parent;
|
|
183
182
|
}
|
|
184
|
-
|
|
185
|
-
|
|
183
|
+
return path_1.default.join(__dirname, '..', '..');
|
|
184
|
+
}
|
|
185
|
+
const DRIVERS_CACHE_ROOT = path_1.default.join(os_1.default.homedir(), '.conductor', 'drivers');
|
|
186
|
+
const DRIVERS_DOWNLOAD_BASE = 'https://github.com/DouweBos/conductor/releases/download';
|
|
187
|
+
const DRIVERS_LOCK_TIMEOUT_MS = 10 * 60 * 1000; // 10 minutes (download can be slow)
|
|
188
|
+
const DRIVERS_LOCK_POLL_MS = 500;
|
|
189
|
+
let _driversDirPromise = null;
|
|
190
|
+
/**
|
|
191
|
+
* Resolve the directory containing the platform driver artifacts
|
|
192
|
+
* (`<dir>/{android,ios,tvos}/...`).
|
|
193
|
+
*
|
|
194
|
+
* Lookup order:
|
|
195
|
+
* 1. Legacy bundled drivers at `<pkg-root>/drivers/` — populated by
|
|
196
|
+
* `make build` for local development.
|
|
197
|
+
* 2. Runtime cache at `~/.conductor/drivers/<version>/` — downloaded
|
|
198
|
+
* on first use from the matching GitHub Release.
|
|
199
|
+
*/
|
|
200
|
+
async function getDriversDir() {
|
|
201
|
+
if (_driversDirPromise)
|
|
202
|
+
return _driversDirPromise;
|
|
203
|
+
_driversDirPromise = (async () => {
|
|
204
|
+
const pkgRoot = findPackageRoot();
|
|
205
|
+
const legacyDir = path_1.default.join(pkgRoot, 'drivers');
|
|
206
|
+
if (fs_1.default.existsSync(legacyDir))
|
|
207
|
+
return legacyDir;
|
|
208
|
+
return await ensureDriversCache(pkgRoot);
|
|
209
|
+
})().catch((err) => {
|
|
210
|
+
_driversDirPromise = null;
|
|
211
|
+
throw err;
|
|
212
|
+
});
|
|
213
|
+
return _driversDirPromise;
|
|
214
|
+
}
|
|
215
|
+
async function ensureDriversCache(pkgRoot) {
|
|
216
|
+
const pkgJsonPath = path_1.default.join(pkgRoot, 'package.json');
|
|
217
|
+
const pkg = JSON.parse(fs_1.default.readFileSync(pkgJsonPath, 'utf-8'));
|
|
218
|
+
const version = pkg.version;
|
|
219
|
+
const cacheDir = path_1.default.join(DRIVERS_CACHE_ROOT, version);
|
|
220
|
+
const completeMarker = path_1.default.join(cacheDir, '.complete');
|
|
221
|
+
if (fs_1.default.existsSync(completeMarker))
|
|
222
|
+
return cacheDir;
|
|
223
|
+
fs_1.default.mkdirSync(DRIVERS_CACHE_ROOT, { recursive: true });
|
|
224
|
+
const lockFile = path_1.default.join(DRIVERS_CACHE_ROOT, `${version}.lock`);
|
|
225
|
+
await acquireDriversLock(lockFile);
|
|
226
|
+
try {
|
|
227
|
+
// Re-check after acquiring lock — another process may have finished.
|
|
228
|
+
if (fs_1.default.existsSync(completeMarker))
|
|
229
|
+
return cacheDir;
|
|
230
|
+
const tmpDir = path_1.default.join(DRIVERS_CACHE_ROOT, `.tmp-${version}-${process.pid}-${Date.now()}`);
|
|
231
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
232
|
+
fs_1.default.mkdirSync(tmpDir, { recursive: true });
|
|
233
|
+
const tarball = path_1.default.join(tmpDir, 'drivers.tar.gz');
|
|
234
|
+
const url = `${DRIVERS_DOWNLOAD_BASE}/v${version}/drivers.tar.gz`;
|
|
235
|
+
(0, verbose_js_1.log)(`Downloading conductor drivers v${version} from ${url}...`);
|
|
236
|
+
try {
|
|
237
|
+
await downloadToFile(url, tarball);
|
|
238
|
+
(0, child_process_1.execFileSync)('tar', ['-xzf', tarball, '-C', tmpDir], { stdio: 'ignore' });
|
|
239
|
+
fs_1.default.unlinkSync(tarball);
|
|
240
|
+
if (fs_1.default.existsSync(cacheDir)) {
|
|
241
|
+
fs_1.default.rmSync(cacheDir, { recursive: true, force: true });
|
|
242
|
+
}
|
|
243
|
+
fs_1.default.renameSync(tmpDir, cacheDir);
|
|
244
|
+
fs_1.default.writeFileSync(completeMarker, version);
|
|
245
|
+
(0, verbose_js_1.log)(`Conductor drivers v${version} ready at ${cacheDir}`);
|
|
246
|
+
pruneOldDriverCaches(version);
|
|
247
|
+
return cacheDir;
|
|
248
|
+
}
|
|
249
|
+
catch (err) {
|
|
250
|
+
fs_1.default.rmSync(tmpDir, { recursive: true, force: true });
|
|
251
|
+
throw new Error(`Failed to download conductor drivers v${version} from ${url}: ${err.message}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
finally {
|
|
255
|
+
try {
|
|
256
|
+
fs_1.default.unlinkSync(lockFile);
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
/* ok */
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Remove cached driver versions other than the current one. Old CLI builds
|
|
265
|
+
* would just re-download on demand, so there's no reason to keep them.
|
|
266
|
+
* Errors are swallowed — pruning is best-effort and must never block startup.
|
|
267
|
+
*/
|
|
268
|
+
function pruneOldDriverCaches(currentVersion) {
|
|
269
|
+
try {
|
|
270
|
+
for (const entry of fs_1.default.readdirSync(DRIVERS_CACHE_ROOT, { withFileTypes: true })) {
|
|
271
|
+
if (!entry.isDirectory())
|
|
272
|
+
continue;
|
|
273
|
+
if (entry.name === currentVersion)
|
|
274
|
+
continue;
|
|
275
|
+
if (entry.name.startsWith('.tmp-'))
|
|
276
|
+
continue; // active concurrent extraction
|
|
277
|
+
const stale = path_1.default.join(DRIVERS_CACHE_ROOT, entry.name);
|
|
278
|
+
try {
|
|
279
|
+
fs_1.default.rmSync(stale, { recursive: true, force: true });
|
|
280
|
+
(0, verbose_js_1.log)(`Pruned stale driver cache ${stale}`);
|
|
281
|
+
}
|
|
282
|
+
catch {
|
|
283
|
+
/* ok — another process may be using it */
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
/* ok */
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
async function acquireDriversLock(lockFile) {
|
|
292
|
+
const deadline = Date.now() + DRIVERS_LOCK_TIMEOUT_MS;
|
|
293
|
+
while (Date.now() < deadline) {
|
|
294
|
+
try {
|
|
295
|
+
const fd = fs_1.default.openSync(lockFile, 'wx');
|
|
296
|
+
fs_1.default.closeSync(fd);
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
catch {
|
|
300
|
+
await (0, utils_js_1.sleep)(DRIVERS_LOCK_POLL_MS);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
throw new Error(`Could not acquire drivers cache lock (${lockFile})`);
|
|
304
|
+
}
|
|
305
|
+
function downloadToFile(url, dest, maxRedirects = 5) {
|
|
306
|
+
return new Promise((resolve, reject) => {
|
|
307
|
+
const fetch = (u, remaining) => {
|
|
308
|
+
const req = https_1.default.get(u, (res) => {
|
|
309
|
+
const status = res.statusCode ?? 0;
|
|
310
|
+
if ((status === 301 ||
|
|
311
|
+
status === 302 ||
|
|
312
|
+
status === 303 ||
|
|
313
|
+
status === 307 ||
|
|
314
|
+
status === 308) &&
|
|
315
|
+
res.headers.location) {
|
|
316
|
+
res.resume();
|
|
317
|
+
if (remaining <= 0) {
|
|
318
|
+
reject(new Error(`Too many redirects fetching ${url}`));
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
const next = new URL(res.headers.location, u).toString();
|
|
322
|
+
fetch(next, remaining - 1);
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
if (status !== 200) {
|
|
326
|
+
res.resume();
|
|
327
|
+
reject(new Error(`HTTP ${status} for ${u}`));
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const file = fs_1.default.createWriteStream(dest);
|
|
331
|
+
res.pipe(file);
|
|
332
|
+
file.on('finish', () => file.close((err) => (err ? reject(err) : resolve())));
|
|
333
|
+
file.on('error', (err) => {
|
|
334
|
+
fs_1.default.rmSync(dest, { force: true });
|
|
335
|
+
reject(err);
|
|
336
|
+
});
|
|
337
|
+
});
|
|
338
|
+
req.on('error', reject);
|
|
339
|
+
};
|
|
340
|
+
fetch(url, maxRedirects);
|
|
341
|
+
});
|
|
186
342
|
}
|
|
187
|
-
const BUNDLED_DRIVERS_DIR = findBundledDriversDir();
|
|
188
343
|
/**
|
|
189
344
|
* Install the Conductor Android driver APKs on the device.
|
|
190
345
|
* Reads pre-built APKs directly from the bundled drivers directory.
|
|
191
346
|
*/
|
|
192
347
|
async function installDriver(deviceId) {
|
|
193
348
|
(0, verbose_js_1.log)(`installDriver: installing Android driver on ${deviceId}`);
|
|
194
|
-
const
|
|
195
|
-
const
|
|
349
|
+
const driversDir = await getDriversDir();
|
|
350
|
+
const appApk = path_1.default.join(driversDir, 'android', 'conductor-app.apk');
|
|
351
|
+
const serverApk = path_1.default.join(driversDir, 'android', 'conductor-server.apk');
|
|
196
352
|
if (!fs_1.default.existsSync(appApk) || !fs_1.default.existsSync(serverApk)) {
|
|
197
|
-
throw new Error(`Conductor driver APKs not found at ${path_1.default.join(
|
|
353
|
+
throw new Error(`Conductor driver APKs not found at ${path_1.default.join(driversDir, 'android')}.\n` +
|
|
198
354
|
`Run 'make package-cli' from the repo root to build and bundle the drivers.`);
|
|
199
355
|
}
|
|
200
356
|
await spawnAndWait('adb', ['-s', deviceId, 'install', '-r', '-t', '-g', appApk]);
|
|
@@ -214,13 +370,14 @@ const IOS_DRIVER_CACHE = path_1.default.join(os_1.default.homedir(), '.conductor
|
|
|
214
370
|
* dir. Re-extracts only when the bundled xctestrun has changed (tracked by mtime).
|
|
215
371
|
*/
|
|
216
372
|
async function setupIOSDriverCache() {
|
|
217
|
-
const
|
|
218
|
-
const
|
|
219
|
-
const
|
|
373
|
+
const driversDir = await getDriversDir();
|
|
374
|
+
const bundledXctestrun = path_1.default.join(driversDir, 'ios', 'conductor-driver-ios-config.xctestrun');
|
|
375
|
+
const bundledDriverZip = path_1.default.join(driversDir, 'ios', 'conductor-driver-ios.zip');
|
|
376
|
+
const bundledRunnerZip = path_1.default.join(driversDir, 'ios', 'conductor-driver-iosUITests-Runner.zip');
|
|
220
377
|
if (!fs_1.default.existsSync(bundledXctestrun) ||
|
|
221
378
|
!fs_1.default.existsSync(bundledDriverZip) ||
|
|
222
379
|
!fs_1.default.existsSync(bundledRunnerZip)) {
|
|
223
|
-
throw new Error(`Conductor iOS driver files not found at ${path_1.default.join(
|
|
380
|
+
throw new Error(`Conductor iOS driver files not found at ${path_1.default.join(driversDir, 'ios')}.\n` +
|
|
224
381
|
`Run 'make package-cli' from the repo root to build and bundle the drivers.`);
|
|
225
382
|
}
|
|
226
383
|
const versionFile = path_1.default.join(IOS_DRIVER_CACHE, '.version');
|
|
@@ -335,13 +492,14 @@ const TVOS_DRIVER_CACHE = path_1.default.join(os_1.default.homedir(), '.conducto
|
|
|
335
492
|
* dir. Re-extracts only when the bundled xctestrun has changed (tracked by mtime).
|
|
336
493
|
*/
|
|
337
494
|
async function setupTvOSDriverCache() {
|
|
338
|
-
const
|
|
339
|
-
const
|
|
340
|
-
const
|
|
495
|
+
const driversDir = await getDriversDir();
|
|
496
|
+
const bundledXctestrun = path_1.default.join(driversDir, 'tvos', 'conductor-driver-tvos-config.xctestrun');
|
|
497
|
+
const bundledDriverZip = path_1.default.join(driversDir, 'tvos', 'conductor-driver-tvos.zip');
|
|
498
|
+
const bundledRunnerZip = path_1.default.join(driversDir, 'tvos', 'conductor-driver-tvosUITests-Runner.zip');
|
|
341
499
|
if (!fs_1.default.existsSync(bundledXctestrun) ||
|
|
342
500
|
!fs_1.default.existsSync(bundledDriverZip) ||
|
|
343
501
|
!fs_1.default.existsSync(bundledRunnerZip)) {
|
|
344
|
-
throw new Error(`Conductor tvOS driver files not found at ${path_1.default.join(
|
|
502
|
+
throw new Error(`Conductor tvOS driver files not found at ${path_1.default.join(driversDir, 'tvos')}.\n` +
|
|
345
503
|
`Run 'make package-cli' from the repo root to build and bundle the drivers.`);
|
|
346
504
|
}
|
|
347
505
|
const versionFile = path_1.default.join(TVOS_DRIVER_CACHE, '.version');
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@houwert/conductor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "CLI tool for mobile app interactions — optimized for AI agents",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
"main": "./dist/index.js",
|
|
18
18
|
"files": [
|
|
19
19
|
"dist/",
|
|
20
|
-
"drivers/",
|
|
21
20
|
"skills/",
|
|
22
21
|
"proto/",
|
|
23
22
|
".claude-plugin/"
|
package/skills/skills.yaml
CHANGED
|
Binary file
|
|
Binary file
|
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>__xctestrun_metadata__</key>
|
|
6
|
-
<dict>
|
|
7
|
-
<key>ContainerInfo</key>
|
|
8
|
-
<dict>
|
|
9
|
-
<key>ContainerName</key>
|
|
10
|
-
<string>conductor-driver-ios</string>
|
|
11
|
-
<key>SchemeName</key>
|
|
12
|
-
<string>conductor-driver-ios</string>
|
|
13
|
-
</dict>
|
|
14
|
-
<key>FormatVersion</key>
|
|
15
|
-
<integer>1</integer>
|
|
16
|
-
</dict>
|
|
17
|
-
<key>conductor-driver-iosUITests</key>
|
|
18
|
-
<dict>
|
|
19
|
-
<key>BlueprintName</key>
|
|
20
|
-
<string>conductor-driver-iosUITests</string>
|
|
21
|
-
<key>BlueprintProviderName</key>
|
|
22
|
-
<string>conductor-driver-ios</string>
|
|
23
|
-
<key>BlueprintProviderRelativePath</key>
|
|
24
|
-
<string>conductor-driver-ios.xcodeproj</string>
|
|
25
|
-
<key>BundleIdentifiersForCrashReportEmphasis</key>
|
|
26
|
-
<array>
|
|
27
|
-
<string>dev.houwert.ConductorDriverLib</string>
|
|
28
|
-
<string>dev.houwert.conductor-driver-ios</string>
|
|
29
|
-
<string>dev.houwert.conductor-driver-iosUITests</string>
|
|
30
|
-
</array>
|
|
31
|
-
<key>CommandLineArguments</key>
|
|
32
|
-
<array/>
|
|
33
|
-
<key>DefaultTestExecutionTimeAllowance</key>
|
|
34
|
-
<integer>600</integer>
|
|
35
|
-
<key>DependentProductPaths</key>
|
|
36
|
-
<array>
|
|
37
|
-
<string>__TESTROOT__/Debug-iphonesimulator/ConductorDriverLib.framework</string>
|
|
38
|
-
<string>__TESTROOT__/Debug-iphonesimulator/conductor-driver-ios.app</string>
|
|
39
|
-
<string>__TESTROOT__/Debug-iphonesimulator/conductor-driver-iosUITests-Runner.app</string>
|
|
40
|
-
<string>__TESTROOT__/Debug-iphonesimulator/conductor-driver-iosUITests-Runner.app/PlugIns/conductor-driver-iosUITests.xctest</string>
|
|
41
|
-
</array>
|
|
42
|
-
<key>DiagnosticCollectionPolicy</key>
|
|
43
|
-
<integer>1</integer>
|
|
44
|
-
<key>EnvironmentVariables</key>
|
|
45
|
-
<dict>
|
|
46
|
-
<key>APP_DISTRIBUTOR_ID_OVERRIDE</key>
|
|
47
|
-
<string>com.apple.AppStore</string>
|
|
48
|
-
<key>OS_ACTIVITY_DT_MODE</key>
|
|
49
|
-
<string>YES</string>
|
|
50
|
-
<key>SQLITE_ENABLE_THREAD_ASSERTIONS</key>
|
|
51
|
-
<string>1</string>
|
|
52
|
-
<key>TERM</key>
|
|
53
|
-
<string>dumb</string>
|
|
54
|
-
</dict>
|
|
55
|
-
<key>IsUITestBundle</key>
|
|
56
|
-
<true/>
|
|
57
|
-
<key>IsXCTRunnerHostedTestBundle</key>
|
|
58
|
-
<true/>
|
|
59
|
-
<key>PreferredScreenCaptureFormat</key>
|
|
60
|
-
<string>screenRecording</string>
|
|
61
|
-
<key>ProductModuleName</key>
|
|
62
|
-
<string>conductor_driver_iosUITests</string>
|
|
63
|
-
<key>RunOrder</key>
|
|
64
|
-
<integer>0</integer>
|
|
65
|
-
<key>SkipTestIdentifiers</key>
|
|
66
|
-
<array>
|
|
67
|
-
<string>ViewHierarchyHandlerTests</string>
|
|
68
|
-
<string>ViewHierarchyHandlerTests/testViewHierarchyHandlerReturnsNonEmptyHierarchy()</string>
|
|
69
|
-
</array>
|
|
70
|
-
<key>SystemAttachmentLifetime</key>
|
|
71
|
-
<string>deleteOnSuccess</string>
|
|
72
|
-
<key>TestBundlePath</key>
|
|
73
|
-
<string>__TESTHOST__/PlugIns/conductor-driver-iosUITests.xctest</string>
|
|
74
|
-
<key>TestHostBundleIdentifier</key>
|
|
75
|
-
<string>dev.houwert.conductor-driver-iosUITests.xctrunner</string>
|
|
76
|
-
<key>TestHostPath</key>
|
|
77
|
-
<string>__TESTROOT__/Debug-iphonesimulator/conductor-driver-iosUITests-Runner.app</string>
|
|
78
|
-
<key>TestLanguage</key>
|
|
79
|
-
<string></string>
|
|
80
|
-
<key>TestRegion</key>
|
|
81
|
-
<string></string>
|
|
82
|
-
<key>TestTimeoutsEnabled</key>
|
|
83
|
-
<false/>
|
|
84
|
-
<key>TestingEnvironmentVariables</key>
|
|
85
|
-
<dict>
|
|
86
|
-
<key>DYLD_FRAMEWORK_PATH</key>
|
|
87
|
-
<string>__TESTROOT__/Debug-iphonesimulator:__TESTROOT__/Debug-iphonesimulator/PackageFrameworks:__PLATFORMS__/iPhoneSimulator.platform/Developer/Library/Frameworks</string>
|
|
88
|
-
<key>DYLD_LIBRARY_PATH</key>
|
|
89
|
-
<string>__TESTROOT__/Debug-iphonesimulator:__PLATFORMS__/iPhoneSimulator.platform/Developer/usr/lib</string>
|
|
90
|
-
<key>XCODE_SCHEME_NAME</key>
|
|
91
|
-
<string>conductor-driver-ios</string>
|
|
92
|
-
<key>__XCODE_BUILT_PRODUCTS_DIR_PATHS</key>
|
|
93
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
94
|
-
<key>__XPC_DYLD_FRAMEWORK_PATH</key>
|
|
95
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
96
|
-
<key>__XPC_DYLD_LIBRARY_PATH</key>
|
|
97
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
98
|
-
</dict>
|
|
99
|
-
<key>ToolchainsSettingValue</key>
|
|
100
|
-
<array/>
|
|
101
|
-
<key>UITargetAppCommandLineArguments</key>
|
|
102
|
-
<array/>
|
|
103
|
-
<key>UITargetAppEnvironmentVariables</key>
|
|
104
|
-
<dict>
|
|
105
|
-
<key>APP_DISTRIBUTOR_ID_OVERRIDE</key>
|
|
106
|
-
<string>com.apple.AppStore</string>
|
|
107
|
-
<key>DYLD_FRAMEWORK_PATH</key>
|
|
108
|
-
<string>__TESTROOT__/Debug-iphonesimulator:__TESTROOT__/Debug-iphonesimulator/PackageFrameworks</string>
|
|
109
|
-
<key>DYLD_LIBRARY_PATH</key>
|
|
110
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
111
|
-
<key>XCODE_SCHEME_NAME</key>
|
|
112
|
-
<string>conductor-driver-ios</string>
|
|
113
|
-
<key>__XCODE_BUILT_PRODUCTS_DIR_PATHS</key>
|
|
114
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
115
|
-
<key>__XPC_DYLD_FRAMEWORK_PATH</key>
|
|
116
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
117
|
-
<key>__XPC_DYLD_LIBRARY_PATH</key>
|
|
118
|
-
<string>__TESTROOT__/Debug-iphonesimulator</string>
|
|
119
|
-
</dict>
|
|
120
|
-
<key>UITargetAppPath</key>
|
|
121
|
-
<string>__TESTROOT__/Debug-iphonesimulator/conductor-driver-ios.app</string>
|
|
122
|
-
<key>UserAttachmentLifetime</key>
|
|
123
|
-
<string>deleteOnSuccess</string>
|
|
124
|
-
</dict>
|
|
125
|
-
</dict>
|
|
126
|
-
</plist>
|
|
Binary file
|
|
Binary file
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
-
<plist version="1.0">
|
|
4
|
-
<dict>
|
|
5
|
-
<key>__xctestrun_metadata__</key>
|
|
6
|
-
<dict>
|
|
7
|
-
<key>ContainerInfo</key>
|
|
8
|
-
<dict>
|
|
9
|
-
<key>ContainerName</key>
|
|
10
|
-
<string>conductor-driver-ios</string>
|
|
11
|
-
<key>SchemeName</key>
|
|
12
|
-
<string>conductor-driver-tvos</string>
|
|
13
|
-
</dict>
|
|
14
|
-
<key>FormatVersion</key>
|
|
15
|
-
<integer>1</integer>
|
|
16
|
-
</dict>
|
|
17
|
-
<key>conductor-driver-tvosUITests</key>
|
|
18
|
-
<dict>
|
|
19
|
-
<key>BlueprintName</key>
|
|
20
|
-
<string>conductor-driver-tvosUITests</string>
|
|
21
|
-
<key>BlueprintProviderName</key>
|
|
22
|
-
<string>conductor-driver-ios</string>
|
|
23
|
-
<key>BlueprintProviderRelativePath</key>
|
|
24
|
-
<string>conductor-driver-ios.xcodeproj</string>
|
|
25
|
-
<key>BundleIdentifiersForCrashReportEmphasis</key>
|
|
26
|
-
<array>
|
|
27
|
-
<string>dev.houwert.ConductorDriverLib</string>
|
|
28
|
-
<string>dev.houwert.conductor-driver-tvos</string>
|
|
29
|
-
<string>dev.houwert.conductor-driver-tvosUITests</string>
|
|
30
|
-
</array>
|
|
31
|
-
<key>CommandLineArguments</key>
|
|
32
|
-
<array/>
|
|
33
|
-
<key>DefaultTestExecutionTimeAllowance</key>
|
|
34
|
-
<integer>600</integer>
|
|
35
|
-
<key>DependentProductPaths</key>
|
|
36
|
-
<array>
|
|
37
|
-
<string>__TESTROOT__/Debug-appletvsimulator/ConductorDriverLib.framework</string>
|
|
38
|
-
<string>__TESTROOT__/Debug-appletvsimulator/conductor-driver-tvos.app</string>
|
|
39
|
-
<string>__TESTROOT__/Debug-appletvsimulator/conductor-driver-tvosUITests-Runner.app</string>
|
|
40
|
-
<string>__TESTROOT__/Debug-appletvsimulator/conductor-driver-tvosUITests-Runner.app/PlugIns/conductor-driver-tvosUITests.xctest</string>
|
|
41
|
-
</array>
|
|
42
|
-
<key>DiagnosticCollectionPolicy</key>
|
|
43
|
-
<integer>1</integer>
|
|
44
|
-
<key>EnvironmentVariables</key>
|
|
45
|
-
<dict>
|
|
46
|
-
<key>APP_DISTRIBUTOR_ID_OVERRIDE</key>
|
|
47
|
-
<string>com.apple.AppStore</string>
|
|
48
|
-
<key>OS_ACTIVITY_DT_MODE</key>
|
|
49
|
-
<string>YES</string>
|
|
50
|
-
<key>SQLITE_ENABLE_THREAD_ASSERTIONS</key>
|
|
51
|
-
<string>1</string>
|
|
52
|
-
<key>TERM</key>
|
|
53
|
-
<string>dumb</string>
|
|
54
|
-
</dict>
|
|
55
|
-
<key>IsUITestBundle</key>
|
|
56
|
-
<true/>
|
|
57
|
-
<key>IsXCTRunnerHostedTestBundle</key>
|
|
58
|
-
<true/>
|
|
59
|
-
<key>PreferredScreenCaptureFormat</key>
|
|
60
|
-
<string>screenRecording</string>
|
|
61
|
-
<key>ProductModuleName</key>
|
|
62
|
-
<string>conductor_driver_tvosUITests</string>
|
|
63
|
-
<key>RunOrder</key>
|
|
64
|
-
<integer>0</integer>
|
|
65
|
-
<key>SystemAttachmentLifetime</key>
|
|
66
|
-
<string>deleteOnSuccess</string>
|
|
67
|
-
<key>TestBundlePath</key>
|
|
68
|
-
<string>__TESTHOST__/PlugIns/conductor-driver-tvosUITests.xctest</string>
|
|
69
|
-
<key>TestHostBundleIdentifier</key>
|
|
70
|
-
<string>dev.houwert.conductor-driver-tvosUITests.xctrunner</string>
|
|
71
|
-
<key>TestHostPath</key>
|
|
72
|
-
<string>__TESTROOT__/Debug-appletvsimulator/conductor-driver-tvosUITests-Runner.app</string>
|
|
73
|
-
<key>TestLanguage</key>
|
|
74
|
-
<string></string>
|
|
75
|
-
<key>TestRegion</key>
|
|
76
|
-
<string></string>
|
|
77
|
-
<key>TestTimeoutsEnabled</key>
|
|
78
|
-
<false/>
|
|
79
|
-
<key>TestingEnvironmentVariables</key>
|
|
80
|
-
<dict>
|
|
81
|
-
<key>DYLD_FRAMEWORK_PATH</key>
|
|
82
|
-
<string>__TESTROOT__/Debug-appletvsimulator:__TESTROOT__/Debug-appletvsimulator/PackageFrameworks:__PLATFORMS__/AppleTVSimulator.platform/Developer/Library/Frameworks</string>
|
|
83
|
-
<key>DYLD_LIBRARY_PATH</key>
|
|
84
|
-
<string>__TESTROOT__/Debug-appletvsimulator:__PLATFORMS__/AppleTVSimulator.platform/Developer/usr/lib</string>
|
|
85
|
-
<key>XCODE_SCHEME_NAME</key>
|
|
86
|
-
<string>conductor-driver-tvos</string>
|
|
87
|
-
<key>__XCODE_BUILT_PRODUCTS_DIR_PATHS</key>
|
|
88
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
89
|
-
<key>__XPC_DYLD_FRAMEWORK_PATH</key>
|
|
90
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
91
|
-
<key>__XPC_DYLD_LIBRARY_PATH</key>
|
|
92
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
93
|
-
</dict>
|
|
94
|
-
<key>ToolchainsSettingValue</key>
|
|
95
|
-
<array/>
|
|
96
|
-
<key>UITargetAppCommandLineArguments</key>
|
|
97
|
-
<array/>
|
|
98
|
-
<key>UITargetAppEnvironmentVariables</key>
|
|
99
|
-
<dict>
|
|
100
|
-
<key>APP_DISTRIBUTOR_ID_OVERRIDE</key>
|
|
101
|
-
<string>com.apple.AppStore</string>
|
|
102
|
-
<key>DYLD_FRAMEWORK_PATH</key>
|
|
103
|
-
<string>__TESTROOT__/Debug-appletvsimulator:__TESTROOT__/Debug-appletvsimulator/PackageFrameworks</string>
|
|
104
|
-
<key>DYLD_LIBRARY_PATH</key>
|
|
105
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
106
|
-
<key>XCODE_SCHEME_NAME</key>
|
|
107
|
-
<string>conductor-driver-tvos</string>
|
|
108
|
-
<key>__XCODE_BUILT_PRODUCTS_DIR_PATHS</key>
|
|
109
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
110
|
-
<key>__XPC_DYLD_FRAMEWORK_PATH</key>
|
|
111
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
112
|
-
<key>__XPC_DYLD_LIBRARY_PATH</key>
|
|
113
|
-
<string>__TESTROOT__/Debug-appletvsimulator</string>
|
|
114
|
-
</dict>
|
|
115
|
-
<key>UITargetAppPath</key>
|
|
116
|
-
<string>__TESTROOT__/Debug-appletvsimulator/conductor-driver-tvos.app</string>
|
|
117
|
-
<key>UserAttachmentLifetime</key>
|
|
118
|
-
<string>deleteOnSuccess</string>
|
|
119
|
-
</dict>
|
|
120
|
-
</dict>
|
|
121
|
-
</plist>
|
|
Binary file
|
|
Binary file
|