@@ -197,11 +197,12 @@ function showSuiteData(data, suiteID) {
197197 {
198198 title : 'Logs' ,
199199 name : 'logs' ,
200- data : 'clientInfo' ,
200+ data : null , // Use null to allow access to the full row data
201201 width : '20%' ,
202202 responsivePriority : 1 ,
203- render : function ( clientInfo , type , row ) {
204- return formatClientLogsList ( data , row . testIndex , clientInfo ) ;
203+ render : function ( _ , type , row ) {
204+ // Pass both clientInfo and the row data to allow showing logs even if clientInfo is null
205+ return formatClientLogsList ( data , row . testIndex , row . clientInfo ) ;
205206 }
206207 } ,
207208 ] ,
@@ -317,21 +318,112 @@ function deselectTest(row, closeDetails) {
317318 history . replaceState ( null , null , '#' ) ;
318319}
319320
320- function testHasClients ( testData ) {
321- return testData . clientInfo && Object . getOwnPropertyNames ( testData . clientInfo ) . length > 0 ;
321+ function testHasClients ( testData , suiteData ) {
322+ // Check if the test has any associated clients directly
323+ if ( testData . clientInfo && Object . getOwnPropertyNames ( testData . clientInfo ) . length > 0 ) {
324+ return true ;
325+ }
326+
327+ // Check for clientLogs in the test result (indicates shared client usage)
328+ if ( testData . summaryResult && testData . summaryResult . clientLogs ) {
329+ return Object . getOwnPropertyNames ( testData . summaryResult . clientLogs ) . length > 0 ;
330+ }
331+
332+ // Check for shared clients at the suite level
333+ if ( suiteData && suiteData . sharedClients && Object . getOwnPropertyNames ( suiteData . sharedClients ) . length > 0 ) {
334+ return true ;
335+ }
336+
337+ return false ;
322338}
323339
324340// formatClientLogsList turns the clientInfo part of a test into a list of links.
325341function formatClientLogsList ( suiteData , testIndex , clientInfo ) {
326342 let links = [ ] ;
327- for ( let instanceID in clientInfo ) {
328- let instanceInfo = clientInfo [ instanceID ] ;
329- let logfile = routes . resultsRoot + instanceInfo . logFile ;
330- let url = routes . clientLog ( suiteData . suiteID , suiteData . name , testIndex , logfile ) ;
331- let link = html . makeLink ( url , instanceInfo . name ) ;
332- link . classList . add ( 'log-link' ) ;
333- links . push ( link . outerHTML ) ;
343+ let testData = suiteData . testCases [ testIndex ] ;
344+
345+ // Process regular clients from clientInfo
346+ if ( clientInfo ) {
347+ for ( let instanceID in clientInfo ) {
348+ let instanceInfo = clientInfo [ instanceID ] ;
349+ if ( instanceInfo . logFile ) {
350+ // For regular (non-shared) clients or for shared clients with client segments,
351+ // we use the logFile directly from clientInfo - this should point to either
352+ // the full log file or to the extracted segment file in shared_clients/
353+ let logfile = routes . resultsRoot + instanceInfo . logFile ;
354+ let url = routes . clientLog ( suiteData . suiteID , suiteData . name , testIndex , logfile ) ;
355+
356+ // Add (shared) indicator to shared client names
357+ let name = instanceInfo . name ;
358+ if ( instanceInfo . isShared || instanceInfo . logFile . includes ( 'shared_clients/' ) ) {
359+ name += ' (shared)' ;
360+ }
361+
362+ let link = html . makeLink ( url , name ) ;
363+ link . classList . add ( 'log-link' ) ;
364+ if ( instanceInfo . isShared || instanceInfo . logFile . includes ( 'shared_clients/' ) ) {
365+ link . classList . add ( 'shared-client-link' ) ;
366+ }
367+ links . push ( link . outerHTML ) ;
368+ }
369+ }
334370 }
371+
372+ // Check for shared client log segments
373+ if ( testData && testData . summaryResult && testData . summaryResult . clientLogs ) {
374+ for ( let clientID in testData . summaryResult . clientLogs ) {
375+ // Skip if we already have a log link for this client
376+ let alreadyHasLink = false ;
377+ if ( clientInfo ) {
378+ for ( let instanceID in clientInfo ) {
379+ if ( instanceID === clientID ) {
380+ alreadyHasLink = true ;
381+ break ;
382+ }
383+ }
384+ }
385+ if ( alreadyHasLink ) continue ;
386+
387+ // Find the shared client in the suite
388+ if ( suiteData . sharedClients && suiteData . sharedClients [ clientID ] ) {
389+ let sharedClient = suiteData . sharedClients [ clientID ] ;
390+
391+ // Look for the log segment file in the shared_clients directory
392+ // The pattern is: shared_clients/timestamp-clientName-clientID-testIndex.log
393+ let dirPath = 'shared_clients/' ;
394+ let pattern = `-${ sharedClient . name } -${ clientID } -test${ testIndex } .log` ;
395+
396+ // We would ideally search for matching files here, but since we can't
397+ // we'll just list the available client, linking to its original logfile
398+ // When clicking, the UI should dynamically try to locate the correct segment
399+ // We need to look for the segment file in the shared_clients directory
400+ // The pattern is now: shared_clients/timestamp-clientName-clientID-testIndex.log
401+ // But we can't search for it directly here, so we'll use the pattern to construct
402+ // a best guess of the filename based on our updated naming convention
403+ let logfile = routes . resultsRoot + sharedClient . logFile ;
404+ let url = routes . clientLog ( suiteData . suiteID , suiteData . name , testIndex , logfile ) ;
405+ let link = html . makeLink ( url , sharedClient . name + ' (shared)' ) ;
406+ link . classList . add ( 'log-link' ) ;
407+ link . classList . add ( 'shared-client-link' ) ;
408+ links . push ( link . outerHTML ) ;
409+ }
410+ }
411+ }
412+
413+ // If we still don't have any links but there are shared clients in the suite,
414+ // add links to the shared clients
415+ if ( links . length === 0 && suiteData . sharedClients ) {
416+ for ( let instanceID in suiteData . sharedClients ) {
417+ let instanceInfo = suiteData . sharedClients [ instanceID ] ;
418+ let logfile = routes . resultsRoot + instanceInfo . logFile ;
419+ let url = routes . clientLog ( suiteData . suiteID , suiteData . name , testIndex , logfile ) ;
420+ let link = html . makeLink ( url , instanceInfo . name + ' (shared)' ) ;
421+ link . classList . add ( 'log-link' ) ;
422+ link . classList . add ( 'shared-client-link' ) ;
423+ links . push ( link . outerHTML ) ;
424+ }
425+ }
426+
335427 return links . join ( ', ' ) ;
336428}
337429
@@ -360,7 +452,7 @@ function formatTestDetails(suiteData, row) {
360452 p . innerHTML = formatTestStatus ( d . summaryResult ) ;
361453 container . appendChild ( p ) ;
362454 }
363- if ( ! row . column ( 'logs:name' ) . responsiveHidden ( ) && testHasClients ( d ) ) {
455+ if ( ! row . column ( 'logs:name' ) . responsiveHidden ( ) && testHasClients ( d , suiteData ) ) {
364456 let p = document . createElement ( 'p' ) ;
365457 p . innerHTML = '<b>Clients:</b> ' + formatClientLogsList ( suiteData , d . testIndex , d . clientInfo ) ;
366458 container . appendChild ( p ) ;
@@ -480,6 +572,33 @@ function formatTestLog(suiteData, testIndex, logData, container) {
480572 }
481573
482574 container . appendChild ( output ) ;
575+
576+ // Show client log segments if available
577+ if ( d . summaryResult . clientLogs && Object . keys ( d . summaryResult . clientLogs ) . length > 0 ) {
578+ let p = document . createElement ( 'p' ) ;
579+ p . innerHTML = '<b>Client Log Segments:</b>' ;
580+ container . appendChild ( p ) ;
581+
582+ let logSegmentsDiv = document . createElement ( 'div' ) ;
583+ logSegmentsDiv . classList . add ( 'client-log-segments' ) ;
584+
585+ for ( let clientID in d . summaryResult . clientLogs ) {
586+ let segment = d . summaryResult . clientLogs [ clientID ] ;
587+ let clientName = clientID ;
588+
589+ // Try to find a friendly name for the client
590+ if ( suiteData . sharedClients && suiteData . sharedClients [ clientID ] ) {
591+ clientName = suiteData . sharedClients [ clientID ] . name || clientID ;
592+ }
593+
594+ let segmentInfo = document . createElement ( 'div' ) ;
595+ segmentInfo . classList . add ( 'client-log-segment' ) ;
596+ segmentInfo . innerHTML = `<b>${ clientName } :</b> Lines ${ segment . start } to ${ segment . end } ` ;
597+ logSegmentsDiv . appendChild ( segmentInfo ) ;
598+ }
599+
600+ container . appendChild ( logSegmentsDiv ) ;
601+ }
483602}
484603
485604function formatTestDetailLines ( lines ) {
0 commit comments