@react-native-harness/cli 1.0.0-alpha.19 → 1.0.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/bundlers/metro.d.ts +2 -2
  2. package/dist/bundlers/metro.d.ts.map +1 -1
  3. package/dist/bundlers/metro.js +47 -24
  4. package/dist/commands/test.d.ts +3 -0
  5. package/dist/commands/test.d.ts.map +1 -0
  6. package/dist/commands/test.js +140 -0
  7. package/dist/discovery/index.d.ts +3 -0
  8. package/dist/discovery/index.d.ts.map +1 -0
  9. package/dist/discovery/index.js +1 -0
  10. package/dist/discovery/testDiscovery.d.ts +11 -0
  11. package/dist/discovery/testDiscovery.d.ts.map +1 -0
  12. package/dist/discovery/testDiscovery.js +29 -0
  13. package/dist/errors/appNotInstalledError.d.ts +7 -0
  14. package/dist/errors/appNotInstalledError.d.ts.map +1 -0
  15. package/dist/errors/appNotInstalledError.js +12 -0
  16. package/dist/errors/bridgeTimeoutError.d.ts +7 -0
  17. package/dist/errors/bridgeTimeoutError.d.ts.map +1 -0
  18. package/dist/errors/bridgeTimeoutError.js +12 -0
  19. package/dist/errors/errorHandler.d.ts +2 -0
  20. package/dist/errors/errorHandler.d.ts.map +1 -0
  21. package/dist/errors/errorHandler.js +152 -0
  22. package/dist/errors/errors.d.ts +45 -0
  23. package/dist/errors/errors.d.ts.map +1 -0
  24. package/dist/errors/errors.js +89 -0
  25. package/dist/jest.d.ts +2 -0
  26. package/dist/jest.d.ts.map +1 -0
  27. package/dist/jest.js +7 -0
  28. package/dist/platforms/android/build.d.ts +3 -2
  29. package/dist/platforms/android/build.d.ts.map +1 -1
  30. package/dist/platforms/android/build.js +24 -49
  31. package/dist/platforms/android/device.d.ts +5 -0
  32. package/dist/platforms/android/device.d.ts.map +1 -0
  33. package/dist/platforms/android/device.js +36 -0
  34. package/dist/platforms/android/emulator.d.ts +0 -1
  35. package/dist/platforms/android/emulator.d.ts.map +1 -1
  36. package/dist/platforms/android/emulator.js +101 -132
  37. package/dist/platforms/android/index.d.ts.map +1 -1
  38. package/dist/platforms/android/index.js +23 -19
  39. package/dist/platforms/ios/build.d.ts +5 -7
  40. package/dist/platforms/ios/build.d.ts.map +1 -1
  41. package/dist/platforms/ios/build.js +41 -116
  42. package/dist/platforms/ios/device.d.ts +11 -0
  43. package/dist/platforms/ios/device.d.ts.map +1 -0
  44. package/dist/platforms/ios/device.js +51 -0
  45. package/dist/platforms/ios/index.d.ts.map +1 -1
  46. package/dist/platforms/ios/index.js +24 -32
  47. package/dist/platforms/ios/simulator.d.ts +4 -4
  48. package/dist/platforms/ios/simulator.d.ts.map +1 -1
  49. package/dist/platforms/ios/simulator.js +104 -131
  50. package/dist/platforms/platform-adapter.d.ts +2 -4
  51. package/dist/platforms/platform-adapter.d.ts.map +1 -1
  52. package/dist/platforms/platform-registry.d.ts.map +1 -1
  53. package/dist/platforms/platform-registry.js +5 -1
  54. package/dist/platforms/vega/build.d.ts +23 -0
  55. package/dist/platforms/vega/build.d.ts.map +1 -0
  56. package/dist/platforms/vega/build.js +55 -0
  57. package/dist/platforms/vega/device.d.ts +57 -0
  58. package/dist/platforms/vega/device.d.ts.map +1 -0
  59. package/dist/platforms/vega/device.js +206 -0
  60. package/dist/platforms/vega/index.d.ts +4 -0
  61. package/dist/platforms/vega/index.d.ts.map +1 -0
  62. package/dist/platforms/vega/index.js +75 -0
  63. package/dist/platforms/web/index.d.ts +3 -1
  64. package/dist/platforms/web/index.d.ts.map +1 -1
  65. package/dist/platforms/web/index.js +9 -50
  66. package/dist/process.js +1 -1
  67. package/dist/reporters/default-reporter.d.ts.map +1 -1
  68. package/dist/reporters/default-reporter.js +22 -17
  69. package/dist/reporters/junit-reporter.d.ts +3 -0
  70. package/dist/reporters/junit-reporter.d.ts.map +1 -0
  71. package/dist/reporters/junit-reporter.js +119 -0
  72. package/dist/reporters/live-reporter.d.ts +20 -0
  73. package/dist/reporters/live-reporter.d.ts.map +1 -0
  74. package/dist/reporters/live-reporter.js +176 -0
  75. package/dist/src/reporters/default-reporter.js +135 -0
  76. package/dist/test-reporter-demo.js +95 -0
  77. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  78. package/dist/utils/status-formatter.d.ts +27 -0
  79. package/dist/utils/status-formatter.d.ts.map +1 -0
  80. package/dist/utils/status-formatter.js +54 -0
  81. package/dist/utils.d.ts +6 -0
  82. package/dist/utils.d.ts.map +1 -0
  83. package/dist/utils.js +26 -0
  84. package/package.json +3 -3
