@@ -197,11 +197,12 @@ function showSuiteData(data, suiteID) {
197
197
{
198
198
title : 'Logs' ,
199
199
name : 'logs' ,
200
- data : 'clientInfo' ,
200
+ data : null , // Use null to allow access to the full row data
201
201
width : '20%' ,
202
202
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 ) ;
205
206
}
206
207
} ,
207
208
] ,
@@ -317,21 +318,112 @@ function deselectTest(row, closeDetails) {
317
318
history . replaceState ( null , null , '#' ) ;
318
319
}
319
320
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 ;
322
338
}
323
339
324
340
// formatClientLogsList turns the clientInfo part of a test into a list of links.
325
341
function formatClientLogsList ( suiteData , testIndex , clientInfo ) {
326
342
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
+ }
334
370
}
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
+
335
427
return links . join ( ', ' ) ;
336
428
}
337
429
@@ -360,7 +452,7 @@ function formatTestDetails(suiteData, row) {
360
452
p . innerHTML = formatTestStatus ( d . summaryResult ) ;
361
453
container . appendChild ( p ) ;
362
454
}
363
- if ( ! row . column ( 'logs:name' ) . responsiveHidden ( ) && testHasClients ( d ) ) {
455
+ if ( ! row . column ( 'logs:name' ) . responsiveHidden ( ) && testHasClients ( d , suiteData ) ) {
364
456
let p = document . createElement ( 'p' ) ;
365
457
p . innerHTML = '<b>Clients:</b> ' + formatClientLogsList ( suiteData , d . testIndex , d . clientInfo ) ;
366
458
container . appendChild ( p ) ;
@@ -480,6 +572,33 @@ function formatTestLog(suiteData, testIndex, logData, container) {
480
572
}
481
573
482
574
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
+ }
483
602
}
484
603
485
604
function formatTestDetailLines ( lines ) {
0 commit comments