11import React , { useEffect , useState , createContext , useContext } from "react" ;
22import { Text , Platform , TextProps } from 'react-native' ;
3+ import parseErrorStack , { StackFrame } from 'react-native/Libraries/Core/Devtools/parseErrorStack' ;
4+ import symbolicateStackTrace from 'react-native/Libraries/Core/Devtools/symbolicateStackTrace' ;
35
46import { Client , CustomContext } from "mocha-remote-client" ;
57
@@ -39,21 +41,40 @@ export const MochaRemoteContext = createContext<MochaRemoteContextValue>({
3941 context : { } ,
4042} ) ;
4143
44+ function isExternalFrame ( { file } : StackFrame ) {
45+ return ! file . includes ( "/mocha-remote/packages/client/dist/" ) && ! file . includes ( "/mocha-remote-client/dist/" )
46+ }
47+
48+ function framesToStack ( error : Error , frames : StackFrame [ ] ) {
49+ const lines = frames . filter ( isExternalFrame ) . map ( ( { methodName, column, file, lineNumber } ) => {
50+ return ` at ${ methodName } (${ file } :${ lineNumber } :${ column } )`
51+ } ) ;
52+ return `${ error . name } : ${ error . message } \n${ lines . join ( "\n" ) } ` ;
53+ }
54+
4255export function MochaRemoteProvider ( { children, tests, title = `React Native on ${ Platform . OS } ` } : MochaRemoteProviderProps ) {
4356 const [ connected , setConnected ] = useState ( false ) ;
4457 const [ status , setStatus ] = useState < Status > ( { kind : "waiting" } ) ;
4558 const [ context , setContext ] = useState < CustomContext > ( { } ) ;
4659 useEffect ( ( ) => {
4760 const client = new Client ( {
4861 title,
62+ async transformFailure ( _ , err ) {
63+ // TODO: Remove the two `as any` once https://github.com/facebook/react-native/pull/43566 gets released
64+ const stack = parseErrorStack ( err . stack as any ) ;
65+ const symbolicated = await symbolicateStackTrace ( stack ) as any ;
66+ err . stack = framesToStack ( err , symbolicated . stack ) ;
67+ return err ;
68+ } ,
4969 tests ( context ) {
50- setContext ( context ) ;
5170 // Adding an async hook before each test to allow the UI to update
5271 beforeEach ( "async-pause" , ( ) => {
5372 return new Promise < void > ( ( resolve ) => setImmediate ( resolve ) ) ;
5473 } ) ;
5574 // Require in the tests
5675 tests ( context ) ;
76+ // Make the context available to context consumers
77+ setContext ( context ) ;
5778 } ,
5879 } )
5980 . on ( "connection" , ( ) => {
@@ -98,7 +119,7 @@ export function MochaRemoteProvider({ children, tests, title = `React Native on
98119 } , [ setStatus , setContext ] ) ;
99120
100121 return (
101- < MochaRemoteContext . Provider value = { { status, connected, context} } >
122+ < MochaRemoteContext . Provider value = { { status, connected, context } } >
102123 { children }
103124 </ MochaRemoteContext . Provider >
104125 ) ;
@@ -125,7 +146,7 @@ function getStatusEmoji(status: Status) {
125146}
126147
127148export function StatusEmoji ( props : TextProps ) {
128- const { status} = useMochaRemoteContext ( ) ;
149+ const { status } = useMochaRemoteContext ( ) ;
129150 return < Text { ...props } > { getStatusEmoji ( status ) } </ Text >
130151}
131152
@@ -144,7 +165,7 @@ function getStatusMessage(status: Status) {
144165}
145166
146167export function StatusText ( props : TextProps ) {
147- const { status} = useMochaRemoteContext ( ) ;
168+ const { status } = useMochaRemoteContext ( ) ;
148169 return < Text { ...props } > { getStatusMessage ( status ) } </ Text >
149170}
150171
@@ -157,6 +178,6 @@ function getConnectionMessage(connected: boolean) {
157178}
158179
159180export function ConnectionText ( props : TextProps ) {
160- const { connected} = useMochaRemoteContext ( ) ;
181+ const { connected } = useMochaRemoteContext ( ) ;
161182 return < Text { ...props } > { getConnectionMessage ( connected ) } </ Text >
162183}
0 commit comments