@react-native-harness/jest 1.2.0-rc.1 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/bridge.test.d.ts +2 -0
- package/dist/__tests__/bridge.test.d.ts.map +1 -0
- package/dist/__tests__/bridge.test.js +142 -0
- package/dist/__tests__/client-log-handler.test.js +116 -72
- package/dist/__tests__/crash-monitor.test.d.ts +2 -0
- package/dist/__tests__/crash-monitor.test.d.ts.map +1 -0
- package/dist/__tests__/crash-monitor.test.js +212 -0
- package/dist/__tests__/execute-run.test.d.ts +2 -0
- package/dist/__tests__/execute-run.test.d.ts.map +1 -0
- package/dist/__tests__/execute-run.test.js +229 -0
- package/dist/__tests__/hook-queue.test.d.ts +2 -0
- package/dist/__tests__/hook-queue.test.d.ts.map +1 -0
- package/dist/__tests__/hook-queue.test.js +56 -0
- package/dist/__tests__/index.test.js +94 -37
- package/dist/__tests__/resource-lock.test.js +24 -24
- package/dist/client-log-handler.d.ts +10 -11
- package/dist/client-log-handler.d.ts.map +1 -1
- package/dist/client-log-handler.js +36 -58
- package/dist/crash-monitor.d.ts +17 -10
- package/dist/crash-monitor.d.ts.map +1 -1
- package/dist/crash-monitor.js +164 -63
- package/dist/execute-run.d.ts +4 -0
- package/dist/execute-run.d.ts.map +1 -0
- package/dist/execute-run.js +151 -0
- package/dist/harness-session.d.ts +34 -0
- package/dist/harness-session.d.ts.map +1 -0
- package/dist/harness-session.js +523 -0
- package/dist/hook-queue.d.ts +6 -0
- package/dist/hook-queue.d.ts.map +1 -0
- package/dist/hook-queue.js +18 -0
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -230
- package/dist/logs.d.ts +1 -0
- package/dist/logs.d.ts.map +1 -1
- package/dist/logs.js +3 -0
- package/dist/resource-lock.d.ts +0 -1
- package/dist/resource-lock.d.ts.map +1 -1
- package/dist/resource-lock.js +1 -1
- package/dist/run.d.ts +2 -2
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +3 -3
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +7 -8
- package/src/__tests__/bridge.test.ts +184 -0
- package/src/__tests__/client-log-handler.test.ts +117 -81
- package/src/__tests__/crash-monitor.test.ts +288 -0
- package/src/__tests__/execute-run.test.ts +325 -0
- package/src/__tests__/hook-queue.test.ts +77 -0
- package/src/__tests__/index.test.ts +135 -55
- package/src/__tests__/resource-lock.test.ts +29 -42
- package/src/client-log-handler.ts +48 -64
- package/src/crash-monitor.ts +248 -0
- package/src/execute-run.ts +199 -0
- package/src/harness-session.ts +734 -0
- package/src/hook-queue.ts +26 -0
- package/src/index.ts +17 -330
- package/src/logs.ts +4 -0
- package/src/resource-lock.ts +1 -1
- package/src/run.ts +5 -5
- package/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/crash-supervisor.test.ts +0 -200
- package/src/__tests__/harness-cache.test.ts +0 -74
- package/src/__tests__/harness.test.ts +0 -923
- package/src/crash-supervisor.ts +0 -321
- package/src/env.d.ts +0 -9
- package/src/harness.ts +0 -870
- package/src/setup.ts +0 -127
- package/src/teardown.ts +0 -14
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { runHarnessTestFile } from './run.js';
|
|
4
|
+
import { NativeCrashError, StartupStallError, } from './errors.js';
|
|
5
|
+
import { DeviceNotRespondingError } from '@react-native-harness/bridge/server';
|
|
6
|
+
const createRunSummary = () => ({ passed: 0, failed: 0, skipped: 0, todo: 0 });
|
|
7
|
+
const applyJestResultToSummary = (summary, result) => {
|
|
8
|
+
summary.passed += result.numPassingTests;
|
|
9
|
+
summary.failed += result.numFailingTests;
|
|
10
|
+
summary.skipped += result.numPendingTests;
|
|
11
|
+
summary.todo += result.numTodoTests;
|
|
12
|
+
};
|
|
13
|
+
class CancelRun extends Error {
|
|
14
|
+
constructor(message) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'CancelRun';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
const buildTestFailure = (err) => {
|
|
20
|
+
if (err instanceof NativeCrashError ||
|
|
21
|
+
err instanceof StartupStallError ||
|
|
22
|
+
err instanceof DeviceNotRespondingError) {
|
|
23
|
+
return { message: err.message, stack: '' };
|
|
24
|
+
}
|
|
25
|
+
return err;
|
|
26
|
+
};
|
|
27
|
+
export const executeRun = async (session, tests, watcher, onStart, onResult, onFailure, globalConfig) => {
|
|
28
|
+
const runId = randomUUID();
|
|
29
|
+
const startTime = Date.now();
|
|
30
|
+
const watchMode = globalConfig.watch || globalConfig.watchAll;
|
|
31
|
+
const rootDir = globalConfig.rootDir ?? process.cwd();
|
|
32
|
+
const testFiles = tests.map((t) => path.relative(rootDir, t.path));
|
|
33
|
+
const summary = createRunSummary();
|
|
34
|
+
const updateRunState = (overrides = {}) => {
|
|
35
|
+
const state = {
|
|
36
|
+
runId,
|
|
37
|
+
startTime,
|
|
38
|
+
testFiles,
|
|
39
|
+
watchMode,
|
|
40
|
+
coverageEnabled: globalConfig.collectCoverage,
|
|
41
|
+
summary,
|
|
42
|
+
status: summary.failed > 0 ? 'failed' : 'passed',
|
|
43
|
+
...overrides,
|
|
44
|
+
};
|
|
45
|
+
session.setRunState(state);
|
|
46
|
+
return state;
|
|
47
|
+
};
|
|
48
|
+
updateRunState();
|
|
49
|
+
await session.callHook('run:started', {
|
|
50
|
+
runId,
|
|
51
|
+
startTime,
|
|
52
|
+
testFiles,
|
|
53
|
+
watchMode,
|
|
54
|
+
coverageEnabled: globalConfig.collectCoverage,
|
|
55
|
+
});
|
|
56
|
+
await session.callHook('metro:initialized', {
|
|
57
|
+
runId,
|
|
58
|
+
port: session.config.metroPort,
|
|
59
|
+
host: session.config.host?.trim() || undefined,
|
|
60
|
+
});
|
|
61
|
+
const shouldResetEnv = session.config.resetEnvironmentBetweenTestFiles;
|
|
62
|
+
let isFirstTest = true;
|
|
63
|
+
let runError;
|
|
64
|
+
try {
|
|
65
|
+
for (const test of tests) {
|
|
66
|
+
if (watcher.isInterrupted())
|
|
67
|
+
throw new CancelRun();
|
|
68
|
+
const relativeTestPath = path.relative(rootDir, test.path);
|
|
69
|
+
const fileStartedAt = Date.now();
|
|
70
|
+
let emittedTestFileFinished = false;
|
|
71
|
+
const emitTestFileFinished = async (options) => {
|
|
72
|
+
emittedTestFileFinished = true;
|
|
73
|
+
await session.callHook('test-file:finished', {
|
|
74
|
+
runId,
|
|
75
|
+
file: relativeTestPath,
|
|
76
|
+
duration: options.duration,
|
|
77
|
+
status: options.status,
|
|
78
|
+
result: options.result,
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
await session.callHook('test-file:started', { runId, file: relativeTestPath });
|
|
82
|
+
try {
|
|
83
|
+
if (shouldResetEnv && !isFirstTest) {
|
|
84
|
+
await session.restartApp(test.path);
|
|
85
|
+
}
|
|
86
|
+
isFirstTest = false;
|
|
87
|
+
session.flushClientLogs();
|
|
88
|
+
await onStart(test);
|
|
89
|
+
await session.ensureAppReady(test.path);
|
|
90
|
+
// Crash detection is handled inside session.runTestFile; NativeCrashError
|
|
91
|
+
// propagates here if a crash wins the race.
|
|
92
|
+
const result = await runHarnessTestFile({
|
|
93
|
+
testPath: test.path,
|
|
94
|
+
session,
|
|
95
|
+
globalConfig,
|
|
96
|
+
projectConfig: test.context.config,
|
|
97
|
+
});
|
|
98
|
+
applyJestResultToSummary(summary, result.jestResult);
|
|
99
|
+
const clientLogs = session.flushClientLogs();
|
|
100
|
+
if (clientLogs.length > 0) {
|
|
101
|
+
result.jestResult.console = clientLogs;
|
|
102
|
+
}
|
|
103
|
+
updateRunState();
|
|
104
|
+
await emitTestFileFinished({
|
|
105
|
+
status: result.harnessResult.status,
|
|
106
|
+
duration: result.duration,
|
|
107
|
+
result: result.harnessResult,
|
|
108
|
+
});
|
|
109
|
+
await onResult(test, result.jestResult);
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
if (!emittedTestFileFinished) {
|
|
113
|
+
await emitTestFileFinished({
|
|
114
|
+
status: 'failed',
|
|
115
|
+
duration: Date.now() - fileStartedAt,
|
|
116
|
+
result: null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
const isRuntimeFailure = err instanceof NativeCrashError ||
|
|
120
|
+
err instanceof StartupStallError ||
|
|
121
|
+
err instanceof DeviceNotRespondingError;
|
|
122
|
+
if (isRuntimeFailure) {
|
|
123
|
+
summary.failed += 1;
|
|
124
|
+
updateRunState();
|
|
125
|
+
}
|
|
126
|
+
if (err instanceof NativeCrashError) {
|
|
127
|
+
session.resetCrashState();
|
|
128
|
+
}
|
|
129
|
+
updateRunState({ error: isRuntimeFailure ? undefined : err });
|
|
130
|
+
onFailure(test, buildTestFailure(err));
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
runError = err;
|
|
136
|
+
if (!(err instanceof CancelRun))
|
|
137
|
+
throw err;
|
|
138
|
+
}
|
|
139
|
+
finally {
|
|
140
|
+
const runState = updateRunState(runError != null ? { error: runError, status: 'failed' } : {});
|
|
141
|
+
await session.callHook('run:finished', {
|
|
142
|
+
runId,
|
|
143
|
+
startTime,
|
|
144
|
+
duration: Date.now() - startTime,
|
|
145
|
+
testFiles,
|
|
146
|
+
summary,
|
|
147
|
+
status: runState.status ?? (runError != null ? 'failed' : 'passed'),
|
|
148
|
+
...(runError != null ? { error: runError } : {}),
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { type HarnessContext, type TestExecutionOptions, type TestSuiteResult } from '@react-native-harness/bridge';
|
|
2
|
+
import { type HarnessPlatform } from '@react-native-harness/platforms';
|
|
3
|
+
import { type HarnessPluginManager, type HarnessRunStatus, type HarnessRunSummary } from '@react-native-harness/plugins';
|
|
4
|
+
import { type Config as HarnessConfig } from '@react-native-harness/config';
|
|
5
|
+
import type { Config as JestConfig } from 'jest-runner';
|
|
6
|
+
import { type ClientLogBuffer } from './client-log-handler.js';
|
|
7
|
+
import { type ResourceLockManager } from './resource-lock.js';
|
|
8
|
+
export type HarnessRunState = {
|
|
9
|
+
readonly runId: string;
|
|
10
|
+
readonly startTime: number;
|
|
11
|
+
readonly testFiles: string[];
|
|
12
|
+
readonly watchMode: boolean;
|
|
13
|
+
readonly coverageEnabled: boolean;
|
|
14
|
+
readonly summary?: HarnessRunSummary;
|
|
15
|
+
readonly status?: HarnessRunStatus;
|
|
16
|
+
readonly error?: unknown;
|
|
17
|
+
};
|
|
18
|
+
export type HarnessRunTestsOptions = Exclude<TestExecutionOptions, 'platform'>;
|
|
19
|
+
export type HarnessSession = {
|
|
20
|
+
readonly config: HarnessConfig;
|
|
21
|
+
readonly context: HarnessContext;
|
|
22
|
+
runTestFile: (path: string, options: HarnessRunTestsOptions) => Promise<TestSuiteResult>;
|
|
23
|
+
ensureAppReady: (testFilePath: string) => Promise<void>;
|
|
24
|
+
restartApp: (testFilePath?: string) => Promise<void>;
|
|
25
|
+
resetCrashState: () => void;
|
|
26
|
+
flushClientLogs: () => ClientLogBuffer;
|
|
27
|
+
callHook: HarnessPluginManager<HarnessConfig, HarnessPlatform>['callHook'];
|
|
28
|
+
setRunState: (state: HarnessRunState | null) => void;
|
|
29
|
+
dispose: (reason?: 'normal' | 'abort' | 'error') => Promise<void>;
|
|
30
|
+
};
|
|
31
|
+
export declare const createHarnessSession: (globalConfig: JestConfig.GlobalConfig, { lockManager }?: {
|
|
32
|
+
lockManager?: ResourceLockManager;
|
|
33
|
+
}) => Promise<HarnessSession>;
|
|
34
|
+
//# sourceMappingURL=harness-session.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-session.d.ts","sourceRoot":"","sources":["../src/harness-session.ts"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,cAAc,EAEnB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACrB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAEL,KAAK,eAAe,EAGrB,MAAM,iCAAiC,CAAC;AASzC,OAAO,EAIL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,+BAA+B,CAAC;AAOvC,OAAO,EAEL,KAAK,MAAM,IAAI,aAAa,EAE7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,aAAa,CAAC;AAMxD,OAAO,EAEL,KAAK,eAAe,EACrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EAEL,KAAK,mBAAmB,EAEzB,MAAM,oBAAoB,CAAC;AAkB5B,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,OAAO,CAAC,oBAAoB,EAAE,UAAU,CAAC,CAAC;AAE/E,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IACjC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,KAAK,OAAO,CAAC,eAAe,CAAC,CAAC;IACzF,cAAc,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,UAAU,EAAE,CAAC,YAAY,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,eAAe,EAAE,MAAM,eAAe,CAAC;IACvC,QAAQ,EAAE,oBAAoB,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC,UAAU,CAAC,CAAC;IAC3E,WAAW,EAAE,CAAC,KAAK,EAAE,eAAe,GAAG,IAAI,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACnE,CAAC;AAuOF,eAAO,MAAM,oBAAoB,GAC/B,cAAc,UAAU,CAAC,YAAY,EACrC,kBAA8C;IAAE,WAAW,CAAC,EAAE,mBAAmB,CAAA;CAAO,KACvF,OAAO,CAAC,cAAc,CA6YxB,CAAC"}
|