@@ -16,211 +16,203 @@ import {
1616 MetroPortUnavailableError ,
1717} from './errors.js' ;
1818
19- export const handleError = ( error : unknown ) : void => {
19+ export const formatError = ( error : unknown ) : string => {
20+ const lines : string [ ] = [ ] ;
21+
2022 if ( error instanceof AssertionError ) {
21- console . error ( `\n❌ Assertion Error` ) ;
22- console . error ( `\nError: ${ error . message } ` ) ;
23- console . error ( `\nPlease check your configuration and try again.` ) ;
23+ lines . push ( `\n❌ Assertion Error` ) ;
24+ lines . push ( `\nError: ${ error . message } ` ) ;
25+ lines . push ( `\nPlease check your configuration and try again.` ) ;
2426 } else if ( error instanceof ConfigValidationError ) {
25- console . error ( `\n❌ Configuration Error` ) ;
26- console . error ( `\nFile: ${ error . filePath } ` ) ;
27- console . error ( `\nValidation errors:` ) ;
27+ lines . push ( `\n❌ Configuration Error` ) ;
28+ lines . push ( `\nFile: ${ error . filePath } ` ) ;
29+ lines . push ( `\nValidation errors:` ) ;
2830 error . validationErrors . forEach ( ( err ) => {
29- console . error ( ` • ${ err } ` ) ;
31+ lines . push ( ` • ${ err } ` ) ;
3032 } ) ;
31- console . error ( `\nPlease fix the configuration errors and try again.` ) ;
33+ lines . push ( `\nPlease fix the configuration errors and try again.` ) ;
3234 } else if ( error instanceof ConfigNotFoundError ) {
33- console . error ( `\n❌ Configuration Not Found` ) ;
34- console . error (
35+ lines . push ( `\n❌ Configuration Not Found` ) ;
36+ lines . push (
3537 `\nCould not find 'rn-harness.config' in '${ error . searchPath } ' or any parent directories.`
3638 ) ;
37- console . error ( `\nSupported file extensions: .js, .mjs, .cjs, .json` ) ;
38- console . error (
39+ lines . push ( `\nSupported file extensions: .js, .mjs, .cjs, .json` ) ;
40+ lines . push (
3941 `\nPlease create a configuration file or run from a directory that contains one.`
4042 ) ;
4143 } else if ( error instanceof ConfigLoadError ) {
42- console . error ( `\n❌ Configuration Load Error` ) ;
43- console . error ( `\nFile: ${ error . filePath } ` ) ;
44- console . error ( `Error: ${ error . message } ` ) ;
44+ lines . push ( `\n❌ Configuration Load Error` ) ;
45+ lines . push ( `\nFile: ${ error . filePath } ` ) ;
46+ lines . push ( `Error: ${ error . message } ` ) ;
4547 if ( error . cause ) {
46- console . error ( `\nCause: ${ error . cause . message } ` ) ;
48+ lines . push ( `\nCause: ${ error . cause . message } ` ) ;
4749 }
48- console . error (
49- `\nPlease check your configuration file syntax and try again.`
50- ) ;
50+ lines . push ( `\nPlease check your configuration file syntax and try again.` ) ;
5151 } else if ( error instanceof NoRunnerSpecifiedError ) {
52- console . error ( '\n❌ No runner specified' ) ;
53- console . error (
52+ lines . push ( '\n❌ No runner specified' ) ;
53+ lines . push (
5454 '\nPlease specify a runner name or set a defaultRunner in your config.'
5555 ) ;
56- console . error ( '\nUsage: react-native-harness test [runner-name] [pattern]' ) ;
57- console . error ( '\nAvailable runners:' ) ;
56+ lines . push ( '\nUsage: react-native-harness test [runner-name] [pattern]' ) ;
57+ lines . push ( '\nAvailable runners:' ) ;
5858 error . availableRunners . forEach ( ( r ) => {
59- console . error ( ` • ${ r . name } (${ r . platform } )` ) ;
59+ lines . push ( ` • ${ r . name } (${ r . platform } )` ) ;
6060 } ) ;
61- console . error (
61+ lines . push (
6262 '\nTo set a default runner, add "defaultRunner" to your config:'
6363 ) ;
64- console . error ( ' { "defaultRunner": "your-runner-name" }' ) ;
64+ lines . push ( ' { "defaultRunner": "your-runner-name" }' ) ;
6565 } else if ( error instanceof RunnerNotFoundError ) {
66- console . error ( `\n❌ Runner "${ error . runnerName } " not found` ) ;
67- console . error ( '\nAvailable runners:' ) ;
66+ lines . push ( `\n❌ Runner "${ error . runnerName } " not found` ) ;
67+ lines . push ( '\nAvailable runners:' ) ;
6868 error . availableRunners . forEach ( ( r ) => {
69- console . error ( ` • ${ r . name } (${ r . platform } )` ) ;
69+ lines . push ( ` • ${ r . name } (${ r . platform } )` ) ;
7070 } ) ;
71- console . error ( '\nTo add a new runner, update your rn-harness.config file.' ) ;
71+ lines . push ( '\nTo add a new runner, update your rn-harness.config file.' ) ;
7272 } else if ( error instanceof EnvironmentInitializationError ) {
73- console . error ( `\n❌ Environment Initialization Error` ) ;
74- console . error ( `\nRunner: ${ error . runnerName } (${ error . platform } )` ) ;
75- console . error ( `\nError: ${ error . message } ` ) ;
73+ lines . push ( `\n❌ Environment Initialization Error` ) ;
74+ lines . push ( `\nRunner: ${ error . runnerName } (${ error . platform } )` ) ;
75+ lines . push ( `\nError: ${ error . message } ` ) ;
7676 if ( error . details ) {
77- console . error ( `\nDetails: ${ error . details } ` ) ;
77+ lines . push ( `\nDetails: ${ error . details } ` ) ;
7878 }
79- console . error ( `\nTroubleshooting steps:` ) ;
80- console . error (
79+ lines . push ( `\nTroubleshooting steps:` ) ;
80+ lines . push (
8181 ` • Verify that ${ error . platform } development environment is properly set up`
8282 ) ;
83- console . error ( ` • Check that the app is built and ready for testing` ) ;
84- console . error ( ` • Ensure all required dependencies are installed` ) ;
83+ lines . push ( ` • Check that the app is built and ready for testing` ) ;
84+ lines . push ( ` • Ensure all required dependencies are installed` ) ;
8585 if ( error . platform === 'ios' ) {
86- console . error ( ` • Verify Xcode and iOS Simulator are working correctly` ) ;
86+ lines . push ( ` • Verify Xcode and iOS Simulator are working correctly` ) ;
8787 } else if ( error . platform === 'android' ) {
88- console . error (
89- ` • Verify Android SDK and emulator are working correctly`
90- ) ;
88+ lines . push ( ` • Verify Android SDK and emulator are working correctly` ) ;
9189 }
92- console . error (
93- `\nPlease check your environment configuration and try again.`
94- ) ;
90+ lines . push ( `\nPlease check your environment configuration and try again.` ) ;
9591 } else if ( error instanceof TestExecutionError ) {
96- console . error ( `\n❌ Test Execution Error` ) ;
97- console . error ( `\nFile: ${ error . testFile } ` ) ;
92+ lines . push ( `\n❌ Test Execution Error` ) ;
93+ lines . push ( `\nFile: ${ error . testFile } ` ) ;
9894 if ( error . testSuite ) {
99- console . error ( `\nSuite: ${ error . testSuite } ` ) ;
95+ lines . push ( `\nSuite: ${ error . testSuite } ` ) ;
10096 }
10197 if ( error . testName ) {
102- console . error ( `\nTest: ${ error . testName } ` ) ;
98+ lines . push ( `\nTest: ${ error . testName } ` ) ;
10399 }
104- console . error ( `\nError: ${ error . message } ` ) ;
105- console . error ( `\nTroubleshooting steps:` ) ;
106- console . error ( ` • Check the test file syntax and logic` ) ;
107- console . error ( ` • Verify all test dependencies are available` ) ;
108- console . error ( ` • Ensure the app is in the expected state for the test` ) ;
109- console . error (
110- ` • Check device/emulator logs for additional error details`
111- ) ;
112- console . error ( `\nPlease check your test file and try again.` ) ;
100+ lines . push ( `\nError: ${ error . message } ` ) ;
101+ lines . push ( `\nTroubleshooting steps:` ) ;
102+ lines . push ( ` • Check the test file syntax and logic` ) ;
103+ lines . push ( ` • Verify all test dependencies are available` ) ;
104+ lines . push ( ` • Ensure the app is in the expected state for the test` ) ;
105+ lines . push ( ` • Check device/emulator logs for additional error details` ) ;
106+ lines . push ( `\nPlease check your test file and try again.` ) ;
113107 } else if ( error instanceof RpcClientError ) {
114- console . error ( `\n❌ RPC Client Error` ) ;
115- console . error ( `\nError: ${ error . message } ` ) ;
108+ lines . push ( `\n❌ RPC Client Error` ) ;
109+ lines . push ( `\nError: ${ error . message } ` ) ;
116110 if ( error . bridgePort ) {
117- console . error ( `\nBridge Port: ${ error . bridgePort } ` ) ;
111+ lines . push ( `\nBridge Port: ${ error . bridgePort } ` ) ;
118112 }
119113 if ( error . connectionStatus ) {
120- console . error ( `\nConnection Status: ${ error . connectionStatus } ` ) ;
114+ lines . push ( `\nConnection Status: ${ error . connectionStatus } ` ) ;
121115 }
122- console . error ( `\nTroubleshooting steps:` ) ;
123- console . error ( ` • Verify the React Native app is running and connected` ) ;
124- console . error ( ` • Check that the bridge port is not blocked by firewall` ) ;
125- console . error (
116+ lines . push ( `\nTroubleshooting steps:` ) ;
117+ lines . push ( ` • Verify the React Native app is running and connected` ) ;
118+ lines . push ( ` • Check that the bridge port is not blocked by firewall` ) ;
119+ lines . push (
126120 ` • Ensure the app has the React Native Harness runtime integrated`
127121 ) ;
128- console . error ( ` • Try restarting the app and test harness` ) ;
129- console . error ( `\nPlease check your bridge connection and try again.` ) ;
122+ lines . push ( ` • Try restarting the app and test harness` ) ;
123+ lines . push ( `\nPlease check your bridge connection and try again.` ) ;
130124 } else if ( error instanceof AppNotInstalledError ) {
131- console . error ( `\n❌ App Not Installed` ) ;
125+ lines . push ( `\n❌ App Not Installed` ) ;
132126 const deviceType =
133127 error . platform === 'ios'
134128 ? 'simulator'
135129 : error . platform === 'android'
136130 ? 'emulator'
137131 : 'virtual device' ;
138- console . error (
132+ lines . push (
139133 `\nThe app "${ error . bundleId } " is not installed on ${ deviceType } "${ error . deviceName } ".`
140134 ) ;
141- console . error ( `\nTo resolve this issue:` ) ;
135+ lines . push ( `\nTo resolve this issue:` ) ;
142136 if ( error . platform === 'ios' ) {
143- console . error (
137+ lines . push (
144138 ` • Build and install the app: npx react-native run-ios --simulator="${ error . deviceName } "`
145139 ) ;
146- console . error (
140+ lines . push (
147141 ` • Or install from Xcode: Open ios/*.xcworkspace and run the project`
148142 ) ;
149143 } else if ( error . platform === 'android' ) {
150- console . error (
151- ` • Build and install the app: npx react-native run-android`
152- ) ;
153- console . error (
144+ lines . push ( ` • Build and install the app: npx react-native run-android` ) ;
145+ lines . push (
154146 ` • Or build manually: ./gradlew assembleDebug && adb install android/app/build/outputs/apk/debug/app-debug.apk`
155147 ) ;
156148 } else if ( error . platform === 'vega' ) {
157- console . error ( ` • Build the Vega app: npm run build:app` ) ;
158- console . error (
149+ lines . push ( ` • Build the Vega app: npm run build:app` ) ;
150+ lines . push (
159151 ` • Install the app: kepler device install-app -p <path-to-vpkg> --device "${ error . deviceName } "`
160152 ) ;
161- console . error (
153+ lines . push (
162154 ` • Or use the combined command: kepler run-kepler <path-to-vpkg> "${ error . bundleId } " -d "${ error . deviceName } "`
163155 ) ;
164156 }
165- console . error ( `\nPlease install the app and try running the tests again.` ) ;
157+ lines . push ( `\nPlease install the app and try running the tests again.` ) ;
166158 } else if ( error instanceof BundlingFailedError ) {
167- console . error ( `\n❌ Test File Bundling Error` ) ;
168- console . error ( `\nFile: ${ error . modulePath } ` ) ;
169- console . error ( `\nError: ${ error . reason } ` ) ;
170- console . error ( `\nTroubleshooting steps:` ) ;
171- console . error ( ` • Check the test file syntax and imports` ) ;
172- console . error ( ` • Verify all imported modules exist and are accessible` ) ;
173- console . error ( ` • Ensure the Metro bundler configuration is correct` ) ;
174- console . error ( ` • Check for any circular dependencies in the test file` ) ;
175- console . error ( ` • Verify that all required packages are installed` ) ;
176- console . error ( `\nPlease fix the bundling issues and try again.` ) ;
159+ lines . push ( `\n❌ Test File Bundling Error` ) ;
160+ lines . push ( `\nFile: ${ error . modulePath } ` ) ;
161+ lines . push ( `\nError: ${ error . reason } ` ) ;
162+ lines . push ( `\nTroubleshooting steps:` ) ;
163+ lines . push ( ` • Check the test file syntax and imports` ) ;
164+ lines . push ( ` • Verify all imported modules exist and are accessible` ) ;
165+ lines . push ( ` • Ensure the Metro bundler configuration is correct` ) ;
166+ lines . push ( ` • Check for any circular dependencies in the test file` ) ;
167+ lines . push ( ` • Verify that all required packages are installed` ) ;
168+ lines . push ( `\nPlease fix the bundling issues and try again.` ) ;
177169 } else if ( error instanceof BridgeTimeoutError ) {
178- console . error ( `\n❌ Bridge Connection Timeout` ) ;
179- console . error (
170+ lines . push ( `\n❌ Bridge Connection Timeout` ) ;
171+ lines . push (
180172 `\nThe bridge connection timed out after ${ error . timeout } ms while waiting for the "${ error . runnerName } " (${ error . platform } ) runner to be ready.`
181173 ) ;
182- console . error ( `\nThis usually indicates that:` ) ;
183- console . error (
174+ lines . push ( `\nThis usually indicates that:` ) ;
175+ lines . push (
184176 ` • The React Native app failed to load or connect to the bridge`
185177 ) ;
186- console . error ( ` • The app crashed during startup` ) ;
187- console . error (
178+ lines . push ( ` • The app crashed during startup` ) ;
179+ lines . push (
188180 ` • Network connectivity issues between the app and the test harness`
189181 ) ;
190- console . error ( ` • The app is taking longer than expected to initialize` ) ;
191- console . error ( `\nTo resolve this issue:` ) ;
192- console . error (
182+ lines . push ( ` • The app is taking longer than expected to initialize` ) ;
183+ lines . push ( `\nTo resolve this issue:` ) ;
184+ lines . push (
193185 ` • Check that the app is properly installed and can start normally`
194186 ) ;
195- console . error (
187+ lines . push (
196188 ` • Verify that the app has the React Native Harness runtime integrated`
197189 ) ;
198- console . error ( ` • Check device/emulator logs for any startup errors` ) ;
199- console . error (
200- ` • Ensure the test harness bridge port (3001) is not blocked`
201- ) ;
202- console . error (
190+ lines . push ( ` • Check device/emulator logs for any startup errors` ) ;
191+ lines . push ( ` • Ensure the test harness bridge port (3001) is not blocked` ) ;
192+ lines . push (
203193 `\nIf the app needs more time to start, consider increasing the timeout in the configuration.`
204194 ) ;
205195 } else if ( error instanceof MetroPortUnavailableError ) {
206- console . error ( `\n❌ Metro Port Unavailable` ) ;
207- console . error ( `\nPort ${ error . port } is already in use or unavailable.` ) ;
208- console . error ( `\nThis usually indicates that:` ) ;
209- console . error ( ` • Another Metro bundler instance is already running` ) ;
210- console . error ( ` • Another application is using port ${ error . port } ` ) ;
211- console . error ( ` • The port is blocked by a firewall or security software` ) ;
212- console . error ( `\nTo resolve this issue:` ) ;
213- console . error ( ` • Stop any running Metro bundler instances` ) ;
214- console . error (
196+ lines . push ( `\n❌ Metro Port Unavailable` ) ;
197+ lines . push ( `\nPort ${ error . port } is already in use or unavailable.` ) ;
198+ lines . push ( `\nThis usually indicates that:` ) ;
199+ lines . push ( ` • Another Metro bundler instance is already running` ) ;
200+ lines . push ( ` • Another application is using port ${ error . port } ` ) ;
201+ lines . push ( ` • The port is blocked by a firewall or security software` ) ;
202+ lines . push ( `\nTo resolve this issue:` ) ;
203+ lines . push ( ` • Stop any running Metro bundler instances` ) ;
204+ lines . push (
215205 ` • Check for other applications using port ${ error . port } : lsof -i :${ error . port } `
216206 ) ;
217- console . error ( ` • Kill the process using the port: kill -9 <PID>` ) ;
218- console . error (
207+ lines . push ( ` • Kill the process using the port: kill -9 <PID>` ) ;
208+ lines . push (
219209 ` • Or use a different port by updating your Metro configuration`
220210 ) ;
221- console . error ( `\nPlease free up the port and try again.` ) ;
211+ lines . push ( `\nPlease free up the port and try again.` ) ;
222212 } else {
223- console . error ( `\n❌ Unexpected Error` ) ;
224- console . error ( error ) ;
213+ // Re-throw the error to be handled by the caller
214+ throw error ;
225215 }
216+
217+ return lines . join ( '' ) ;
226218} ;
0 commit comments