@react-native-harness/platform-android 1.1.0-rc.2 → 1.1.0-rc.3
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/README.md +9 -2
- package/dist/__tests__/adb.test.js +283 -10
- package/dist/__tests__/avd-config.test.d.ts +2 -0
- package/dist/__tests__/avd-config.test.d.ts.map +1 -0
- package/dist/__tests__/avd-config.test.js +174 -0
- package/dist/__tests__/ci-action.test.d.ts +2 -0
- package/dist/__tests__/ci-action.test.d.ts.map +1 -0
- package/dist/__tests__/ci-action.test.js +46 -0
- package/dist/__tests__/emulator-startup.test.d.ts +2 -0
- package/dist/__tests__/emulator-startup.test.d.ts.map +1 -0
- package/dist/__tests__/emulator-startup.test.js +19 -0
- package/dist/__tests__/environment.test.d.ts +2 -0
- package/dist/__tests__/environment.test.d.ts.map +1 -0
- package/dist/__tests__/environment.test.js +51 -0
- package/dist/__tests__/instance.test.d.ts +2 -0
- package/dist/__tests__/instance.test.d.ts.map +1 -0
- package/dist/__tests__/instance.test.js +423 -0
- package/dist/adb.d.ts +23 -0
- package/dist/adb.d.ts.map +1 -1
- package/dist/adb.js +265 -16
- package/dist/app-monitor.d.ts.map +1 -1
- package/dist/app-monitor.js +27 -7
- package/dist/assertions.d.ts +5 -0
- package/dist/assertions.d.ts.map +1 -0
- package/dist/assertions.js +6 -0
- package/dist/avd-config.d.ts +41 -0
- package/dist/avd-config.d.ts.map +1 -0
- package/dist/avd-config.js +173 -0
- package/dist/config.d.ts +77 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -0
- package/dist/emulator-startup.d.ts +3 -0
- package/dist/emulator-startup.d.ts.map +1 -0
- package/dist/emulator-startup.js +17 -0
- package/dist/emulator.d.ts +6 -0
- package/dist/emulator.d.ts.map +1 -0
- package/dist/emulator.js +27 -0
- package/dist/environment.d.ts +28 -0
- package/dist/environment.d.ts.map +1 -0
- package/dist/environment.js +295 -0
- package/dist/errors.d.ts +7 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +14 -0
- package/dist/factory.d.ts.map +1 -1
- package/dist/factory.js +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/instance.d.ts +6 -0
- package/dist/instance.d.ts.map +1 -0
- package/dist/instance.js +234 -0
- package/dist/reader.d.ts +6 -0
- package/dist/reader.d.ts.map +1 -0
- package/dist/reader.js +57 -0
- package/dist/runner.d.ts +2 -2
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +12 -52
- package/dist/targets.d.ts +1 -1
- package/dist/targets.d.ts.map +1 -1
- package/dist/targets.js +2 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/types.d.ts +381 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +107 -0
- package/package.json +4 -4
- package/src/__tests__/adb.test.ts +419 -15
- package/src/__tests__/avd-config.test.ts +206 -0
- package/src/__tests__/ci-action.test.ts +81 -0
- package/src/__tests__/emulator-startup.test.ts +32 -0
- package/src/__tests__/environment.test.ts +87 -0
- package/src/__tests__/instance.test.ts +610 -0
- package/src/adb.ts +423 -16
- package/src/app-monitor.ts +56 -18
- package/src/avd-config.ts +290 -0
- package/src/config.ts +8 -0
- package/src/emulator-startup.ts +28 -0
- package/src/environment.ts +510 -0
- package/src/errors.ts +19 -0
- package/src/factory.ts +4 -0
- package/src/index.ts +7 -1
- package/src/instance.ts +380 -0
- package/src/runner.ts +23 -69
- package/src/targets.ts +11 -8
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
export { androidEmulator, physicalAndroidDevice, androidPlatform, } from './factory.js';
|
|
2
2
|
export type { AndroidPlatformConfig } from './config.js';
|
|
3
|
+
export { getNormalizedAvdCacheConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
4
|
+
export { getHostAndroidSystemImageArch } from './environment.js';
|
|
5
|
+
export { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
3
6
|
export { getRunTargets } from './targets.js';
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACzD,OAAO,EACL,2BAA2B,EAC3B,wBAAwB,GACzB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,MAAM,aAAa,CAAC;AAC9E,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,5 @@
|
|
|
1
1
|
export { androidEmulator, physicalAndroidDevice, androidPlatform, } from './factory.js';
|
|
2
|
+
export { getNormalizedAvdCacheConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
3
|
+
export { getHostAndroidSystemImageArch } from './environment.js';
|
|
4
|
+
export { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
2
5
|
export { getRunTargets } from './targets.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type HarnessPlatformInitOptions, HarnessPlatformRunner } from '@react-native-harness/platforms';
|
|
2
|
+
import type { Config as HarnessConfig } from '@react-native-harness/config';
|
|
3
|
+
import { AndroidPlatformConfig } from './config.js';
|
|
4
|
+
export declare const getAndroidEmulatorPlatformInstance: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig, init: HarnessPlatformInitOptions) => Promise<HarnessPlatformRunner>;
|
|
5
|
+
export declare const getAndroidPhysicalDevicePlatformInstance: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig) => Promise<HarnessPlatformRunner>;
|
|
6
|
+
//# sourceMappingURL=instance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"instance.d.ts","sourceRoot":"","sources":["../src/instance.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,0BAA0B,EAC/B,qBAAqB,EACtB,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,EACL,qBAAqB,EAGtB,MAAM,aAAa,CAAC;AAgKrB,eAAO,MAAM,kCAAkC,GAC7C,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,CAoI/B,CAAC;AAEF,eAAO,MAAM,wCAAwC,GACnD,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,KAC3B,OAAO,CAAC,qBAAqB,CAiE/B,CAAC"}
|
package/dist/instance.js
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { AppNotInstalledError, DeviceNotFoundError, } from '@react-native-harness/platforms';
|
|
2
|
+
import { logger } from '@react-native-harness/tools';
|
|
3
|
+
import { assertAndroidDeviceEmulator, assertAndroidDevicePhysical, } from './config.js';
|
|
4
|
+
import { isAvdCompatible, readAvdConfig, resolveAvdCachingEnabled, } from './avd-config.js';
|
|
5
|
+
import { getAdbId } from './adb-id.js';
|
|
6
|
+
import * as adb from './adb.js';
|
|
7
|
+
import { applyHarnessDebugHttpHost, clearHarnessDebugHttpHost, } from './shared-prefs.js';
|
|
8
|
+
import { getDeviceName } from './utils.js';
|
|
9
|
+
import { createAndroidAppMonitor } from './app-monitor.js';
|
|
10
|
+
import { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
|
|
11
|
+
import { ensureAndroidEmulatorEnvironment, getHostAndroidSystemImageArch, } from './environment.js';
|
|
12
|
+
import { isInteractive } from '@react-native-harness/tools';
|
|
13
|
+
import fs from 'node:fs';
|
|
14
|
+
const androidInstanceLogger = logger.child('android-instance');
|
|
15
|
+
const createNoopAppMonitor = () => ({
|
|
16
|
+
start: async () => undefined,
|
|
17
|
+
stop: async () => undefined,
|
|
18
|
+
dispose: async () => undefined,
|
|
19
|
+
addListener: () => undefined,
|
|
20
|
+
removeListener: () => undefined,
|
|
21
|
+
});
|
|
22
|
+
const getHarnessAppPath = () => {
|
|
23
|
+
const appPath = process.env.HARNESS_APP_PATH;
|
|
24
|
+
if (!appPath) {
|
|
25
|
+
throw new HarnessAppPathError('missing');
|
|
26
|
+
}
|
|
27
|
+
if (!fs.existsSync(appPath)) {
|
|
28
|
+
throw new HarnessAppPathError('invalid', appPath);
|
|
29
|
+
}
|
|
30
|
+
return appPath;
|
|
31
|
+
};
|
|
32
|
+
const configureAndroidRuntime = async (adbId, config, harnessConfig) => {
|
|
33
|
+
const metroPort = harnessConfig.metroPort;
|
|
34
|
+
await Promise.all([
|
|
35
|
+
adb.reversePort(adbId, metroPort),
|
|
36
|
+
adb.reversePort(adbId, 8080),
|
|
37
|
+
adb.setHideErrorDialogs(adbId, true),
|
|
38
|
+
applyHarnessDebugHttpHost(adbId, config.bundleId, `localhost:${metroPort}`),
|
|
39
|
+
]);
|
|
40
|
+
return adb.getAppUid(adbId, config.bundleId);
|
|
41
|
+
};
|
|
42
|
+
const startAndWaitForBoot = async ({ emulatorName, signal, mode, }) => {
|
|
43
|
+
await adb.startEmulator(emulatorName, mode);
|
|
44
|
+
return adb.waitForBoot(emulatorName, signal);
|
|
45
|
+
};
|
|
46
|
+
const recreateAvd = async ({ emulatorConfig, }) => {
|
|
47
|
+
if (!emulatorConfig.avd) {
|
|
48
|
+
throw new HarnessEmulatorConfigError(emulatorConfig.name);
|
|
49
|
+
}
|
|
50
|
+
await adb.createAvd({
|
|
51
|
+
name: emulatorConfig.name,
|
|
52
|
+
apiLevel: emulatorConfig.avd.apiLevel,
|
|
53
|
+
profile: emulatorConfig.avd.profile,
|
|
54
|
+
diskSize: emulatorConfig.avd.diskSize,
|
|
55
|
+
heapSize: emulatorConfig.avd.heapSize,
|
|
56
|
+
});
|
|
57
|
+
};
|
|
58
|
+
const prepareCachedAvd = async ({ emulatorConfig, signal, }) => {
|
|
59
|
+
const emulatorName = emulatorConfig.name;
|
|
60
|
+
const hostArch = getHostAndroidSystemImageArch();
|
|
61
|
+
const hasExistingAvd = await adb.hasAvd(emulatorName);
|
|
62
|
+
const avdConfig = hasExistingAvd ? await readAvdConfig(emulatorName) : null;
|
|
63
|
+
const compatibility = avdConfig == null
|
|
64
|
+
? { compatible: false, reason: 'Missing AVD config.ini.' }
|
|
65
|
+
: isAvdCompatible({
|
|
66
|
+
emulator: emulatorConfig,
|
|
67
|
+
avdConfig,
|
|
68
|
+
hostArch,
|
|
69
|
+
});
|
|
70
|
+
if (!hasExistingAvd || !compatibility.compatible) {
|
|
71
|
+
logger.info(hasExistingAvd
|
|
72
|
+
? 'Recreating incompatible Android emulator %s...'
|
|
73
|
+
: 'Creating Android emulator %s...', emulatorName);
|
|
74
|
+
if (hasExistingAvd && !compatibility.compatible) {
|
|
75
|
+
androidInstanceLogger.debug('Android AVD %s is not reusable: %s', emulatorName, compatibility.reason);
|
|
76
|
+
await adb.deleteAvd(emulatorName);
|
|
77
|
+
}
|
|
78
|
+
await recreateAvd({ emulatorConfig });
|
|
79
|
+
const generationAdbId = await startAndWaitForBoot({
|
|
80
|
+
emulatorName,
|
|
81
|
+
signal,
|
|
82
|
+
mode: 'clean-snapshot-generation',
|
|
83
|
+
});
|
|
84
|
+
logger.info('Saving Android emulator snapshot for %s...', emulatorName);
|
|
85
|
+
await adb.stopEmulator(generationAdbId);
|
|
86
|
+
await adb.waitForEmulatorDisconnect(generationAdbId, signal);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
logger.info('Using cached Android emulator %s...', emulatorName);
|
|
90
|
+
}
|
|
91
|
+
return startAndWaitForBoot({
|
|
92
|
+
emulatorName,
|
|
93
|
+
signal,
|
|
94
|
+
mode: 'snapshot-reuse',
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
export const getAndroidEmulatorPlatformInstance = async (config, harnessConfig, init) => {
|
|
98
|
+
assertAndroidDeviceEmulator(config.device);
|
|
99
|
+
const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
|
|
100
|
+
const emulatorConfig = config.device;
|
|
101
|
+
const emulatorName = emulatorConfig.name;
|
|
102
|
+
const avdConfig = emulatorConfig.avd;
|
|
103
|
+
const avdCachingEnabled = resolveAvdCachingEnabled({
|
|
104
|
+
avd: avdConfig,
|
|
105
|
+
isInteractive: isInteractive(),
|
|
106
|
+
});
|
|
107
|
+
let adbId = await getAdbId(emulatorConfig);
|
|
108
|
+
let startedByHarness = false;
|
|
109
|
+
androidInstanceLogger.debug('resolved Android emulator %s with adb id %s', emulatorConfig.name, adbId ?? 'not-found');
|
|
110
|
+
if (!adbId) {
|
|
111
|
+
if (!avdConfig) {
|
|
112
|
+
throw new HarnessEmulatorConfigError(emulatorConfig.name);
|
|
113
|
+
}
|
|
114
|
+
await ensureAndroidEmulatorEnvironment(avdConfig.apiLevel);
|
|
115
|
+
adbId = avdCachingEnabled
|
|
116
|
+
? await prepareCachedAvd({
|
|
117
|
+
emulatorConfig,
|
|
118
|
+
signal: init.signal,
|
|
119
|
+
})
|
|
120
|
+
: await (async () => {
|
|
121
|
+
if (!(await adb.hasAvd(emulatorConfig.name))) {
|
|
122
|
+
logger.info('Creating Android emulator %s...', emulatorName);
|
|
123
|
+
androidInstanceLogger.debug('creating Android AVD %s before startup', emulatorConfig.name);
|
|
124
|
+
await recreateAvd({ emulatorConfig });
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
logger.info('Using existing Android emulator %s...', emulatorName);
|
|
128
|
+
}
|
|
129
|
+
androidInstanceLogger.debug('starting Android emulator %s', emulatorConfig.name);
|
|
130
|
+
return startAndWaitForBoot({
|
|
131
|
+
emulatorName: emulatorConfig.name,
|
|
132
|
+
signal: init.signal,
|
|
133
|
+
});
|
|
134
|
+
})();
|
|
135
|
+
startedByHarness = true;
|
|
136
|
+
androidInstanceLogger.debug('Android emulator %s connected as %s', emulatorConfig.name, adbId);
|
|
137
|
+
}
|
|
138
|
+
else if (emulatorConfig.avd) {
|
|
139
|
+
await ensureAndroidEmulatorEnvironment(emulatorConfig.avd.apiLevel);
|
|
140
|
+
}
|
|
141
|
+
if (!adbId) {
|
|
142
|
+
throw new DeviceNotFoundError(getDeviceName(emulatorConfig));
|
|
143
|
+
}
|
|
144
|
+
androidInstanceLogger.debug('waiting for Android emulator %s to finish booting', adbId);
|
|
145
|
+
const isInstalled = await adb.isAppInstalled(adbId, config.bundleId);
|
|
146
|
+
if (!isInstalled) {
|
|
147
|
+
const appPath = getHarnessAppPath();
|
|
148
|
+
await adb.installApp(adbId, appPath);
|
|
149
|
+
}
|
|
150
|
+
const appUid = await configureAndroidRuntime(adbId, config, harnessConfig);
|
|
151
|
+
return {
|
|
152
|
+
startApp: async (options) => {
|
|
153
|
+
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
154
|
+
config.appLaunchOptions);
|
|
155
|
+
},
|
|
156
|
+
restartApp: async (options) => {
|
|
157
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
158
|
+
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
159
|
+
config.appLaunchOptions);
|
|
160
|
+
},
|
|
161
|
+
stopApp: async () => {
|
|
162
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
163
|
+
},
|
|
164
|
+
dispose: async () => {
|
|
165
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
166
|
+
await clearHarnessDebugHttpHost(adbId, config.bundleId);
|
|
167
|
+
await adb.setHideErrorDialogs(adbId, false);
|
|
168
|
+
if (startedByHarness) {
|
|
169
|
+
logger.info('Shutting down Android emulator %s...', emulatorName);
|
|
170
|
+
await adb.stopEmulator(adbId);
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
isAppRunning: async () => {
|
|
174
|
+
return await adb.isAppRunning(adbId, config.bundleId);
|
|
175
|
+
},
|
|
176
|
+
createAppMonitor: (options) => {
|
|
177
|
+
if (!detectNativeCrashes) {
|
|
178
|
+
return createNoopAppMonitor();
|
|
179
|
+
}
|
|
180
|
+
return createAndroidAppMonitor({
|
|
181
|
+
adbId,
|
|
182
|
+
bundleId: config.bundleId,
|
|
183
|
+
appUid,
|
|
184
|
+
crashArtifactWriter: options?.crashArtifactWriter,
|
|
185
|
+
});
|
|
186
|
+
},
|
|
187
|
+
};
|
|
188
|
+
};
|
|
189
|
+
export const getAndroidPhysicalDevicePlatformInstance = async (config, harnessConfig) => {
|
|
190
|
+
assertAndroidDevicePhysical(config.device);
|
|
191
|
+
const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
|
|
192
|
+
const adbId = await getAdbId(config.device);
|
|
193
|
+
if (!adbId) {
|
|
194
|
+
throw new DeviceNotFoundError(getDeviceName(config.device));
|
|
195
|
+
}
|
|
196
|
+
const isInstalled = await adb.isAppInstalled(adbId, config.bundleId);
|
|
197
|
+
if (!isInstalled) {
|
|
198
|
+
throw new AppNotInstalledError(config.bundleId, getDeviceName(config.device));
|
|
199
|
+
}
|
|
200
|
+
const appUid = await configureAndroidRuntime(adbId, config, harnessConfig);
|
|
201
|
+
return {
|
|
202
|
+
startApp: async (options) => {
|
|
203
|
+
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
204
|
+
config.appLaunchOptions);
|
|
205
|
+
},
|
|
206
|
+
restartApp: async (options) => {
|
|
207
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
208
|
+
await adb.startApp(adbId, config.bundleId, config.activityName, options ??
|
|
209
|
+
config.appLaunchOptions);
|
|
210
|
+
},
|
|
211
|
+
stopApp: async () => {
|
|
212
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
213
|
+
},
|
|
214
|
+
dispose: async () => {
|
|
215
|
+
await adb.stopApp(adbId, config.bundleId);
|
|
216
|
+
await clearHarnessDebugHttpHost(adbId, config.bundleId);
|
|
217
|
+
await adb.setHideErrorDialogs(adbId, false);
|
|
218
|
+
},
|
|
219
|
+
isAppRunning: async () => {
|
|
220
|
+
return await adb.isAppRunning(adbId, config.bundleId);
|
|
221
|
+
},
|
|
222
|
+
createAppMonitor: (options) => {
|
|
223
|
+
if (!detectNativeCrashes) {
|
|
224
|
+
return createNoopAppMonitor();
|
|
225
|
+
}
|
|
226
|
+
return createAndroidAppMonitor({
|
|
227
|
+
adbId,
|
|
228
|
+
bundleId: config.bundleId,
|
|
229
|
+
appUid,
|
|
230
|
+
crashArtifactWriter: options?.crashArtifactWriter,
|
|
231
|
+
});
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
};
|
package/dist/reader.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../src/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,MAAM,YAAY,CAAC;AAsElD,eAAO,MAAM,SAAS,GACpB,KAAK,MAAM,KACV,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAUjD,CAAC"}
|
package/dist/reader.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { ConfigSchema } from './types.js';
|
|
2
|
+
import { ConfigValidationError, ConfigNotFoundError, ConfigLoadError, } from './errors.js';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import fs from 'node:fs';
|
|
5
|
+
import { createRequire } from 'node:module';
|
|
6
|
+
import { ZodError } from 'zod';
|
|
7
|
+
const extensions = ['.js', '.mjs', '.cjs', '.json'];
|
|
8
|
+
const importUp = async (dir, name) => {
|
|
9
|
+
const filePath = path.join(dir, name);
|
|
10
|
+
for (const ext of extensions) {
|
|
11
|
+
const filePathWithExt = `${filePath}${ext}`;
|
|
12
|
+
if (fs.existsSync(filePathWithExt)) {
|
|
13
|
+
let rawConfig;
|
|
14
|
+
try {
|
|
15
|
+
if (ext === '.mjs') {
|
|
16
|
+
rawConfig = await import(filePathWithExt).then((module) => module.default);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
const require = createRequire(import.meta.url);
|
|
20
|
+
rawConfig = require(filePathWithExt);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
throw new ConfigLoadError(filePathWithExt, error instanceof Error ? error : undefined);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const config = ConfigSchema.parse(rawConfig);
|
|
28
|
+
return { config, filePathWithExt, configDir: dir };
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof ZodError) {
|
|
32
|
+
const validationErrors = error.errors.map((err) => {
|
|
33
|
+
const path = err.path.length > 0 ? ` at "${err.path.join('.')}"` : '';
|
|
34
|
+
return `${err.message}${path}`;
|
|
35
|
+
});
|
|
36
|
+
throw new ConfigValidationError(filePathWithExt, validationErrors);
|
|
37
|
+
}
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const parentDir = path.dirname(dir);
|
|
43
|
+
if (parentDir === dir) {
|
|
44
|
+
throw new ConfigNotFoundError(dir);
|
|
45
|
+
}
|
|
46
|
+
return importUp(parentDir, name);
|
|
47
|
+
};
|
|
48
|
+
export const getConfig = async (dir) => {
|
|
49
|
+
const { config, configDir } = await importUp(dir, 'rn-harness.config');
|
|
50
|
+
return {
|
|
51
|
+
config: {
|
|
52
|
+
...config,
|
|
53
|
+
reporter: config.reporter,
|
|
54
|
+
},
|
|
55
|
+
projectRoot: configDir,
|
|
56
|
+
};
|
|
57
|
+
};
|
package/dist/runner.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { HarnessPlatformRunner } from '@react-native-harness/platforms';
|
|
1
|
+
import { HarnessPlatformRunner, type HarnessPlatformInitOptions } from '@react-native-harness/platforms';
|
|
2
2
|
import type { Config as HarnessConfig } from '@react-native-harness/config';
|
|
3
3
|
import { type AndroidPlatformConfig } from './config.js';
|
|
4
|
-
declare const getAndroidRunner: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig) => Promise<HarnessPlatformRunner>;
|
|
4
|
+
declare const getAndroidRunner: (config: AndroidPlatformConfig, harnessConfig: HarnessConfig, init: HarnessPlatformInitOptions) => Promise<HarnessPlatformRunner>;
|
|
5
5
|
export default getAndroidRunner;
|
|
6
6
|
//# sourceMappingURL=runner.d.ts.map
|
package/dist/runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../src/runner.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,KAAK,0BAA0B,EAChC,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EAAE,MAAM,IAAI,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAEL,KAAK,qBAAqB,EAE3B,MAAM,aAAa,CAAC;AAWrB,QAAA,MAAM,gBAAgB,GACpB,QAAQ,qBAAqB,EAC7B,eAAe,aAAa,EAC5B,MAAM,0BAA0B,KAC/B,OAAO,CAAC,qBAAqB,CAoB/B,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
package/dist/runner.js
CHANGED
|
@@ -1,56 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
import { applyHarnessDebugHttpHost, clearHarnessDebugHttpHost, } from './shared-prefs.js';
|
|
6
|
-
import { getDeviceName } from './utils.js';
|
|
7
|
-
import { createAndroidAppMonitor } from './app-monitor.js';
|
|
8
|
-
const getAndroidRunner = async (config, harnessConfig) => {
|
|
1
|
+
import { AndroidPlatformConfigSchema, isAndroidDeviceEmulator, } from './config.js';
|
|
2
|
+
import { getAndroidEmulatorPlatformInstance, getAndroidPhysicalDevicePlatformInstance, } from './instance.js';
|
|
3
|
+
import { ensureAndroidEmulatorEnvironment, ensureAndroidPhysicalDeviceEnvironment, initializeAndroidProcessEnv, } from './environment.js';
|
|
4
|
+
const getAndroidRunner = async (config, harnessConfig, init) => {
|
|
9
5
|
const parsedConfig = AndroidPlatformConfigSchema.parse(config);
|
|
10
|
-
|
|
11
|
-
if (
|
|
12
|
-
|
|
6
|
+
initializeAndroidProcessEnv();
|
|
7
|
+
if (isAndroidDeviceEmulator(parsedConfig.device)) {
|
|
8
|
+
if (parsedConfig.device.avd) {
|
|
9
|
+
await ensureAndroidEmulatorEnvironment(parsedConfig.device.avd.apiLevel);
|
|
10
|
+
}
|
|
11
|
+
return getAndroidEmulatorPlatformInstance(parsedConfig, harnessConfig, init);
|
|
13
12
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
throw new AppNotInstalledError(parsedConfig.bundleId, getDeviceName(parsedConfig.device));
|
|
17
|
-
}
|
|
18
|
-
const metroPort = harnessConfig.metroPort;
|
|
19
|
-
await Promise.all([
|
|
20
|
-
adb.reversePort(adbId, metroPort),
|
|
21
|
-
adb.reversePort(adbId, 8080),
|
|
22
|
-
adb.reversePort(adbId, harnessConfig.webSocketPort),
|
|
23
|
-
adb.setHideErrorDialogs(adbId, true),
|
|
24
|
-
applyHarnessDebugHttpHost(adbId, parsedConfig.bundleId, `localhost:${metroPort}`),
|
|
25
|
-
]);
|
|
26
|
-
const appUid = await adb.getAppUid(adbId, parsedConfig.bundleId);
|
|
27
|
-
return {
|
|
28
|
-
startApp: async (options) => {
|
|
29
|
-
await adb.startApp(adbId, parsedConfig.bundleId, parsedConfig.activityName, options ??
|
|
30
|
-
parsedConfig.appLaunchOptions);
|
|
31
|
-
},
|
|
32
|
-
restartApp: async (options) => {
|
|
33
|
-
await adb.stopApp(adbId, parsedConfig.bundleId);
|
|
34
|
-
await adb.startApp(adbId, parsedConfig.bundleId, parsedConfig.activityName, options ??
|
|
35
|
-
parsedConfig.appLaunchOptions);
|
|
36
|
-
},
|
|
37
|
-
stopApp: async () => {
|
|
38
|
-
await adb.stopApp(adbId, parsedConfig.bundleId);
|
|
39
|
-
},
|
|
40
|
-
dispose: async () => {
|
|
41
|
-
await adb.stopApp(adbId, parsedConfig.bundleId);
|
|
42
|
-
await clearHarnessDebugHttpHost(adbId, parsedConfig.bundleId);
|
|
43
|
-
await adb.setHideErrorDialogs(adbId, false);
|
|
44
|
-
},
|
|
45
|
-
isAppRunning: async () => {
|
|
46
|
-
return await adb.isAppRunning(adbId, parsedConfig.bundleId);
|
|
47
|
-
},
|
|
48
|
-
createAppMonitor: (options) => createAndroidAppMonitor({
|
|
49
|
-
adbId,
|
|
50
|
-
bundleId: parsedConfig.bundleId,
|
|
51
|
-
appUid,
|
|
52
|
-
crashArtifactWriter: options?.crashArtifactWriter,
|
|
53
|
-
}),
|
|
54
|
-
};
|
|
13
|
+
await ensureAndroidPhysicalDeviceEnvironment();
|
|
14
|
+
return getAndroidPhysicalDevicePlatformInstance(parsedConfig, harnessConfig);
|
|
55
15
|
};
|
|
56
16
|
export default getAndroidRunner;
|
package/dist/targets.d.ts
CHANGED
package/dist/targets.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../src/targets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"targets.d.ts","sourceRoot":"","sources":["../src/targets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAC;AAI5D,eAAO,MAAM,aAAa,QAAa,OAAO,CAAC,SAAS,EAAE,CAoCzD,CAAC"}
|
package/dist/targets.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as adb from './adb.js';
|
|
2
|
+
import { ensureAndroidDiscoveryEnvironment } from './environment.js';
|
|
2
3
|
export const getRunTargets = async () => {
|
|
4
|
+
await ensureAndroidDiscoveryEnvironment();
|
|
3
5
|
const [avds, connectedDevices] = await Promise.all([
|
|
4
6
|
adb.getAvds(),
|
|
5
7
|
adb.getConnectedDevices(),
|