@react-native-harness/platform-android 1.1.0-rc.3 → 1.1.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/__tests__/adb.test.js +77 -5
- package/dist/__tests__/environment.test.js +67 -1
- package/dist/__tests__/instance.test.js +1 -1
- package/dist/__tests__/targets.test.d.ts +2 -0
- package/dist/__tests__/targets.test.d.ts.map +1 -0
- package/dist/__tests__/targets.test.js +49 -0
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +47 -13
- package/dist/config.d.ts +16 -16
- package/dist/environment.d.ts +3 -0
- package/dist/environment.d.ts.map +1 -1
- package/dist/environment.js +33 -11
- package/dist/instance.d.ts.map +1 -1
- package/dist/instance.js +2 -4
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +2 -5
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +4 -2
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/__tests__/adb.test.ts +133 -28
- package/src/__tests__/environment.test.ts +135 -10
- package/src/__tests__/instance.test.ts +49 -49
- package/src/__tests__/targets.test.ts +53 -0
- package/src/adb.ts +106 -48
- package/src/environment.ts +99 -55
- package/src/instance.ts +17 -17
- package/src/runner.ts +5 -10
- package/src/targets.ts +9 -2
- package/dist/assertions.d.ts +0 -5
- package/dist/assertions.d.ts.map +0 -1
- package/dist/assertions.js +0 -6
- package/dist/emulator.d.ts +0 -6
- package/dist/emulator.d.ts.map +0 -1
- package/dist/emulator.js +0 -27
- package/dist/reader.d.ts +0 -6
- package/dist/reader.d.ts.map +0 -1
- package/dist/reader.js +0 -57
- package/dist/types.d.ts +0 -381
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -107
package/src/adb.ts
CHANGED
|
@@ -5,6 +5,12 @@ import type { ChildProcessByStdio } from 'node:child_process';
|
|
|
5
5
|
import { access, rm } from 'node:fs/promises';
|
|
6
6
|
import type { Readable } from 'node:stream';
|
|
7
7
|
import {
|
|
8
|
+
getAvdConfigPath,
|
|
9
|
+
getAvdDirectory,
|
|
10
|
+
readAvdConfig,
|
|
11
|
+
} from './avd-config.js';
|
|
12
|
+
import {
|
|
13
|
+
ensureAndroidEmulatorAvailable,
|
|
8
14
|
ensureAndroidSdkPackages,
|
|
9
15
|
getAdbBinaryPath,
|
|
10
16
|
getAndroidSystemImagePackage,
|
|
@@ -12,7 +18,6 @@ import {
|
|
|
12
18
|
getEmulatorBinaryPath,
|
|
13
19
|
getHostAndroidSystemImageArch,
|
|
14
20
|
getRequiredAndroidSdkPackages,
|
|
15
|
-
getSdkManagerBinaryPath,
|
|
16
21
|
} from './environment.js';
|
|
17
22
|
import {
|
|
18
23
|
getEmulatorStartupArgs,
|
|
@@ -36,14 +41,14 @@ const waitForAbort = (signal: AbortSignal): Promise<never> => {
|
|
|
36
41
|
() => {
|
|
37
42
|
reject(signal.reason);
|
|
38
43
|
},
|
|
39
|
-
{ once: true }
|
|
44
|
+
{ once: true },
|
|
40
45
|
);
|
|
41
46
|
});
|
|
42
47
|
};
|
|
43
48
|
|
|
44
49
|
const waitWithSignal = async (
|
|
45
50
|
ms: number,
|
|
46
|
-
signal: AbortSignal
|
|
51
|
+
signal: AbortSignal,
|
|
47
52
|
): Promise<void> => {
|
|
48
53
|
if (signal.aborted) {
|
|
49
54
|
throw signal.reason;
|
|
@@ -52,18 +57,13 @@ const waitWithSignal = async (
|
|
|
52
57
|
await Promise.race([wait(ms), waitForAbort(signal)]);
|
|
53
58
|
};
|
|
54
59
|
|
|
55
|
-
const getAvdConfigPath = (name: string): string =>
|
|
56
|
-
`${
|
|
57
|
-
process.env.ANDROID_AVD_HOME ?? `${process.env.HOME}/.android/avd`
|
|
58
|
-
}/${name}.avd/config.ini`;
|
|
59
|
-
|
|
60
60
|
const EMULATOR_STARTUP_OBSERVATION_TIMEOUT_MS = 5000;
|
|
61
61
|
const EMULATOR_OUTPUT_BUFFER_LIMIT = 16 * 1024;
|
|
62
62
|
|
|
63
63
|
export const emulatorProcess = {
|
|
64
64
|
startDetachedProcess: (
|
|
65
65
|
file: string,
|
|
66
|
-
args: readonly string[]
|
|
66
|
+
args: readonly string[],
|
|
67
67
|
): ChildProcessByStdio<null, Readable, Readable> =>
|
|
68
68
|
nodeSpawn(file, args, {
|
|
69
69
|
detached: true,
|
|
@@ -74,7 +74,7 @@ export const emulatorProcess = {
|
|
|
74
74
|
const appendBoundedOutput = (
|
|
75
75
|
output: string,
|
|
76
76
|
chunk: string,
|
|
77
|
-
limit: number = EMULATOR_OUTPUT_BUFFER_LIMIT
|
|
77
|
+
limit: number = EMULATOR_OUTPUT_BUFFER_LIMIT,
|
|
78
78
|
): string => {
|
|
79
79
|
const nextOutput = output + chunk;
|
|
80
80
|
|
|
@@ -131,16 +131,11 @@ const formatEmulatorStartupError = ({
|
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
const ensureEmulatorInstalled = async (): Promise<string> => {
|
|
134
|
-
|
|
134
|
+
await ensureAndroidEmulatorAvailable();
|
|
135
135
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
} catch {
|
|
140
|
-
await spawn(getSdkManagerBinaryPath(), ['emulator']);
|
|
141
|
-
await access(emulatorBinaryPath);
|
|
142
|
-
return emulatorBinaryPath;
|
|
143
|
-
}
|
|
136
|
+
const emulatorBinaryPath = getEmulatorBinaryPath();
|
|
137
|
+
await access(emulatorBinaryPath);
|
|
138
|
+
return emulatorBinaryPath;
|
|
144
139
|
};
|
|
145
140
|
|
|
146
141
|
export type CreateAvdOptions = {
|
|
@@ -160,15 +155,77 @@ export const getRequiredEmulatorPackages = (apiLevel: number): string[] => {
|
|
|
160
155
|
};
|
|
161
156
|
|
|
162
157
|
export const verifyAndroidEmulatorSdk = async (
|
|
163
|
-
apiLevel: number
|
|
158
|
+
apiLevel: number,
|
|
164
159
|
): Promise<void> => {
|
|
165
160
|
await ensureAndroidSdkPackages(getRequiredEmulatorPackages(apiLevel));
|
|
166
161
|
};
|
|
167
162
|
|
|
163
|
+
const listAvdProfiles = async (): Promise<string[]> => {
|
|
164
|
+
const { stdout } = await spawn(getAvdManagerBinaryPath(), ['list', 'device']);
|
|
165
|
+
|
|
166
|
+
return stdout
|
|
167
|
+
.split('\n')
|
|
168
|
+
.map((line) => line.match(/^id:\s+\d+\s+or\s+"([^"]+)"/i)?.[1]?.trim())
|
|
169
|
+
.filter((profile): profile is string => profile != null && profile !== '');
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
const ensureAvdProfileAvailable = async (profile: string): Promise<void> => {
|
|
173
|
+
const availableProfiles = await listAvdProfiles();
|
|
174
|
+
|
|
175
|
+
if (availableProfiles.includes(profile)) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const availableProfilesList =
|
|
180
|
+
availableProfiles.length > 0
|
|
181
|
+
? availableProfiles.join(', ')
|
|
182
|
+
: 'None reported by avdmanager.';
|
|
183
|
+
|
|
184
|
+
throw new Error(
|
|
185
|
+
`Android AVD profile "${profile}" is not available on this machine. Available profiles: ${availableProfilesList}`,
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const ensureAvdConfigExists = async (name: string): Promise<string> => {
|
|
190
|
+
const configPath = getAvdConfigPath(name);
|
|
191
|
+
|
|
192
|
+
if ((await readAvdConfig(name)) == null) {
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Android AVD "${name}" was created, but config.ini was not found at ${configPath}.`,
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
return configPath;
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
const getAvdIniPath = (name: string): string => {
|
|
202
|
+
const avdHome =
|
|
203
|
+
process.env.ANDROID_AVD_HOME ?? `${process.env.HOME}/.android/avd`;
|
|
204
|
+
return `${avdHome}/${name}.ini`;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const ensureAvdIniExists = async ({
|
|
208
|
+
name,
|
|
209
|
+
apiLevel,
|
|
210
|
+
}: {
|
|
211
|
+
name: string;
|
|
212
|
+
apiLevel: number;
|
|
213
|
+
}): Promise<string> => {
|
|
214
|
+
const iniPath = getAvdIniPath(name);
|
|
215
|
+
|
|
216
|
+
const avdDirectory = getAvdDirectory(name);
|
|
217
|
+
await spawn('bash', [
|
|
218
|
+
'-lc',
|
|
219
|
+
`printf '%s\n%s\n%s\n%s\n' 'avd.ini.encoding=UTF-8' 'path=${avdDirectory}' 'path.rel=avd/${name}.avd' 'target=android-${apiLevel}' > "${iniPath}"`,
|
|
220
|
+
]);
|
|
221
|
+
|
|
222
|
+
return iniPath;
|
|
223
|
+
};
|
|
224
|
+
|
|
168
225
|
export const getStartAppArgs = (
|
|
169
226
|
bundleId: string,
|
|
170
227
|
activityName: string,
|
|
171
|
-
options?: AndroidAppLaunchOptions
|
|
228
|
+
options?: AndroidAppLaunchOptions,
|
|
172
229
|
): string[] => {
|
|
173
230
|
const args = [
|
|
174
231
|
'shell',
|
|
@@ -197,7 +254,7 @@ export const getStartAppArgs = (
|
|
|
197
254
|
|
|
198
255
|
if (!Number.isSafeInteger(value)) {
|
|
199
256
|
throw new Error(
|
|
200
|
-
`Android app launch option "${key}" must be a safe integer
|
|
257
|
+
`Android app launch option "${key}" must be a safe integer.`,
|
|
201
258
|
);
|
|
202
259
|
}
|
|
203
260
|
|
|
@@ -209,7 +266,7 @@ export const getStartAppArgs = (
|
|
|
209
266
|
|
|
210
267
|
export const isAppInstalled = async (
|
|
211
268
|
adbId: string,
|
|
212
|
-
bundleId: string
|
|
269
|
+
bundleId: string,
|
|
213
270
|
): Promise<boolean> => {
|
|
214
271
|
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
215
272
|
'-s',
|
|
@@ -226,7 +283,7 @@ export const isAppInstalled = async (
|
|
|
226
283
|
export const reversePort = async (
|
|
227
284
|
adbId: string,
|
|
228
285
|
port: number,
|
|
229
|
-
hostPort: number = port
|
|
286
|
+
hostPort: number = port,
|
|
230
287
|
): Promise<void> => {
|
|
231
288
|
await spawn(getAdbBinaryPath(), [
|
|
232
289
|
'-s',
|
|
@@ -239,7 +296,7 @@ export const reversePort = async (
|
|
|
239
296
|
|
|
240
297
|
export const stopApp = async (
|
|
241
298
|
adbId: string,
|
|
242
|
-
bundleId: string
|
|
299
|
+
bundleId: string,
|
|
243
300
|
): Promise<void> => {
|
|
244
301
|
await spawn(getAdbBinaryPath(), [
|
|
245
302
|
'-s',
|
|
@@ -255,7 +312,7 @@ export const startApp = async (
|
|
|
255
312
|
adbId: string,
|
|
256
313
|
bundleId: string,
|
|
257
314
|
activityName: string,
|
|
258
|
-
options?: AndroidAppLaunchOptions
|
|
315
|
+
options?: AndroidAppLaunchOptions,
|
|
259
316
|
): Promise<void> => {
|
|
260
317
|
await spawn(getAdbBinaryPath(), [
|
|
261
318
|
'-s',
|
|
@@ -274,7 +331,7 @@ export const getDeviceIds = async (): Promise<string[]> => {
|
|
|
274
331
|
};
|
|
275
332
|
|
|
276
333
|
export const getEmulatorName = async (
|
|
277
|
-
adbId: string
|
|
334
|
+
adbId: string,
|
|
278
335
|
): Promise<string | null> => {
|
|
279
336
|
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
280
337
|
'-s',
|
|
@@ -288,7 +345,7 @@ export const getEmulatorName = async (
|
|
|
288
345
|
|
|
289
346
|
export const getShellProperty = async (
|
|
290
347
|
adbId: string,
|
|
291
|
-
property: string
|
|
348
|
+
property: string,
|
|
292
349
|
): Promise<string | null> => {
|
|
293
350
|
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
294
351
|
'-s',
|
|
@@ -310,7 +367,7 @@ export type DeviceInfo = {
|
|
|
310
367
|
};
|
|
311
368
|
|
|
312
369
|
export const getDeviceInfo = async (
|
|
313
|
-
adbId: string
|
|
370
|
+
adbId: string,
|
|
314
371
|
): Promise<DeviceInfo | null> => {
|
|
315
372
|
const manufacturer = await getShellProperty(adbId, 'ro.product.manufacturer');
|
|
316
373
|
const model = await getShellProperty(adbId, 'ro.product.model');
|
|
@@ -336,7 +393,7 @@ export const stopEmulator = async (adbId: string): Promise<void> => {
|
|
|
336
393
|
|
|
337
394
|
export const installApp = async (
|
|
338
395
|
adbId: string,
|
|
339
|
-
appPath: string
|
|
396
|
+
appPath: string,
|
|
340
397
|
): Promise<void> => {
|
|
341
398
|
await spawn(getAdbBinaryPath(), ['-s', adbId, 'install', '-r', appPath]);
|
|
342
399
|
};
|
|
@@ -355,19 +412,20 @@ export const createAvd = async ({
|
|
|
355
412
|
}: CreateAvdOptions): Promise<void> => {
|
|
356
413
|
const systemImagePackage = getAndroidSystemImagePackage(
|
|
357
414
|
apiLevel,
|
|
358
|
-
getHostAndroidSystemImageArch()
|
|
415
|
+
getHostAndroidSystemImageArch(),
|
|
359
416
|
);
|
|
360
417
|
|
|
361
418
|
await verifyAndroidEmulatorSdk(apiLevel);
|
|
419
|
+
await ensureAvdProfileAvailable(profile);
|
|
362
420
|
await spawn('bash', [
|
|
363
421
|
'-lc',
|
|
364
|
-
`printf 'no\n' | "${getAvdManagerBinaryPath()}" create avd --force --name "${name}" --package "${systemImagePackage}" --device "${profile}"`,
|
|
422
|
+
`printf 'no\n' | "${getAvdManagerBinaryPath()}" create avd --force --name "${name}" --package "${systemImagePackage}" --device "${profile}" -p "${getAvdDirectory(name)}"`,
|
|
365
423
|
]);
|
|
424
|
+
await ensureAvdIniExists({ name, apiLevel });
|
|
425
|
+
const configPath = await ensureAvdConfigExists(name);
|
|
366
426
|
await spawn('bash', [
|
|
367
427
|
'-lc',
|
|
368
|
-
`printf '%s\n%s\n' 'disk.dataPartition.size=${diskSize}' 'vm.heapSize=${heapSize}' >> "${
|
|
369
|
-
name
|
|
370
|
-
)}"`,
|
|
428
|
+
`printf '%s\n%s\n' 'disk.dataPartition.size=${diskSize}' 'vm.heapSize=${heapSize}' >> "${configPath}"`,
|
|
371
429
|
]);
|
|
372
430
|
};
|
|
373
431
|
|
|
@@ -379,7 +437,7 @@ export const deleteAvd = async (name: string): Promise<void> => {
|
|
|
379
437
|
{
|
|
380
438
|
force: true,
|
|
381
439
|
recursive: true,
|
|
382
|
-
}
|
|
440
|
+
},
|
|
383
441
|
);
|
|
384
442
|
await rm(
|
|
385
443
|
`${
|
|
@@ -387,18 +445,18 @@ export const deleteAvd = async (name: string): Promise<void> => {
|
|
|
387
445
|
}/${name}.ini`,
|
|
388
446
|
{
|
|
389
447
|
force: true,
|
|
390
|
-
}
|
|
448
|
+
},
|
|
391
449
|
);
|
|
392
450
|
};
|
|
393
451
|
|
|
394
452
|
export const startEmulator = async (
|
|
395
453
|
name: string,
|
|
396
|
-
mode: EmulatorBootMode = 'default-boot'
|
|
454
|
+
mode: EmulatorBootMode = 'default-boot',
|
|
397
455
|
): Promise<void> => {
|
|
398
456
|
const emulatorBinaryPath = await ensureEmulatorInstalled();
|
|
399
457
|
const childProcess = emulatorProcess.startDetachedProcess(
|
|
400
458
|
emulatorBinaryPath,
|
|
401
|
-
getEmulatorStartupArgs(name, mode)
|
|
459
|
+
getEmulatorStartupArgs(name, mode),
|
|
402
460
|
);
|
|
403
461
|
|
|
404
462
|
let stdout = '';
|
|
@@ -434,7 +492,7 @@ export const startEmulator = async (
|
|
|
434
492
|
stdout,
|
|
435
493
|
stderr,
|
|
436
494
|
error,
|
|
437
|
-
})
|
|
495
|
+
}),
|
|
438
496
|
);
|
|
439
497
|
});
|
|
440
498
|
|
|
@@ -446,7 +504,7 @@ export const startEmulator = async (
|
|
|
446
504
|
stderr,
|
|
447
505
|
exitCode,
|
|
448
506
|
signal,
|
|
449
|
-
})
|
|
507
|
+
}),
|
|
450
508
|
);
|
|
451
509
|
});
|
|
452
510
|
});
|
|
@@ -462,7 +520,7 @@ export const startEmulator = async (
|
|
|
462
520
|
});
|
|
463
521
|
|
|
464
522
|
const observationTimeout = wait(EMULATOR_STARTUP_OBSERVATION_TIMEOUT_MS).then(
|
|
465
|
-
() => 'timeout' as const
|
|
523
|
+
() => 'timeout' as const,
|
|
466
524
|
);
|
|
467
525
|
|
|
468
526
|
try {
|
|
@@ -478,7 +536,7 @@ export const startEmulator = async (
|
|
|
478
536
|
|
|
479
537
|
export const waitForEmulator = async (
|
|
480
538
|
name: string,
|
|
481
|
-
signal: AbortSignal
|
|
539
|
+
signal: AbortSignal,
|
|
482
540
|
): Promise<string> => {
|
|
483
541
|
while (!signal.aborted) {
|
|
484
542
|
const adbIds = await getDeviceIds();
|
|
@@ -503,7 +561,7 @@ export const waitForEmulator = async (
|
|
|
503
561
|
|
|
504
562
|
export const waitForEmulatorDisconnect = async (
|
|
505
563
|
adbId: string,
|
|
506
|
-
signal: AbortSignal
|
|
564
|
+
signal: AbortSignal,
|
|
507
565
|
): Promise<void> => {
|
|
508
566
|
while (!signal.aborted) {
|
|
509
567
|
const adbIds = await getDeviceIds();
|
|
@@ -520,7 +578,7 @@ export const waitForEmulatorDisconnect = async (
|
|
|
520
578
|
|
|
521
579
|
export const waitForBoot = async (
|
|
522
580
|
name: string,
|
|
523
|
-
signal: AbortSignal
|
|
581
|
+
signal: AbortSignal,
|
|
524
582
|
): Promise<string> => {
|
|
525
583
|
while (!signal.aborted) {
|
|
526
584
|
const adbIds = await getDeviceIds();
|
|
@@ -549,7 +607,7 @@ export const waitForBoot = async (
|
|
|
549
607
|
|
|
550
608
|
export const isAppRunning = async (
|
|
551
609
|
adbId: string,
|
|
552
|
-
bundleId: string
|
|
610
|
+
bundleId: string,
|
|
553
611
|
): Promise<boolean> => {
|
|
554
612
|
try {
|
|
555
613
|
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
@@ -571,7 +629,7 @@ export const isAppRunning = async (
|
|
|
571
629
|
|
|
572
630
|
export const getAppUid = async (
|
|
573
631
|
adbId: string,
|
|
574
|
-
bundleId: string
|
|
632
|
+
bundleId: string,
|
|
575
633
|
): Promise<number> => {
|
|
576
634
|
const { stdout } = await spawn(getAdbBinaryPath(), [
|
|
577
635
|
'-s',
|
|
@@ -596,7 +654,7 @@ export const getAppUid = async (
|
|
|
596
654
|
|
|
597
655
|
export const setHideErrorDialogs = async (
|
|
598
656
|
adbId: string,
|
|
599
|
-
hide: boolean
|
|
657
|
+
hide: boolean,
|
|
600
658
|
): Promise<void> => {
|
|
601
659
|
await spawn(getAdbBinaryPath(), [
|
|
602
660
|
'-s',
|