@@ -709,6 +709,10 @@ function wireLogStreamOutput(logStreamProcess, state) {
709709 }
710710
711711 const normalized = stripAnsi ( line ) ;
712+ state . recentRawLines . push ( normalized ) ;
713+ if ( state . recentRawLines . length > 400 ) {
714+ state . recentRawLines . splice ( 0 , state . recentRawLines . length - 400 ) ;
715+ }
712716 if ( ! includeLine ( normalized ) ) {
713717 return ;
714718 }
@@ -864,13 +868,7 @@ function collectRecentSimulatorLogs(udid, pid) {
864868 const text = result . stdout || "" ;
865869 let lines = text
866870 . split ( / \r ? \n / )
867- . filter ( ( line ) =>
868- line . includes ( "CONSOLE LOG:" ) ||
869- line . includes ( "NativeScriptException" ) ||
870- line . includes ( "Uncaught" ) ||
871- line . includes ( "EXC_BAD_ACCESS" ) ||
872- line . includes ( "heap" )
873- ) ;
871+ . filter ( Boolean ) ;
874872
875873 // Keep only the most recent app run in this log window.
876874 const startIndex = ( ( ) => {
@@ -895,6 +893,106 @@ function collectRecentSimulatorLogs(udid, pid) {
895893 return lines . join ( "\n" ) ;
896894}
897895
896+ function getRecentRawLogTail ( state , maxLines = 80 ) {
897+ if ( ! state . recentRawLines || state . recentRawLines . length === 0 ) {
898+ return "" ;
899+ }
900+
901+ return state . recentRawLines . slice ( - maxLines ) . join ( "\n" ) ;
902+ }
903+
904+ function readJunitFileState ( udid ) {
905+ const dataContainer = getAppDataContainerPath ( udid ) ;
906+ if ( ! dataContainer ) {
907+ return {
908+ dataContainer : null ,
909+ junitPath : null ,
910+ exists : false ,
911+ complete : false ,
912+ sizeBytes : 0 ,
913+ tail : "" ,
914+ documentsEntries : [ ]
915+ } ;
916+ }
917+
918+ const documentsPath = path . join ( dataContainer , "Documents" ) ;
919+ const junitPath = path . join ( documentsPath , "junit-result.xml" ) ;
920+ const documentsEntries = fs . existsSync ( documentsPath )
921+ ? fs . readdirSync ( documentsPath ) . sort ( )
922+ : [ ] ;
923+
924+ if ( ! fs . existsSync ( junitPath ) ) {
925+ return {
926+ dataContainer,
927+ junitPath,
928+ exists : false ,
929+ complete : false ,
930+ sizeBytes : 0 ,
931+ tail : "" ,
932+ documentsEntries
933+ } ;
934+ }
935+
936+ const xml = fs . readFileSync ( junitPath , "utf8" ) ;
937+ return {
938+ dataContainer,
939+ junitPath,
940+ exists : true ,
941+ complete : xml . includes ( "</testsuites>" ) ,
942+ sizeBytes : Buffer . byteLength ( xml , "utf8" ) ,
943+ tail : xml . slice ( - 2000 ) ,
944+ documentsEntries
945+ } ;
946+ }
947+
948+ function collectSimulatorProcessSnapshot ( udid ) {
949+ const result = run ( "xcrun" , [ "simctl" , "spawn" , udid , "ps" , "-axo" , "pid,ppid,stat,etime,command" ] ) ;
950+ if ( result . status !== 0 ) {
951+ return "" ;
952+ }
953+
954+ const lines = ( result . stdout || "" )
955+ . split ( / \r ? \n / )
956+ . filter ( ( line ) => / P I D | T e s t R u n n e r | l a u n c h d _ s i m | U I K i t A p p l i c a t i o n / i. test ( line ) ) ;
957+
958+ return lines . join ( "\n" ) ;
959+ }
960+
961+ function formatInactivityDiagnostics ( udid , state , pid ) {
962+ const sections = [ ] ;
963+ const rawTail = getRecentRawLogTail ( state ) ;
964+ if ( rawTail ) {
965+ sections . push ( `--- Recent raw simulator log lines ---\n${ rawTail } ` ) ;
966+ }
967+
968+ const simulatorLogs = collectRecentSimulatorLogs ( udid , pid ) ;
969+ if ( simulatorLogs ) {
970+ sections . push ( `--- Recent TestRunner simulator logs ---\n${ simulatorLogs } ` ) ;
971+ }
972+
973+ const junitState = readJunitFileState ( udid ) ;
974+ const junitSummaryLines = [
975+ `data container: ${ junitState . dataContainer || "<missing>" } ` ,
976+ `junit path: ${ junitState . junitPath || "<missing>" } ` ,
977+ `junit exists: ${ junitState . exists } ` ,
978+ `junit complete: ${ junitState . complete } ` ,
979+ `junit size bytes: ${ junitState . sizeBytes } ` ,
980+ `documents entries: ${ junitState . documentsEntries . length > 0 ? junitState . documentsEntries . join ( ", " ) : "<empty>" } `
981+ ] ;
982+ if ( junitState . tail ) {
983+ junitSummaryLines . push ( "junit tail:" ) ;
984+ junitSummaryLines . push ( junitState . tail ) ;
985+ }
986+ sections . push ( `--- App container state ---\n${ junitSummaryLines . join ( "\n" ) } ` ) ;
987+
988+ const processSnapshot = collectSimulatorProcessSnapshot ( udid ) ;
989+ if ( processSnapshot ) {
990+ sections . push ( `--- Simulator process snapshot ---\n${ processSnapshot } ` ) ;
991+ }
992+
993+ return sections . join ( "\n\n" ) ;
994+ }
995+
898996function parseJasmineSummary ( logText ) {
899997 const re = / ( S U C C E S S | F A I L U R E ) : \s + ( \d + ) \s + s p e c s , \s + ( \d + ) \s + f a i l u r e (?: s ) ? \, \s + ( \d + ) \s + s k i p p e d , \s + ( \d + ) \s + d i s a b l e d / i;
900998 const match = logText . match ( re ) ;
@@ -990,7 +1088,13 @@ async function main() {
9901088 let launchProcess ;
9911089 let logStreamProcess ;
9921090 let exitCode = 0 ;
993- const launchState = { logs : "" , jasmineSummary : null , fatalDetected : false , lastActivityAt : Date . now ( ) } ;
1091+ const launchState = {
1092+ logs : "" ,
1093+ jasmineSummary : null ,
1094+ fatalDetected : false ,
1095+ lastActivityAt : Date . now ( ) ,
1096+ recentRawLines : [ ]
1097+ } ;
9941098
9951099 try {
9961100 if ( enableLiveLogStream ) {
@@ -1043,11 +1147,10 @@ async function main() {
10431147 } else {
10441148 const closeResult = launchResult || { code : 0 , signal : null } ;
10451149 const launchPid = extractLaunchPid ( launchState . logs ) ;
1046- const simulatorLogs = collectRecentSimulatorLogs ( udid , launchPid ) ;
1047- if ( simulatorLogs ) {
1048- launchState . logs += `\n${ simulatorLogs } ` ;
1049- console . log ( "\n--- TestRunner Logs (simulator) ---" ) ;
1050- console . log ( simulatorLogs ) ;
1150+ const inactivityDiagnostics = formatInactivityDiagnostics ( udid , launchState , launchPid ) ;
1151+ if ( inactivityDiagnostics ) {
1152+ launchState . logs += `\n${ inactivityDiagnostics } ` ;
1153+ console . log ( `\n${ inactivityDiagnostics } ` ) ;
10511154 }
10521155
10531156 const jasmineSummary = launchState . jasmineSummary || parseJasmineSummary ( launchState . logs ) ;
0 commit comments