@react-native-harness/jest 1.1.0-rc.1 → 1.1.0-rc.2

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 (68) hide show
  1. package/dist/__tests__/harness-cache.test.d.ts +2 -0
  2. package/dist/__tests__/harness-cache.test.d.ts.map +1 -0
  3. package/dist/__tests__/harness-cache.test.js +51 -0
  4. package/dist/__tests__/harness.test.js +340 -47
  5. package/dist/__tests__/index.test.d.ts +2 -0
  6. package/dist/__tests__/index.test.d.ts.map +1 -0
  7. package/dist/__tests__/index.test.js +42 -0
  8. package/dist/cli-args.d.ts +1 -0
  9. package/dist/cli-args.d.ts.map +1 -1
  10. package/dist/cli-args.js +5 -0
  11. package/dist/crash-supervisor.d.ts.map +1 -1
  12. package/dist/crash-supervisor.js +7 -6
  13. package/dist/errors.d.ts +1 -0
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js +1 -0
  16. package/dist/harness.d.ts +23 -1
  17. package/dist/harness.d.ts.map +1 -1
  18. package/dist/harness.js +396 -50
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +205 -58
  21. package/dist/logs.d.ts +1 -0
  22. package/dist/logs.d.ts.map +1 -1
  23. package/dist/logs.js +3 -0
  24. package/dist/run.d.ts +7 -1
  25. package/dist/run.d.ts.map +1 -1
  26. package/dist/run.js +13 -8
  27. package/dist/setup.d.ts.map +1 -1
  28. package/dist/setup.js +18 -2
  29. package/dist/tsconfig.lib.tsbuildinfo +1 -1
  30. package/package.json +7 -6
  31. package/src/__tests__/harness-cache.test.ts +74 -0
  32. package/src/__tests__/harness.test.ts +469 -51
  33. package/src/__tests__/index.test.ts +61 -0
  34. package/src/cli-args.ts +6 -0
  35. package/src/crash-supervisor.ts +13 -6
  36. package/src/env.d.ts +1 -1
  37. package/src/errors.ts +5 -0
  38. package/src/harness.ts +504 -58
  39. package/src/index.ts +276 -64
  40. package/src/logs.ts +4 -0
  41. package/src/run.ts +20 -10
  42. package/src/setup.ts +22 -1
  43. package/tsconfig.json +3 -3
  44. package/tsconfig.lib.json +6 -6
  45. package/dist/cli-args.test.d.ts +0 -2
  46. package/dist/cli-args.test.d.ts.map +0 -1
  47. package/dist/cli-args.test.js +0 -1
  48. package/dist/crash-monitor.d.ts +0 -16
  49. package/dist/crash-monitor.d.ts.map +0 -1
  50. package/dist/crash-monitor.js +0 -75
  51. package/dist/event-mapper.d.ts +0 -16
  52. package/dist/event-mapper.d.ts.map +0 -1
  53. package/dist/event-mapper.js +0 -120
  54. package/dist/global-setup.d.ts +0 -3
  55. package/dist/global-setup.d.ts.map +0 -1
  56. package/dist/global-setup.js +0 -60
  57. package/dist/global-teardown.d.ts +0 -3
  58. package/dist/global-teardown.d.ts.map +0 -1
  59. package/dist/global-teardown.js +0 -11
  60. package/dist/harness-reporter.d.ts +0 -8
  61. package/dist/harness-reporter.d.ts.map +0 -1
  62. package/dist/harness-reporter.js +0 -12
  63. package/dist/jest-options.d.ts +0 -2
  64. package/dist/jest-options.d.ts.map +0 -1
  65. package/dist/jest-options.js +0 -1
  66. package/dist/types.d.ts +0 -17
  67. package/dist/types.d.ts.map +0 -1
  68. package/dist/types.js +0 -1
package/dist/index.js CHANGED
@@ -5,7 +5,23 @@ import { teardown } from './teardown.js';
5
5
  import { HarnessError } from '@react-native-harness/tools';
6
6
  import { getErrorMessage } from './logs.js';
7
7
  import { DeviceNotRespondingError } from '@react-native-harness/bridge/server';
