@react-native-harness/jest 1.0.0 → 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.
- package/dist/__tests__/crash-supervisor.test.d.ts +2 -0
- package/dist/__tests__/crash-supervisor.test.d.ts.map +1 -0
- package/dist/__tests__/crash-supervisor.test.js +151 -0
- package/dist/__tests__/errors.test.d.ts +2 -0
- package/dist/__tests__/errors.test.d.ts.map +1 -0
- package/dist/__tests__/errors.test.js +54 -0
- package/dist/__tests__/harness-cache.test.d.ts +2 -0
- package/dist/__tests__/harness-cache.test.d.ts.map +1 -0
- package/dist/__tests__/harness-cache.test.js +51 -0
- package/dist/__tests__/harness.test.d.ts +2 -0
- package/dist/__tests__/harness.test.d.ts.map +1 -0
- package/dist/__tests__/harness.test.js +399 -0
- package/dist/__tests__/index.test.d.ts +2 -0
- package/dist/__tests__/index.test.d.ts.map +1 -0
- package/dist/__tests__/index.test.js +42 -0
- package/dist/cli-args.d.ts +1 -0
- package/dist/cli-args.d.ts.map +1 -1
- package/dist/cli-args.js +5 -0
- package/dist/crash-supervisor.d.ts +21 -0
- package/dist/crash-supervisor.d.ts.map +1 -0
- package/dist/crash-supervisor.js +210 -0
- package/dist/errors.d.ts +9 -4
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +43 -8
- package/dist/harness.d.ts +30 -8
- package/dist/harness.d.ts.map +1 -1
- package/dist/harness.js +440 -98
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +205 -57
- package/dist/logs.d.ts +1 -0
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +3 -0
- package/dist/run.d.ts +7 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +13 -8
- package/dist/setup.d.ts.map +1 -1
- package/dist/setup.js +18 -6
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +7 -6
- package/src/__tests__/crash-supervisor.test.ts +200 -0
- package/src/__tests__/errors.test.ts +70 -0
- package/src/__tests__/harness-cache.test.ts +74 -0
- package/src/__tests__/harness.test.ts +547 -0
- package/src/__tests__/index.test.ts +61 -0
- package/src/cli-args.ts +6 -0
- package/src/crash-supervisor.ts +321 -0
- package/src/env.d.ts +1 -1
- package/src/errors.ts +68 -8
- package/src/harness.ts +566 -120
- package/src/index.ts +276 -66
- package/src/logs.ts +4 -0
- package/src/run.ts +20 -10
- package/src/setup.ts +22 -6
- package/tsconfig.json +3 -3
- package/tsconfig.lib.json +6 -6
- package/dist/cli-args.test.d.ts +0 -2
- package/dist/cli-args.test.d.ts.map +0 -1
- package/dist/cli-args.test.js +0 -1
- package/dist/crash-monitor.d.ts +0 -16
- package/dist/crash-monitor.d.ts.map +0 -1
- package/dist/crash-monitor.js +0 -75
- package/dist/event-mapper.d.ts +0 -16
- package/dist/event-mapper.d.ts.map +0 -1
- package/dist/event-mapper.js +0 -120
- package/dist/global-setup.d.ts +0 -3
- package/dist/global-setup.d.ts.map +0 -1
- package/dist/global-setup.js +0 -60
- package/dist/global-teardown.d.ts +0 -3
- package/dist/global-teardown.d.ts.map +0 -1
- package/dist/global-teardown.js +0 -11
- package/dist/harness-reporter.d.ts +0 -8
- package/dist/harness-reporter.d.ts.map +0 -1
- package/dist/harness-reporter.js +0 -12
- package/dist/jest-options.d.ts +0 -2
- package/dist/jest-options.d.ts.map +0 -1
- package/dist/jest-options.js +0 -1
- package/dist/types.d.ts +0 -17
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -1
- package/src/crash-monitor.ts +0 -109
package/src/index.ts
CHANGED
|
@@ -11,13 +11,40 @@ import type {
|
|
|
11
11
|
import pLimit from 'p-limit';
|
|
12
12
|
import { runHarnessTestFile } from './run.js';
|
|
13
13
|
import { Config as HarnessConfig } from '@react-native-harness/config';
|
|
14
|
-
import { type Harness } from './harness.js';
|
|
14
|
+
import { type Harness, type HarnessRunState } from './harness.js';
|
|
15
15
|
import { setup } from './setup.js';
|
|
16
16
|
import { teardown } from './teardown.js';
|
|
17
17
|
import { HarnessError } from '@react-native-harness/tools';
|
|
18
18
|
import { getErrorMessage } from './logs.js';
|
|
19
19
|
import { DeviceNotRespondingError } from '@react-native-harness/bridge/server';
|
|
20
|
-
import { NativeCrashError } from './errors.js';
|
|
20
|
+
import { NativeCrashError, StartupStallError } from './errors.js';
|
|
21
|
+
import { logger } from '@react-native-harness/tools';
|
|
22
|
+
import { randomUUID } from 'node:crypto';
|
|
23
|
+
import path from 'node:path';
|
|
24
|
+
|
|
25
|
+
const runLogger = logger.child('run');
|
|
26
|
+
|
|
27
|
+
const createRunSummary = () => ({
|
|
28
|
+
passed: 0,
|
|
29
|
+
failed: 0,
|
|
30
|
+
skipped: 0,
|
|
31
|
+
todo: 0,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const applyJestResultToSummary = (
|
|
35
|
+
summary: ReturnType<typeof createRunSummary>,
|
|
36
|
+
result: {
|
|
37
|
+
numPassingTests: number;
|
|
38
|
+
numFailingTests: number;
|
|
39
|
+
numPendingTests: number;
|
|
40
|
+
numTodoTests: number;
|
|
41
|
+
}
|
|
42
|
+
) => {
|
|
43
|
+
summary.passed += result.numPassingTests;
|
|
44
|
+
summary.failed += result.numFailingTests;
|
|
45
|
+
summary.skipped += result.numPendingTests;
|
|
46
|
+
summary.todo += result.numTodoTests;
|
|
47
|
+
};
|
|
21
48
|
|
|
22
49
|
class CancelRun extends Error {
|
|
23
50
|
constructor(message?: string) {
|
|
@@ -87,83 +114,266 @@ export default class JestHarness implements CallbackTestRunnerInterface {
|
|
|
87
114
|
): Promise<void> {
|
|
88
115
|
const mutex = pLimit(1);
|
|
89
116
|
let isFirstTest = true;
|
|
117
|
+
const startTime = Date.now();
|
|
118
|
+
const runId = randomUUID();
|
|
119
|
+
const watchMode = this.#globalConfig.watch || this.#globalConfig.watchAll;
|
|
120
|
+
const rootDir = this.#globalConfig.rootDir ?? process.cwd();
|
|
121
|
+
const testFiles = tests.map((test) =>
|
|
122
|
+
path.relative(rootDir, test.path)
|
|
123
|
+
);
|
|
124
|
+
const summary = createRunSummary();
|
|
125
|
+
const updateRunState = (overrides: Partial<HarnessRunState> = {}) => {
|
|
126
|
+
const nextRunState: HarnessRunState = {
|
|
127
|
+
runId,
|
|
128
|
+
startTime,
|
|
129
|
+
testFiles,
|
|
130
|
+
watchMode,
|
|
131
|
+
coverageEnabled: this.#globalConfig.collectCoverage,
|
|
132
|
+
summary,
|
|
133
|
+
status: summary.failed > 0 ? 'failed' : 'passed',
|
|
134
|
+
...overrides,
|
|
135
|
+
};
|
|
90
136
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
});
|
|
116
|
-
}
|
|
137
|
+
harness.setRunState(nextRunState);
|
|
138
|
+
return nextRunState;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
updateRunState();
|
|
142
|
+
runLogger.debug(
|
|
143
|
+
'run started: runId=%s files=%d watchMode=%s coverage=%s',
|
|
144
|
+
runId,
|
|
145
|
+
testFiles.length,
|
|
146
|
+
watchMode,
|
|
147
|
+
this.#globalConfig.collectCoverage
|
|
148
|
+
);
|
|
149
|
+
await harness.callHook('run:started', {
|
|
150
|
+
runId,
|
|
151
|
+
startTime,
|
|
152
|
+
testFiles,
|
|
153
|
+
watchMode,
|
|
154
|
+
coverageEnabled: this.#globalConfig.collectCoverage,
|
|
155
|
+
});
|
|
156
|
+
await harness.callHook('metro:initialized', {
|
|
157
|
+
runId,
|
|
158
|
+
port: harnessConfig.metroPort,
|
|
159
|
+
host: harnessConfig.host?.trim() || undefined,
|
|
160
|
+
});
|
|
117
161
|
|
|
118
|
-
|
|
119
|
-
|
|
162
|
+
try {
|
|
163
|
+
await tests.reduce(
|
|
164
|
+
(promise, test) =>
|
|
165
|
+
mutex(() => {
|
|
166
|
+
let didApplySummary = false;
|
|
167
|
+
|
|
168
|
+
return promise
|
|
169
|
+
.then(async () => {
|
|
170
|
+
const relativeTestPath = path.relative(
|
|
171
|
+
rootDir,
|
|
120
172
|
test.path
|
|
121
173
|
);
|
|
174
|
+
const testFileStartedAt = Date.now();
|
|
175
|
+
let didEmitTestFileFinished = false;
|
|
176
|
+
|
|
177
|
+
await harness.callHook('test-file:started', {
|
|
178
|
+
runId,
|
|
179
|
+
file: relativeTestPath,
|
|
180
|
+
});
|
|
181
|
+
runLogger.debug('test file started: %s', relativeTestPath);
|
|
182
|
+
|
|
183
|
+
const emitTestFileFinished = async (options: {
|
|
184
|
+
status: 'passed' | 'failed' | 'skipped' | 'todo';
|
|
185
|
+
duration: number;
|
|
186
|
+
result: Awaited<ReturnType<typeof runHarnessTestFile>>['harnessResult'] | null;
|
|
187
|
+
}) => {
|
|
188
|
+
didEmitTestFileFinished = true;
|
|
189
|
+
runLogger.debug(
|
|
190
|
+
'test file finished: %s status=%s duration=%dms',
|
|
191
|
+
relativeTestPath,
|
|
192
|
+
options.status,
|
|
193
|
+
options.duration
|
|
194
|
+
);
|
|
195
|
+
await harness.callHook('test-file:finished', {
|
|
196
|
+
runId,
|
|
197
|
+
file: relativeTestPath,
|
|
198
|
+
duration: options.duration,
|
|
199
|
+
status: options.status,
|
|
200
|
+
result: options.result,
|
|
201
|
+
});
|
|
202
|
+
};
|
|
122
203
|
|
|
123
204
|
try {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
205
|
+
if (watcher.isInterrupted()) {
|
|
206
|
+
throw new CancelRun();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
if (
|
|
210
|
+
harnessConfig.resetEnvironmentBetweenTestFiles &&
|
|
211
|
+
!isFirstTest
|
|
212
|
+
) {
|
|
213
|
+
runLogger.debug(
|
|
214
|
+
'resetting environment before %s',
|
|
215
|
+
relativeTestPath
|
|
216
|
+
);
|
|
217
|
+
await harness.restart(test.path);
|
|
218
|
+
}
|
|
219
|
+
isFirstTest = false;
|
|
220
|
+
|
|
221
|
+
const result = await onStart(test).then(async () => {
|
|
222
|
+
if (!harnessConfig.detectNativeCrashes) {
|
|
223
|
+
runLogger.debug(
|
|
224
|
+
'native crash detection disabled for %s',
|
|
225
|
+
relativeTestPath
|
|
226
|
+
);
|
|
227
|
+
await harness.ensureAppReady(test.path);
|
|
228
|
+
return runHarnessTestFile({
|
|
229
|
+
testPath: test.path,
|
|
230
|
+
harness,
|
|
231
|
+
globalConfig: this.#globalConfig,
|
|
232
|
+
projectConfig: test.context.config,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
await harness.ensureAppReady(test.path);
|
|
237
|
+
harness.crashSupervisor.beginTestRun(test.path);
|
|
238
|
+
runLogger.debug(
|
|
239
|
+
'native crash detection armed for %s',
|
|
240
|
+
relativeTestPath
|
|
241
|
+
);
|
|
242
|
+
const crashPromise =
|
|
243
|
+
harness.crashSupervisor.waitForCrash(test.path);
|
|
244
|
+
|
|
245
|
+
try {
|
|
246
|
+
return await Promise.race([
|
|
247
|
+
runHarnessTestFile({
|
|
248
|
+
testPath: test.path,
|
|
249
|
+
harness,
|
|
250
|
+
globalConfig: this.#globalConfig,
|
|
251
|
+
projectConfig: test.context.config,
|
|
252
|
+
}),
|
|
253
|
+
crashPromise,
|
|
254
|
+
]);
|
|
255
|
+
} finally {
|
|
256
|
+
harness.crashSupervisor.cancelCrashWaiters();
|
|
257
|
+
}
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
applyJestResultToSummary(summary, result.jestResult);
|
|
261
|
+
didApplySummary = true;
|
|
262
|
+
updateRunState();
|
|
263
|
+
await emitTestFileFinished({
|
|
264
|
+
status: result.harnessResult.status,
|
|
265
|
+
duration: result.duration,
|
|
266
|
+
result: result.harnessResult,
|
|
267
|
+
});
|
|
133
268
|
|
|
134
269
|
return result;
|
|
135
|
-
}
|
|
136
|
-
|
|
270
|
+
} catch (error) {
|
|
271
|
+
if (!didEmitTestFileFinished) {
|
|
272
|
+
await emitTestFileFinished({
|
|
273
|
+
status: 'failed',
|
|
274
|
+
duration: Date.now() - testFileStartedAt,
|
|
275
|
+
result: null,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
throw error;
|
|
280
|
+
}
|
|
281
|
+
})
|
|
282
|
+
.then(async (result) => {
|
|
283
|
+
if (!result) {
|
|
284
|
+
return;
|
|
137
285
|
}
|
|
138
|
-
});
|
|
139
|
-
})
|
|
140
|
-
.then((result) => onResult(test, result))
|
|
141
|
-
.catch(async (err) => {
|
|
142
|
-
if (err instanceof NativeCrashError) {
|
|
143
|
-
onFailure(test, {
|
|
144
|
-
message: err.message,
|
|
145
|
-
stack: '',
|
|
146
|
-
});
|
|
147
286
|
|
|
148
|
-
|
|
149
|
-
|
|
287
|
+
await onResult(test, result.jestResult);
|
|
288
|
+
})
|
|
289
|
+
.catch(async (err) => {
|
|
290
|
+
if (
|
|
291
|
+
err instanceof NativeCrashError ||
|
|
292
|
+
err instanceof StartupStallError ||
|
|
293
|
+
err instanceof DeviceNotRespondingError
|
|
294
|
+
) {
|
|
295
|
+
runLogger.debug(
|
|
296
|
+
'classified runtime failure for %s: %s',
|
|
297
|
+
test.path,
|
|
298
|
+
err.name
|
|
299
|
+
);
|
|
300
|
+
summary.failed += 1;
|
|
301
|
+
updateRunState();
|
|
302
|
+
}
|
|
150
303
|
|
|
151
|
-
|
|
152
|
-
|
|
304
|
+
if (err instanceof NativeCrashError) {
|
|
305
|
+
harness.crashSupervisor.reset();
|
|
306
|
+
onFailure(test, {
|
|
307
|
+
message: err.message,
|
|
308
|
+
stack: '',
|
|
309
|
+
});
|
|
153
310
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
message: err.message,
|
|
157
|
-
stack: '',
|
|
158
|
-
});
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
159
313
|
|
|
160
|
-
|
|
161
|
-
|
|
314
|
+
if (err instanceof StartupStallError) {
|
|
315
|
+
onFailure(test, {
|
|
316
|
+
message: err.message,
|
|
317
|
+
stack: '',
|
|
318
|
+
});
|
|
162
319
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (err instanceof DeviceNotRespondingError) {
|
|
324
|
+
onFailure(test, {
|
|
325
|
+
message: err.message,
|
|
326
|
+
stack: '',
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
if (!(err instanceof CancelRun) && !didApplySummary) {
|
|
333
|
+
summary.failed += 1;
|
|
334
|
+
}
|
|
335
|
+
updateRunState({ error: err });
|
|
336
|
+
onFailure(test, err);
|
|
337
|
+
});
|
|
338
|
+
}),
|
|
339
|
+
Promise.resolve()
|
|
340
|
+
);
|
|
341
|
+
|
|
342
|
+
const runState = updateRunState();
|
|
343
|
+
runLogger.debug(
|
|
344
|
+
'run finished: runId=%s status=%s duration=%dms',
|
|
345
|
+
runId,
|
|
346
|
+
runState.status ?? 'passed',
|
|
347
|
+
Date.now() - startTime
|
|
348
|
+
);
|
|
349
|
+
await harness.callHook('run:finished', {
|
|
350
|
+
runId,
|
|
351
|
+
startTime,
|
|
352
|
+
duration: Date.now() - startTime,
|
|
353
|
+
testFiles,
|
|
354
|
+
summary,
|
|
355
|
+
status: runState.status ?? 'passed',
|
|
356
|
+
});
|
|
357
|
+
} catch (error) {
|
|
358
|
+
const runState = updateRunState({
|
|
359
|
+
error,
|
|
360
|
+
status: 'failed',
|
|
361
|
+
});
|
|
362
|
+
runLogger.debug(
|
|
363
|
+
'run failed: runId=%s status=%s',
|
|
364
|
+
runId,
|
|
365
|
+
runState.status ?? 'failed'
|
|
366
|
+
);
|
|
367
|
+
await harness.callHook('run:finished', {
|
|
368
|
+
runId,
|
|
369
|
+
startTime,
|
|
370
|
+
duration: Date.now() - startTime,
|
|
371
|
+
testFiles,
|
|
372
|
+
summary,
|
|
373
|
+
status: runState.status ?? 'failed',
|
|
374
|
+
error,
|
|
375
|
+
});
|
|
376
|
+
throw error;
|
|
377
|
+
}
|
|
168
378
|
}
|
|
169
379
|
}
|
package/src/logs.ts
CHANGED
|
@@ -31,6 +31,10 @@ export const logMetroPrewarmCompleted = (runner: HarnessPlatform): void => {
|
|
|
31
31
|
);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
+
export const logMetroCacheReused = (runner: HarnessPlatform): void => {
|
|
35
|
+
log(`${TAG} Reusing Metro cache for ${chalk.bold(runner.name)}\n`);
|
|
36
|
+
};
|
|
37
|
+
|
|
34
38
|
export const getErrorMessage = (error: HarnessError): string => {
|
|
35
39
|
return `${ERROR_TAG} ${error.message}\n`;
|
|
36
40
|
};
|
package/src/run.ts
CHANGED
|
@@ -65,7 +65,12 @@ export type RunHarnessTestFile = (options: {
|
|
|
65
65
|
harness: Harness;
|
|
66
66
|
projectConfig: JestConfig.ProjectConfig;
|
|
67
67
|
globalConfig: JestConfig.GlobalConfig;
|
|
68
|
-
}) => Promise<
|
|
68
|
+
}) => Promise<{
|
|
69
|
+
jestResult: JestTestResult;
|
|
70
|
+
harnessResult: HarnessTestSuiteResult;
|
|
71
|
+
relativeTestPath: string;
|
|
72
|
+
duration: number;
|
|
73
|
+
}>;
|
|
69
74
|
|
|
70
75
|
export const runHarnessTestFile: RunHarnessTestFile = async ({
|
|
71
76
|
testPath,
|
|
@@ -84,7 +89,7 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
|
|
|
84
89
|
(setupFile) => path.relative(globalConfig.rootDir, setupFile)
|
|
85
90
|
);
|
|
86
91
|
|
|
87
|
-
const
|
|
92
|
+
const harnessResult = await harness.runTests(relativeTestPath, {
|
|
88
93
|
testNamePattern: globalConfig.testNamePattern,
|
|
89
94
|
setupFiles,
|
|
90
95
|
setupFilesAfterEnv,
|
|
@@ -92,7 +97,7 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
|
|
|
92
97
|
});
|
|
93
98
|
const end = Date.now();
|
|
94
99
|
|
|
95
|
-
const allTests = flattenTests(
|
|
100
|
+
const allTests = flattenTests(harnessResult);
|
|
96
101
|
const stats = calculateStats(allTests);
|
|
97
102
|
|
|
98
103
|
// Convert TestResult[] to the format expected by toTestResult
|
|
@@ -115,12 +120,12 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
|
|
|
115
120
|
});
|
|
116
121
|
|
|
117
122
|
// Check if the entire suite was skipped
|
|
118
|
-
const skipped =
|
|
123
|
+
const skipped = harnessResult.status === 'skipped';
|
|
119
124
|
|
|
120
125
|
// Get error message from suite if it failed
|
|
121
|
-
const errorMessage =
|
|
126
|
+
const errorMessage = harnessResult.error?.message || null;
|
|
122
127
|
|
|
123
|
-
const
|
|
128
|
+
const jestResult = toTestResult({
|
|
124
129
|
stats: {
|
|
125
130
|
failures: stats.failures,
|
|
126
131
|
pending: stats.pending,
|
|
@@ -133,15 +138,20 @@ export const runHarnessTestFile: RunHarnessTestFile = async ({
|
|
|
133
138
|
errorMessage,
|
|
134
139
|
tests,
|
|
135
140
|
jestTestPath: testPath,
|
|
136
|
-
coverage:
|
|
141
|
+
coverage: harnessResult.coverage as JestTestResult['coverage'],
|
|
137
142
|
});
|
|
138
143
|
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
jestResult.failureMessage = formatResultsErrors(
|
|
145
|
+
jestResult.testResults,
|
|
141
146
|
projectConfig,
|
|
142
147
|
globalConfig,
|
|
143
148
|
testPath
|
|
144
149
|
);
|
|
145
150
|
|
|
146
|
-
return
|
|
151
|
+
return {
|
|
152
|
+
jestResult,
|
|
153
|
+
harnessResult,
|
|
154
|
+
relativeTestPath,
|
|
155
|
+
duration: end - start,
|
|
156
|
+
};
|
|
147
157
|
};
|
package/src/setup.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getConfig,
|
|
3
3
|
type Config as HarnessConfig,
|
|
4
|
+
ConfigSchema,
|
|
4
5
|
} from '@react-native-harness/config';
|
|
5
6
|
import type { Config as JestConfig } from 'jest-runner';
|
|
6
7
|
import { getHarness } from './harness.js';
|
|
@@ -9,12 +10,17 @@ import { getAdditionalCliArgs, HarnessCliArgs } from './cli-args.js';
|
|
|
9
10
|
import { logTestEnvironmentReady, logTestRunHeader } from './logs.js';
|
|
10
11
|
import { NoRunnerSpecifiedError, RunnerNotFoundError } from './errors.js';
|
|
11
12
|
import { HarnessPlatform } from '@react-native-harness/platforms';
|
|
13
|
+
import { logger } from '@react-native-harness/tools';
|
|
14
|
+
|
|
15
|
+
const setupLogger = logger.child('setup');
|
|
12
16
|
|
|
13
17
|
const getHarnessConfig = async (
|
|
14
18
|
globalConfig: JestConfig.GlobalConfig
|
|
15
19
|
): Promise<HarnessConfig> => {
|
|
16
20
|
const projectRoot = globalConfig.rootDir;
|
|
21
|
+
setupLogger.debug('loading Harness config from %s', projectRoot);
|
|
17
22
|
const { config: harnessConfig } = await getConfig(projectRoot);
|
|
23
|
+
setupLogger.debug('loaded Harness config');
|
|
18
24
|
return harnessConfig;
|
|
19
25
|
};
|
|
20
26
|
|
|
@@ -36,23 +42,19 @@ const getHarnessRunner = (
|
|
|
36
42
|
throw new RunnerNotFoundError(selectedRunnerName);
|
|
37
43
|
}
|
|
38
44
|
|
|
45
|
+
setupLogger.debug('selected runner %s (%s)', runner.name, runner.platformId);
|
|
39
46
|
return runner;
|
|
40
47
|
};
|
|
41
48
|
|
|
42
49
|
export const setup = async (globalConfig: JestConfig.GlobalConfig) => {
|
|
43
50
|
preRunMessage.remove(process.stderr);
|
|
44
|
-
|
|
51
|
+
let harnessConfig =
|
|
45
52
|
global.HARNESS_CONFIG ?? (await getHarnessConfig(globalConfig));
|
|
46
53
|
|
|
47
54
|
if (global.HARNESS) {
|
|
48
55
|
// Do not setup again if HARNESS is already initialized
|
|
49
56
|
// This is useful when running tests in watch mode
|
|
50
57
|
|
|
51
|
-
if (harnessConfig.resetEnvironmentBetweenTestFiles) {
|
|
52
|
-
// In watch mode, we want to restart the environment before each test run
|
|
53
|
-
await global.HARNESS.restart();
|
|
54
|
-
}
|
|
55
|
-
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
|
|
@@ -62,6 +64,15 @@ export const setup = async (globalConfig: JestConfig.GlobalConfig) => {
|
|
|
62
64
|
});
|
|
63
65
|
|
|
64
66
|
const cliArgs = getAdditionalCliArgs();
|
|
67
|
+
|
|
68
|
+
if (cliArgs.metroPort != null) {
|
|
69
|
+
setupLogger.debug('applying CLI metro port override: %d', cliArgs.metroPort);
|
|
70
|
+
harnessConfig = ConfigSchema.parse({
|
|
71
|
+
...harnessConfig,
|
|
72
|
+
metroPort: cliArgs.metroPort,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
65
76
|
const selectedRunner = getHarnessRunner(harnessConfig, cliArgs);
|
|
66
77
|
|
|
67
78
|
if (globalConfig.collectCoverage) {
|
|
@@ -72,19 +83,24 @@ export const setup = async (globalConfig: JestConfig.GlobalConfig) => {
|
|
|
72
83
|
if (harnessConfig.coverage?.root) {
|
|
73
84
|
process.env.RN_HARNESS_COVERAGE_ROOT = harnessConfig.coverage.root;
|
|
74
85
|
}
|
|
86
|
+
|
|
87
|
+
setupLogger.debug('coverage enabled for this run');
|
|
75
88
|
}
|
|
76
89
|
|
|
77
90
|
if (harnessConfig.disableViewFlattening) {
|
|
78
91
|
process.env.RN_HARNESS_VIEW_FLATTENING = 'false';
|
|
92
|
+
setupLogger.debug('view flattening disabled for runtime');
|
|
79
93
|
}
|
|
80
94
|
|
|
81
95
|
logTestRunHeader(selectedRunner);
|
|
96
|
+
setupLogger.debug('creating Harness instance');
|
|
82
97
|
const harness = await getHarness(
|
|
83
98
|
harnessConfig,
|
|
84
99
|
selectedRunner,
|
|
85
100
|
globalConfig.rootDir
|
|
86
101
|
);
|
|
87
102
|
logTestEnvironmentReady(selectedRunner);
|
|
103
|
+
setupLogger.debug('Harness instance is ready');
|
|
88
104
|
|
|
89
105
|
global.HARNESS_CONFIG = harnessConfig;
|
|
90
106
|
global.HARNESS = harness;
|
package/tsconfig.json
CHANGED
package/tsconfig.lib.json
CHANGED
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
"emitDeclarationOnly": false,
|
|
9
9
|
"forceConsistentCasingInFileNames": true,
|
|
10
10
|
"types": ["node"],
|
|
11
|
-
"lib": ["DOM"]
|
|
11
|
+
"lib": ["DOM", "ES2022"]
|
|
12
12
|
},
|
|
13
13
|
"include": ["src/**/*.ts"],
|
|
14
14
|
"references": [
|
|
15
15
|
{
|
|
16
|
-
"path": "../
|
|
16
|
+
"path": "../tools/tsconfig.lib.json"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"path": "../
|
|
19
|
+
"path": "../platforms/tsconfig.lib.json"
|
|
20
20
|
},
|
|
21
21
|
{
|
|
22
|
-
"path": "../
|
|
22
|
+
"path": "../plugins/tsconfig.lib.json"
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
"path": "../
|
|
25
|
+
"path": "../config/tsconfig.lib.json"
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
|
-
"path": "../
|
|
28
|
+
"path": "../bundler-metro/tsconfig.lib.json"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
"path": "../bridge/tsconfig.lib.json"
|
package/dist/cli-args.test.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli-args.test.d.ts","sourceRoot":"","sources":["../src/cli-args.test.ts"],"names":[],"mappings":""}
|
package/dist/cli-args.test.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/dist/crash-monitor.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { HarnessPlatformRunner } from '@react-native-harness/platforms';
|
|
2
|
-
import { BridgeServer } from '@react-native-harness/bridge/server';
|
|
3
|
-
export type CrashMonitor = {
|
|
4
|
-
startMonitoring(testFilePath: string): Promise<never>;
|
|
5
|
-
stopMonitoring(): void;
|
|
6
|
-
markIntentionalRestart(): void;
|
|
7
|
-
clearIntentionalRestart(): void;
|
|
8
|
-
dispose(): void;
|
|
9
|
-
};
|
|
10
|
-
export type CrashMonitorOptions = {
|
|
11
|
-
interval: number;
|
|
12
|
-
platformRunner: HarnessPlatformRunner;
|
|
13
|
-
bridgeServer: BridgeServer;
|
|
14
|
-
};
|
|
15
|
-
export declare const createCrashMonitor: ({ interval, platformRunner, bridgeServer, }: CrashMonitorOptions) => CrashMonitor;
|
|
16
|
-
//# sourceMappingURL=crash-monitor.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crash-monitor.d.ts","sourceRoot":"","sources":["../src/crash-monitor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAInE,MAAM,MAAM,YAAY,GAAG;IACzB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACtD,cAAc,IAAI,IAAI,CAAC;IACvB,sBAAsB,IAAI,IAAI,CAAC;IAC/B,uBAAuB,IAAI,IAAI,CAAC;IAChC,OAAO,IAAI,IAAI,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,qBAAqB,CAAC;IACtC,YAAY,EAAE,YAAY,CAAC;CAC5B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,6CAIhC,mBAAmB,KAAG,YAqFxB,CAAC"}
|