@@ -1,123 +1,48 @@
1
- import { exec } from 'node:child_process';
2
- import { reloadApp } from '../../bundlers/metro.js';
1
+ import { spawn, spawnAndForget } from '@react-native-harness/tools';
2
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
3
3
  export const listDevices = async () => {
4
- return new Promise((resolve, reject) => {
5
- exec('xcrun simctl list devices --json', (error, stdout) => {
6
- if (error) {
7
- reject(error);
8
- return;
9
- }
10
- try {
11
- const devices = JSON.parse(stdout);
12
- resolve(devices);
13
- }
14
- catch (parseError) {
15
- reject(parseError);
16
- }
17
- });
18
- });
19
- };
20
- export const getDeviceByName = async (simulatorName) => {
21
- try {
22
- const devices = await listDevices();
23
- for (const runtime in devices.devices) {
24
- const runtimeDevices = devices.devices[runtime];
25
- for (const device of runtimeDevices) {
26
- if (device.name === simulatorName && device.isAvailable) {
27
- return device;
28
- }
29
- }
30
- }
4
+ const { stdout } = await spawn('xcrun', [
5
+ 'simctl',
6
+ 'list',
7
+ 'devices',
8
+ '--json',
9
+ ]);
10
+ return JSON.parse(stdout);
11
+ };
12
+ export const getDeviceByName = async (simulatorName, systemVersion
13
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
14
+ ) => {
15
+ const devices = await listDevices();
16
+ const expectedRuntimeId = `com.apple.CoreSimulator.SimRuntime.iOS-${systemVersion.replace(/\./, '-')}`;
17
+ const runtime = devices.devices[expectedRuntimeId];
18
+ if (!runtime) {
31
19
  return null;
32
20
  }
33
- catch (error) {
34
- throw error;
21
+ const runtimeDevices = devices.devices[runtime];
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ const device = runtimeDevices.find((d) => d.name === simulatorName);
24
+ if (device) {
25
+ return device;
35
26
  }
36
- };
37
- export const installPods = async () => {
38
- return new Promise((resolve, reject) => {
39
- exec('cd ios && bundle exec pod install', (error) => {
40
- if (error) {
41
- console.warn('CocoaPods install failed:', error.message);
42
- reject(error);
43
- return;
44
- }
45
- resolve();
46
- });
47
- });
27
+ return null;
48
28
  };
49
29
  export const listApps = async (udid) => {
50
- return new Promise((resolve, reject) => {
51
- exec(`xcrun simctl listapps ${udid}`, (error, stdout) => {
52
- if (error) {
53
- reject(error);
54
- return;
55
- }
56
- resolve(stdout);
57
- });
58
- });
59
- };
60
- export const isAppInstalled = async (simulatorName, bundleId) => {
61
- try {
62
- const device = await getDeviceByName(simulatorName);
63
- if (!device) {
64
- return false;
65
- }
66
- const appList = await listApps(device.udid);
67
- return appList.includes(bundleId);
68
- }
69
- catch (error) {
70
- throw error;
71
- }
72
- };
73
- export const buildIOSApp = async (simulatorName, maxRetries = 2) => {
74
- return new Promise((resolve, reject) => {
75
- let attempts = 0;
76
- const attemptBuild = async () => {
77
- attempts++;
78
- try {
79
- await installPods();
80
- }
81
- catch { }
82
- exec(`npx react-native run-ios --simulator="${simulatorName}" --no-packager`, async (error) => {
83
- if (error) {
84
- if (attempts <= maxRetries) {
85
- try {
86
- await reloadApp(8081);
87
- setTimeout(attemptBuild, 3000);
88
- }
89
- catch (reloadError) {
90
- setTimeout(attemptBuild, 3000);
91
- }
92
- }
93
- else {
94
- reject(error);
95
- }
96
- return;
97
- }
98
- resolve();
99
- });
100
- };
101
- attemptBuild();
102
- });
103
- };
104
- export const runApp = async (simulatorName, appName) => {
105
- return new Promise((resolve, reject) => {
106
- exec(`xcrun simctl terminate "${simulatorName}" ${appName}`, () => {
107
- exec(`xcrun simctl launch "${simulatorName}" ${appName}`, (error) => {
108
- if (error) {
109
- reject(error);
110
- return;
111
- }
112
- resolve();
113
- });
114
- });
115
- });
116
- };
117
- export const killApp = async (simulatorName, appName) => {
118
- return new Promise((resolve) => {
119
- exec(`xcrun simctl terminate "${simulatorName}" ${appName}`, () => {
120
- resolve();
121
- });
122
- });
30
+ const { stdout: plistOutput } = await spawn('xcrun', [
31
+ 'simctl',
32
+ 'listapps',
33
+ udid,
34
+ ]);
35
+ const { stdout: jsonOutput } = await spawn('plutil', ['-convert', 'json', '-o', '-', '-'], { stdin: { string: plistOutput } });
36
+ return Object.keys(JSON.parse(jsonOutput));
37
+ };
38
+ export const isAppInstalled = async (udid, bundleId) => {
39
+ const appList = await listApps(udid);
40
+ return appList.includes(bundleId);
41
+ };
42
+ export const runApp = async (udid, appName) => {
43
+ await killApp(udid, appName);
44
+ await spawn('xcrun', ['simctl', 'launch', udid, appName]);
45
+ };
46
+ export const killApp = async (udid, appName) => {
47
+ await spawnAndForget('xcrun', ['simctl', 'terminate', udid, appName]);
123
48
  };
@@ -0,0 +1,11 @@
1
+ type Device = any;
2
+ export declare const listDevices: () => Promise<{
3
+ devices: Device[];
4
+ }>;
5
+ export declare const getDeviceByName: (simulatorName: string) => Promise<Device | null>;
6
+ export declare const listApps: (udid: string) => Promise<string[]>;
7
+ export declare const isAppInstalled: (simulatorName: string, bundleId: string) => Promise<boolean>;
8
+ export declare const runApp: (simulatorName: string, appName: string) => Promise<void>;
9
+ export declare const killApp: (simulatorName: string, appName: string) => Promise<void>;
10
+ export {};
11
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/platforms/ios/device.ts"],"names":[],"mappings":"AAGA,KAAK,MAAM,GAAG,GAAG,CAAC;AAElB,eAAO,MAAM,WAAW,QAAa,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE,CAQjE,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,eAAe,MAAM,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAavB,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,MAAM,EAAE,CAY7D,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,eAAe,MAAM,EACrB,UAAU,MAAM,KACf,OAAO,CAAC,OAAO,CASjB,CAAC;AAEF,eAAO,MAAM,MAAM,GACjB,eAAe,MAAM,EACrB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAGd,CAAC;AAEF,eAAO,MAAM,OAAO,GAClB,eAAe,MAAM,EACrB,SAAS,MAAM,KACd,OAAO,CAAC,IAAI,CAOd,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { spawn, spawnAndForget } from '@react-native-harness/tools';
2
+ export const listDevices = async () => {
3
+ const { stdout } = await spawn('xcrun', [
4
+ 'simctl',
5
+ 'list',
6
+ 'devices',
7
+ '--json',
8
+ ]);
9
+ return JSON.parse(stdout);
10
+ };
11
+ export const getDeviceByName = async (simulatorName) => {
12
+ const devices = await listDevices();
13
+ for (const runtime in devices.devices) {
14
+ const runtimeDevices = devices.devices[runtime];
15
+ for (const device of runtimeDevices) {
16
+ if (device.name === simulatorName && device.isAvailable) {
17
+ return device;
18
+ }
19
+ }
20
+ }
21
+ return null;
22
+ };
23
+ export const listApps = async (udid) => {
24
+ const { stdout: plistOutput } = await spawn('xcrun', [
25
+ 'simctl',
26
+ 'listapps',
27
+ udid,
28
+ ]);
29
+ const { stdout: jsonOutput } = await spawn('plutil', ['-convert', 'json', '-o', '-', '-'], { stdin: { string: plistOutput } });
30
+ return Object.keys(JSON.parse(jsonOutput));
31
+ };
32
+ export const isAppInstalled = async (simulatorName, bundleId) => {
33
+ const device = await getDeviceByName(simulatorName);
34
+ if (!device) {
35
+ throw new Error(`Simulator ${simulatorName} not found`);
36
+ }
37
+ const appList = await listApps(device.udid);
38
+ return appList.includes(bundleId);
39
+ };
40
+ export const runApp = async (simulatorName, appName) => {
41
+ await killApp(simulatorName, appName);
42
+ await spawn('xcrun', ['simctl', 'launch', simulatorName, appName]);
43
+ };
44
+ export const killApp = async (simulatorName, appName) => {
45
+ await spawnAndForget('xcrun', [
46
+ 'simctl',
47
+ 'terminate',
48
+ simulatorName,
49
+ appName,
50
+ ]);
51
+ };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/platforms/ios/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAc9D,QAAA,MAAM,kBAAkB,EAAE,eAgDzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/platforms/ios/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAa9D,QAAA,MAAM,kBAAkB,EAAE,eA8CzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -1,50 +1,42 @@
1
- import { getAppiumInteractionEngine } from '@react-native-harness/interaction-engine';
2
- import { assertNativeRunner } from '@react-native-harness/config';
3
- import { runSimulator } from './simulator.js';
4
- import { buildIOSApp, isAppInstalled, runApp, killApp } from './build.js';
1
+ import { assertIOSRunnerConfig, } from '@react-native-harness/config';
2
+ import { getSimulatorDeviceId, getSimulatorStatus, runSimulator, stopSimulator, } from './simulator.js';
3
+ import { isAppInstalled, runApp, killApp } from './build.js';
5
4
  import { killWithAwait } from '../../process.js';
6
5
  import { runMetro } from '../../bundlers/metro.js';
7
- const measure = async (fn, name) => {
8
- const start = performance.now();
9
- const result = await fn();
10
- const end = performance.now();
11
- console.log(`${name} took ${end - start}ms`);
12
- return result;
13
- };
6
+ import { AppNotInstalledError } from '../../errors/errors.js';
7
+ import { assert } from '../../utils.js';
14
8
  const iosPlatformAdapter = {
15
9
  name: 'ios',
16
- getEnvironment: async (config) => {
17
- assertNativeRunner(config);
18
- let simulator = null;
19
- // Start metro and interaction engine in parallel
10
+ getEnvironment: async (runner) => {
11
+ assertIOSRunnerConfig(runner);
12
+ // TODO: system version is also important as there may be two emulators with the same name
13
+ // but different system versions
14
+ let shouldStopSimulator = false;
15
+ const udid = await getSimulatorDeviceId(runner.deviceId, runner.systemVersion);
16
+ assert(!!udid, 'Simulator not found');
17
+ const simulatorStatus = await getSimulatorStatus(udid);
20
18
  const metroPromise = runMetro();
21
- const interactionEnginePromise = getAppiumInteractionEngine(config);
22
- // Start simulator
23
- simulator = (await measure(() => runSimulator(config.runner.deviceId), 'runSimulator'));
24
- console.log('simulator started');
25
- const isInstalled = await measure(() => isAppInstalled(config.runner.deviceId, config.runner.bundleId), 'isAppInstalled');
26
- console.log(isInstalled);
27
- if (!isInstalled) {
28
- await buildIOSApp(config.runner.deviceId);
19
+ if (simulatorStatus === 'stopped') {
20
+ await runSimulator(udid);
21
+ shouldStopSimulator = true;
29
22
  }
30
- else {
31
- await runApp(config.runner.deviceId, config.runner.bundleId);
23
+ const isInstalled = await isAppInstalled(udid, runner.bundleId);
24
+ if (!isInstalled) {
25
+ throw new AppNotInstalledError(runner.deviceId, runner.bundleId, 'ios');
32
26
  }
33
- const interactionEngine = await interactionEnginePromise;
34
27
  const metro = await metroPromise;
28
+ await runApp(udid, runner.bundleId);
35
29
  return {
36
30
  restart: async () => {
37
- await runApp(config.runner.deviceId, config.runner.bundleId);
31
+ await runApp(udid, runner.bundleId);
38
32
  },
39
33
  dispose: async () => {
40
- if (simulator) {
41
- await killWithAwait(simulator);
34
+ await killApp(udid, runner.bundleId);
35
+ if (shouldStopSimulator) {
36
+ await stopSimulator(udid);
42
37
  }
43
- await interactionEngine.close();
44
38
  await killWithAwait(metro);
45
- await killApp(config.runner.deviceId, config.runner.bundleId);
46
39
  },
47
- interactionEngine,
48
40
  };
49
41
  },
50
42
  };
@@ -1,11 +1,11 @@
1
1
  export type IOSSimulatorStatus = 'stopped' | 'loading' | 'running';
2
- export declare const getSimulatorDeviceId: (simulatorName: string) => Promise<string | null>;
2
+ export declare const getSimulatorDeviceId: (simulatorName: string, systemVersion: string) => Promise<string | null>;
3
3
  export declare const getAvailableSimulators: () => Promise<Array<{
4
4
  name: string;
5
5
  udid: string;
6
6
  runtime: string;
7
7
  }>>;
8
- export declare const getSimulatorStatus: (simulatorName: string) => Promise<IOSSimulatorStatus>;
9
- export declare const runSimulator: (name: string) => Promise<void>;
10
- export declare const stopSimulator: (name: string) => Promise<void>;
8
+ export declare const getSimulatorStatus: (udid: string) => Promise<IOSSimulatorStatus>;
9
+ export declare const runSimulator: (udid: string) => Promise<void>;
10
+ export declare const stopSimulator: (udid: string) => Promise<void>;
11
11
  //# sourceMappingURL=simulator.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"simulator.d.ts","sourceRoot":"","sources":["../../../src/platforms/ios/simulator.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnE,eAAO,MAAM,oBAAoB,GAC/B,eAAe,MAAM,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CAgCvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAO,OAAO,CAC/C,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAsCvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,eAAe,MAAM,KACpB,OAAO,CAAC,kBAAkB,CAwC5B,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAmD7D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAWxD,CAAC"}
1
+ {"version":3,"file":"simulator.d.ts","sourceRoot":"","sources":["../../../src/platforms/ios/simulator.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;AAEnE,eAAO,MAAM,oBAAoB,GAC/B,eAAe,MAAM,EACrB,eAAe,MAAM,KACpB,OAAO,CAAC,MAAM,GAAG,IAAI,CA+BvB,CAAC;AAEF,eAAO,MAAM,sBAAsB,QAAa,OAAO,CACrD,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAoCvD,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,KACX,OAAO,CAAC,kBAAkB,CAiC5B,CAAC;AAEF,eAAO,MAAM,YAAY,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAkC7D,CAAC;AAEF,eAAO,MAAM,aAAa,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,IAAI,CAE9D,CAAC"}
@@ -1,128 +1,108 @@
1
- import { exec } from 'node:child_process';
2
- export const getSimulatorDeviceId = (simulatorName) => {
3
- return new Promise((resolve) => {
4
- exec(`xcrun simctl list devices --json`, (error, stdout) => {
5
- if (error) {
6
- resolve(null);
7
- return;
8
- }
9
- try {
10
- const devices = JSON.parse(stdout);
11
- // Find the device across all iOS versions
12
- for (const runtime in devices.devices) {
13
- if (runtime.includes('iOS')) {
14
- const runtimeDevices = devices.devices[runtime];
15
- const device = runtimeDevices.find((d) => d.name === simulatorName && d.state === 'Booted');
16
- if (device) {
17
- resolve(device.udid);
18
- return;
19
- }
20
- }
21
- }
22
- resolve(null);
23
- }
24
- catch (parseError) {
25
- resolve(null);
26
- }
27
- });
28
- });
1
+ import { spawn, SubprocessError } from '@react-native-harness/tools';
2
+ export const getSimulatorDeviceId = async (simulatorName, systemVersion) => {
3
+ try {
4
+ const { stdout } = await spawn('xcrun', [
5
+ 'simctl',
6
+ 'list',
7
+ 'devices',
8
+ '--json',
9
+ ]);
10
+ const devices = JSON.parse(stdout);
11
+ const expectedRuntimeId = `com.apple.CoreSimulator.SimRuntime.iOS-${systemVersion.replace(/\./, '-')}`;
12
+ const runtime = devices.devices[expectedRuntimeId];
13
+ if (!runtime) {
14
+ return null;
15
+ }
16
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
+ const device = runtime.find((d) => d.name === simulatorName);
18
+ if (device) {
19
+ return device.udid;
20
+ }
21
+ return null;
22
+ }
23
+ catch {
24
+ return null;
25
+ }
29
26
  };
30
- export const getAvailableSimulators = () => {
31
- return new Promise((resolve) => {
32
- exec(`xcrun simctl list devices --json`, (error, stdout) => {
33
- if (error) {
34
- resolve([]);
35
- return;
36
- }
37
- try {
38
- const devices = JSON.parse(stdout);
39
- const simulators = [];
40
- for (const runtime in devices.devices) {
41
- if (runtime.includes('iOS')) {
42
- const runtimeDevices = devices.devices[runtime];
43
- runtimeDevices.forEach((device) => {
44
- if (device.isAvailable) {
45
- simulators.push({
46
- name: device.name,
47
- udid: device.udid,
48
- runtime: runtime,
49
- });
50
- }
27
+ export const getAvailableSimulators = async () => {
28
+ try {
29
+ const { stdout } = await spawn('xcrun', [
30
+ 'simctl',
31
+ 'list',
32
+ 'devices',
33
+ '--json',
34
+ ]);
35
+ const devices = JSON.parse(stdout);
36
+ const simulators = [];
37
+ for (const runtime in devices.devices) {
38
+ if (runtime.includes('iOS')) {
39
+ const runtimeDevices = devices.devices[runtime];
40
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41
+ runtimeDevices.forEach((device) => {
42
+ if (device.isAvailable) {
43
+ simulators.push({
44
+ name: device.name,
45
+ udid: device.udid,
46
+ runtime: runtime,
51
47
  });
52
48
  }
53
- }
54
- resolve(simulators);
49
+ });
55
50
  }
56
- catch (parseError) {
57
- resolve([]);
58
- }
59
- });
60
- });
51
+ }
52
+ return simulators;
53
+ }
54
+ catch {
55
+ return [];
56
+ }
61
57
  };
62
- export const getSimulatorStatus = (simulatorName) => {
63
- return new Promise((resolve) => {
64
- exec(`xcrun simctl list devices --json`, (error, stdout) => {
65
- if (error) {
66
- resolve('stopped');
67
- return;
68
- }
69
- try {
70
- const devices = JSON.parse(stdout);
71
- for (const runtime in devices.devices) {
72
- if (runtime.includes('iOS')) {
73
- const runtimeDevices = devices.devices[runtime];
74
- const device = runtimeDevices.find((d) => d.name === simulatorName);
75
- if (device) {
76
- switch (device.state) {
77
- case 'Booted':
78
- resolve('running');
79
- return;
80
- case 'Booting':
81
- resolve('loading');
82
- return;
83
- default:
84
- resolve('stopped');
85
- return;
86
- }
87
- }
58
+ export const getSimulatorStatus = async (udid) => {
59
+ try {
60
+ const { stdout } = await spawn('xcrun', [
61
+ 'simctl',
62
+ 'list',
63
+ 'devices',
64
+ '--json',
65
+ ]);
66
+ const devices = JSON.parse(stdout);
67
+ for (const runtime in devices.devices) {
68
+ if (runtime.includes('iOS')) {
69
+ const runtimeDevices = devices.devices[runtime];
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ const device = runtimeDevices.find((d) => d.udid === udid);
72
+ if (device) {
73
+ switch (device.state) {
74
+ case 'Booted':
75
+ return 'running';
76
+ case 'Booting':
77
+ return 'loading';
78
+ default:
79
+ return 'stopped';
88
80
  }
89
81
  }
90
- resolve('stopped');
91
82
  }
92
- catch (parseError) {
93
- resolve('stopped');
94
- }
95
- });
96
- });
83
+ }
84
+ return 'stopped';
85
+ }
86
+ catch {
87
+ return 'stopped';
88
+ }
97
89
  };
98
- export const runSimulator = async (name) => {
99
- const deviceId = await getSimulatorDeviceId(name);
100
- if (!deviceId) {
101
- throw new Error('Simulator not found');
90
+ export const runSimulator = async (udid) => {
91
+ try {
92
+ await spawn('xcrun', ['simctl', 'boot', udid]);
102
93
  }
103
- await new Promise((resolve, reject) => {
104
- exec(`xcrun simctl boot ${deviceId}`, (bootError) => {
105
- if (bootError &&
106
- !bootError.message.includes('Unable to boot device in current state: Booted')) {
107
- reject(bootError);
108
- return;
109
- }
110
- resolve();
111
- });
112
- });
113
- await new Promise((resolve, reject) => {
114
- exec('open -a Simulator', (error) => {
115
- if (error) {
116
- reject(error);
117
- return;
118
- }
119
- resolve();
120
- });
121
- });
94
+ catch (bootError) {
95
+ // Ignore if simulator is already booted
96
+ if (bootError instanceof SubprocessError &&
97
+ !bootError.stderr?.includes('Unable to boot device in current state: Booted')) {
98
+ throw bootError;
99
+ }
100
+ }
101
+ await spawn('open', ['-a', 'Simulator']);
122
102
  let attempts = 0;
123
103
  while (true) {
124
104
  attempts++;
125
- const status = await getSimulatorStatus(name);
105
+ const status = await getSimulatorStatus(udid);
126
106
  if (status === 'running') {
127
107
  break;
128
108
  }
@@ -132,25 +112,18 @@ export const runSimulator = async (name) => {
132
112
  await new Promise((resolve) => setTimeout(resolve, 1000));
133
113
  }
134
114
  };
135
- export const stopSimulator = (name) => {
136
- return new Promise((resolve, reject) => {
137
- getSimulatorDeviceId(name).then((simulatorId) => {
138
- if (!simulatorId) {
139
- resolve(); // Already stopped
140
- return;
141
- }
142
- stopSimulatorById(simulatorId, resolve, reject);
143
- });
144
- });
115
+ export const stopSimulator = async (udid) => {
116
+ await stopSimulatorById(udid);
145
117
  };
146
- const stopSimulatorById = (simulatorId, resolve, reject) => {
147
- // Shutdown the simulator
148
- exec(`xcrun simctl shutdown ${simulatorId}`, (shutdownError) => {
149
- if (shutdownError &&
150
- !shutdownError.message.includes('Unable to shutdown device in current state: Shutdown')) {
151
- reject(shutdownError);
152
- return;
118
+ const stopSimulatorById = async (udid) => {
119
+ try {
120
+ await spawn('xcrun', ['simctl', 'shutdown', udid]);
121
+ }
122
+ catch (shutdownError) {
123
+ // Ignore if simulator is already shut down
124
+ if (shutdownError instanceof SubprocessError &&
125
+ !shutdownError.stderr?.includes('Unable to shutdown device in current state: Shutdown')) {
126
+ throw shutdownError;
153
127
  }
154
- resolve();
155
- });
128
+ }
156
129
  };
@@ -1,12 +1,10 @@
1
- import { Config } from '@react-native-harness/config';
2
- import { InteractionEngine } from '@react-native-harness/interaction-engine';
1
+ import { TestRunnerConfig } from '@react-native-harness/config';
3
2
  export type Environment = {
4
3
  restart: () => Promise<void>;
5
4
  dispose: () => Promise<void>;
6
- interactionEngine: InteractionEngine;
7
5
  };
8
6
  export type PlatformAdapter = {
9
7
  name: string;
10
- getEnvironment: (config: Config) => Promise<Environment>;
8
+ getEnvironment: (runner: TestRunnerConfig) => Promise<Environment>;
11
9
  };
12
10
  //# sourceMappingURL=platform-adapter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform-adapter.d.ts","sourceRoot":"","sources":["../../src/platforms/platform-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,8BAA8B,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAE7E,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,iBAAiB,EAAE,iBAAiB,CAAC;CACtC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1D,CAAC"}
1
+ {"version":3,"file":"platform-adapter.d.ts","sourceRoot":"","sources":["../../src/platforms/platform-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhE,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACpE,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"platform-registry.d.ts","sourceRoot":"","sources":["../../src/platforms/platform-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AASxD,eAAO,MAAM,kBAAkB,GAC7B,cAAc,MAAM,KACnB,OAAO,CAAC,eAAe,CAUzB,CAAC"}
1
+ {"version":3,"file":"platform-registry.d.ts","sourceRoot":"","sources":["../../src/platforms/platform-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAaxD,eAAO,MAAM,kBAAkB,GAC7B,cAAc,MAAM,KACnB,OAAO,CAAC,eAAe,CAUzB,CAAC"}
@@ -1,8 +1,12 @@
1
1
  import androidPlatformAdapter from './android/index.js';
2
2
  import iosPlatformAdapter from './ios/index.js';
3
+ import webPlatformAdapter from './web/index.js';
4
+ import vegaPlatformAdapter from './vega/index.js';
3
5
  const platformAdapters = {
4
6
  android: androidPlatformAdapter,
5
7
  ios: iosPlatformAdapter,
8
+ web: webPlatformAdapter,
9
+ vega: vegaPlatformAdapter,
6
10
  };
7
11
  export const getPlatformAdapter = async (platformName) => {
8
12
  if (!(platformName in platformAdapters)) {
@@ -11,7 +15,7 @@ export const getPlatformAdapter = async (platformName) => {
11
15
  try {
12
16
  return platformAdapters[platformName];
13
17
  }
14
- catch (error) {
18
+ catch {
15
19
  throw new Error(`Platform adapter for ${platformName} not found`);
16
20
  }
17
21
  };