8
- import { NativeCrashError } from './errors.js';
8
+ import { NativeCrashError, StartupStallError } from './errors.js';
9
+ import { logger } from '@react-native-harness/tools';
10
+ import { randomUUID } from 'node:crypto';
11
+ import path from 'node:path';
12
+ const runLogger = logger.child('run');
13
+ const createRunSummary = () => ({
14
+ passed: 0,
15
+ failed: 0,
16
+ skipped: 0,
17
+ todo: 0,
18
+ });
19
+ const applyJestResultToSummary = (summary, result) => {
20
+ summary.passed += result.numPassingTests;
21
+ summary.failed += result.numFailingTests;
22
+ summary.skipped += result.numPendingTests;
23
+ summary.todo += result.numTodoTests;
24
+ };
9
25
  class CancelRun extends Error {
10
26
  constructor(message) {
11
27
  super(message);
@@ -44,64 +60,195 @@ export default class JestHarness {
44
60
  async _createInBandTestRun(tests, watcher, harness, harnessConfig, onStart, onResult, onFailure) {
45
61
  const mutex = pLimit(1);
46
62
  let isFirstTest = true;
47
- return tests.reduce((promise, test) => mutex(() => promise
48
- .then(async () => {
49
- if (watcher.isInterrupted()) {
50
- throw new CancelRun();
51
- }
52
- if (harnessConfig.resetEnvironmentBetweenTestFiles &&
53
- !isFirstTest) {
54
- await harness.restart(test.path);
55
- }
56
- isFirstTest = false;
57
- return onStart(test).then(async () => {
58
- if (!harnessConfig.detectNativeCrashes) {
59
- await harness.ensureAppReady(test.path);
60
- return runHarnessTestFile({
61
- testPath: test.path,
62
- harness,
63
- globalConfig: this.#globalConfig,
64
- projectConfig: test.context.config,
63
+ const startTime = Date.now();
64
+ const runId = randomUUID();
65
+ const watchMode = this.#globalConfig.watch || this.#globalConfig.watchAll;
66
+ const rootDir = this.#globalConfig.rootDir ?? process.cwd();
67
+ const testFiles = tests.map((test) => path.relative(rootDir, test.path));
68
+ const summary = createRunSummary();
69
+ const updateRunState = (overrides = {}) => {
70
+ const nextRunState = {
71
+ runId,
72
+ startTime,
73
+ testFiles,
74
+ watchMode,
75
+ coverageEnabled: this.#globalConfig.collectCoverage,
76
+ summary,
77
+ status: summary.failed > 0 ? 'failed' : 'passed',
78
+ ...overrides,
79
+ };
80
+ harness.setRunState(nextRunState);
81
+ return nextRunState;
82
+ };
83
+ updateRunState();
84
+ runLogger.debug('run started: runId=%s files=%d watchMode=%s coverage=%s', runId, testFiles.length, watchMode, this.#globalConfig.collectCoverage);
85
+ await harness.callHook('run:started', {
86
+ runId,
87
+ startTime,
88
+ testFiles,
89
+ watchMode,
90
+ coverageEnabled: this.#globalConfig.collectCoverage,
91
+ });
92
+ await harness.callHook('metro:initialized', {
93
+ runId,
94
+ port: harnessConfig.metroPort,
95
+ host: harnessConfig.host?.trim() || undefined,
96
+ });
97
+ try {
98
+ await tests.reduce((promise, test) => mutex(() => {
99
+ let didApplySummary = false;
100
+ return promise
101
+ .then(async () => {
102
+ const relativeTestPath = path.relative(rootDir, test.path);
103
+ const testFileStartedAt = Date.now();
104
+ let didEmitTestFileFinished = false;
105
+ await harness.callHook('test-file:started', {
106
+ runId,
107
+ file: relativeTestPath,
65
108
  });
66
- }
67
- await harness.ensureAppReady(test.path);
68
- harness.crashSupervisor.beginTestRun(test.path);
69
- const crashPromise = harness.crashSupervisor.waitForCrash(test.path);
70
- try {
71
- const result = await Promise.race([
72
- runHarnessTestFile({
73
- testPath: test.path,
74
- harness,
75
- globalConfig: this.#globalConfig,
76
- projectConfig: test.context.config,
77
- }),
78
- crashPromise,
79
- ]);
80
- return result;
81
- }
82
- finally {
83
- harness.crashSupervisor.cancelCrashWaiters();
84
- }
85
- });
86
- })
87
- .then((result) => onResult(test, result))
88
- .catch(async (err) => {
89
- if (err instanceof NativeCrashError) {
90
- harness.crashSupervisor.reset();
91
- onFailure(test, {
92
- message: err.message,
93
- stack: '',
109
+ runLogger.debug('test file started: %s', relativeTestPath);
110
+ const emitTestFileFinished = async (options) => {
111
+ didEmitTestFileFinished = true;
112
+ runLogger.debug('test file finished: %s status=%s duration=%dms', relativeTestPath, options.status, options.duration);
113
+ await harness.callHook('test-file:finished', {
114
+ runId,
115
+ file: relativeTestPath,
116
+ duration: options.duration,
117
+ status: options.status,
118
+ result: options.result,
119
+ });
120
+ };
121
+ try {
122
+ if (watcher.isInterrupted()) {
123
+ throw new CancelRun();
124
+ }
125
+ if (harnessConfig.resetEnvironmentBetweenTestFiles &&
126
+ !isFirstTest) {
127
+ runLogger.debug('resetting environment before %s', relativeTestPath);
128
+ await harness.restart(test.path);
129
+ }
130
+ isFirstTest = false;
131
+ const result = await onStart(test).then(async () => {
132
+ if (!harnessConfig.detectNativeCrashes) {
133
+ runLogger.debug('native crash detection disabled for %s', relativeTestPath);
134
+ await harness.ensureAppReady(test.path);
135
+ return runHarnessTestFile({
136
+ testPath: test.path,
137
+ harness,
138
+ globalConfig: this.#globalConfig,
139
+ projectConfig: test.context.config,
140
+ });
141
+ }
142
+ await harness.ensureAppReady(test.path);
143
+ harness.crashSupervisor.beginTestRun(test.path);
144
+ runLogger.debug('native crash detection armed for %s', relativeTestPath);
145
+ const crashPromise = harness.crashSupervisor.waitForCrash(test.path);
146
+ try {
147
+ return await Promise.race([
148
+ runHarnessTestFile({
149
+ testPath: test.path,
150
+ harness,
151
+ globalConfig: this.#globalConfig,
152
+ projectConfig: test.context.config,
153
+ }),
154
+ crashPromise,
155
+ ]);
156
+ }
157
+ finally {
158
+ harness.crashSupervisor.cancelCrashWaiters();
159
+ }
160
+ });
161
+ applyJestResultToSummary(summary, result.jestResult);
162
+ didApplySummary = true;
163
+ updateRunState();
164
+ await emitTestFileFinished({
165
+ status: result.harnessResult.status,
166
+ duration: result.duration,
167
+ result: result.harnessResult,
168
+ });
169
+ return result;
170
+ }
171
+ catch (error) {
172
+ if (!didEmitTestFileFinished) {
173
+ await emitTestFileFinished({
174
+ status: 'failed',
175
+ duration: Date.now() - testFileStartedAt,
176
+ result: null,
177
+ });
178
+ }
179
+ throw error;
180
+ }
181
+ })
182
+ .then(async (result) => {
183
+ if (!result) {
184
+ return;
185
+ }
186
+ await onResult(test, result.jestResult);
187
+ })
188
+ .catch(async (err) => {
189
+ if (err instanceof NativeCrashError ||
190
+ err instanceof StartupStallError ||
191
+ err instanceof DeviceNotRespondingError) {
192
+ runLogger.debug('classified runtime failure for %s: %s', test.path, err.name);
193
+ summary.failed += 1;
194
+ updateRunState();
195
+ }
196
+ if (err instanceof NativeCrashError) {
197
+ harness.crashSupervisor.reset();
198
+ onFailure(test, {
199
+ message: err.message,
200
+ stack: '',
201
+ });
202
+ return;
203
+ }
204
+ if (err instanceof StartupStallError) {
205
+ onFailure(test, {
206
+ message: err.message,
207
+ stack: '',
208
+ });
209
+ return;
210
+ }
211
+ if (err instanceof DeviceNotRespondingError) {
212
+ onFailure(test, {
213
+ message: err.message,
214
+ stack: '',
215
+ });
216
+ return;
217
+ }
218
+ if (!(err instanceof CancelRun) && !didApplySummary) {
219
+ summary.failed += 1;
220
+ }
221
+ updateRunState({ error: err });
222
+ onFailure(test, err);
94
223
  });
95
- return;
96
- }
97
- if (err instanceof DeviceNotRespondingError) {
98
- onFailure(test, {
99
- message: err.message,
100
- stack: '',
101
- });
102
- return;
103
- }
104
- onFailure(test, err);
105
- })), Promise.resolve());
224
+ }), Promise.resolve());
225
+ const runState = updateRunState();
226
+ runLogger.debug('run finished: runId=%s status=%s duration=%dms', runId, runState.status ?? 'passed', Date.now() - startTime);
227
+ await harness.callHook('run:finished', {
228
+ runId,
229
+ startTime,
230
+ duration: Date.now() - startTime,
231
+ testFiles,
232
+ summary,
233
+ status: runState.status ?? 'passed',
234
+ });
235
+ }
236
+ catch (error) {
237
+ const runState = updateRunState({
238
+ error,
239
+ status: 'failed',
240
+ });
241
+ runLogger.debug('run failed: runId=%s status=%s', runId, runState.status ?? 'failed');
242
+ await harness.callHook('run:finished', {
243
+ runId,
244
+ startTime,
245
+ duration: Date.now() - startTime,
246
+ testFiles,
247
+ summary,
248
+ status: runState.status ?? 'failed',
249
+ error,
250
+ });
251
+ throw error;
252
+ }
106
253
  }
107
254
  }
package/dist/logs.d.ts CHANGED
@@ -4,5 +4,6 @@ export declare const log: (message: string) => void;
4
4
  export declare const logTestRunHeader: (runner: HarnessPlatform) => void;
5
5
  export declare const logTestEnvironmentReady: (runner: HarnessPlatform) => void;
6
6
  export declare const logMetroPrewarmCompleted: (runner: HarnessPlatform) => void;
7
+ export declare const logMetroCacheReused: (runner: HarnessPlatform) => void;
7
8
  export declare const getErrorMessage: (error: HarnessError) => string;
8
9
  //# sourceMappingURL=logs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAY3D,eAAO,MAAM,GAAG,GAAI,SAAS,MAAM,KAAG,IAErC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,eAAe,KAAG,IAI1D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,eAAe,KAAG,IAEjE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,QAAQ,eAAe,KAAG,IAIlE,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,KAAG,MAErD,CAAC"}
1
+ {"version":3,"file":"logs.d.ts","sourceRoot":"","sources":["../src/logs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAY3D,eAAO,MAAM,GAAG,GAAI,SAAS,MAAM,KAAG,IAErC,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,QAAQ,eAAe,KAAG,IAI1D,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,eAAe,KAAG,IAEjE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAI,QAAQ,eAAe,KAAG,IAIlE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,QAAQ,eAAe,KAAG,IAE7D,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,OAAO,YAAY,KAAG,MAErD,CAAC"}
package/dist/logs.js CHANGED
@@ -18,6 +18,9 @@ export const logTestEnvironmentReady = (runner) => {
18
18
  export const logMetroPrewarmCompleted = (runner) => {
19
19
  log(`${TAG} Metro pre-warm for ${chalk.bold(runner.name)} completed\n`);
20
20
  };
21
+ export const logMetroCacheReused = (runner) => {
22
+ log(`${TAG} Reusing Metro cache for ${chalk.bold(runner.name)}\n`);
23
+ };
21
24
  export const getErrorMessage = (error) => {
22
25
  return `${ERROR_TAG} ${error.message}\n`;
23
26
  };
package/dist/run.d.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  import type { Config as JestConfig } from 'jest-runner';
2
2
  import { TestResult as JestTestResult } from '@jest/test-result';
3
+ import type { TestSuiteResult as HarnessTestSuiteResult } from '@react-native-harness/bridge';
3
4
  import type { Harness } from './harness.js';
4
5
  export type RunHarnessTestFile = (options: {
5
6
  testPath: string;
6
7
  harness: Harness;
7
8
  projectConfig: JestConfig.ProjectConfig;
8
9
  globalConfig: JestConfig.GlobalConfig;
9
- }) => Promise<JestTestResult>;
10
+ }) => Promise<{
11
+ jestResult: JestTestResult;
12
+ harnessResult: HarnessTestSuiteResult;
13
+ relativeTestPath: string;
14
+ duration: number;
15
+ }>;
10
16
  export declare const runHarnessTestFile: RunHarnessTestFile;
11
17
  //# sourceMappingURL=run.d.ts.map
package/dist/run.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAKjE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuD5C,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC;IACxC,YAAY,EAAE,UAAU,CAAC,YAAY,CAAC;CACvC,KAAK,OAAO,CAAC,cAAc,CAAC,CAAC;AAE9B,eAAO,MAAM,kBAAkB,EAAE,kBA6EhC,CAAC"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../src/run.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,UAAU,IAAI,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EACV,eAAe,IAAI,sBAAsB,EAE1C,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAuD5C,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,EAAE;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC;IACxC,YAAY,EAAE,UAAU,CAAC,YAAY,CAAC;CACvC,KAAK,OAAO,CAAC;IACZ,UAAU,EAAE,cAAc,CAAC;IAC3B,aAAa,EAAE,sBAAsB,CAAC;IACtC,gBAAgB,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC,CAAC;AAEH,eAAO,MAAM,kBAAkB,EAAE,kBAkFhC,CAAC"}
package/dist/run.js CHANGED
@@ -48,14 +48,14 @@ export const runHarnessTestFile = async ({ testPath, globalConfig, projectConfig
48
48
  // Extract setup files from Jest config and convert to relative paths
49
49
  const setupFiles = projectConfig.setupFiles?.map((setupFile) => path.relative(globalConfig.rootDir, setupFile));
50
50
  const setupFilesAfterEnv = projectConfig.setupFilesAfterEnv?.map((setupFile) => path.relative(globalConfig.rootDir, setupFile));
51
- const results = await harness.runTests(relativeTestPath, {
51
+ const harnessResult = await harness.runTests(relativeTestPath, {
52
52
  testNamePattern: globalConfig.testNamePattern,
53
53
  setupFiles,
54
54
  setupFilesAfterEnv,
55
55
  runner: harness.context.platform.runner,
56
56
  });
57
57
  const end = Date.now();
58
- const allTests = flattenTests(results);
58
+ const allTests = flattenTests(harnessResult);
59
59
  const stats = calculateStats(allTests);
60
60
  // Convert TestResult[] to the format expected by toTestResult
61
61
  const tests = allTests.map((test) => {
@@ -75,10 +75,10 @@ export const runHarnessTestFile = async ({ testPath, globalConfig, projectConfig
75
75
  };
76
76
  });
77
77
  // Check if the entire suite was skipped
78
- const skipped = results.status === 'skipped';
78
+ const skipped = harnessResult.status === 'skipped';
79
79
  // Get error message from suite if it failed
80
- const errorMessage = results.error?.message || null;
81
- const totalResults = toTestResult({
80
+ const errorMessage = harnessResult.error?.message || null;
81
+ const jestResult = toTestResult({
82
82
  stats: {
83
83
  failures: stats.failures,
84
84
  pending: stats.pending,
@@ -91,8 +91,13 @@ export const runHarnessTestFile = async ({ testPath, globalConfig, projectConfig
91
91
  errorMessage,
92
92
  tests,
93
93
  jestTestPath: testPath,
94
- coverage: results.coverage,
94
+ coverage: harnessResult.coverage,
95
95
  });
96
- totalResults.failureMessage = formatResultsErrors(totalResults.testResults, projectConfig, globalConfig, testPath);
97
- return totalResults;
96
+ jestResult.failureMessage = formatResultsErrors(jestResult.testResults, projectConfig, globalConfig, testPath);
97
+ return {
98
+ jestResult,
99
+ harnessResult,
100
+ relativeTestPath,
101
+ duration: end - start,
102
+ };
98
103
  };
@@ -1 +1 @@
1
- {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAqCxD,eAAO,MAAM,KAAK,GAAU,cAAc,UAAU,CAAC,YAAY,kBA4ChE,CAAC"}
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AA2CxD,eAAO,MAAM,KAAK,GAAU,cAAc,UAAU,CAAC,YAAY,kBA0DhE,CAAC"}
package/dist/setup.js CHANGED
@@ -1,12 +1,16 @@
1
- import { getConfig, } from '@react-native-harness/config';
1
+ import { getConfig, ConfigSchema, } from '@react-native-harness/config';
2
2
  import { getHarness } from './harness.js';
3
3
  import { preRunMessage } from 'jest-util';
4
4
  import { getAdditionalCliArgs } from './cli-args.js';
5
5
  import { logTestEnvironmentReady, logTestRunHeader } from './logs.js';
6
6
  import { NoRunnerSpecifiedError, RunnerNotFoundError } from './errors.js';
7
+ import { logger } from '@react-native-harness/tools';
8
+ const setupLogger = logger.child('setup');
7
9
  const getHarnessConfig = async (globalConfig) => {
8
10
  const projectRoot = globalConfig.rootDir;
11
+ setupLogger.debug('loading Harness config from %s', projectRoot);
9
12
  const { config: harnessConfig } = await getConfig(projectRoot);
13
+ setupLogger.debug('loaded Harness config');
10
14
  return harnessConfig;
11
15
  };
12
16
  const getHarnessRunner = (config, cliArgs) => {
@@ -18,11 +22,12 @@ const getHarnessRunner = (config, cliArgs) => {
18
22
  if (!runner) {
19
23
  throw new RunnerNotFoundError(selectedRunnerName);
20
24
  }
25
+ setupLogger.debug('selected runner %s (%s)', runner.name, runner.platformId);
21
26
  return runner;
22
27
  };
23
28
  export const setup = async (globalConfig) => {
24
29
  preRunMessage.remove(process.stderr);
25
- const harnessConfig = global.HARNESS_CONFIG ?? (await getHarnessConfig(globalConfig));
30
+ let harnessConfig = global.HARNESS_CONFIG ?? (await getHarnessConfig(globalConfig));
26
31
  if (global.HARNESS) {
27
32
  // Do not setup again if HARNESS is already initialized
28
33
  // This is useful when running tests in watch mode
@@ -33,6 +38,13 @@ export const setup = async (globalConfig) => {
33
38
  await global.HARNESS.dispose();
34
39
  });
35
40
  const cliArgs = getAdditionalCliArgs();
41
+ if (cliArgs.metroPort != null) {
42
+ setupLogger.debug('applying CLI metro port override: %d', cliArgs.metroPort);
43
+ harnessConfig = ConfigSchema.parse({
44
+ ...harnessConfig,
45
+ metroPort: cliArgs.metroPort,
46
+ });
47
+ }
36
48
  const selectedRunner = getHarnessRunner(harnessConfig, cliArgs);
37
49
  if (globalConfig.collectCoverage) {
38
50
  // This is going to be used by @react-native-harness/babel-preset
@@ -41,13 +53,17 @@ export const setup = async (globalConfig) => {
41
53
  if (harnessConfig.coverage?.root) {
42
54
  process.env.RN_HARNESS_COVERAGE_ROOT = harnessConfig.coverage.root;
43
55
  }
56
+ setupLogger.debug('coverage enabled for this run');
44
57
  }
45
58
  if (harnessConfig.disableViewFlattening) {
46
59
  process.env.RN_HARNESS_VIEW_FLATTENING = 'false';
60
+ setupLogger.debug('view flattening disabled for runtime');
47
61
  }
48
62
  logTestRunHeader(selectedRunner);
63
+ setupLogger.debug('creating Harness instance');
49
64
  const harness = await getHarness(harnessConfig, selectedRunner, globalConfig.rootDir);
50
65
  logTestEnvironmentReady(selectedRunner);
66
+ setupLogger.debug('Harness instance is ready');
51
67
  global.HARNESS_CONFIG = harnessConfig;
52
68
  global.HARNESS = harness;
53
69
  };