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

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/src/index.ts CHANGED
@@ -97,16 +97,17 @@ export default class JestHarness implements CallbackTestRunnerInterface {
97
97
  throw new CancelRun();
98
98
  }
99
99
 
100
- if (
101
- harnessConfig.resetEnvironmentBetweenTestFiles &&
102
- !isFirstTest
103
- ) {
104
- await harness.restart();
105
- }
106
- isFirstTest = false;
100
+ if (
101
+ harnessConfig.resetEnvironmentBetweenTestFiles &&
102
+ !isFirstTest
103
+ ) {
104
+ await harness.restart(test.path);
105
+ }
106
+ isFirstTest = false;
107
107
 
108
108
  return onStart(test).then(async () => {
109
109
  if (!harnessConfig.detectNativeCrashes) {
110
+ await harness.ensureAppReady(test.path);
110
111
  return runHarnessTestFile({
111
112
  testPath: test.path,
112
113
  harness,
@@ -115,10 +116,9 @@ export default class JestHarness implements CallbackTestRunnerInterface {
115
116
  });
116
117
  }
117
118
 
118
- // Start crash monitoring
119
- const crashPromise = harness.crashMonitor.startMonitoring(
120
- test.path
121
- );
119
+ await harness.ensureAppReady(test.path);
120
+ harness.crashSupervisor.beginTestRun(test.path);
121
+ const crashPromise = harness.crashSupervisor.waitForCrash(test.path);
122
122
 
123
123
  try {
124
124
  const result = await Promise.race([
@@ -133,21 +133,19 @@ export default class JestHarness implements CallbackTestRunnerInterface {
133
133
 
134
134
  return result;
135
135
  } finally {
136
- harness.crashMonitor.stopMonitoring();
136
+ harness.crashSupervisor.cancelCrashWaiters();
137
137
  }
138
138
  });
139
139
  })
140
140
  .then((result) => onResult(test, result))
141
141
  .catch(async (err) => {
142
142
  if (err instanceof NativeCrashError) {
143
+ harness.crashSupervisor.reset();
143
144
  onFailure(test, {
144
145
  message: err.message,
145
146
  stack: '',
146
147
  });
147
148
 
148
- // Restart the app for the next test file
149
- await harness.restart();
150
-
151
149
  return;
152
150
  }
153
151
 
package/src/setup.ts CHANGED
@@ -48,11 +48,6 @@ export const setup = async (globalConfig: JestConfig.GlobalConfig) => {
48
48
  // Do not setup again if HARNESS is already initialized
49
49
  // This is useful when running tests in watch mode
50
50
 
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
51
  return;
57
52
  }
58
53
 
@@ -1,109 +0,0 @@
1
- import { HarnessPlatformRunner } from '@react-native-harness/platforms';
2
- import { BridgeServer } from '@react-native-harness/bridge/server';
3
- import { NativeCrashError } from './errors.js';
4
- import { logger } from '@react-native-harness/tools';
5
-
6
- export type CrashMonitor = {
7
- startMonitoring(testFilePath: string): Promise<never>;
8
- stopMonitoring(): void;
9
- markIntentionalRestart(): void;
10
- clearIntentionalRestart(): void;
11
- dispose(): void;
12
- };
13
-
14
- export type CrashMonitorOptions = {
15
- interval: number;
16
- platformRunner: HarnessPlatformRunner;
17
- bridgeServer: BridgeServer;
18
- };
19
-
20
- export const createCrashMonitor = ({
21
- interval,
22
- platformRunner,
23
- bridgeServer,
24
- }: CrashMonitorOptions): CrashMonitor => {
25
- let pollingInterval: NodeJS.Timeout | null = null;
26
- let isIntentionalRestart = false;
27
- let currentTestFilePath: string | null = null;
28
- let rejectFn: ((error: NativeCrashError) => void) | null = null;
29
-
30
- const handleDisconnect = () => {
31
- // Verify if it's actually a crash by checking if app is still running
32
- if (!isIntentionalRestart && currentTestFilePath) {
33
- // Capture the value to avoid it being null when setTimeout callback runs
34
- const testFilePath = currentTestFilePath;
35
- logger.debug('Bridge disconnected, checking if app crashed');
36
- // Use a slight delay to allow the OS to clean up the process
37
- setTimeout(async () => {
38
- const isRunning = await platformRunner.isAppRunning();
39
- if (!isRunning && !isIntentionalRestart && rejectFn) {
40
- logger.debug(`Native crash detected during: ${testFilePath}`);
41
- rejectFn(new NativeCrashError(testFilePath));
42
- }
43
- }, 100);
44
- }
45
- };
46
-
47
- const startMonitoring = (testFilePath: string): Promise<never> => {
48
- currentTestFilePath = testFilePath;
49
-
50
- return new Promise<never>((_, reject) => {
51
- rejectFn = reject;
52
-
53
- // Listen for bridge disconnect as early indicator
54
- bridgeServer.on('disconnect', handleDisconnect);
55
-
56
- // Poll for app running status
57
- pollingInterval = setInterval(async () => {
58
- // Skip check during intentional restarts
59
- if (isIntentionalRestart) {
60
- return;
61
- }
62
-
63
- try {
64
- const isRunning = await platformRunner.isAppRunning();
65
-
66
- if (!isRunning && currentTestFilePath) {
67
- logger.debug(
68
- `Native crash detected during: ${currentTestFilePath}`
69
- );
70
- stopMonitoring();
71
- reject(new NativeCrashError(currentTestFilePath));
72
- }
73
- } catch (error) {
74
- logger.error('Error checking app status:', error);
75
- }
76
- }, interval);
77
- });
78
- };
79
-
80
- const stopMonitoring = () => {
81
- if (pollingInterval) {
82
- clearInterval(pollingInterval);
83
- pollingInterval = null;
84
- }
85
- bridgeServer.off('disconnect', handleDisconnect);
86
- currentTestFilePath = null;
87
- rejectFn = null;
88
- };
89
-
90
- const markIntentionalRestart = () => {
91
- isIntentionalRestart = true;
92
- };
93
-
94
- const clearIntentionalRestart = () => {
95
- isIntentionalRestart = false;
96
- };
97
-
98
- const dispose = () => {
99
- stopMonitoring();
100
- };
101
-
102
- return {
103
- startMonitoring,
104
- stopMonitoring,
105
- markIntentionalRestart,
106
- clearIntentionalRestart,
107
- dispose,
108
- };
109
- };